tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / kits / interface / TextInput.cpp
blobd334cc636475c22ce3f55c3769ea3a410dc55a61
1 /*
2 * Copyright 2001-2015, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Frans van Nispen (xlr8@tref.nl)
7 * Marc Flerackers (mflerackers@androme.be)
8 */
11 #include "TextInput.h"
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
17 #include <ControlLook.h>
18 #include <InterfaceDefs.h>
19 #include <LayoutUtils.h>
20 #include <Message.h>
21 #include <String.h>
22 #include <TextControl.h>
23 #include <TextView.h>
24 #include <Window.h>
27 namespace BPrivate {
30 _BTextInput_::_BTextInput_(BRect frame, BRect textRect, uint32 resizeMask,
31 uint32 flags)
33 BTextView(frame, "_input_", textRect, resizeMask, flags),
34 fPreviousText(NULL)
36 MakeResizable(true);
40 _BTextInput_::_BTextInput_(BMessage* archive)
42 BTextView(archive),
43 fPreviousText(NULL)
45 MakeResizable(true);
49 _BTextInput_::~_BTextInput_()
51 free(fPreviousText);
55 BArchivable*
56 _BTextInput_::Instantiate(BMessage* archive)
58 if (validate_instantiation(archive, "_BTextInput_"))
59 return new _BTextInput_(archive);
61 return NULL;
65 status_t
66 _BTextInput_::Archive(BMessage* data, bool deep) const
68 return BTextView::Archive(data, true);
72 void
73 _BTextInput_::MouseDown(BPoint where)
75 if (!IsFocus()) {
76 MakeFocus(true);
77 return;
80 // only pass through to base class if we already have focus
81 BTextView::MouseDown(where);
85 void
86 _BTextInput_::FrameResized(float width, float height)
88 BTextView::FrameResized(width, height);
90 AlignTextRect();
94 void
95 _BTextInput_::KeyDown(const char* bytes, int32 numBytes)
97 switch (*bytes) {
98 case B_ENTER:
100 if (!TextControl()->IsEnabled())
101 break;
103 if (fPreviousText == NULL || strcmp(Text(), fPreviousText) != 0) {
104 TextControl()->Invoke();
105 free(fPreviousText);
106 fPreviousText = strdup(Text());
109 SelectAll();
110 break;
113 case B_TAB:
114 BView::KeyDown(bytes, numBytes);
115 break;
117 default:
118 BTextView::KeyDown(bytes, numBytes);
119 break;
124 void
125 _BTextInput_::MakeFocus(bool state)
127 if (state == IsFocus())
128 return;
130 BTextView::MakeFocus(state);
132 if (state) {
133 SetInitialText();
134 SelectAll();
135 } else {
136 if (strcmp(Text(), fPreviousText) != 0)
137 TextControl()->Invoke();
139 free(fPreviousText);
140 fPreviousText = NULL;
143 if (Window() != NULL) {
144 // Invalidate parent to draw or remove the focus mark
145 if (BTextControl* parent = dynamic_cast<BTextControl*>(Parent())) {
146 BRect frame = Frame();
147 frame.InsetBy(-1.0, -1.0);
148 parent->Invalidate(frame);
154 BSize
155 _BTextInput_::MinSize()
157 BSize min;
158 min.height = ceilf(LineHeight(0) + 2.0);
159 // we always add at least one pixel vertical inset top/bottom for
160 // the text rect.
161 min.width = min.height * 3;
162 return BLayoutUtils::ComposeSize(ExplicitMinSize(), min);
166 void
167 _BTextInput_::AlignTextRect()
169 // the label font could require the control to be higher than
170 // necessary for the text view, we compensate this by layouting
171 // the text rect to be in the middle, normally this means there
172 // is one pixel spacing on each side
173 BRect textRect(Bounds());
174 float vInset = max_c(1,
175 floorf((textRect.Height() - LineHeight(0)) / 2.0));
176 float hInset = 2;
177 float textFontWidth = TextRect().right;
179 if (be_control_look != NULL) {
180 switch (Alignment()) {
181 case B_ALIGN_LEFT:
182 hInset = be_control_look->DefaultLabelSpacing();
183 break;
185 case B_ALIGN_RIGHT:
186 hInset = textRect.right - textFontWidth;
187 hInset -= be_control_look->DefaultLabelSpacing();
188 break;
190 case B_ALIGN_CENTER:
191 hInset = (textRect.right - textFontWidth) / 2.0;
192 break;
194 default:
195 break;
199 textRect.InsetBy(hInset, vInset);
200 SetTextRect(textRect);
204 void
205 _BTextInput_::SetInitialText()
207 free(fPreviousText);
208 fPreviousText = NULL;
210 if (Text() != NULL)
211 fPreviousText = strdup(Text());
215 void
216 _BTextInput_::Paste(BClipboard* clipboard)
218 BTextView::Paste(clipboard);
219 Invalidate();
223 void
224 _BTextInput_::InsertText(const char* inText, int32 inLength,
225 int32 inOffset, const text_run_array* inRuns)
227 // Filter all line breaks, note that inText is not terminated.
228 if (inLength == 1) {
229 if (*inText == '\n' || *inText == '\r')
230 BTextView::InsertText(" ", 1, inOffset, inRuns);
231 else
232 BTextView::InsertText(inText, 1, inOffset, inRuns);
233 } else {
234 BString filteredText(inText, inLength);
235 filteredText.ReplaceAll('\n', ' ');
236 filteredText.ReplaceAll('\r', ' ');
237 BTextView::InsertText(filteredText.String(), inLength, inOffset,
238 inRuns);
241 TextControl()->InvokeNotify(TextControl()->ModificationMessage(),
242 B_CONTROL_MODIFIED);
246 void
247 _BTextInput_::DeleteText(int32 fromOffset, int32 toOffset)
249 BTextView::DeleteText(fromOffset, toOffset);
251 TextControl()->InvokeNotify(TextControl()->ModificationMessage(),
252 B_CONTROL_MODIFIED);
256 BTextControl*
257 _BTextInput_::TextControl()
259 BTextControl* textControl = NULL;
260 if (Parent() != NULL)
261 textControl = dynamic_cast<BTextControl*>(Parent());
263 if (textControl == NULL)
264 debugger("_BTextInput_ should have a BTextControl as parent");
266 return textControl;
270 } // namespace BPrivate