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