xref: /haiku/src/kits/interface/TextInput.cpp (revision 39241fe22890fb958b6ba32d6ab9526da98be187)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2001-2004, Haiku, Inc.
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 //	Authors:		Frans van Nispen (xlr8@tref.nl)
24 //					Marc Flerackers (mflerackers@androme.be)
25 //	Description:	The BTextView derivative owned by an instance of
26 //					BTextControl.
27 //------------------------------------------------------------------------------
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #include <InterfaceDefs.h>
33 #include <Message.h>
34 #include <TextControl.h>
35 #include <TextView.h>
36 #include <Window.h>
37 
38 #include "TextInput.h"
39 
40 
41 _BTextInput_::_BTextInput_(BRect frame, BRect textRect, uint32 resizeMask,
42 						   uint32 flags)
43 	:	BTextView(frame, "_input_", textRect, resizeMask, flags),
44 		fPreviousText(NULL),
45 		fBool(false)
46 {
47 	MakeResizable(true);
48 }
49 
50 
51 _BTextInput_::_BTextInput_(BMessage *archive)
52 	:	BTextView(archive),
53 		fPreviousText(NULL),
54 		fBool(false)
55 {
56 	MakeResizable(true);
57 }
58 
59 
60 _BTextInput_::~_BTextInput_()
61 {
62 	free(fPreviousText);
63 }
64 
65 
66 BArchivable *
67 _BTextInput_::Instantiate(BMessage *archive)
68 {
69 	if (validate_instantiation(archive, "_BTextInput_"))
70 		return new _BTextInput_(archive);
71 	else
72 		return NULL;
73 }
74 
75 
76 status_t
77 _BTextInput_::Archive(BMessage *data, bool deep) const
78 {
79 	return BTextView::Archive(data, true);
80 }
81 
82 
83 void
84 _BTextInput_::FrameResized(float width, float height)
85 {
86 	BTextView::FrameResized(width, height);
87 	AlignTextRect();
88 }
89 
90 
91 void
92 _BTextInput_::KeyDown(const char* bytes, int32 numBytes)
93 {
94 	switch (*bytes) {
95 		case B_ENTER:
96 		{
97 			if (!TextControl()->IsEnabled())
98 				break;
99 
100 			if(strcmp(Text(), fPreviousText) != 0) {
101 				TextControl()->Invoke();
102 				free(fPreviousText);
103 				fPreviousText = strdup(Text());
104 			}
105 
106 			SelectAll();
107 			break;
108 		}
109 
110 		case B_TAB:
111 			BView::KeyDown(bytes, numBytes);
112 			break;
113 
114 		default:
115 			BTextView::KeyDown(bytes, numBytes);
116 			break;
117 	}
118 }
119 
120 
121 void
122 _BTextInput_::MakeFocus(bool state)
123 {
124 	if (state == IsFocus())
125 		return;
126 
127 	BTextView::MakeFocus(state);
128 
129 	if (state) {
130 		SetInitialText();
131 
132 		fBool = true;
133 
134 		if (Window()) {
135 			BMessage *message = Window()->CurrentMessage();
136 
137 			if (message && message->what == B_KEY_DOWN)
138 				SelectAll();
139 		}
140 	} else {
141 		if (strcmp(Text(), fPreviousText) != 0)
142 			TextControl()->Invoke();
143 
144 		free(fPreviousText);
145 		fPreviousText = NULL;
146 		fBool = false;
147 
148 		if (Window()) {
149 			BMessage *message = Window()->CurrentMessage();
150 
151 			if (message && message->what == B_MOUSE_DOWN)
152 				Select(0, 0);
153 		}
154 	}
155 
156 	if (Window()) {
157 		Draw(Bounds());
158 		Flush();
159 	}
160 }
161 
162 
163 void
164 _BTextInput_::AlignTextRect()
165 {
166 	// TODO
167 }
168 
169 
170 void
171 _BTextInput_::SetInitialText()
172 {
173 	if (fPreviousText) {
174 		free(fPreviousText);
175 		fPreviousText = NULL;
176 	}
177 
178 	if (Text())
179 		fPreviousText = strdup(Text());
180 }
181 
182 
183 void
184 _BTextInput_::Paste(BClipboard *clipboard)
185 {
186 	BTextView::Paste(clipboard);
187 	Invalidate();
188 }
189 
190 
191 void
192 _BTextInput_::InsertText(const char *inText, int32 inLength,
193 							  int32 inOffset, const text_run_array *inRuns)
194 {
195 	char *buffer = NULL;
196 
197 	if (strpbrk(inText, "\r\n") && inLength <= 1024) {
198 		buffer = (char *)malloc(inLength);
199 
200 		if (buffer) {
201 			strcpy(buffer, inText);
202 
203 			for (int32 i = 0; i < inLength; i++)
204 				if (buffer[i] == '\r' || buffer[i] == '\n')
205 					buffer[i] = ' ';
206 		}
207 	}
208 
209 	BTextView::InsertText(buffer ? buffer : inText, inLength, inOffset,
210 		inRuns);
211 
212 	TextControl()->InvokeNotify(TextControl()->ModificationMessage(),
213 		B_CONTROL_MODIFIED);
214 
215 	free(buffer);
216 }
217 
218 
219 void
220 _BTextInput_::DeleteText(int32 fromOffset, int32 toOffset)
221 {
222 	BTextView::DeleteText(fromOffset, toOffset);
223 
224 	TextControl()->InvokeNotify(TextControl()->ModificationMessage(),
225 		B_CONTROL_MODIFIED);
226 }
227 
228 
229 BTextControl *
230 _BTextInput_::TextControl()
231 {
232 	BTextControl *textControl = NULL;
233 
234 	if (Parent())
235 		textControl = dynamic_cast<BTextControl*>(Parent());
236 
237 	if (!textControl)
238 		debugger("_BTextInput_ should have a BTextControl as parent");
239 
240 	return textControl;
241 }
242