1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2005-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2013-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 // handles input dialogs, last-message-buffer, MessageBoard-commands
17 
18 #ifndef INC_C4MessageInput
19 #define INC_C4MessageInput
20 
21 #include "gui/C4Gui.h"
22 #include "object/C4ObjectPtr.h"
23 
24 const int32_t C4MSGB_BackBufferMax  = 20;
25 
26 // chat input dialog
27 class C4ChatInputDialog : public C4GUI::InputDialog
28 {
29 private:
30 	typedef C4GUI::InputDialog BaseClass;
31 	class C4KeyBinding *pKeyHistoryUp, *pKeyHistoryDown, *pKeyAbort, *pKeyNickComplete, *pKeyPlrControl, *pKeyGamepadControl, *pKeyBackClose;
32 
33 	bool fObjInput;    // input queried by script?
34 	bool fUppercase;   // script input converted to uppercase
35 	class C4Object *pTarget; // target object for script callback
36 	int32_t iPlr;      // target player for script callback
37 
38 	// last message lookup
39 	int32_t BackIndex;
40 
41 	bool fProcessed; // set if chat input has been processed
42 
43 	static C4ChatInputDialog *pInstance; // singleton-instance
44 
45 private:
46 	bool KeyHistoryUpDown(bool fUp);
47 	bool KeyCompleteNick(); // complete nick at cursor pos of edit
48 	bool KeyPlrControl(const C4KeyCodeEx &key);
49 	bool KeyGamepadControlDown(const C4KeyCodeEx &key);
50 	bool KeyGamepadControlUp(const C4KeyCodeEx &key);
51 	bool KeyGamepadControlPressed(const C4KeyCodeEx &key);
52 	bool KeyBackspaceClose(); // close if chat text box is empty (on backspace)
53 
54 protected:
55 	// chat input callback
56 	C4GUI::Edit::InputResult OnChatInput(C4GUI::Edit *edt, bool fPasting, bool fPastingMore);
57 	void OnChatCancel();
58 	void OnClosed(bool fOK) override;
59 
GetID()60 	const char *GetID() override { return "ChatDialog"; }
61 public:
62 	C4ChatInputDialog(bool fObjInput, C4Object *pScriptTarget, bool fUpperCase, bool fTeam, int32_t iPlr, const StdStrBuf &rsInputQuery); // ctor - construct by screen ratios
63 	~C4ChatInputDialog() override;
64 
65 	// place on top of normal dialogs
GetZOrdering()66 	int32_t GetZOrdering() override { return C4GUI_Z_CHAT; }
67 
68 	// align by screen, not viewport
IsFreePlaceDialog()69 	bool IsFreePlaceDialog() override { return true; }
70 
71 	// place more to the bottom of the screen
IsBottomPlacementDialog()72 	bool IsBottomPlacementDialog() override { return true; }
73 
74 	// true for dialogs that receive full keyboard and mouse input even in shared mode
IsExclusiveDialog()75 	bool IsExclusiveDialog() override { return true; }
76 
77 	// don't enable mouse just for this dlg
IsMouseControlled()78 	bool IsMouseControlled() override { return false; }
79 
80 	// usually processed by edit;
81 	// but may reach this if the user managed to deselect the edit control
OnEnter()82 	bool OnEnter() override { OnChatInput(pEdit, false, false); return true; }
83 
IsShown()84 	static bool IsShown() { return !!pInstance; } // external query fn whether dlg is visible
GetInstance()85 	static C4ChatInputDialog *GetInstance() { return pInstance; }
86 
IsScriptQueried()87 	bool IsScriptQueried() const { return fObjInput; }
GetScriptTargetObject()88 	class C4Object *GetScriptTargetObject() const { return pTarget; }
GetScriptTargetPlayer()89 	int32_t GetScriptTargetPlayer() const { return iPlr; }
90 };
91 
92 
93 class C4MessageBoardCommand
94 {
95 public:
96 	C4MessageBoardCommand();
97 
98 public:
99 	char Name[C4MaxName + 1];
100 	char Script[_MAX_FNAME+30+1];
101 
102 	C4MessageBoardCommand *Next;
103 };
104 
105 
106 class C4MessageInput
107 {
108 public:
C4MessageInput()109 	C4MessageInput() { Default(); }
~C4MessageInput()110 	~C4MessageInput() { Clear(); }
111 	void Default();
112 	void Clear();
113 	bool Init();
114 
115 private:
116 	// last input messages to be accessed via 'up'/'down' in input dialog
117 	char BackBuffer[C4MSGB_BackBufferMax][C4MaxMessage];
118 
119 	// MessageBoard-commands
120 private:
121 	class C4MessageBoardCommand *pCommands{nullptr};
122 public:
123 	void AddCommand(const char *strCommand, const char *strScript);
124 	class C4MessageBoardCommand *GetCommand(const char *strName);
125 
126 	// Input
127 public:
128 	bool CloseTypeIn();
129 	bool StartTypeIn(bool fObjInput = false, C4Object *pObj = nullptr, bool fUpperCase = false, bool fTeam = false, int32_t iPlr = -1, const StdStrBuf &rsInputQuery = StdStrBuf());
130 	bool KeyStartTypeIn(bool fTeam);
131 	bool ToggleTypeIn();
132 	bool IsTypeIn();
GetTypeIn()133 	C4ChatInputDialog *GetTypeIn() { return C4ChatInputDialog::GetInstance(); }
134 	void StoreBackBuffer(const char *szMessage);
135 	const char *GetBackBuffer(int32_t iIndex);
136 	bool ProcessInput(const char *szText);
137 	bool ProcessCommand(const char *szCommand);
138 
139 public:
140 	void ClearPointers(C4Object *pObj);
141 	void AbortMsgBoardQuery(C4Object *pObj, int32_t iPlr);
142 
143 	friend class C4ChatInputDialog;
144 };
145 
146 extern C4MessageInput MessageInput;
147 
148 // script query to ask a player for a string
149 class C4MessageBoardQuery
150 {
151 public:
152 	C4ObjectPtr CallbackObj; // callback target object
153 	StdStrBuf sInputQuery;   // question being asked to the player
154 	bool fAnswered{false};          // if set, an answer packet is in the queue (NOSAVE, as the queue isn't saved either!)
155 	bool fIsUppercase{false};       // if set, any input is converted to uppercase be4 sending to script
156 
157 	// linked list to allow for multiple queries
158 	C4MessageBoardQuery *pNext{nullptr};
159 
160 	// ctors
C4MessageBoardQuery(C4Object * pCallbackObj,const StdStrBuf & rsInputQuery,bool fIsUppercase)161 	C4MessageBoardQuery(C4Object *pCallbackObj, const StdStrBuf &rsInputQuery, bool fIsUppercase)
162 			: CallbackObj(pCallbackObj), fIsUppercase(fIsUppercase), pNext(nullptr)
163 	{
164 		sInputQuery.Copy(rsInputQuery);
165 	}
166 
C4MessageBoardQuery()167 	C4MessageBoardQuery() : CallbackObj(nullptr) {}
168 
169 	// use default copy ctor
170 
171 
172 	// compilation
173 	void CompileFunc(StdCompiler *pComp);
174 };
175 
176 
177 #endif // INC_C4MessageInput
178