FINAL CUT
ftermdata.h
1 /***********************************************************************
2 * ftermdata.h - Data class for FTerm *
3 * *
4 * This file is part of the FINAL CUT widget toolkit *
5 * *
6 * Copyright 2018-2023 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  * ▕ FTermData ▏
28  * ▕▁▁▁▁▁▁▁▁▁▁▁▏
29  */
30 
31 #ifndef FTERMDATA_H
32 #define FTERMDATA_H
33 
34 #if !defined (USE_FINAL_H) && !defined (COMPILE_FINAL_CUT)
35  #error "Only <final/final.h> can be included directly."
36 #endif
37 
38 #include <atomic>
39 #include <bitset>
40 #include <memory>
41 #include <mutex>
42 #include <string>
43 #include <unordered_map>
44 #include <vector>
45 
46 #include "final/fc.h"
47 #include "final/ftypes.h"
48 #include "final/util/frect.h"
49 #include "final/util/fstring.h"
50 
51 namespace finalcut
52 {
53 
54 //----------------------------------------------------------------------
55 // class FCharSubstitution
56 //----------------------------------------------------------------------
57 
59 {
60  public:
61  struct Map
62  {
63  wchar_t from;
64  wchar_t to;
65  };
66 
67  auto getMappedChar (wchar_t) const -> wchar_t;
68  void setCharMapping (const Map&);
69  auto isEmpty() const -> bool;
70  void sort();
71 
72  private:
73  std::vector<Map> sub_map{};
74 };
75 
76 // FTermData inline functions
77 //----------------------------------------------------------------------
78 inline auto FCharSubstitution::getMappedChar (wchar_t c) const -> wchar_t
79 {
80  const auto& cend = sub_map.cend();
81  auto iter = std::find_if ( sub_map.cbegin(), cend,
82  [&c] (const auto& map)
83  {
84  return map.from == c;
85  } );
86 
87  if ( iter == cend )
88  return L'\0';
89 
90  return iter->to;
91 }
92 
93 //----------------------------------------------------------------------
94 inline void FCharSubstitution::setCharMapping (const Map& m)
95 {
96  const auto& end = sub_map.end();
97  auto iter = std::find_if ( sub_map.begin(), end,
98  [&m] (const auto& map)
99  {
100  return map.from == m.from;
101  } );
102 
103  if ( iter == end )
104  sub_map.push_back(m);
105  else
106  iter->to = m.to;
107 }
108 
109 //----------------------------------------------------------------------
110 inline auto FCharSubstitution::isEmpty() const -> bool
111 {
112  return sub_map.empty();
113 }
114 
115 //----------------------------------------------------------------------
116 inline void FCharSubstitution::sort()
117 {
118  std::sort ( sub_map.begin(), sub_map.end()
119  , [] (const auto& lhs, const auto& rhs)
120  {
121  return lhs.from < rhs.from;
122  }
123  );
124 }
125 
126 
127 //----------------------------------------------------------------------
128 // class FTermData
129 //----------------------------------------------------------------------
130 
131 class FTermData final
132 {
133  public:
135  {
136  int primary;
137  int secondary;
138  };
139 
140  // Using-declaration
141  using EncodingMap = std::unordered_map<std::string, Encoding>;
142 
143  // Constructors
144  FTermData () = default;
145 
146  // Accessors
147  auto getClassName() const -> FString;
148  static auto getInstance() -> FTermData&;
149  auto getEncodingList() & -> EncodingMap&;
150  auto getCharSubstitutionMap() & -> FCharSubstitution&;
151  auto getTerminalEncoding() const -> Encoding;
152  auto getTerminalGeometry() & -> FRect&;
153  auto getTerminalGeometry() const & -> const FRect&;
154  auto getTTYFileDescriptor() const noexcept -> int;
155  auto getBaudrate() const noexcept -> uInt;
156  auto getTermType() const & -> const std::string&;
157  auto getTermFileName() const & -> const std::string&;
158  auto getGnomeTerminalID() const noexcept -> int;
159  auto getKittyVersion() const noexcept -> kittyVersion;
160  auto getXtermFont() const & -> const FString&;
161  auto getXtermTitle() const & -> const FString&;
162 #if DEBUG
163  auto getFramebufferBpp() const noexcept -> int;
164 #endif
165 
166  // Inquiries
167  auto hasShadowCharacter() const noexcept -> bool;
168  auto hasHalfBlockCharacter() const noexcept -> bool;
169  auto hasCursorOptimisation() const noexcept -> bool;
170  auto isCursorHidden() const noexcept -> bool;
171  auto hasAlternateScreen() const noexcept -> bool;
172  auto isInAlternateScreen() const noexcept -> bool;
173  auto hasASCIIConsole() const noexcept -> bool;
174  auto hasVT100Console() const noexcept -> bool;
175  auto hasUTF8Console() const noexcept -> bool;
176  auto isUTF8() const noexcept -> bool;
177  auto isNewFont() const noexcept -> bool;
178  auto isVGAFont() const noexcept -> bool;
179  auto isMonochron() const noexcept -> bool;
180  auto hasTermResized() -> bool;
181  auto isTermType (FTermType) const -> bool;
182  auto isTermType (FTermTypeT) const -> bool;
183 
184  // Mutators
185  void setTermEncoding (Encoding) noexcept;
186  void setTTYFileDescriptor (int) noexcept;
187  void setBaudrate (uInt) noexcept;
188  void supportShadowCharacter (bool = true) noexcept;
189  void supportHalfBlockCharacter (bool = true) noexcept;
190  void supportCursorOptimisation (bool = true) noexcept;
191  void setCursorHidden (bool = true) noexcept;
192  void useAlternateScreen (bool = true) noexcept;
193  void setAlternateScreenInUse (bool = true) noexcept;
194  void setASCIIConsole (bool = true) noexcept;
195  void setVT100Console (bool = true) noexcept;
196  void setUTF8Console (bool = true) noexcept;
197  void setUTF8 (bool = true) noexcept;
198  void setNewFont (bool = true) noexcept;
199  void setVGAFont (bool = true) noexcept;
200  void setMonochron (bool = true) noexcept;
201  void setTermResized (bool = true);
202  void setTermType (const std::string&);
203  void setTermType (FTermType);
204  void unsetTermType (FTermType);
205  void setTermFileName (const std::string&);
206  void setGnomeTerminalID (int) noexcept;
207  void setKittyVersion (const kittyVersion&);
208  void setXtermFont (const FString&);
209  void setXtermTitle (const FString&);
210 #if DEBUG
211  void setFramebufferBpp (int) noexcept;
212 #endif
213 
214  private:
215  // Encoding-related fields
216  struct EncodingInfo
217  {
218  EncodingMap encoding_list{};
219  FCharSubstitution char_substitution_map{};
220  Encoding term_encoding{Encoding::Unknown};
221  };
222 
223  // Terminal properties
224  struct TerminalProperties
225  {
226  FRect terminal_geometry{}; // current terminal geometry
227  FString xterm_font{};
228  FString xterm_title{};
229  FTermTypeT terminal_type{};
230  // Teletype (tty) file descriptor is still undefined (-1)
231  int fd_tty{-1};
232  };
233 
234  // Version and other settings
235  struct TerminalSettings
236  {
237  // Gnome terminal id from SecDA
238  // Example: vte version 0.40.0 = 0 * 100 + 40 * 100 + 0 = 4000
239  // a.b.c = a * 100 + b * 100 + c
240  int gnome_terminal_id{0};
241  kittyVersion kitty_version{0, 0};
242 #if DEBUG
243  int framebuffer_bpp{-1};
244 #endif
245  uInt baudrate{0};
246  std::string termtype{};
247  std::string termfilename{};
248  };
249 
250  // Synchronization and state
251  struct SynchronizationState
252  {
253  std::mutex resize_mutex{};
254  std::atomic<int> resize_count{0};
255  };
256 
257  struct Flags
258  {
259  bool shadow_character{true};
260  bool half_block_character{true};
261  bool cursor_optimisation{true};
262  bool hidden_cursor{false}; // Global cursor hidden state
263  bool use_alternate_screen{true};
264  bool alternate_screen{false};
265  bool ascii_console{false};
266  bool vt100_console{false};
267  bool utf8_console{false};
268  bool utf8_state{false};
269  bool new_font{false};
270  bool vga_font{false};
271  bool monochron{false};
272  };
273 
274  // Data members
275  EncodingInfo encoding_info{};
276  TerminalProperties terminal_properties{};
277  TerminalSettings terminal_settings{};
278  SynchronizationState synchronization_state{};
279  Flags flags{};
280 };
281 
282 // FTermData inline functions
283 //----------------------------------------------------------------------
284 inline auto FTermData::getClassName() const -> FString
285 { return "FTermData"; }
286 
287 //----------------------------------------------------------------------
288 inline auto FTermData::getInstance() -> FTermData&
289 {
290  static const auto& data = std::make_unique<FTermData>();
291  return *data;
292 }
293 
294 //----------------------------------------------------------------------
295 inline auto FTermData::getEncodingList() & -> EncodingMap&
296 { return encoding_info.encoding_list; }
297 
298 //----------------------------------------------------------------------
299 inline auto FTermData::getCharSubstitutionMap() & -> FCharSubstitution&
300 { return encoding_info.char_substitution_map; }
301 
302 //----------------------------------------------------------------------
303 inline auto FTermData::getTerminalEncoding() const -> Encoding
304 { return encoding_info.term_encoding; }
305 
306 //----------------------------------------------------------------------
307 inline auto FTermData::getTerminalGeometry() & -> FRect&
308 { return terminal_properties.terminal_geometry; }
309 
310 //----------------------------------------------------------------------
311 inline auto FTermData::getTerminalGeometry() const & -> const FRect&
312 { return terminal_properties.terminal_geometry; }
313 
314 //----------------------------------------------------------------------
315 inline auto FTermData::getTTYFileDescriptor() const noexcept -> int
316 { return terminal_properties.fd_tty; }
317 
318 //----------------------------------------------------------------------
319 inline auto FTermData::getBaudrate() const noexcept -> uInt
320 { return terminal_settings.baudrate; }
321 
322 //----------------------------------------------------------------------
323 inline auto FTermData::getTermType() const & -> const std::string&
324 { return terminal_settings.termtype; }
325 
326 //----------------------------------------------------------------------
327 inline auto FTermData::getTermFileName() const & -> const std::string&
328 { return terminal_settings.termfilename; }
329 
330 //----------------------------------------------------------------------
331 inline auto FTermData::getGnomeTerminalID() const noexcept -> int
332 { return terminal_settings.gnome_terminal_id; }
333 
334 //----------------------------------------------------------------------
335 inline auto FTermData::getKittyVersion() const noexcept -> kittyVersion
336 { return terminal_settings.kitty_version; }
337 
338 //----------------------------------------------------------------------
339 inline auto FTermData::getXtermFont() const & -> const FString&
340 { return terminal_properties.xterm_font; }
341 
342 //----------------------------------------------------------------------
343 inline auto FTermData::getXtermTitle() const & -> const FString&
344 { return terminal_properties.xterm_title; }
345 
346 //----------------------------------------------------------------------
347 #if DEBUG
348 inline auto FTermData::getFramebufferBpp() const noexcept -> int
349 { return terminal_settings.framebuffer_bpp; }
350 #endif
351 
352 //----------------------------------------------------------------------
353 inline auto FTermData::hasShadowCharacter() const noexcept -> bool
354 { return flags.shadow_character; }
355 
356 //----------------------------------------------------------------------
357 inline auto FTermData::hasHalfBlockCharacter() const noexcept -> bool
358 { return flags.half_block_character; }
359 
360 //----------------------------------------------------------------------
361 inline auto FTermData::hasCursorOptimisation() const noexcept -> bool
362 { return flags.cursor_optimisation; }
363 
364 //----------------------------------------------------------------------
365 inline auto FTermData::isCursorHidden() const noexcept -> bool
366 { return flags.hidden_cursor; }
367 
368 //----------------------------------------------------------------------
369 inline auto FTermData::hasAlternateScreen() const noexcept -> bool
370 { return flags.use_alternate_screen; }
371 
372 //----------------------------------------------------------------------
373 inline auto FTermData::isInAlternateScreen() const noexcept -> bool
374 { return flags.alternate_screen; }
375 
376 //----------------------------------------------------------------------
377 inline auto FTermData::hasASCIIConsole() const noexcept -> bool
378 { return flags.ascii_console; }
379 
380 //----------------------------------------------------------------------
381 inline auto FTermData::hasVT100Console() const noexcept -> bool
382 { return flags.vt100_console; }
383 
384 //----------------------------------------------------------------------
385 inline auto FTermData::hasUTF8Console() const noexcept -> bool
386 { return flags.utf8_console; }
387 
388 //----------------------------------------------------------------------
389 inline auto FTermData::isUTF8() const noexcept -> bool
390 { return flags.utf8_state; }
391 
392 //----------------------------------------------------------------------
393 inline auto FTermData::isNewFont() const noexcept -> bool
394 { return flags.new_font; }
395 
396 //----------------------------------------------------------------------
397 inline auto FTermData::isVGAFont() const noexcept -> bool
398 { return flags.vga_font; }
399 
400 //----------------------------------------------------------------------
401 inline auto FTermData::isMonochron() const noexcept -> bool
402 { return flags.monochron; }
403 
404 //----------------------------------------------------------------------
405 inline auto FTermData::hasTermResized() -> bool
406 {
407  std::lock_guard<std::mutex> resize_lock_guard(synchronization_state.resize_mutex);
408  return synchronization_state.resize_count.load() > 0;
409 }
410 
411 //----------------------------------------------------------------------
412 inline auto FTermData::isTermType (FTermType type) const -> bool
413 { return terminal_properties.terminal_type & static_cast<FTermTypeT>(type); }
414 
415 //----------------------------------------------------------------------
416 inline auto FTermData::isTermType (FTermTypeT mask) const -> bool
417 { return terminal_properties.terminal_type & mask; }
418 
419 //----------------------------------------------------------------------
420 inline void FTermData::setTermEncoding (Encoding enc) noexcept
421 { encoding_info.term_encoding = enc; }
422 
423 //----------------------------------------------------------------------
424 inline void FTermData::setTTYFileDescriptor (int fd) noexcept
425 { terminal_properties.fd_tty = fd; }
426 
427 //----------------------------------------------------------------------
428 inline void FTermData::setBaudrate (uInt baud) noexcept
429 { terminal_settings.baudrate = baud; }
430 
431 //----------------------------------------------------------------------
432 inline void FTermData::supportShadowCharacter (bool available) noexcept
433 { flags.shadow_character = available; }
434 
435 //----------------------------------------------------------------------
436 inline void FTermData::supportHalfBlockCharacter (bool available) noexcept
437 { flags.half_block_character = available; }
438 
439 //----------------------------------------------------------------------
440 inline void FTermData::supportCursorOptimisation (bool available) noexcept
441 { flags.cursor_optimisation = available; }
442 
443 //----------------------------------------------------------------------
444 inline void FTermData::setCursorHidden (bool hidden_state) noexcept
445 { flags.hidden_cursor = hidden_state; }
446 
447 //----------------------------------------------------------------------
448 inline void FTermData::useAlternateScreen (bool use) noexcept
449 { flags.use_alternate_screen = use; }
450 
451 //----------------------------------------------------------------------
452 inline void FTermData::setAlternateScreenInUse (bool in_use) noexcept
453 { flags.alternate_screen = in_use; }
454 
455 //----------------------------------------------------------------------
456 inline void FTermData::setASCIIConsole (bool ascii) noexcept
457 { flags.ascii_console = ascii; }
458 
459 //----------------------------------------------------------------------
460 inline void FTermData::setVT100Console (bool vt100) noexcept
461 { flags.vt100_console = vt100; }
462 
463 //----------------------------------------------------------------------
464 inline void FTermData::setUTF8Console (bool utf8) noexcept
465 { flags.utf8_console = utf8; }
466 
467 //----------------------------------------------------------------------
468 inline void FTermData::setUTF8 (bool utf8) noexcept
469 { flags.utf8_state = utf8; }
470 
471 //----------------------------------------------------------------------
472 inline void FTermData::setNewFont (bool nfont) noexcept
473 { flags.new_font = nfont; }
474 
475 //----------------------------------------------------------------------
476 inline void FTermData::setVGAFont (bool vga) noexcept
477 { flags.vga_font = vga; }
478 
479 //----------------------------------------------------------------------
480 inline void FTermData::setMonochron (bool mono) noexcept
481 { flags.monochron = mono; }
482 
483 //----------------------------------------------------------------------
484 inline void FTermData::setTermResized (bool resize)
485 {
486  std::lock_guard<std::mutex> resize_lock_guard(synchronization_state.resize_mutex);
487 
488  if ( resize )
489  ++synchronization_state.resize_count;
490  else if ( synchronization_state.resize_count.load() > 0 )
491  --synchronization_state.resize_count;
492 }
493 
494 //----------------------------------------------------------------------
495 inline void FTermData::setTermType (const std::string& name)
496 {
497  if ( ! name.empty() )
498  terminal_settings.termtype = name;
499 }
500 
501 //----------------------------------------------------------------------
502 inline void FTermData::setTermType (FTermType type)
503 { terminal_properties.terminal_type |= static_cast<FTermTypeT>(type); }
504 
505 //----------------------------------------------------------------------
506 inline void FTermData::unsetTermType (FTermType type)
507 { terminal_properties.terminal_type &= ~(static_cast<FTermTypeT>(type)); }
508 
509 //----------------------------------------------------------------------
510 inline void FTermData::setTermFileName (const std::string& file_name)
511 {
512  if ( ! file_name.empty() )
513  terminal_settings.termfilename = file_name;
514 }
515 
516 //----------------------------------------------------------------------
517 inline void FTermData::setGnomeTerminalID (int id) noexcept
518 { terminal_settings.gnome_terminal_id = id; }
519 
520 //----------------------------------------------------------------------
521 inline void FTermData::setKittyVersion(const kittyVersion& version)
522 {
523  terminal_settings.kitty_version.primary = version.primary;
524  terminal_settings.kitty_version.secondary = version.secondary;
525 }
526 
527 //----------------------------------------------------------------------
528 inline void FTermData::setXtermFont (const FString& font)
529 { terminal_properties.xterm_font = font; }
530 
531 //----------------------------------------------------------------------
532 inline void FTermData::setXtermTitle (const FString& title)
533 { terminal_properties.xterm_title = title; }
534 
535 //----------------------------------------------------------------------
536 #if DEBUG && defined(__linux__)
537 inline void FTermData::setFramebufferBpp (int bpp) noexcept
538 { terminal_settings.framebuffer_bpp = bpp; }
539 #endif
540 
541 } // namespace finalcut
542 
543 #endif // FTERMDATA_H
Definition: ftermdata.h:61
Definition: ftermdata.h:58
Definition: frect.h:56
Definition: class_template.cpp:25
Definition: ftermdata.h:134
Definition: fstring.h:79
Definition: ftermdata.h:131