]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/textctrl.cpp
Added background colour again
[wxWidgets.git] / src / gtk1 / textctrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: textctrl.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling, Vadim Zeitlin
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "textctrl.h"
12 #endif
13
14 #include "wx/textctrl.h"
15 #include "wx/utils.h"
16 #include <wx/intl.h>
17
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <ctype.h>
21
22 //-----------------------------------------------------------------------------
23 // "changed"
24 //-----------------------------------------------------------------------------
25
26 static void gtk_text_changed_callback( GtkWidget *WXUNUSED(widget), wxTextCtrl *win )
27 {
28 win->SetModified();
29
30 wxCommandEvent event( wxEVT_COMMAND_TEXT_UPDATED, win->m_windowId );
31 wxString val( win->GetValue() );
32 if (!val.IsNull()) event.m_commandString = WXSTRINGCAST val;
33 event.SetEventObject( win );
34 win->GetEventHandler()->ProcessEvent( event );
35 }
36
37 //-----------------------------------------------------------------------------
38 // wxTextCtrl
39 //-----------------------------------------------------------------------------
40
41 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl,wxControl)
42
43 BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
44 EVT_CHAR(wxTextCtrl::OnChar)
45 END_EVENT_TABLE()
46
47 wxTextCtrl::wxTextCtrl() : streambuf()
48 {
49 if (allocate()) setp(base(),ebuf());
50
51 m_modified = FALSE;
52 }
53
54 wxTextCtrl::wxTextCtrl( wxWindow *parent, wxWindowID id, const wxString &value,
55 const wxPoint &pos, const wxSize &size,
56 int style, const wxValidator& validator, const wxString &name ) : streambuf()
57 {
58 if (allocate()) setp(base(),ebuf());
59
60 m_modified = FALSE;
61 Create( parent, id, value, pos, size, style, validator, name );
62 }
63
64 bool wxTextCtrl::Create( wxWindow *parent, wxWindowID id, const wxString &value,
65 const wxPoint &pos, const wxSize &size,
66 int style, const wxValidator& validator, const wxString &name )
67 {
68 m_needParent = TRUE;
69
70 PreCreation( parent, id, pos, size, style, name );
71
72 SetValidator( validator );
73
74 bool bMultiLine = (style & wxTE_MULTILINE) != 0;
75 if ( bMultiLine )
76 {
77 // a multi-line edit control: create a vertical scrollbar by default and
78 // horizontal if requested
79 bool bHasHScrollbar = (style & wxHSCROLL) != 0;
80
81 // create our control...
82 m_text = gtk_text_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
83
84 // ... and put into the upper left hand corner of the table
85 m_widget = gtk_table_new(bHasHScrollbar ? 2 : 1, 2, FALSE);
86 gtk_table_attach(GTK_TABLE(m_widget), m_text, 0, 1, 0, 1,
87 GTK_FILL | GTK_EXPAND,
88 GTK_FILL | GTK_EXPAND | GTK_SHRINK,
89 0, 0);
90
91 // put the horizontal scrollbar in the lower left hand corner
92 if (bHasHScrollbar)
93 {
94 GtkWidget *hscrollbar = gtk_hscrollbar_new(GTK_TEXT(m_text)->hadj);
95 gtk_table_attach(GTK_TABLE(m_widget), hscrollbar, 0, 1, 1, 2,
96 GTK_EXPAND | GTK_FILL,
97 GTK_FILL,
98 0, 0);
99 gtk_widget_show(hscrollbar);
100 }
101
102 // finally, put the vertical scrollbar in the upper right corner
103 GtkWidget *vscrollbar = gtk_vscrollbar_new(GTK_TEXT(m_text)->vadj);
104 gtk_table_attach(GTK_TABLE(m_widget), vscrollbar, 1, 2, 0, 1,
105 GTK_FILL,
106 GTK_EXPAND | GTK_FILL | GTK_SHRINK,
107 0, 0);
108 gtk_widget_show( vscrollbar );
109 }
110 else
111 {
112 // a single-line text control: no need for scrollbars
113 m_widget =
114 m_text = gtk_entry_new();
115 }
116
117 wxSize newSize = size;
118 if (newSize.x == -1) newSize.x = 80;
119 if (newSize.y == -1) newSize.y = 26;
120 SetSize( newSize.x, newSize.y );
121
122 PostCreation();
123
124 if (bMultiLine)
125 {
126 gtk_widget_realize(m_text);
127 gtk_widget_show(m_text);
128 }
129
130 // we want to be notified about text changes
131 gtk_signal_connect(GTK_OBJECT(m_text), "changed",
132 GTK_SIGNAL_FUNC(gtk_text_changed_callback),
133 (gpointer)this);
134
135 if (!value.IsNull())
136 {
137 gint tmp = 0;
138 gtk_editable_insert_text( GTK_EDITABLE(m_text), value, value.Length(), &tmp );
139 }
140
141 if (style & wxTE_READONLY)
142 {
143 }
144 else
145 {
146 if (bMultiLine)
147 gtk_text_set_editable( GTK_TEXT(m_text), 1 );
148 }
149
150 Show( TRUE );
151
152 SetBackgroundColour( parent->GetBackgroundColour() );
153
154 return TRUE;
155 }
156
157 wxString wxTextCtrl::GetValue() const
158 {
159 wxCHECK_MSG( m_text != NULL, "", "invalid text ctrl" );
160
161 wxString tmp;
162 if (m_windowStyle & wxTE_MULTILINE)
163 {
164 gint len = gtk_text_get_length( GTK_TEXT(m_text) );
165 char *text = gtk_editable_get_chars( GTK_EDITABLE(m_text), 0, len );
166 tmp = text;
167 g_free( text );
168 }
169 else
170 {
171 tmp = gtk_entry_get_text( GTK_ENTRY(m_text) );
172 }
173 return tmp;
174 }
175
176 void wxTextCtrl::SetValue( const wxString &value )
177 {
178 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
179
180 wxString tmp = "";
181 if (!value.IsNull()) tmp = value;
182 if (m_windowStyle & wxTE_MULTILINE)
183 {
184 gint len = gtk_text_get_length( GTK_TEXT(m_text) );
185 gtk_editable_delete_text( GTK_EDITABLE(m_text), 0, len );
186 len = 0;
187 gtk_editable_insert_text( GTK_EDITABLE(m_text), tmp, tmp.Length(), &len );
188 }
189 else
190 {
191 gtk_entry_set_text( GTK_ENTRY(m_text), tmp );
192 }
193 }
194
195 void wxTextCtrl::WriteText( const wxString &text )
196 {
197 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
198
199 if (text.IsNull()) return;
200
201 if (m_windowStyle & wxTE_MULTILINE)
202 {
203 gint len = gtk_text_get_length( GTK_TEXT(m_text) );
204 gtk_editable_insert_text( GTK_EDITABLE(m_text), text, text.Length(), &len );
205 }
206 else
207 {
208 gtk_entry_append_text( GTK_ENTRY(m_text), text );
209 }
210 }
211
212 bool wxTextCtrl::LoadFile( const wxString &file )
213 {
214 wxCHECK_MSG( m_text != NULL, FALSE, "invalid text ctrl" );
215
216 if (!wxFileExists(file)) return FALSE;
217
218 Clear();
219
220 FILE *fp = NULL;
221 struct stat statb;
222
223 if ((stat ((char*) (const char*) file, &statb) == -1) || (statb.st_mode & S_IFMT) != S_IFREG ||
224 !(fp = fopen ((char*) (const char*) file, "r")))
225 {
226 return FALSE;
227 }
228 else
229 {
230 gint len = statb.st_size;
231 char *text;
232 if (!(text = (char*)malloc ((unsigned) (len + 1))))
233 {
234 fclose (fp);
235 return FALSE;
236 }
237 if (fread (text, sizeof (char), len, fp) != (size_t) len)
238 {
239 }
240 fclose (fp);
241
242 text[len] = 0;
243
244 if (m_windowStyle & wxTE_MULTILINE)
245 {
246 gtk_editable_insert_text( GTK_EDITABLE(m_text), text, 0, &len );
247 }
248 else
249 {
250 gtk_entry_set_text( GTK_ENTRY(m_text), text );
251 }
252
253 free (text);
254 m_modified = FALSE;
255 return TRUE;
256 }
257 return FALSE;
258 }
259
260 bool wxTextCtrl::SaveFile( const wxString &file )
261 {
262 wxCHECK_MSG( m_text != NULL, FALSE, "invalid text ctrl" );
263
264 if (file == "") return FALSE;
265
266 FILE *fp;
267
268 if (!(fp = fopen ((char*) (const char*) file, "w")))
269 {
270 return FALSE;
271 }
272 else
273 {
274 char *text = NULL;
275 gint len = 0;
276
277 if (m_windowStyle & wxTE_MULTILINE)
278 {
279 len = gtk_text_get_length( GTK_TEXT(m_text) );
280 text = gtk_editable_get_chars( GTK_EDITABLE(m_text), 0, len );
281 }
282 else
283 {
284 text = gtk_entry_get_text( GTK_ENTRY(m_text) );
285 }
286
287 if (fwrite (text, sizeof (char), len, fp) != (size_t) len)
288 {
289 // Did not write whole file
290 }
291
292 // Make sure newline terminates the file
293 if (text[len - 1] != '\n')
294 fputc ('\n', fp);
295
296 fclose (fp);
297
298 if (m_windowStyle & wxTE_MULTILINE) g_free( text );
299
300 m_modified = FALSE;
301 return TRUE;
302 }
303
304 return TRUE;
305 }
306
307 wxString wxTextCtrl::GetLineText( long lineNo ) const
308 {
309 if (m_windowStyle & wxTE_MULTILINE)
310 {
311 gint len = gtk_text_get_length( GTK_TEXT(m_text) );
312 char *text = gtk_editable_get_chars( GTK_EDITABLE(m_text), 0, len );
313
314 if (text)
315 {
316 wxString buf("");
317 long i;
318 int currentLine = 0;
319 for (i = 0; currentLine != lineNo && text[i]; i++ )
320 if (text[i] == '\n')
321 currentLine++;
322 // Now get the text
323 int j;
324 for (j = 0; text[i] && text[i] != '\n'; i++, j++ )
325 buf += text[i];
326
327 g_free( text );
328 return buf;
329 }
330 else
331 return wxEmptyString;
332 }
333 else
334 {
335 if (lineNo == 0) return GetValue();
336 return wxEmptyString;
337 }
338 }
339
340 void wxTextCtrl::OnDropFiles( wxDropFilesEvent &WXUNUSED(event) )
341 {
342 wxFAIL_MSG( "wxTextCtrl::GetLineText( lineNo ) not implemented" );
343 }
344
345 long wxTextCtrl::PositionToXY( long WXUNUSED(pos), long *WXUNUSED(x), long *WXUNUSED(y) ) const
346 {
347 wxFAIL_MSG( "wxTextCtrl::XYToPosition not implemented" );
348
349 return 0;
350 }
351
352 long wxTextCtrl::XYToPosition( long WXUNUSED(x), long WXUNUSED(y) ) const
353 {
354 wxFAIL_MSG( "wxTextCtrl::XYToPosition not implemented" );
355
356 return 0;
357 }
358
359 int wxTextCtrl::GetLineLength(long lineNo) const
360 {
361 wxString str = GetLineText (lineNo);
362 return (int) str.Length();
363 }
364
365 int wxTextCtrl::GetNumberOfLines() const
366 {
367 if (m_windowStyle & wxTE_MULTILINE)
368 {
369 gint len = gtk_text_get_length( GTK_TEXT(m_text) );
370 char *text = gtk_editable_get_chars( GTK_EDITABLE(m_text), 0, len );
371
372 if (text)
373 {
374 int currentLine = 0;
375 for (int i = 0; i < len; i++ )
376 if (text[i] == '\n')
377 currentLine++;
378
379 g_free( text );
380 return currentLine;
381 }
382 else
383 return 0;
384 }
385 else
386 {
387 return 1;
388 }
389 }
390
391 void wxTextCtrl::SetInsertionPoint( long pos )
392 {
393 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
394
395 int tmp = (int) pos;
396 if (m_windowStyle & wxTE_MULTILINE)
397 gtk_text_set_point( GTK_TEXT(m_text), tmp );
398 else
399 gtk_entry_set_position( GTK_ENTRY(m_text), tmp );
400 }
401
402 void wxTextCtrl::SetInsertionPointEnd()
403 {
404 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
405
406 int pos = 0;
407 if (m_windowStyle & wxTE_MULTILINE)
408 pos = gtk_text_get_length( GTK_TEXT(m_text) );
409 else
410 pos = GTK_ENTRY(m_text)->text_length;
411 SetInsertionPoint( pos-1 );
412 }
413
414 void wxTextCtrl::SetEditable( bool editable )
415 {
416 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
417
418 if (m_windowStyle & wxTE_MULTILINE)
419 gtk_text_set_editable( GTK_TEXT(m_text), editable );
420 else
421 gtk_entry_set_editable( GTK_ENTRY(m_text), editable );
422 }
423
424 void wxTextCtrl::SetSelection( long from, long to )
425 {
426 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
427
428 gtk_editable_select_region( GTK_EDITABLE(m_text), (gint)from, (gint)to );
429 }
430
431 void wxTextCtrl::ShowPosition( long WXUNUSED(pos) )
432 {
433 wxFAIL_MSG( "wxTextCtrl::ShowPosition not implemented" );
434 }
435
436 long wxTextCtrl::GetInsertionPoint() const
437 {
438 wxCHECK_MSG( m_text != NULL, 0, "invalid text ctrl" );
439
440 return (long) GTK_EDITABLE(m_text)->current_pos;
441 }
442
443 long wxTextCtrl::GetLastPosition() const
444 {
445 wxCHECK_MSG( m_text != NULL, 0, "invalid text ctrl" );
446
447 int pos = 0;
448 if (m_windowStyle & wxTE_MULTILINE)
449 pos = gtk_text_get_length( GTK_TEXT(m_text) );
450 else
451 pos = GTK_ENTRY(m_text)->text_length;
452 return (long)pos-1;
453 }
454
455 void wxTextCtrl::Remove( long from, long to )
456 {
457 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
458
459 gtk_editable_delete_text( GTK_EDITABLE(m_text), (gint)from, (gint)to );
460 }
461
462 void wxTextCtrl::Replace( long from, long to, const wxString &value )
463 {
464 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
465
466 gtk_editable_delete_text( GTK_EDITABLE(m_text), (gint)from, (gint)to );
467 if (value.IsNull()) return;
468 gint pos = (gint)to;
469 gtk_editable_insert_text( GTK_EDITABLE(m_text), value, value.Length(), &pos );
470 }
471
472 void wxTextCtrl::Cut()
473 {
474 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
475
476 #if (GTK_MINOR_VERSION == 1)
477 gtk_editable_cut_clipboard( GTK_EDITABLE(m_text) );
478 #else
479 gtk_editable_cut_clipboard( GTK_EDITABLE(m_text), 0 );
480 #endif
481 }
482
483 void wxTextCtrl::Copy()
484 {
485 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
486
487 #if (GTK_MINOR_VERSION == 1)
488 gtk_editable_copy_clipboard( GTK_EDITABLE(m_text) );
489 #else
490 gtk_editable_copy_clipboard( GTK_EDITABLE(m_text), 0 );
491 #endif
492 }
493
494 void wxTextCtrl::Paste()
495 {
496 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
497
498 #if (GTK_MINOR_VERSION == 1)
499 gtk_editable_paste_clipboard( GTK_EDITABLE(m_text) );
500 #else
501 gtk_editable_paste_clipboard( GTK_EDITABLE(m_text), 0 );
502 #endif
503 }
504
505 void wxTextCtrl::Clear()
506 {
507 SetValue( "" );
508 }
509
510 void wxTextCtrl::OnChar( wxKeyEvent &key_event )
511 {
512 if ((key_event.KeyCode() == WXK_RETURN) && (m_windowStyle & wxPROCESS_ENTER))
513 {
514 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
515 event.SetEventObject(this);
516 if (GetEventHandler()->ProcessEvent(event)) return;
517 }
518 else if (key_event.KeyCode() == WXK_TAB)
519 {
520 wxNavigationKeyEvent event;
521 event.SetDirection( key_event.m_shiftDown );
522 event.SetWindowChange(FALSE);
523 event.SetEventObject(this);
524
525 if (GetEventHandler()->ProcessEvent(event)) return;
526 }
527 key_event.Skip();
528 }
529
530 int wxTextCtrl::overflow( int WXUNUSED(c) )
531 {
532 int len = pptr() - pbase();
533 char *txt = new char[len+1];
534 strncpy(txt, pbase(), len);
535 txt[len] = '\0';
536 (*this) << txt;
537 setp(pbase(), epptr());
538 delete[] txt;
539 return EOF;
540 }
541
542 int wxTextCtrl::sync()
543 {
544 int len = pptr() - pbase();
545 char *txt = new char[len+1];
546 strncpy(txt, pbase(), len);
547 txt[len] = '\0';
548 (*this) << txt;
549 setp(pbase(), epptr());
550 delete[] txt;
551 return 0;
552 }
553
554 int wxTextCtrl::underflow()
555 {
556 return EOF;
557 }
558
559 wxTextCtrl& wxTextCtrl::operator<<(const wxString& s)
560 {
561 WriteText(s);
562 return *this;
563 }
564
565 wxTextCtrl& wxTextCtrl::operator<<(float f)
566 {
567 static char buf[100];
568 sprintf(buf, "%.2f", f);
569 WriteText(buf);
570 return *this;
571 }
572
573 wxTextCtrl& wxTextCtrl::operator<<(double d)
574 {
575 static char buf[100];
576 sprintf(buf, "%.2f", d);
577 WriteText(buf);
578 return *this;
579 }
580
581 wxTextCtrl& wxTextCtrl::operator<<(int i)
582 {
583 static char buf[100];
584 sprintf(buf, "%i", i);
585 WriteText(buf);
586 return *this;
587 }
588
589 wxTextCtrl& wxTextCtrl::operator<<(long i)
590 {
591 static char buf[100];
592 sprintf(buf, "%ld", i);
593 WriteText(buf);
594 return *this;
595 }
596
597 wxTextCtrl& wxTextCtrl::operator<<(const char c)
598 {
599 char buf[2];
600
601 buf[0] = c;
602 buf[1] = 0;
603 WriteText(buf);
604 return *this;
605 }
606
607 GtkWidget* wxTextCtrl::GetConnectWidget()
608 {
609 return GTK_WIDGET(m_text);
610 }
611
612 bool wxTextCtrl::IsOwnGtkWindow( GdkWindow *window )
613 {
614 if (m_windowStyle & wxTE_MULTILINE)
615 return (window == GTK_TEXT(m_text)->text_area);
616 else
617 return (window == GTK_ENTRY(m_text)->text_area);
618 }
619
620 void wxTextCtrl::SetFont( const wxFont &font )
621 {
622 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
623
624 wxControl::SetFont( font );
625
626 // doesn't work
627 }
628
629 void wxTextCtrl::SetBackgroundColour( const wxColour &colour )
630 {
631 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
632
633 wxControl::SetBackgroundColour( colour );
634
635 if (!m_backgroundColour.Ok()) return;
636
637 if (m_windowStyle & wxTE_MULTILINE)
638 {
639 GdkWindow *window = GTK_TEXT(m_text)->text_area;
640 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
641 gdk_window_set_background( window, m_backgroundColour.GetColor() );
642 gdk_window_clear( window );
643 }
644 else
645 {
646 gtk_widget_set_style( m_text, m_widgetStyle );
647 }
648 }
649