| | 1 | /* The FrobTadsApplication class represents the main application object. |
| | 2 | * It provides an easy to use interface to the screen. It is also |
| | 3 | * responsible for starting the TADS2/3 VM. |
| | 4 | * |
| | 5 | * This class defines an abstract screen I/O interface which has to be |
| | 6 | * implemented in an API-specific subclass. |
| | 7 | */ |
| | 8 | #ifndef FROBTADSAPP_H |
| | 9 | #define FROBTADSAPP_H |
| | 10 | |
| | 11 | #include "common.h" |
| | 12 | |
| | 13 | #include "os.h" |
| | 14 | extern "C" { |
| | 15 | #include "osgen.h" |
| | 16 | } |
| | 17 | |
| | 18 | |
| | 19 | /* Global application pointer. |
| | 20 | */ |
| | 21 | extern class FrobTadsApplication* globalApp; |
| | 22 | |
| | 23 | class FrobTadsApplication { |
| | 24 | public: |
| | 25 | // Signal handlers are such a pain in the ass... Has to be |
| | 26 | // friend. |
| | 27 | friend RETSIGTYPE winResizeHandler(int); |
| | 28 | |
| | 29 | // Instead of using a gazillion of constructor-arguments, we |
| | 30 | // group them inside this structure. |
| | 31 | struct FrobOptions { |
| | 32 | bool useColors; // Enable colors? |
| | 33 | bool forceColors; // Force colors? |
| | 34 | bool defColors; // Use default colors for color pair 0? |
| | 35 | bool softScroll; // Scroll softly? |
| | 36 | bool exitPause; // Pause prior to exit? |
| | 37 | bool changeDir; // Change to the game's directory? |
| | 38 | int textColor; // Default text color. |
| | 39 | int bgColor; // Default background color. |
| | 40 | int statTextColor; // Default text color of statusline. |
| | 41 | int statBgColor; // Default background color of statusline. |
| | 42 | unsigned scrollBufSize; // Scroll-back buffer size. |
| | 43 | int safetyLevel; // File I/O safety level. |
| | 44 | char characterSet[40]; // Local character set name. |
| | 45 | }; |
| | 46 | |
| | 47 | // Our options. Once set, they remain constant during run-time |
| | 48 | // so there's no reason to protect them. |
| | 49 | const FrobOptions options; |
| | 50 | |
| | 51 | private: |
| | 52 | /* Runs the T2VM. |
| | 53 | */ |
| | 54 | int |
| | 55 | fRunTads2( char* filename ); |
| | 56 | |
| | 57 | /* Runs the T3VM. |
| | 58 | */ |
| | 59 | int |
| | 60 | fRunTads3( char* filename ); |
| | 61 | |
| | 62 | protected: |
| | 63 | // We store the remaining input-timeout here in case a |
| | 64 | // window-resize occurs; the signal handler can then restore it. |
| | 65 | int fRemainingTimeout; |
| | 66 | |
| | 67 | // Are we using colors? |
| | 68 | bool fColorsEnabled; |
| | 69 | |
| | 70 | public: |
| | 71 | FrobTadsApplication( const FrobOptions& opts ); |
| | 72 | |
| | 73 | /* Are colors enabled? |
| | 74 | */ |
| | 75 | bool |
| | 76 | colorsEnabled() const |
| | 77 | { return this->fColorsEnabled; } |
| | 78 | |
| | 79 | /* Starts the VM and returns its exit code. Which VM is started |
| | 80 | * is given by the 'vm' argument: 0 for TADS2, non-0 for TADS3. |
| | 81 | */ |
| | 82 | int |
| | 83 | runTads( const char* filename, int vm ); |
| | 84 | |
| | 85 | /* Change the current working directory, if possible. Returns |
| | 86 | * true on success, false on failure. |
| | 87 | */ |
| | 88 | bool |
| | 89 | changeDirectory( const char* dir ); |
| | 90 | |
| | 91 | |
| | 92 | /* ============================================================ |
| | 93 | * Pure virtual functions follow. This is the interface that |
| | 94 | * has to be implemented in an API-specific subclass. |
| | 95 | * ============================================================ |
| | 96 | */ |
| | 97 | protected: |
| | 98 | /* Initialize the display. This is called once just prior to |
| | 99 | * starting a game. |
| | 100 | */ |
| | 101 | virtual void |
| | 102 | init() = 0; |
| | 103 | |
| | 104 | /* Re-initialize the display and any internal book-keeping data |
| | 105 | * if needed. This is called every time the terminal |
| | 106 | * dimensions change. This usually means the new dimensions |
| | 107 | * have to be detected and a new output window will be created. |
| | 108 | */ |
| | 109 | virtual void |
| | 110 | resizeEvent() = 0; |
| | 111 | |
| | 112 | public: |
| | 113 | /* Moves the cursor to the specified position. |
| | 114 | */ |
| | 115 | virtual void |
| | 116 | moveCursor( int line, int column ) = 0; |
| | 117 | |
| | 118 | /* Prints a string at the specified position, using 'attrs' as |
| | 119 | * atributes. |
| | 120 | */ |
| | 121 | virtual void |
| | 122 | print( int line, int column, int attrs, const char* str ) = 0; |
| | 123 | |
| | 124 | /* Flush any pending output. That means everything that is not |
| | 125 | * printed yet due to buffered output (if applicable) should be |
| | 126 | * printed now. |
| | 127 | */ |
| | 128 | virtual void |
| | 129 | flush() = 0; |
| | 130 | |
| | 131 | /* Clears a portion of the screen. |
| | 132 | */ |
| | 133 | virtual void |
| | 134 | clear( int top, int left, int bottom, int right, int attrs ) = 0; |
| | 135 | |
| | 136 | /* Scroll the specified region of the screen 1 line up/down. |
| | 137 | * 'attrs' holds the attributes of the generated empty lines. |
| | 138 | */ |
| | 139 | virtual void |
| | 140 | scrollRegionUp( int top, int left, int bottom, int right, int attrs ) = 0; |
| | 141 | |
| | 142 | virtual void |
| | 143 | scrollRegionDown( int top, int left, int bottom, int right, int attrs ) = 0; |
| | 144 | |
| | 145 | /* Reads a character from the keyboard and returns it. If a |
| | 146 | * function key has been pressed, then a curses KEY_* value is |
| | 147 | * returned (have a look at your system's <curses.h> header for |
| | 148 | * a list of KEY_ macros). |
| | 149 | * |
| | 150 | * If 'cursorVisible' is false, no cursor is shown while waiting |
| | 151 | * for a key-press. |
| | 152 | * |
| | 153 | * If 'timeout' is > 0, then the routine will wait for a key |
| | 154 | * only for 'timeout' milliseconds. If a key has been pressed |
| | 155 | * before the timeout expires it is returned as usual. If the |
| | 156 | * timeout expires and there's still no key, ERR is returned. |
| | 157 | * |
| | 158 | * Note that KEY_BACKSPACE and KEY_DL are handled correctly; you |
| | 159 | * don't need to use the low-level curses routines erasechar() |
| | 160 | * and killchar(). Just check for KEY_BACKSPACE and KEY_DL. |
| | 161 | */ |
| | 162 | virtual int |
| | 163 | getRawChar( bool cursorVisible, int timeout ) = 0; |
| | 164 | |
| | 165 | /* Pause for 'ms' milliseconds. |
| | 166 | */ |
| | 167 | virtual void |
| | 168 | sleep( int ms ) = 0; |
| | 169 | |
| | 170 | /* Returns the height (lines) of the screen. |
| | 171 | */ |
| | 172 | virtual int |
| | 173 | height() const = 0; |
| | 174 | |
| | 175 | /* Returns the width (columns) of the screen. |
| | 176 | */ |
| | 177 | virtual int |
| | 178 | width() const = 0; |
| | 179 | }; |
| | 180 | |
| | 181 | #endif // FROBTADSAPP |