Bugz Door Project
door.h
1 #ifndef DOOR_H
2 #define DOOR_H
3 
4 #include "anyoption.h"
5 #include <cstdint>
6 #include <ctime>
7 #include <fstream>
8 #include <functional>
9 #include <future>
10 #include <iostream>
11 #include <memory>
12 #include <ostream>
13 #include <vector>
14 
15 // raw mode
16 #include <termios.h>
17 #include <unistd.h>
18 
19 #define CSI "\x1b["
20 
21 // getkey definitions
22 #define XKEY_START 0x1000
23 
24 #define XKEY_UP_ARROW 0x1001
25 #define XKEY_DOWN_ARROW 0x1002
26 #define XKEY_RIGHT_ARROW 0x1003
27 #define XKEY_LEFT_ARROW 0x1004
28 
29 #define XKEY_HOME 0x1010
30 #define XKEY_END 0x1011
31 #define XKEY_PGUP 0x1012
32 #define XKEY_PGDN 0x1023
33 #define XKEY_INSERT 0x1024
34 #define XKEY_DELETE 0x7f
35 
36 #define XKEY_F1 0x1021
37 #define XKEY_F2 0x1022
38 #define XKEY_F3 0x1023
39 #define XKEY_F4 0x1024
40 #define XKEY_F5 0x1025
41 #define XKEY_F6 0x1026
42 #define XKEY_F7 0x1027
43 #define XKEY_F8 0x1028
44 #define XKEY_F9 0x1029
45 #define XKEY_F10 0x102a
46 #define XKEY_F11 0x102b
47 #define XKEY_F12 0x102c
48 
49 #define XKEY_UNKNOWN 0x1111
50 
56 namespace door {
57 
58 extern bool unicode;
59 extern bool full_cp437;
60 extern bool debug_capture;
61 
62 /*
63 Translate CP437 strings to unicode for output.
64 
65 if (door::unicode) {
66  // perform translation
67 }
68 
69  */
70 void cp437toUnicode(std::string input, std::string &out);
71 void cp437toUnicode(const char *input, std::string &out);
72 
73 /*
74 door 2.0
75  */
76 
84 enum class COLOR : std::int8_t {
86  BLACK,
88  RED,
90  GREEN,
92  BROWN,
94  YELLOW = 3,
96  BLUE,
98  MAGENTA,
100  CYAN,
102  WHITE
103 };
104 
108 enum class ATTR : std::int8_t {
110  RESET,
112  BOLD,
114  BRIGHT = 1,
116  BLINK = 5,
118  INVERSE = 7
119 };
120 
131 class ANSIColor {
136  // Track attributes (ATTR)
138  unsigned int reset : 1;
140  unsigned int bold : 1;
142  unsigned int blink : 1;
144  unsigned int inverse : 1;
145 
146 public:
147  // default initialization here
148  ANSIColor();
149  ANSIColor(ATTR a);
150  ANSIColor(COLOR f);
151  ANSIColor(COLOR f, ATTR a);
152  ANSIColor(COLOR f, ATTR a1, ATTR a2);
153  ANSIColor(COLOR f, COLOR b);
154  ANSIColor(COLOR f, COLOR b, ATTR a);
155  ANSIColor(COLOR f, COLOR b, ATTR a1, ATTR a2);
156  ANSIColor &Attr(ATTR a);
157  bool operator==(const ANSIColor &c) const;
158  bool operator!=(const ANSIColor &c) const;
159  void setFg(COLOR f);
160  void setFg(COLOR f, ATTR a);
161  void setBg(COLOR b);
162  COLOR getFg() { return fg; };
163  COLOR getBg() { return bg; };
164  void attr(ATTR a);
165 
169  std::string output(void) const;
170 
171  std::string debug(void);
172 
177  std::string output(ANSIColor &previous) const;
178 
184  friend std::ostream &operator<<(std::ostream &os, const ANSIColor &c);
185 };
186 
193 class Door : public std::ostream, private std::streambuf {
194 
195 private:
196  std::streamsize xsputn(const char *s, std::streamsize n) override;
197  int overflow(int c) override;
198  std::string doorname;
199  void parse_dropfile(const char *filepath);
200  void init(void);
201  std::time_t startup;
202  struct termios tio_default;
203  // getkey functions
204  signed int getch(void);
205  void unget(char c);
206  char get(void);
207  char buffer[5];
208  unsigned int bpos;
209  bool has_dropfile;
210  bool debugging;
211  std::string dropfilename;
212  vector<std::string> dropfilelines;
213  ofstream logf;
214  void detect_unicode_and_screen(void);
215 
216  // time thread - time left
217  std::promise<void> stop_thread;
218  // std::future<void> stop_future;
219 
220  // atomic seconds_elapsed ?
221  int seconds_elapsed;
222  void time_thread_run(std::future<void> future);
223  std::thread time_thread;
224 
225 public:
230  Door(std::string dname, int argc, char *argv[]);
232  Door(Door &) = delete;
233  virtual ~Door();
234  ofstream &log(void);
235  // void log(std::string output);
236  AnyOption opt;
237  std::string debug_buffer;
238 
245  bool track;
246  int cx;
247  int cy;
248  int width;
249  int height;
250  int inactivity;
251  std::string username;
252  std::string handle;
253  std::string location;
254  std::string sysop;
255  // std::string bbsname;
256  int node;
257  atomic<int> time_left;
258  atomic<int> time_used;
259 
260  signed int getkey(void);
261  bool haskey(void);
262  int get_input(void);
263  signed int sleep_key(int secs);
264  std::string input_string(int max);
265  int get_one_of(const char *keys);
266 };
267 
268 // Use this to define the deprecated colorizer [POC]
269 // typedef std::function<void(Door &, std::string &)> colorFunction;
270 
279 class ColorOutput {
280 public:
281  ColorOutput();
282  void reset(void);
283 
287  int pos;
289  int len;
290 };
291 
292 /*
293 No, don't do this.
294 
295 Instead, return an iterator/generator.
296  */
297 
307 class Render {
308 public:
309  Render(const std::string txt);
311  const std::string text;
313  std::vector<ColorOutput> outputs;
314  void append(ANSIColor color, int len = 1);
315  void output(std::ostream &os);
316 };
317 
341 typedef std::function<Render(const std::string &)> renderFunction;
342 
360 typedef std::function<std::string(void)> updateFunction;
361 
367 class Clrscr {
368 public:
369  Clrscr(void);
370  friend std::ostream &operator<<(std::ostream &os, const Clrscr &clr);
371 };
372 
377 extern Clrscr cls;
378 
384 class NewLine {
385 public:
386  NewLine(void);
387  friend std::ostream &operator<<(std::ostream &os, const NewLine &nl);
388 };
389 
393 extern NewLine nl;
394 
401 
403 enum class Justify { NONE, LEFT, RIGHT, CENTER };
404 
411 class Goto {
413  int x;
415  int y;
416 
417 public:
418  Goto(int xpos, int ypos);
422  Goto(const Goto &) = default;
423  void set(int xpos, int ypos);
424  friend std::ostream &operator<<(std::ostream &os, const Goto &g);
425 };
426 
427 extern const char SaveCursor[];
428 extern const char RestoreCursor[];
429 
430 #ifdef EXPERIMENTAL
431 
432 /* should we try to derive a base class, so you can have multilines of
433  * multilines? */
434 
435 class LineBase {
436 public:
437  virtual ~LineBase() = default;
438  virtual bool update(void) = 0;
439  // friend std::ostream &operator<<(std::ostream &os, const LineBase &lb) = 0;
440 };
441 
442 class BasicLine {
443 private:
444  std::string text;
445  bool hasColor;
446  ANSIColor color;
448  renderFunction render;
450  updateFunction updater;
451 
452 public:
453  BasicLine(std::string txt);
454  BasicLine(std::string txt, ANSIColor c);
455  BasicLine(const BasicLine &rhs) = default;
456  virtual ~BasicLine() = default;
457 
458  bool hasRender(void);
459  void setText(std::string txt);
460  void setColor(ANSIColor c);
461  void setRender(renderFunction rf);
462  void setUpdater(updateFunction uf);
463  bool update(void);
464 
465  friend std::ostream &operator<<(std::ostream &os, const BasicLine &l);
466 };
467 
468 class MultiLine {
469 private:
470  std::vector<std::shared_ptr<BasicLine>> lines;
471 
472 public:
473  MultiLine();
474  void append(std::shared_ptr<BasicLine> bl);
475 
476  bool update(void);
477  friend std::ostream &operator<<(std::ostream &os, const MultiLine &l);
478 };
479 
480 #endif
481 
488 class Line {
489 private:
491  std::string text;
492 
494  bool hasColor;
498  std::string padding;
501 
506 
507  int width;
508 
512  // void makeWidth(int width);
513 
514 public:
515  Line(const std::string &txt, int width = 0);
516  Line(const char *txt, int width = 0);
517  Line(const std::string &txt, int width, ANSIColor c);
518  Line(const char *txt, int width, ANSIColor c);
519  Line(const std::string &txt, int width, renderFunction rf);
520  Line(const char *txt, int width, renderFunction rf);
521  Line(const Line &rhs);
522  Line(Line &&rhs);
523  // ~Line();
524 
525  bool hasRender(void);
526  int length(void); // const;
527  void fit(void);
532  void setPadding(std::string &padstring, ANSIColor padColor);
537  void setPadding(const char *padstring, ANSIColor padcolor);
538  void setText(std::string &txt);
539  void setText(const char *txt);
540  const char *getText(void) { return text.c_str(); };
541  void setColor(ANSIColor c);
542  void setRender(renderFunction rf);
543  void setUpdater(updateFunction uf);
544  bool update(void);
545 
546  std::string debug(void);
547 
560  friend std::ostream &operator<<(std::ostream &os, const Line &l);
561 };
562 
565 
570 enum class BorderStyle {
572  NONE,
574  SINGLE,
576  DOUBLE,
582  BLANK
583 };
584 
585 class Panel {
586 protected:
587  int x;
588  int y;
589  int width; // or padding ?
590  BorderStyle border_style;
591  ANSIColor border_color;
598  std::vector<std::unique_ptr<Line>> lines;
599  bool hidden;
600  // when you show panel, should it mark it as
601  // redisplay everything?? maybe??
602  bool shown_once; // ?? maybe shown_once_already ?
603  std::unique_ptr<Line> title;
604  int offset;
605 
606 public:
607  Panel(int x, int y, int width);
608  Panel(int width);
609 
610  // Panel(const Panel &);
611  Panel(Panel &) = delete; // default;
612  Panel(Panel &&ref);
613 
614  void set(int x, int y);
615  /*
616  void get(int &x, int &y) {
617  x = this->x;
618  y = this->y;
619  }; */
620  void setTitle(std::unique_ptr<Line> T, int off = 1);
621  void setStyle(BorderStyle bs);
622  void setColor(ANSIColor c);
623  int getWidth(void) { return width; };
624  int getHeight(void) {
625  if (border_style == BorderStyle::NONE)
626  return lines.size();
627  else
628  return lines.size() + 2;
629  };
630  void hide(void);
631  void show(void);
632  void addLine(std::unique_ptr<Line> l);
633  // bool delLine(std::shared_ptr<Line> l); // ?
634  /*
635  void display(void);
636  void update(void);
637  */
638 
649  bool update(Door &d);
650  void update(Door &d, int line);
651  void update(void);
652  door::Goto gotoEnd(void);
653  std::unique_ptr<Line> spacer_line(bool single);
654  void lineSetBack(ANSIColor back);
655  friend std::ostream &operator<<(std::ostream &os, const Panel &p);
656 };
657 
658 /*
659 Menu - defaults to double lines.
660 Has colorize for selected item / non-selected.
661 Arrow keys + ENTER, or keypress to select an item.
662 [O] Option Displayed Here
663 
664 [ + ] = c1
665 O = c2
666 Remaining UC TEXT = c3
667 Remaining LC text = c4
668 
669 // Colors for CS and CU (color selected, color unselected)
670  */
671 
672 class Menu : public Panel {
673 private:
674  unsigned int chosen;
675  std::vector<char> options;
676  renderFunction selectedRender;
677  renderFunction unselectedRender;
678  /*
679  std::function<void(Door &d, std::string &)> selectedColorizer;
680  std::function<void(Door &d, std::string &)> unselectedColorizer;
681  */
682 
683 public:
684  static renderFunction defaultSelectedRender;
685  static renderFunction defaultUnselectedRender;
686  /*
687  static std::function<void(Door &d, std::string &)> defaultSelectedColorizer;
688  static std::function<void(Door &d, std::string &)> defaultUnselectedColorizer;
689  */
690 
691  Menu(int x, int y, int width);
692  Menu(int width);
693  // Menu(const Menu &);
694  Menu(const Menu &) = delete;
695  Menu(Menu &&);
696 
697  void addSelection(char c, const char *line);
698  void addSelection(char c, const char *line, updateFunction update);
699  void defaultSelection(int d);
700  void setRender(bool selected, renderFunction render);
701 
702  int choose(Door &door);
703  char which(int d);
704 
706  ANSIColor c4);
707 };
708 
709 class Screen {
710 private:
711  // bool hidden;
712  std::vector<std::unique_ptr<Panel>> panels;
713 
714 public:
715  Screen(void);
716  Screen(Screen &) = default;
717  void addPanel(std::unique_ptr<Panel> p);
718  /*
719 bool delPanel(std::shared_ptr<Panel> p);
720 
721 void hide(void);
722 void show(void);
723 */
724  bool update(Door &d);
725  void update(void);
726 
727  friend std::ostream &operator<<(std::ostream &os, const Screen &s);
728 };
729 
730 /*
731 screen - contains panels.
732  - default to 1,1 X 80,24
733  - refresh(style) could redraw panels by order they were added,
734  or could redraw panels from top to bottom, left to right.
735 
736 crazy ideas:
737  hide panels / z-order
738  how to handle panel on top of other panels?
739  Can I have you win + show animated final score calculations?
740 
741 panel - has X,Y and width, optional length. contains lines.
742  length could be simply number of "lines".
743  - has optional border. double/single/Ds/Sd TOPbottom
744  - has optional title.
745  - has optional footer.
746 
747  addLine()
748  append() - Appends another line to current line.
749 
750  set(X,Y) - set a "line" at a given X,Y position.
751 
752 menu - another type of panel, contains menu options/lines.
753 
754 lightmenu - like above, but allows arrow keys to select menu options.
755 
756 line - contains text.
757  (Maybe a "dirty" flag is needed here?)
758  - has optional (width)
759  - has optional (justify - L, R, Center)
760  - has optional padding (# of blank chars)
761  - has color (of text)
762  - has formatter/coloring function (to colorize the text)
763  Example would be one that sets capital letters to one color, lower to another.
764  Another example would be one that displays Score: XXX, where Score is one
765  color, : is another, and XXX is yet another. Properly padded, of course.
766  - has "lambda" function to update the value? (Maybe?)
767  Idea would be that I could update the score, and panel.update(). It would
768  call all the line.update() functions and only update anything that has
769  changed.
770 
771  Crazy ideas:
772  Can I delete a line, and have it automatically removed from a panel?
773 
774 lightline - text, changes format/coloring if focus/nofocus is set?
775 
776  */
777 
778 } // namespace door
779 #endif
door::Goto
ANSI Goto X, Y position.
Definition: door.h:411
door::Line::length
int length(void)
Definition: lines.cpp:203
door::Line::fit
void fit(void)
Definition: lines.cpp:225
door::Door
Definition: door.h:193
door::NewLine
CR+LF.
Definition: door.h:384
door::COLOR::BROWN
@ BROWN
BROWN (3)
door::Line::paddingColor
ANSIColor paddingColor
Padding color.
Definition: door.h:500
door::Render::output
void output(std::ostream &os)
Definition: door.cpp:1071
door::ColorOutput::ColorOutput
ColorOutput()
Definition: door.cpp:1039
door::ANSIColor::Attr
ANSIColor & Attr(ATTR a)
Definition: ansicolor.cpp:111
door::Line::updater
updateFunction updater
updateFunction to use when updating.
Definition: door.h:505
door::ATTR::BLINK
@ BLINK
SLOW BLINK.
door::ATTR::BOLD
@ BOLD
BOLD is the same as BRIGHT.
door::Door::log
ofstream & log(void)
Give ofstream handle for logging.
Definition: door.cpp:507
door::Clrscr::Clrscr
Clrscr(void)
Definition: door.cpp:1114
door::ColorOutput::c
ANSIColor c
Color to use for this fragment.
Definition: door.h:285
door::Door::Door
Door(std::string dname, int argc, char *argv[])
Definition: door.cpp:139
door::ANSIColor::operator==
bool operator==(const ANSIColor &c) const
Definition: ansicolor.cpp:137
door::Goto::x
int x
X-Position.
Definition: door.h:413
door::Render::append
void append(ANSIColor color, int len=1)
Definition: door.cpp:1086
door::Door::previous
ANSIColor previous
Definition: door.h:244
door::COLOR::CYAN
@ CYAN
CYAN (6)
door::ATTR::INVERSE
@ INVERSE
INVERSE is Background on Foreground.
door::ANSIColor::fg
COLOR fg
Foreground color.
Definition: door.h:133
door::Door::sleep_key
signed int sleep_key(int secs)
Waits secs seconds for a keypress.
Definition: door.cpp:864
door::ANSIColor::inverse
unsigned int inverse
inverse
Definition: door.h:144
door::Render::outputs
std::vector< ColorOutput > outputs
Vector of ColorOutput object.
Definition: door.h:313
door::ATTR::BRIGHT
@ BRIGHT
BRIGHT is the same as BOLD.
door::Line::setColor
void setColor(ANSIColor c)
Definition: lines.cpp:277
door::Line::Line
Line(const std::string &txt, int width=0)
Definition: lines.cpp:121
door::NewLine::NewLine
NewLine(void)
Definition: door.cpp:1148
door::operator<<
std::ostream & operator<<(std::ostream &os, const ANSIColor &c)
Definition: ansicolor.cpp:339
door::ANSIColor::operator!=
bool operator!=(const ANSIColor &c) const
Definition: ansicolor.cpp:150
door::ColorOutput::pos
int pos
Starting position of Render.text.
Definition: door.h:287
door::Goto::operator<<
friend std::ostream & operator<<(std::ostream &os, const Goto &g)
Definition: door.cpp:1199
door::COLOR
COLOR
The colors available under ANSI-BBS.
Definition: door.h:84
door::ANSIColor
Foreground, Background and Attributes.
Definition: door.h:131
door::Door::input_string
std::string input_string(int max)
Input a string of requested max length.
Definition: door.cpp:913
door::Door::get_one_of
int get_one_of(const char *keys)
Get one of these keys.
Definition: door.cpp:964
door::Menu
Definition: door.h:672
AnyOption
Definition: anyoption.h:35
door::Line::render
renderFunction render
renderFunction to use when rendering Line.
Definition: door.h:503
door::COLOR::GREEN
@ GREEN
GREEN (2)
door::COLOR::MAGENTA
@ MAGENTA
MAGENTA (5)
door::Goto::y
int y
Y-Position.
Definition: door.h:415
door::renderFunction
std::function< Render(const std::string &)> renderFunction
Render output function.
Definition: door.h:341
door::BorderStyle::DOUBLE_SINGLE
@ DOUBLE_SINGLE
DOUBLE top SINGLE side (4)
door::Line::color
ANSIColor color
Line color.
Definition: door.h:496
door::Render::Render
Render(const std::string txt)
Definition: door.cpp:1060
door::Panel::spacer_line
std::unique_ptr< Line > spacer_line(bool single)
Create a spacer line using block drawing characters.
Definition: panel.cpp:332
door::BorderStyle::NONE
@ NONE
NONE (0)
door::ANSIColor::blink
unsigned int blink
blink slow blinking text
Definition: door.h:142
door::cls
Clrscr cls
Definition: door.cpp:1142
door::Line::setPadding
void setPadding(std::string &padstring, ANSIColor padColor)
Definition: lines.cpp:256
door::ANSIColor::reset
unsigned int reset
reset flag / always send color and attributes
Definition: door.h:138
door::Line
Text and ANSIColor.
Definition: door.h:488
door::Line::operator<<
friend std::ostream & operator<<(std::ostream &os, const Line &l)
Definition: lines.cpp:354
door::Render::text
const std::string text
Complete text to be rendered.
Definition: door.h:311
door::Clrscr::operator<<
friend std::ostream & operator<<(std::ostream &os, const Clrscr &clr)
Definition: door.cpp:1126
door::COLOR::RED
@ RED
RED (1)
door::Menu::Menu
Menu(int x, int y, int width)
Construct a new Menu object.
Definition: panel.cpp:544
door::ATTR::RESET
@ RESET
RESET forces all attributes (and Colors) to be sent.
door::BorderStyle::DOUBLE
@ DOUBLE
DOUBLE (2)
door::Panel::lines
std::vector< std::unique_ptr< Line > > lines
Definition: door.h:598
door::updateFunction
std::function< std::string(void)> updateFunction
Definition: door.h:360
door::nl
NewLine nl
Definition: door.cpp:1170
door::Panel::update
bool update(Door &d)
Updates a panel.
Definition: panel.cpp:248
door::BorderStyle::SINGLE_DOUBLE
@ SINGLE_DOUBLE
SINGLE top DOUBLE side (3)
door::Line::hasRender
bool hasRender(void)
Definition: lines.cpp:188
door::ANSIColor::output
std::string output(void) const
Definition: ansicolor.cpp:180
door::rBlueYellow
renderFunction rBlueYellow
BlueYellow Render example function.
Definition: door.cpp:1227
door::Line::text
std::string text
Text of the line.
Definition: door.h:491
door::COLOR::YELLOW
@ YELLOW
YELLOW (3)
door::ATTR
ATTR
ANSI-BBS text attributes.
Definition: door.h:108
door::Panel::set
void set(int x, int y)
Set the panels X and Y screen position.
Definition: panel.cpp:80
door::reset
ANSIColor reset(ATTR::RESET)
reset colors to normal
Definition: door.h:400
door::ANSIColor::ANSIColor
ANSIColor()
Definition: ansicolor.cpp:16
door::COLOR::WHITE
@ WHITE
WHITE (7)
door::Line::update
bool update(void)
Definition: lines.cpp:319
door::Panel::lineSetBack
void lineSetBack(ANSIColor back)
Set background of all lines in the panel.
Definition: panel.cpp:319
door::Line::padding
std::string padding
Padding characters.
Definition: door.h:498
door::BorderStyle::SINGLE
@ SINGLE
SINGLE (1)
door::Door::xsputn
std::streamsize xsputn(const char *s, std::streamsize n) override
Definition: door.cpp:992
door::BorderStyle
BorderStyle
Definition: door.h:570
door::ANSIColor::operator<<
friend std::ostream & operator<<(std::ostream &os, const ANSIColor &c)
Definition: ansicolor.cpp:339
door
The BBS door project. This is an attempt at writing a C++ BBS door toolkit.
Definition: ansicolor.cpp:9
door::BorderStyle::BLANK
@ BLANK
BLANK (5)
door::Door::overflow
int overflow(int c) override
Definition: door.cpp:1019
door::ColorOutput::len
int len
Length.
Definition: door.h:289
door::Justify
Justify
Definition: door.h:403
door::Menu::choose
int choose(Door &door)
Definition: panel.cpp:715
door::Menu::makeRender
static renderFunction makeRender(ANSIColor c1, ANSIColor c2, ANSIColor c3, ANSIColor c4)
Definition: panel.cpp:670
door::COLOR::BLUE
@ BLUE
BLUE (4)
door::Clrscr
Clear the screen.
Definition: door.h:367
door::ColorOutput::reset
void reset(void)
Definition: door.cpp:1047
door::ANSIColor::bg
COLOR bg
Background color.
Definition: door.h:135
door::Screen
Definition: door.h:709
door::Goto::Goto
Goto(int xpos, int ypos)
Definition: door.cpp:1178
door::Line::setText
void setText(std::string &txt)
Definition: lines.cpp:243
door::COLOR::BLACK
@ BLACK
BLACK (0)
door::Render
Rendering a string with ANSIColor.
Definition: door.h:307
door::Line::hasColor
bool hasColor
Do we have color?
Definition: door.h:494
door::Panel
Definition: door.h:585
door::NewLine::operator<<
friend std::ostream & operator<<(std::ostream &os, const NewLine &nl)
Definition: door.cpp:1156
door::Line::setUpdater
void setUpdater(updateFunction uf)
Definition: lines.cpp:298
door::ColorOutput
This holds an ANSIColor and text position + length.
Definition: door.h:279
door::ANSIColor::bold
unsigned int bold
bold / bright flag
Definition: door.h:140
door::Line::setRender
void setRender(renderFunction rf)
Definition: lines.cpp:289