FINAL CUT
fmouse.h
1 /***********************************************************************
2 * fmouse.h - Read mouse events *
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 /* Inheritance diagram
24  * ═══════════════════
25  *
26  * ▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏
27  * ▕ FMouseData ▏
28  * ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▁▏
29  * ▲
30  * │
31  * ▕▔▔▔▔▔▔▔▔▔▔▏
32  * ▕ FMouse ▏
33  * ▕▁▁▁▁▁▁▁▁▁▁▏
34  * ▲
35  * │
36  * ┌─────────────┬──────┴───────┬─────────────┐
37  * │ │ │ │
38  * ▕▔▔▔▔▔▔▔▔▔▔▔▏ ▕▔▔▔▔▔▔▔▔▔▔▔▏ ▕▔▔▔▔▔▔▔▔▔▔▔▏ ▕▔▔▔▔▔▔▔▔▔▔▔▔▔▏
39  * ▕ FMouseGPM ▏ ▕ FMouseX11 ▏ ▕ FMouseSGR ▏ ▕ FMouseUrxvt ▏
40  * ▕▁▁▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▏
41  *
42  *
43  *
44  * ▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏1 1▕▔▔▔▔▔▔▔▔▔▔▔▏
45  * ▕ FMouseControl ▏- -┬- - -▕ FMouseGPM ▏
46  * ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▏ : ▕▁▁▁▁▁▁▁▁▁▁▁▏
47  * :
48  * : 1▕▔▔▔▔▔▔▔▔▔▔▔▏
49  * :- - -▕ FMouseX11 ▏
50  * : ▕▁▁▁▁▁▁▁▁▁▁▁▏
51  * :
52  * : 1▕▔▔▔▔▔▔▔▔▔▔▔▏
53  * └- - -▕ FMouseSGR ▏
54  * : ▕▁▁▁▁▁▁▁▁▁▁▁▏
55  * :
56  * : 1▕▔▔▔▔▔▔▔▔▔▔▔▔▔▏
57  * └- - -▕ FMouseUrxvt ▏
58  * ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▏
59  */
60 
61 #ifndef FMOUSE_H
62 #define FMOUSE_H
63 
64 #if !defined (USE_FINAL_H) && !defined (COMPILE_FINAL_CUT)
65  #error "Only <final/final.h> can be included directly."
66 #endif
67 
68 #include <cstddef>
69 #include <functional>
70 #include <memory>
71 #include <utility>
72 #include <vector>
73 
74 #include "final/input/fkeyboard.h"
75 #include "final/util/fpoint.h"
76 
77 #if defined(__linux__)
78  #include <linux/keyboard.h> // need for gpm keyboard modifiers
79 #endif
80 
81 #ifdef F_HAVE_LIBGPM
82  #include <gpm.h>
83 #endif
84 
85 namespace finalcut
86 {
87 
88 //----------------------------------------------------------------------
89 // class FMouseData
90 //----------------------------------------------------------------------
91 
93 {
94  public:
95  // Constructor
96  FMouseData() = default;
97 
98  // Copy constructor
99  FMouseData (const FMouseData&) = default;
100 
101  // Move constructor
102  FMouseData (FMouseData&&) noexcept = default;
103 
104  // Destructor
105  virtual ~FMouseData() noexcept;
106 
107  // Copy assignment operator (=)
108  auto operator = (const FMouseData&) -> FMouseData& = default;
109 
110  // Move assignment operator (=)
111  auto operator = (FMouseData&&) noexcept -> FMouseData& = default;
112 
113  // Accessors
114  virtual auto getClassName() const -> FString;
115  auto getPos() const & noexcept -> const FPoint&;
116 
117  // Inquiries
118  auto isLeftButtonPressed() const noexcept -> bool;
119  auto isLeftButtonReleased() const noexcept -> bool;
120  auto isLeftButtonDoubleClick() const noexcept -> bool;
121  auto isRightButtonPressed() const noexcept -> bool;
122  auto isRightButtonReleased() const noexcept -> bool;
123  auto isMiddleButtonPressed() const noexcept -> bool;
124  auto isMiddleButtonReleased() const noexcept -> bool;
125  auto isShiftKeyPressed() const noexcept -> bool;
126  auto isControlKeyPressed() const noexcept -> bool;
127  auto isMetaKeyPressed() const noexcept -> bool;
128  auto isWheelUp() const noexcept -> bool;
129  auto isWheelDown() const noexcept -> bool;
130  auto isWheelLeft() const noexcept -> bool;
131  auto isWheelRight() const noexcept -> bool;
132  auto isMoved() const noexcept -> bool;
133 
134  // Methods
135  void clearButtonState() noexcept;
136 
137  protected:
138  // Enumerations
139  enum class State : uChar
140  {
141  Undefined = 0,
142  Pressed = 1,
143  Released = 2,
144  DoubleClick = 3
145  };
146 
148  {
149  State left_button{};
150  State right_button{};
151  State middle_button{};
152  bool shift_button{};
153  bool control_button{};
154  bool meta_button{};
155  bool wheel_up{};
156  bool wheel_down{};
157  bool wheel_left{};
158  bool wheel_right{};
159  bool mouse_moved{};
160  };
161 
162  // Accessors
163  auto getButtonState() & noexcept -> FMouseButton&;
164  auto getButtonState() const & noexcept -> const FMouseButton&;
165 
166  // Mutator
167  void setPos (const FPoint&) noexcept;
168 
169  private:
170  // Data members
171  FMouseButton b_state{};
172  FPoint mouse{0, 0}; // mouse click position
173 };
174 
175 
176 //----------------------------------------------------------------------
177 // class FMouse
178 //----------------------------------------------------------------------
179 
180 class FMouse : public FMouseData
181 {
182  public:
183  // Enumeration
184  enum class MouseType
185  {
186  None = 0,
187  Gpm = 1,
188  X11 = 2,
189  Sgr = 3,
190  Urxvt = 4
191  };
192 
193  // Constructor
194  FMouse();
195 
196  // Accessors
197  auto getClassName() const -> FString override;
198  auto getMouseTypeID() const noexcept -> MouseType;
199  void clearEvent() noexcept;
200 
201  // Mutators
202  void setMaxWidth (uInt16) noexcept;
203  void setMaxHeight (uInt16) noexcept;
204  void setDblclickInterval (const uInt64) noexcept;
205 
206  // Inquiries
207  virtual auto hasData() -> bool = 0;
208  auto hasEvent() const noexcept -> bool;
209  auto hasUnprocessedInput() const noexcept -> bool;
210 
211  // Methods
212  template <typename ClassT>
213  static auto createMouseObject() -> std::unique_ptr<ClassT>;
214  virtual void setRawData (FKeyboard::keybuffer&) = 0;
215  virtual void processEvent (const TimeValue&) = 0;
216 
217  protected:
218  // Accessors
219  auto getNewPos() const & noexcept -> const FPoint&;
220  auto getMaxWidth() const noexcept -> uInt16;
221  auto getMaxHeight() const noexcept -> uInt16;
222  auto getDblclickInterval() const noexcept -> uInt64;
223  auto getMousePressedTime() const noexcept -> TimeValue;
224 
225  // Mutator
226  void setMouseTypeID (MouseType) noexcept;
227  void setNewPos (int, int) noexcept;
228  void useNewPos() noexcept;
229  void setPending (bool = true) noexcept;
230  void setEvent() noexcept;
231  void setMousePressedTime (const TimeValue&) noexcept;
232  void resetMousePressedTime() noexcept;
233 
234  // Inquiry
235  auto isDblclickTimeout (const TimeValue&) const -> bool;
236 
237  private:
238  // Data members
239  bool mouse_event_occurred{false};
240  bool unprocessed_buffer_data{false};
241  MouseType MouseType_id{MouseType::None};
242  uInt16 max_width{80};
243  uInt16 max_height{25};
244  uInt64 dblclick_interval{500000}; // 500 ms
245  TimeValue time_mousepressed{};
246  FPoint new_mouse_position{};
247 };
248 
249 //----------------------------------------------------------------------
250 template <typename ClassT>
251 inline auto FMouse::createMouseObject() -> std::unique_ptr<ClassT>
252 {
253  return std::make_unique<ClassT>();
254 }
255 
256 
257 #ifdef F_HAVE_LIBGPM
258 //----------------------------------------------------------------------
259 // class FMouseGPM
260 //----------------------------------------------------------------------
261 
262 class FMouseGPM final : public FMouse
263 {
264  public:
265  // Constructor
266  FMouseGPM();
267 
268  // Accessors
269  auto getClassName() const -> FString override;
270 
271  // Mutators
272  void setStdinNo(int) noexcept;
273 
274  // Inquiry
275  auto hasData() noexcept -> bool override;
276  auto isGpmMouseEnabled() const noexcept -> bool;
277 
278  // Methods
279  void setRawData (FKeyboard::keybuffer&) noexcept override;
280  void processEvent (const TimeValue&) override;
281  auto gpmMouse (bool = true) -> bool;
282  auto enableGpmMouse() -> bool;
283  auto disableGpmMouse() -> bool;
284  auto hasSignificantEvents() const noexcept -> bool;
285  void interpretKeyDown() noexcept;
286  void interpretKeyUp() noexcept;
287  auto getGpmKeyPressed (bool = true) -> bool;
288  void drawPointer() const;
289 
290  private:
291  // Enumeration
292  enum class gpmEventType
293  {
294  None = 0,
295  Keyboard = 1,
296  Mouse = 2
297  };
298 
299  // Method
300  void handleMouseEvent();
301  void resetMouseState();
302  void handleMouseMovement();
303  void handleMouseWheel();
304  void interpretMouseEvent();
305  void updateMousePosition();
306  auto gpmEvent (bool = true) const -> gpmEventType;
307 
308  // Data member
309  Gpm_Event gpm_ev{};
310  bool has_gpm_mouse_data{false};
311  bool gpm_mouse_enabled{false};
312  int stdin_no{0};
313 };
314 
315 //----------------------------------------------------------------------
316 inline auto FMouseGPM::enableGpmMouse() -> bool
317 { return gpmMouse(true); }
318 
319 //----------------------------------------------------------------------
320 inline auto FMouseGPM::disableGpmMouse() -> bool
321 { return gpmMouse(false); }
322 
323 //----------------------------------------------------------------------
324 inline auto FMouseGPM::isGpmMouseEnabled() const noexcept -> bool
325 { return gpm_mouse_enabled; }
326 #endif // F_HAVE_LIBGPM
327 
328 
329 //----------------------------------------------------------------------
330 // class FMouseX11
331 //----------------------------------------------------------------------
332 
333 class FMouseX11 final : public FMouse
334 {
335  public:
336  // Constructor
337  FMouseX11();
338 
339  // Accessors
340  auto getClassName() const -> FString override;
341 
342  // Inquiry
343  auto hasData() noexcept -> bool override;
344 
345  // Methods
346  void setRawData (FKeyboard::keybuffer&) noexcept override;
347  void processEvent (const TimeValue&) override;
348 
349  private:
350  // Enumeration
351  enum btn_states
352  {
353  key_shift = 0x04,
354  key_meta = 0x08,
355  key_ctrl = 0x10,
356  key_button_mask = 0x1c,
357  button1_pressed = 0x20,
358  button2_pressed = 0x21,
359  button3_pressed = 0x22,
360  all_buttons_released = 0x23,
361  button1_pressed_move = 0x40,
362  button2_pressed_move = 0x41,
363  button3_pressed_move = 0x42,
364  button_mask = 0x63,
365  button_up = 0x60, // Mouse wheel scrolls up
366  button_down = 0x61, // Mouse wheel scrolls down
367  button_left = 0x62, // Mouse wheel left tilt
368  button_right = 0x63 // Mouse wheel right tilt
369  };
370 
371  // Constant
372  static constexpr std::size_t MOUSE_BUF_SIZE = 4;
373 
374  // Methods
375  void setKeyState (int) noexcept;
376  void setMoveState (const FPoint&, int) noexcept;
377  auto isMouseClickButton (const int) const noexcept -> bool;
378  auto isMouseWheelButton (const int) const noexcept -> bool;
379  auto noChanges (const FPoint&, uChar) const noexcept -> bool;
380  void handleMouseClickButton (int, const TimeValue&) noexcept;
381  void handleMouseWheelButton (int) noexcept;
382  void setButtonState (const int, const TimeValue&) noexcept;
383  void handleButton1Pressed (const TimeValue& time) noexcept;
384  void handleButtonRelease() noexcept;
385 
386  // Data member
387  std::array<char, MOUSE_BUF_SIZE>x11_mouse{};
388  uChar x11_button_state{all_buttons_released};
389 };
390 
391 
392 //----------------------------------------------------------------------
393 // class FMouseSGR
394 //----------------------------------------------------------------------
395 
396 class FMouseSGR final : public FMouse
397 {
398  public:
399  // Constructor
400  FMouseSGR();
401 
402  // Accessors
403  auto getClassName() const -> FString override;
404 
405  // Inquiry
406  auto hasData() noexcept -> bool override;
407 
408  // Methods
409  void setRawData (FKeyboard::keybuffer&) noexcept override;
410  void processEvent (const TimeValue&) override;
411 
412  private:
413  struct Tokens
414  {
415  sInt16 x{0};
416  sInt16 y{0};
417  int btn{0};
418  const char* p{nullptr}; // Current read position
419  };
420 
421  // Enumerations
422  enum class ParseError { No, Yes };
423 
424  enum x11_ext_btn_states
425  {
426  key_shift = 0x04,
427  key_meta = 0x08,
428  key_ctrl = 0x10,
429  key_button_mask = 0x1c,
430  button1 = 0x00,
431  button2 = 0x01,
432  button3 = 0x02,
433  button1_move = 0x20,
434  button2_move = 0x21,
435  button3_move = 0x22,
436  button_mask = 0xe3,
437  button_up = 0x40, // Mouse wheel scrolls up
438  button_down = 0x41, // Mouse wheel scrolls down
439  button_left = 0x42, // Mouse wheel left tilt
440  button_right = 0x43, // Mouse wheel right tilt
441  pressed = 'M',
442  released = 'm'
443  };
444 
445  // Constant
446  static constexpr std::size_t MOUSE_BUF_SIZE = 13;
447 
448  // Methods
449  void setKeyState (int) noexcept;
450  void setMoveState (const FPoint&, int) noexcept;
451  auto isMouseClickButton (const int) const noexcept -> bool;
452  auto isMouseWheelButton (const int) const noexcept -> bool;
453  auto parseSGRMouseString (Tokens&) const noexcept -> ParseError;
454  auto noChanges (const FPoint&, uChar) const noexcept -> bool;
455  void handleMouseClickButton (int, const TimeValue&) noexcept;
456  void handleMouseWheelButton (int) noexcept;
457  void setPressedButtonState (const int, const TimeValue&) noexcept;
458  void handleButton1Pressed (const TimeValue& time) noexcept;
459  void setReleasedButtonState (const int) noexcept;
460 
461  // Data members
462  std::array<char, MOUSE_BUF_SIZE> sgr_mouse{};
463  uChar sgr_button_state{0x23};
464 };
465 
466 
467 //----------------------------------------------------------------------
468 // class FMouseUrxvt
469 //----------------------------------------------------------------------
470 
471 class FMouseUrxvt final : public FMouse
472 {
473  public:
474  // Constructor
475  FMouseUrxvt();
476 
477  // Accessors
478  auto getClassName() const -> FString override;
479 
480  // Inquiry
481  auto hasData() noexcept -> bool override;
482 
483  // Methods
484  void setRawData (FKeyboard::keybuffer&) noexcept override;
485  void processEvent (const TimeValue&) override;
486 
487  private:
488  struct Tokens
489  {
490  sInt16 x{0};
491  sInt16 y{0};
492  int btn{0};
493  bool x_neg{false};
494  bool y_neg{false};
495  const char* p{nullptr}; // Current read position
496  };
497 
498  // Enumerations
499  enum class ParseError { No, Yes };
500 
501  enum urxvt_btn_states
502  {
503  key_shift = 0x04,
504  key_meta = 0x08,
505  key_ctrl = 0x10,
506  key_button_mask = 0x1c,
507  button1_pressed = 0x20,
508  button2_pressed = 0x21,
509  button3_pressed = 0x22,
510  all_buttons_released = 0x23,
511  button1_pressed_move = 0x40,
512  button2_pressed_move = 0x41,
513  button3_pressed_move = 0x42,
514  button_mask = 0xe3,
515  button_up = 0x60, // Mouse wheel scrolls up
516  button_down = 0x61, // Mouse wheel scrolls down
517  button_left = 0x62, // Mouse wheel left tilt
518  button_right = 0x63 // Mouse wheel right tilt
519  };
520 
521  // Constant
522  static constexpr std::size_t MOUSE_BUF_SIZE = 14;
523 
524  // Methods
525  void setKeyState (int) noexcept;
526  void setMoveState (const FPoint&, int) noexcept;
527  auto isMouseClickButton (const int) const noexcept -> bool;
528  auto isMouseWheelButton (const int) const noexcept -> bool;
529  auto parseUrxvtMouseString (Tokens&) const noexcept -> ParseError;
530  void adjustAndSetPosition (Tokens&);
531  auto noChanges (const FPoint&, uChar) const noexcept -> bool;
532  void handleMouseClickButton (int, const TimeValue&) noexcept;
533  void handleButtonRelease() noexcept;
534  void handleMouseWheelButton (int) noexcept;
535  void setButtonState (const int, const TimeValue&) noexcept;
536 
537  // Data members
538  std::array<char, MOUSE_BUF_SIZE> urxvt_mouse{};
539  uChar urxvt_button_state{all_buttons_released};
540 };
541 
542 
543 //----------------------------------------------------------------------
544 // class FMouseCommand
545 //----------------------------------------------------------------------
546 
547 class FMouseCommand final
548 {
549  public:
550  // Constructors
551  FMouseCommand() = default;
552 
553  explicit FMouseCommand (std::function<void()>&& fn)
554  : handler1(std::move(fn))
555  { }
556 
557  explicit FMouseCommand (std::function<void(const FMouseData&)>&& fn)
558  : handler2(std::move(fn))
559  { }
560 
561  // Method
562  inline void execute() const
563  {
564  handler1();
565  }
566 
567  template <typename T>
568  inline void execute(T&& arg) const
569  {
570  handler2(std::forward<T>(arg));
571  }
572 
573  private:
574  // Data members
575  std::function<void()> handler1{};
576  std::function<void(const FMouseData&)> handler2{};
577 };
578 
579 
580 //----------------------------------------------------------------------
581 // class FMouseControl
582 //----------------------------------------------------------------------
583 
585 {
586  public:
587  // Using-declaration
588  using FMouseDataPtr = std::shared_ptr<FMouseData>;
589 
590  // Constructor
591  FMouseControl();
592 
593  // Destructor
594  virtual ~FMouseControl();
595 
596  // Accessors
597  virtual auto getClassName() const -> FString;
598  static auto getInstance() -> FMouseControl&;
599  static auto getCurrentMouseEvent() -> FMouseDataPtr&;
600  auto getPos() & -> const FPoint&;
601  void clearEvent();
602 
603  // Mutators
604  void setStdinNo (int);
605  void setMaxWidth (uInt16);
606  void setMaxHeight (uInt16);
607  void setDblclickInterval (const uInt64) const;
608  void setEventCommand (const FMouseCommand&);
609  void setEnableXTermMouseCommand (const FMouseCommand&);
610  void setDisableXTermMouseCommand (const FMouseCommand&);
611  void useGpmMouse (bool = true);
612  void useXtermMouse (bool = true);
613 
614  // Inquiries
615  auto hasData() -> bool;
616  auto hasEvent() -> bool;
617  auto isLeftButtonPressed() -> bool;
618  auto isLeftButtonReleased() -> bool;
619  auto isLeftButtonDoubleClick() -> bool;
620  auto isRightButtonPressed() -> bool;
621  auto isRightButtonReleased() -> bool;
622  auto isMiddleButtonPressed() -> bool;
623  auto isMiddleButtonReleased() -> bool;
624  auto isShiftKeyPressed() -> bool;
625  auto isControlKeyPressed() -> bool;
626  auto isMetaKeyPressed() -> bool;
627  auto isWheelUp() -> bool;
628  auto isWheelDown() -> bool;
629  auto isWheelLeft() -> bool;
630  auto isWheelRight() -> bool;
631  auto isMoved() -> bool;
632  auto hasUnprocessedInput() const -> bool;
633  auto hasDataInQueue() const -> bool;
634  auto isGpmMouseEnabled() noexcept -> bool;
635 
636  // Methods
637  void enable();
638  void disable();
639  virtual void setRawData ( const FMouse::MouseType&
641  virtual void processEvent (const TimeValue&);
642  void processQueuedInput();
643  auto getGpmKeyPressed (bool = true) -> bool;
644  void drawPointer();
645 
646  private:
647  // Constants
648  static constexpr std::size_t MAX_QUEUE_SIZE = 64;
649 
650  // Using-declarations
651  using FMousePtr = std::unique_ptr<FMouse>;
652  using FMouseProtocol = std::vector<FMousePtr>;
654 
655  // Accessor
656  auto findMouseWithType (const FMouse::MouseType&) const -> FMouseProtocol::const_iterator;
657  auto findMouseWithData() const -> FMouseProtocol::const_iterator;
658  auto findMouseWithEvent() const -> FMouseProtocol::const_iterator;
659 
660  // Mutators
661  void xtermMouse (bool = true) const;
662  void enableXTermMouse() const;
663  void disableXTermMouse() const;
664  static void setCurrentMouseEvent (const FMouseDataPtr&);
665  static void resetCurrentMouseEvent();
666 
667  // Data member
668  FMouseProtocol mouse_protocol{};
669  FMouseCommand event_cmd{};
670  FMouseCommand enable_xterm_mouse_cmd{};
671  FMouseCommand disable_xterm_mouse_cmd{};
672  MouseQueue fmousedata_queue{};
673  FPoint zero_point{0, 0};
674  bool use_gpm_mouse{false};
675  bool use_xterm_mouse{false};
676 };
677 
678 // FMouseControl inline functions
679 //----------------------------------------------------------------------
680 inline auto FMouseControl::getClassName() const -> FString
681 { return "FMouseControl"; }
682 
683 //----------------------------------------------------------------------
684 inline void FMouseControl::setEventCommand (const FMouseCommand& cmd)
685 { event_cmd = cmd; }
686 
687 //----------------------------------------------------------------------
688 inline void FMouseControl::setEnableXTermMouseCommand (const FMouseCommand& cmd)
689 { enable_xterm_mouse_cmd = cmd; }
690 
691 //----------------------------------------------------------------------
692 inline void FMouseControl::setDisableXTermMouseCommand (const FMouseCommand& cmd)
693 { disable_xterm_mouse_cmd = cmd; }
694 
695 //----------------------------------------------------------------------
696 inline auto FMouseControl::hasDataInQueue() const -> bool
697 { return ! fmousedata_queue.isEmpty(); }
698 
699 //----------------------------------------------------------------------
700 inline void FMouseControl::enableXTermMouse() const
701 { xtermMouse(true); }
702 
703 //----------------------------------------------------------------------
704 inline void FMouseControl::disableXTermMouse() const
705 { xtermMouse(false); }
706 
707 } // namespace finalcut
708 
709 #endif // FMOUSE_H
Definition: fmouse.h:396
Definition: fmouse.h:547
Definition: fmouse.h:147
Definition: fmouse.h:471
Definition: class_template.cpp:25
Definition: fmouse.h:333
Definition: fpoint.h:50
Definition: fmouse.h:92
Definition: fmouse.h:180
Definition: fstring.h:79
Definition: fmouse.h:584