xref: /haiku/src/kits/interface/TextInput.cpp (revision 51978af14a173e7fae0563b562be5603bc652aeb)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2001-2002, OpenBeOS
3 //
4 //	Permission is hereby granted, free of charge, to any person obtaining a
5 //	copy of this software and associated documentation files (the "Software"),
6 //	to deal in the Software without restriction, including without limitation
7 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 //	and/or sell copies of the Software, and to permit persons to whom the
9 //	Software is furnished to do so, subject to the following conditions:
10 //
11 //	The above copyright notice and this permission notice shall be included in
12 //	all copies or substantial portions of the Software.
13 //
14 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 //	DEALINGS IN THE SOFTWARE.
21 //
22 //	File Name:		TextInput.cpp
23 //	Author:			Frans van Nispen (xlr8@tref.nl)
24 //	Description:	The BTextView derivative owned by an instance of
25 //					BTextControl.
26 //------------------------------------------------------------------------------
27 
28 // Standard Includes -----------------------------------------------------------
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 
33 // System Includes -------------------------------------------------------------
34 #include <InterfaceDefs.h>
35 #include <TextControl.h>
36 #include <Window.h>
37 #include <Message.h>
38 #include <TextView.h>
39 
40 // Project Includes ------------------------------------------------------------
41 
42 // Local Includes --------------------------------------------------------------
43 #include "TextInput.h"
44 
45 // Local Defines ---------------------------------------------------------------
46 
47 // Globals ---------------------------------------------------------------------
48 
49 
50 //------------------------------------------------------------------------------
51 _BTextInput_::_BTextInput_(BRect frame, BRect textRect, uint32 resizeMask,
52 						   uint32 flags)
53 	:	BTextView(frame, "_input_", textRect, resizeMask, flags),
54 		fPreviousText(NULL),
55 		fBool(false)
56 {
57 	MakeResizable(true);
58 }
59 //------------------------------------------------------------------------------
60 _BTextInput_::_BTextInput_(BMessage *archive)
61 	:	BTextView(archive),
62 		fPreviousText(NULL),
63 		fBool(false)
64 {
65 	MakeResizable(true);
66 }
67 //------------------------------------------------------------------------------
68 _BTextInput_::~_BTextInput_()
69 {
70 	if (fPreviousText)
71 		free(fPreviousText);
72 }
73 //------------------------------------------------------------------------------
74 BArchivable *_BTextInput_::Instantiate(BMessage *archive)
75 {
76 	if (validate_instantiation(archive, "_BTextInput_"))
77 		return new _BTextInput_(archive);
78 	else
79 		return NULL;
80 }
81 //------------------------------------------------------------------------------
82 status_t _BTextInput_::Archive(BMessage *data, bool deep) const
83 {
84 	return BTextView::Archive(data, true);
85 }
86 //------------------------------------------------------------------------------
87 void _BTextInput_::FrameResized(float width, float height)
88 {
89 	BTextView::FrameResized(width, height);
90 	AlignTextRect();
91 }
92 //------------------------------------------------------------------------------
93 void _BTextInput_::KeyDown(const char* bytes, int32 numBytes)
94 {
95 	switch (*bytes)
96 	{
97 		case B_ENTER:
98 		{
99 			if (!TextControl()->IsEnabled())
100 				break;
101 
102 			if(strcmp(Text(), fPreviousText) != 0)
103 			{
104 				TextControl()->Invoke();
105 				free(fPreviousText);
106 				fPreviousText = strdup(Text());
107 			}
108 
109 			SelectAll();
110 			break;
111 		}
112 
113 		case B_TAB:
114 			BView::KeyDown(bytes, numBytes);
115 			break;
116 
117 		default:
118 			BTextView::KeyDown(bytes, numBytes);
119 	}
120 }
121 //------------------------------------------------------------------------------
122 void _BTextInput_::MakeFocus(bool state)
123 {
124 	if (state == IsFocus())
125 		return;
126 
127 	BTextView::MakeFocus(state);
128 
129 	if (state)
130 	{
131 		SetInitialText();
132 
133 		fBool = true;
134 
135 		if (Window())
136 		{
137 			BMessage *msg = Window()->CurrentMessage();
138 
139 			if (msg && msg->what == B_KEY_DOWN)
140 				SelectAll();
141 		}
142 	}
143 	else
144 	{
145 		if (strcmp(Text(), fPreviousText) != 0)
146 			TextControl()->Invoke();
147 
148 		free(fPreviousText);
149 		fPreviousText = NULL;
150 		fBool = false;
151 
152 		if (Window())
153 		{
154 			BMessage *msg = Window()->CurrentMessage();
155 
156 			if (msg && msg->what == B_MOUSE_DOWN)
157 			{
158 				Select(0, 0);
159 			}
160 		}
161 	}
162 
163 	if (Window())
164 	{
165 		Draw(Bounds());
166 		Flush();
167 	}
168 }
169 //------------------------------------------------------------------------------
170 void _BTextInput_::AlignTextRect()
171 {
172 	// TODO
173 }
174 //------------------------------------------------------------------------------
175 void _BTextInput_::SetInitialText()
176 {
177 	if (fPreviousText)
178 	{
179 		free(fPreviousText);
180 		fPreviousText = NULL;
181 	}
182 
183 	if (Text())
184 		fPreviousText = strdup(Text());
185 }
186 //------------------------------------------------------------------------------
187 void _BTextInput_::Paste(BClipboard *clipboard)
188 {
189 	BTextView::Paste(clipboard);
190 	Invalidate();
191 }
192 //------------------------------------------------------------------------------
193 void _BTextInput_::InsertText(const char *inText, int32 inLength,
194 							  int32 inOffset, const text_run_array *inRuns)
195 {
196 	char *buffer = NULL;
197 
198 	if (strpbrk(inText, "\r\n") && inLength <= 1024)
199 	{
200 		buffer = (char*)malloc(inLength);
201 
202 		if (buffer)
203 		{
204 			strcpy(buffer, inText);
205 
206 			for (int32 i = 0; i < inLength; i++)
207 				if (buffer[i] == '\r' || buffer[i] == '\n')
208 					buffer[i] = ' ';
209 		}
210 	}
211 
212 	BTextView::InsertText(buffer ? buffer : inText, inLength, inOffset,
213 		inRuns);
214 
215 	TextControl()->InvokeNotify(TextControl()->ModificationMessage(),
216 		B_CONTROL_MODIFIED);
217 
218 	if (buffer)
219 		free(buffer);
220 }
221 //------------------------------------------------------------------------------
222 void _BTextInput_::DeleteText(int32 fromOffset, int32 toOffset)
223 {
224 	BTextView::DeleteText(fromOffset, toOffset);
225 
226 	TextControl()->InvokeNotify(TextControl()->ModificationMessage(),
227 		B_CONTROL_MODIFIED);
228 }
229 //------------------------------------------------------------------------------
230 BTextControl *_BTextInput_::TextControl()
231 {
232 	BTextControl *textControl;
233 
234 	if (Parent())
235 		textControl = dynamic_cast<BTextControl*>(Parent());
236 	else
237 		textControl = NULL;
238 
239 	if (!textControl)
240 		debugger("_BTextInput_ should have a BTextControl as parent");
241 
242 	return textControl;
243 }
244 //------------------------------------------------------------------------------
245