FINAL CUT
foptimove.h
1 /***********************************************************************
2 * foptimove.cpp - Cursor movement optimization *
3 * *
4 * This file is part of the FINAL CUT widget toolkit *
5 * *
6 * Copyright 2015-2024 Markus Gans *
7 * *
8 * FINAL CUT is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU Lesser General Public License as *
10 * published by the Free Software Foundation; either version 3 of *
11 * the License, or (at your option) any later version. *
12 * *
13 * FINAL CUT is distributed in the hope that it will be useful, but *
14 * WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public *
19 * License along with this program. If not, see *
20 * <http://www.gnu.org/licenses/>. *
21 ***********************************************************************/
22 
23 /* Standalone class
24  * ════════════════
25  *
26  * ▕▔▔▔▔▔▔▔▔▔▔▔▏
27  * ▕ FOptiMove ▏
28  * ▕▁▁▁▁▁▁▁▁▁▁▁▏
29  */
30 
31 // The cursor optimization based on ncurses lib_mvcur.c
32 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
33 
34 #ifndef FOPTIMOVE_H
35 #define FOPTIMOVE_H
36 
37 #if !defined (USE_FINAL_H) && !defined (COMPILE_FINAL_CUT)
38  #error "Only <final/final.h> can be included directly."
39 #endif
40 
41 #include <cassert>
42 #include <cctype>
43 #include <climits>
44 #include <cstdlib>
45 #include <cstring>
46 #include <iostream>
47 #include <string>
48 
49 #include "final/util/fstring.h"
50 
51 namespace finalcut
52 {
53 
54 //----------------------------------------------------------------------
55 // class FOptiMove
56 //----------------------------------------------------------------------
57 
58 class FOptiMove final
59 {
60  public:
62  {
63  const char* t_cursor_up;
64  const char* t_cursor_down;
65  const char* t_cursor_left;
66  const char* t_cursor_right;
67  const char* t_cursor_home;
68  const char* t_cursor_to_ll;
69  const char* t_carriage_return;
70  const char* t_tab;
71  const char* t_back_tab;
72  };
73 
75  {
76  const char* t_parm_up_cursor;
77  const char* t_parm_down_cursor;
78  const char* t_parm_left_cursor;
79  const char* t_parm_right_cursor;
80  const char* t_cursor_address;
81  const char* t_column_address;
82  const char* t_row_address;
83  };
84 
85  struct TermEnvEdit
86  {
87  const char* t_erase_chars;
88  const char* t_repeat_char;
89  const char* t_repeat_last_char;
90  const char* t_clr_bol;
91  const char* t_clr_eol;
92  };
93 
94  struct TermEnv
95  {
96  TermEnvCursor cursor;
97  TermEnvParamCursor param_cursor;
98  TermEnvEdit edit;
99  int tabstop;
100  bool automatic_left_margin;
101  bool eat_nl_glitch;
102  };
103 
104  // Constructor
105  explicit FOptiMove (int = 0);
106 
107  // Accessors
108  auto getClassName() const -> FString;
109  static auto getInstance() -> FOptiMove&;
110  auto getCursorHomeLength() const -> uInt;
111  auto getCarriageReturnLength() const -> uInt;
112  auto getCursorToLLLength() const -> uInt;
113  auto getTabLength() const -> uInt;
114  auto getBackTabLength() const -> uInt;
115  auto getCursorUpLength() const -> uInt;
116  auto getCursorDownLength() const -> uInt;
117  auto getCursorLeftLength() const -> uInt;
118  auto getCursorRightLength() const -> uInt;
119  auto getCursorAddressLength() const -> uInt;
120  auto getColumnAddressLength() const -> uInt;
121  auto getRowAddressLength() const -> uInt;
122  auto getParmUpCursorLength() const -> uInt;
123  auto getParmDownCursorLength() const -> uInt;
124  auto getParmLeftCursorLength() const -> uInt;
125  auto getParmRightCursorLength() const -> uInt;
126  auto getEraseCharsLength() const -> uInt;
127  auto getRepeatCharLength() const -> uInt;
128  auto getClrBolLength() const -> uInt;
129  auto getClrEolLength() const -> uInt;
130 
131  // Mutators
132  void setBaudRate (int);
133  void setTabStop (int);
134  void setTermSize (std::size_t, std::size_t);
135  void setTermEnvironment (const TermEnv&);
136  void set_cursor_home (const char[]);
137  void set_cursor_to_ll (const char[]);
138  void set_carriage_return (const char[]);
139  void set_tabular (const char[]);
140  void set_back_tab (const char[]);
141  void set_cursor_up (const char[]);
142  void set_cursor_down (const char[]);
143  void set_cursor_left (const char[]);
144  void set_cursor_right (const char[]);
145  void set_cursor_address (const char[]);
146  void set_column_address (const char[]);
147  void set_row_address (const char[]);
148  void set_parm_up_cursor (const char[]);
149  void set_parm_down_cursor (const char[]);
150  void set_parm_left_cursor (const char[]);
151  void set_parm_right_cursor (const char[]);
152  void set_erase_chars (const char[]);
153  void set_repeat_char (const char[]);
154  void set_repeat_last_char (const char[]);
155  void set_clr_bol (const char[]);
156  void set_clr_eol (const char[]);
157  void set_auto_left_margin (bool = true) noexcept;
158  void set_eat_newline_glitch (bool = true) noexcept;
159 
160  // Methods
161  void check_boundaries (int&, int&, int&, int&) const;
162  auto moveCursor (int, int, int, int) -> std::string;
163 
164  private:
165  struct Capability
166  {
167  const char* cap;
168  int duration;
169  int length;
170  };
171 
172  struct Cursor
173  {
174  Capability up{};
175  Capability down{};
176  Capability left{};
177  Capability right{};
178  Capability home{};
179  Capability to_ll{};
180  Capability carriage_return{};
181  Capability tab{};
182  Capability back_tab{};
183  };
184 
185  struct ParamCursor
186  {
187  Capability up{};
188  Capability down{};
189  Capability left{};
190  Capability right{};
191  Capability column_address{};
192  Capability row_address{};
193  Capability address{};
194  };
195 
196  struct Edit
197  {
198  Capability erase_chars{};
199  Capability repeat_char{};
200  Capability repeat_last_char{};
201  Capability clr_bol{};
202  Capability clr_eol{};
203  };
204 
205  struct Dimension
206  {
207  std::size_t width{};
208  std::size_t height{};
209  };
210 
211  // Constant
212  static constexpr std::string::size_type BUF_SIZE{512u};
213 
214  // Constants
215  static constexpr int LONG_DURATION{INT_MAX};
216  // value for a long capability waiting time
217  static constexpr int MOVE_LIMIT{7};
218  // maximum character distance to avoid direct cursor addressing
219 
220  // Methods
221  void calculateCharDuration();
222  auto capDuration (const char[], int) const -> int;
223  auto capDurationToLength (int) const -> int;
224  auto repeatedAppend (std::string&, const Capability&, int) const -> int;
225  auto relativeMove (std::string&, int, int, int, int) const -> int;
226  auto verticalMove (std::string&, int, int) const -> int;
227  void downMove (std::string&, int&, int, int) const;
228  void upMove (std::string&, int&, int, int) const;
229  auto horizontalMove (std::string&, int, int) const -> int;
230  void moveWithParmRightCursor (std::string&, int&, int) const;
231  void moveWithRightCursor (std::string&, int&, int, int, int) const;
232  void rightMove (std::string&, int&, int, int) const;
233  void moveWithParmLeftCursor (std::string&, int&, int) const;
234  void moveWithLeftCursor (std::string&, int&, int, int, int) const;
235  void leftMove (std::string&, int&, int, int) const;
236 
237  auto isWideMove (int, int, int, int) const -> bool;
238  auto isMethod0Faster (int&, int, int) -> bool;
239  auto isMethod1Faster (int&, int, int, int, int) -> bool;
240  auto isMethod2Faster (int&, int, int, int) -> bool;
241  auto isMethod3Faster (int&, int, int) -> bool;
242  auto isMethod4Faster (int&, int, int) -> bool;
243  auto isMethod5Faster (int&, int, int, int) -> bool;
244  void moveByMethod (int, int, int, int, int);
245  void moveWithCarriageReturn (int, int, int);
246  void moveWithHome (int, int);
247  void moveWithToLL (int, int);
248  void moveWithCRAndWrapToLeft (int, int, int, int);
249 
250  // Data members
251  Cursor cursor{};
252  ParamCursor parm_cursor{};
253  Edit edit{};
254  Dimension screen{80, 24};
255  int char_duration{1};
256  int baudrate{9600};
257  int tabstop{0};
258  std::string move_buf{};
259  std::string temp_result{};
260  bool automatic_left_margin{false};
261  bool eat_nl_glitch{false};
262 
263  // Friend function
264  friend void printDurations (const FOptiMove&);
265 };
266 
267 
268 // FOptiMove inline functions
269 //----------------------------------------------------------------------
270 inline auto FOptiMove::getClassName() const -> FString
271 { return "FOptiMove"; }
272 
273 //----------------------------------------------------------------------
274 inline auto FOptiMove::getCursorHomeLength() const -> uInt
275 { return static_cast<uInt>(cursor.home.length); }
276 
277 //----------------------------------------------------------------------
278 inline auto FOptiMove::getCarriageReturnLength() const -> uInt
279 { return static_cast<uInt>(cursor.carriage_return.length); }
280 
281 //----------------------------------------------------------------------
282 inline auto FOptiMove::getCursorToLLLength() const -> uInt
283 { return static_cast<uInt>(cursor.to_ll.length); }
284 
285 //----------------------------------------------------------------------
286 inline auto FOptiMove::getTabLength() const -> uInt
287 { return static_cast<uInt>(cursor.tab.length); }
288 
289 //----------------------------------------------------------------------
290 inline auto FOptiMove::getBackTabLength() const -> uInt
291 { return static_cast<uInt>(cursor.back_tab.length); }
292 
293 //----------------------------------------------------------------------
294 inline auto FOptiMove::getCursorUpLength() const -> uInt
295 { return static_cast<uInt>(cursor.up.length); }
296 
297 //----------------------------------------------------------------------
298 inline auto FOptiMove::getCursorDownLength() const -> uInt
299 { return static_cast<uInt>(cursor.down.length); }
300 
301 //----------------------------------------------------------------------
302 inline auto FOptiMove::getCursorLeftLength() const -> uInt
303 { return static_cast<uInt>(cursor.left.length); }
304 
305 //----------------------------------------------------------------------
306 inline auto FOptiMove::getCursorRightLength() const -> uInt
307 { return static_cast<uInt>(cursor.right.length); }
308 
309 //----------------------------------------------------------------------
310 inline auto FOptiMove::getCursorAddressLength() const -> uInt
311 { return static_cast<uInt>(parm_cursor.address.length); }
312 
313 //----------------------------------------------------------------------
314 inline auto FOptiMove::getColumnAddressLength() const -> uInt
315 { return static_cast<uInt>(parm_cursor.column_address.length); }
316 
317 //----------------------------------------------------------------------
318 inline auto FOptiMove::getRowAddressLength() const -> uInt
319 { return static_cast<uInt>(parm_cursor.row_address.length); }
320 
321 //----------------------------------------------------------------------
322 inline auto FOptiMove::getParmUpCursorLength() const -> uInt
323 { return static_cast<uInt>(parm_cursor.up.length); }
324 
325 //----------------------------------------------------------------------
326 inline auto FOptiMove::getParmDownCursorLength() const -> uInt
327 { return static_cast<uInt>(parm_cursor.down.length); }
328 
329 //----------------------------------------------------------------------
330 inline auto FOptiMove::getParmLeftCursorLength() const -> uInt
331 { return static_cast<uInt>(parm_cursor.left.length); }
332 
333 //----------------------------------------------------------------------
334 inline auto FOptiMove::getParmRightCursorLength() const -> uInt
335 { return static_cast<uInt>(parm_cursor.right.length); }
336 
337 //----------------------------------------------------------------------
338 inline auto FOptiMove::getEraseCharsLength() const -> uInt
339 { return static_cast<uInt>(edit.erase_chars.length); }
340 
341 //----------------------------------------------------------------------
342 inline auto FOptiMove::getRepeatCharLength() const -> uInt
343 { return static_cast<uInt>(edit.repeat_char.length); }
344 
345 //----------------------------------------------------------------------
346 inline auto FOptiMove::getClrBolLength() const -> uInt
347 { return static_cast<uInt>(edit.clr_bol.length); }
348 
349 //----------------------------------------------------------------------
350 inline auto FOptiMove::getClrEolLength() const -> uInt
351 { return static_cast<uInt>(edit.clr_eol.length); }
352 
353 //----------------------------------------------------------------------
354 inline void FOptiMove::set_auto_left_margin (bool bcap) noexcept
355 { automatic_left_margin = bcap; }
356 
357 //----------------------------------------------------------------------
358 inline void FOptiMove::set_eat_newline_glitch (bool bcap) noexcept
359 { eat_nl_glitch = bcap; }
360 
361 
362 // FOptiMove non-member function forward declaration
363 //----------------------------------------------------------------------
364 void printDurations (const FOptiMove&);
365 
366 } // namespace finalcut
367 
368 #endif // FOPTIMOVE_H
Definition: foptimove.h:74
Definition: foptimove.h:94
Definition: foptimove.h:58
Definition: class_template.cpp:25
Definition: foptimove.h:85
Definition: fstring.h:79
Definition: foptimove.h:61