]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/textctrl.cpp
5fd1f455a198de10eaaabd5b16d0b84ef6b30c01
[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 #include "wx/settings.h"
18
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <ctype.h>
22
23 #include "gdk/gdk.h"
24 #include "gtk/gtk.h"
25 #include "gdk/gdkkeysyms.h"
26
27 //-----------------------------------------------------------------------------
28 // data
29 //-----------------------------------------------------------------------------
30
31 extern bool g_blockEventsOnDrag;
32
33 //-----------------------------------------------------------------------------
34 // "changed"
35 //-----------------------------------------------------------------------------
36
37 static void
38 gtk_text_changed_callback( GtkWidget *WXUNUSED(widget), wxTextCtrl *win )
39 {
40 win->SetModified();
41
42 win->CalculateScrollbar();
43
44 wxCommandEvent event( wxEVT_COMMAND_TEXT_UPDATED, win->m_windowId );
45 event.SetString( win->GetValue() );
46 event.SetEventObject( win );
47 win->GetEventHandler()->ProcessEvent( event );
48 }
49
50 //-----------------------------------------------------------------------------
51 // "size_allocate"
52 //-----------------------------------------------------------------------------
53
54 static void
55 gtk_text_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* WXUNUSED(alloc), wxTextCtrl *win )
56 {
57 win->CalculateScrollbar();
58 }
59
60 //-----------------------------------------------------------------------------
61 // wxTextCtrl
62 //-----------------------------------------------------------------------------
63
64 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl,wxControl)
65
66 BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
67 EVT_CHAR(wxTextCtrl::OnChar)
68
69 EVT_MENU(wxID_CUT, wxTextCtrl::OnCut)
70 EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy)
71 EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste)
72 EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo)
73 EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo)
74
75 EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut)
76 EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy)
77 EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste)
78 EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo)
79 EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo)
80 END_EVENT_TABLE()
81
82 #ifndef NO_TEXT_WINDOW_STREAM
83 wxTextCtrl::wxTextCtrl() : streambuf()
84 {
85 if (allocate()) setp(base(),ebuf());
86
87 m_modified = FALSE;
88 }
89 #else
90 wxTextCtrl::wxTextCtrl()
91 {
92 m_modified = FALSE;
93 }
94 #endif
95
96 #ifndef NO_TEXT_WINDOW_STREAM
97 wxTextCtrl::wxTextCtrl( wxWindow *parent, wxWindowID id, const wxString &value,
98 const wxPoint &pos, const wxSize &size,
99 int style, const wxValidator& validator, const wxString &name ) : streambuf()
100 {
101 if (allocate()) setp(base(),ebuf());
102
103 m_modified = FALSE;
104 Create( parent, id, value, pos, size, style, validator, name );
105 }
106 #else
107 wxTextCtrl::wxTextCtrl( wxWindow *parent, wxWindowID id, const wxString &value,
108 const wxPoint &pos, const wxSize &size,
109 int style, const wxValidator& validator, const wxString &name )
110 {
111 m_modified = FALSE;
112 Create( parent, id, value, pos, size, style, validator, name );
113 }
114 #endif
115
116 bool wxTextCtrl::Create( wxWindow *parent, wxWindowID id, const wxString &value,
117 const wxPoint &pos, const wxSize &size,
118 int style, const wxValidator& validator, const wxString &name )
119 {
120 m_needParent = TRUE;
121 m_acceptsFocus = TRUE;
122
123 PreCreation( parent, id, pos, size, style, name );
124
125 SetValidator( validator );
126
127 m_vScrollbarVisible = TRUE;
128
129 bool multi_line = (style & wxTE_MULTILINE) != 0;
130 if ( multi_line )
131 {
132 // a multi-line edit control: create a vertical scrollbar by default and
133 // horizontal if requested
134 bool bHasHScrollbar = (style & wxHSCROLL) != 0;
135
136 // create our control...
137 m_text = gtk_text_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
138
139 // ... and put into the upper left hand corner of the table
140 m_widget = gtk_table_new(bHasHScrollbar ? 2 : 1, 2, FALSE);
141 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
142
143 gtk_table_attach( GTK_TABLE(m_widget), m_text, 0, 1, 0, 1,
144 (GtkAttachOptions)(GTK_FILL | GTK_EXPAND | GTK_SHRINK),
145 (GtkAttachOptions)(GTK_FILL | GTK_EXPAND | GTK_SHRINK),
146 0, 0);
147
148 // put the horizontal scrollbar in the lower left hand corner
149 if (bHasHScrollbar)
150 {
151 GtkWidget *hscrollbar = gtk_hscrollbar_new(GTK_TEXT(m_text)->hadj);
152 GTK_WIDGET_UNSET_FLAGS( hscrollbar, GTK_CAN_FOCUS );
153
154 gtk_table_attach(GTK_TABLE(m_widget), hscrollbar, 0, 1, 1, 2,
155 (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
156 GTK_FILL,
157 0, 0);
158 gtk_widget_show(hscrollbar);
159 }
160
161 // finally, put the vertical scrollbar in the upper right corner
162 m_vScrollbar = gtk_vscrollbar_new( GTK_TEXT(m_text)->vadj );
163 GTK_WIDGET_UNSET_FLAGS( m_vScrollbar, GTK_CAN_FOCUS );
164
165 gtk_table_attach(GTK_TABLE(m_widget), m_vScrollbar, 1, 2, 0, 1,
166 GTK_FILL,
167 (GtkAttachOptions)(GTK_EXPAND | GTK_FILL | GTK_SHRINK),
168 0, 0);
169 gtk_widget_show( m_vScrollbar );
170
171 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
172 GTK_SIGNAL_FUNC(gtk_text_size_callback), (gpointer)this );
173 }
174 else
175 {
176 // a single-line text control: no need for scrollbars
177 m_widget =
178 m_text = gtk_entry_new();
179 }
180
181 wxSize newSize = size;
182 if (newSize.x == -1) newSize.x = 80;
183 if (newSize.y == -1) newSize.y = 26;
184 SetSize( newSize.x, newSize.y );
185
186 m_parent->AddChild( this );
187
188 (m_parent->m_insertCallback)( m_parent, this );
189
190 PostCreation();
191
192 if (multi_line)
193 {
194 gtk_widget_realize(m_text);
195 gtk_widget_show(m_text);
196 }
197
198 // we want to be notified about text changes
199 gtk_signal_connect( GTK_OBJECT(m_text), "changed",
200 GTK_SIGNAL_FUNC(gtk_text_changed_callback), (gpointer)this);
201
202 if (!value.IsEmpty())
203 {
204 gint tmp = 0;
205 gtk_editable_insert_text( GTK_EDITABLE(m_text), value, value.Length(), &tmp );
206
207 if (multi_line)
208 {
209 /* bring editable's cursor uptodate. bug in GTK. */
210
211 GTK_EDITABLE(m_text)->current_pos = gtk_text_get_point( GTK_TEXT(m_text) );
212 }
213 }
214
215 if (style & wxTE_PASSWORD)
216 {
217 if (!multi_line)
218 gtk_entry_set_visibility( GTK_ENTRY(m_text), FALSE );
219 }
220
221 if (style & wxTE_READONLY)
222 {
223 if (!multi_line)
224 gtk_entry_set_editable( GTK_ENTRY(m_text), FALSE );
225 }
226 else
227 {
228 if (multi_line)
229 gtk_text_set_editable( GTK_TEXT(m_text), 1 );
230 }
231
232 Show( TRUE );
233
234 SetBackgroundColour( parent->GetBackgroundColour() );
235 SetForegroundColour( parent->GetForegroundColour() );
236
237 return TRUE;
238 }
239
240 void wxTextCtrl::CalculateScrollbar()
241 {
242 if ((m_windowStyle & wxTE_MULTILINE) == 0) return;
243
244 GtkAdjustment *adj = GTK_TEXT(m_text)->vadj;
245
246 if (adj->upper - adj->page_size < 0.8)
247 {
248 if (m_vScrollbarVisible)
249 {
250 gtk_widget_hide( m_vScrollbar );
251
252 m_vScrollbarVisible = FALSE;
253 }
254 }
255 else
256 {
257 if (!m_vScrollbarVisible)
258 {
259 gtk_widget_show( m_vScrollbar );
260
261 m_vScrollbarVisible = TRUE;
262 }
263 }
264 }
265
266 wxString wxTextCtrl::GetValue() const
267 {
268 wxCHECK_MSG( m_text != NULL, "", "invalid text ctrl" );
269
270 wxString tmp;
271 if (m_windowStyle & wxTE_MULTILINE)
272 {
273 gint len = gtk_text_get_length( GTK_TEXT(m_text) );
274 char *text = gtk_editable_get_chars( GTK_EDITABLE(m_text), 0, len );
275 tmp = text;
276 g_free( text );
277 }
278 else
279 {
280 tmp = gtk_entry_get_text( GTK_ENTRY(m_text) );
281 }
282 return tmp;
283 }
284
285 void wxTextCtrl::SetValue( const wxString &value )
286 {
287 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
288
289 wxString tmp = "";
290 if (!value.IsNull()) tmp = value;
291 if (m_windowStyle & wxTE_MULTILINE)
292 {
293 gint len = gtk_text_get_length( GTK_TEXT(m_text) );
294 gtk_editable_delete_text( GTK_EDITABLE(m_text), 0, len );
295 len = 0;
296 gtk_editable_insert_text( GTK_EDITABLE(m_text), tmp, tmp.Length(), &len );
297 }
298 else
299 {
300 gtk_entry_set_text( GTK_ENTRY(m_text), tmp );
301 }
302 }
303
304 void wxTextCtrl::WriteText( const wxString &text )
305 {
306 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
307
308 if (text.IsNull()) return;
309
310 if (m_windowStyle & wxTE_MULTILINE)
311 {
312 /* this moves the cursor pos to behind the inserted text */
313 gint len = GTK_EDITABLE(m_text)->current_pos;
314
315 gtk_editable_insert_text( GTK_EDITABLE(m_text), text, text.Length(), &len );
316
317 /* bring editable's cursor uptodate. bug in GTK. */
318 GTK_EDITABLE(m_text)->current_pos = gtk_text_get_point( GTK_TEXT(m_text) );
319 }
320 else
321 {
322 /* this moves the cursor pos to behind the inserted text */
323 gint len = GTK_EDITABLE(m_text)->current_pos;
324 gtk_editable_insert_text( GTK_EDITABLE(m_text), text, text.Length(), &len );
325
326 /* bring editable's cursor uptodate. bug in GTK. */
327 GTK_EDITABLE(m_text)->current_pos += text.Len();
328
329 /* bring entry's cursor uptodate. bug in GTK. */
330 gtk_entry_set_position( GTK_ENTRY(m_text), GTK_EDITABLE(m_text)->current_pos );
331 }
332 }
333
334 void wxTextCtrl::AppendText( const wxString &text )
335 {
336 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
337
338 if (m_windowStyle & wxTE_MULTILINE)
339 {
340 /* we'll insert at the last position */
341 gint len = gtk_text_get_length( GTK_TEXT(m_text) );
342 gtk_editable_insert_text( GTK_EDITABLE(m_text), text, text.Length(), &len );
343
344 /* bring editable's cursor uptodate. bug in GTK. */
345 GTK_EDITABLE(m_text)->current_pos = gtk_text_get_point( GTK_TEXT(m_text) );
346 }
347 else
348 {
349 gtk_entry_append_text( GTK_ENTRY(m_text), text );
350 }
351 }
352
353 bool wxTextCtrl::LoadFile( const wxString &file )
354 {
355 wxCHECK_MSG( m_text != NULL, FALSE, "invalid text ctrl" );
356
357 if (!wxFileExists(file)) return FALSE;
358
359 Clear();
360
361 FILE *fp = (FILE*) NULL;
362 struct stat statb;
363
364 if ((stat ((char*) (const char*) file, &statb) == -1) || (statb.st_mode & S_IFMT) != S_IFREG ||
365 !(fp = fopen ((char*) (const char*) file, "r")))
366 {
367 return FALSE;
368 }
369 else
370 {
371 gint len = statb.st_size;
372 char *text;
373 if (!(text = (char*)malloc ((unsigned) (len + 1))))
374 {
375 fclose (fp);
376 return FALSE;
377 }
378 if (fread (text, sizeof (char), len, fp) != (size_t) len)
379 {
380 }
381 fclose (fp);
382
383 text[len] = 0;
384
385 if (m_windowStyle & wxTE_MULTILINE)
386 {
387 gint pos = 0;
388 gtk_editable_insert_text( GTK_EDITABLE(m_text), text, len, &pos );
389 }
390 else
391 {
392 gtk_entry_set_text( GTK_ENTRY(m_text), text );
393 }
394
395 free (text);
396 m_modified = FALSE;
397 return TRUE;
398 }
399 return FALSE;
400 }
401
402 bool wxTextCtrl::SaveFile( const wxString &file )
403 {
404 wxCHECK_MSG( m_text != NULL, FALSE, "invalid text ctrl" );
405
406 if (file == "") return FALSE;
407
408 FILE *fp;
409
410 if (!(fp = fopen ((char*) (const char*) file, "w")))
411 {
412 return FALSE;
413 }
414 else
415 {
416 char *text = (char*) NULL;
417 gint len = 0;
418
419 if (m_windowStyle & wxTE_MULTILINE)
420 {
421 len = gtk_text_get_length( GTK_TEXT(m_text) );
422 text = gtk_editable_get_chars( GTK_EDITABLE(m_text), 0, len );
423 }
424 else
425 {
426 text = gtk_entry_get_text( GTK_ENTRY(m_text) );
427 }
428
429 if (fwrite (text, sizeof (char), len, fp) != (size_t) len)
430 {
431 // Did not write whole file
432 }
433
434 // Make sure newline terminates the file
435 if (text[len - 1] != '\n')
436 fputc ('\n', fp);
437
438 fclose (fp);
439
440 if (m_windowStyle & wxTE_MULTILINE) g_free( text );
441
442 m_modified = FALSE;
443 return TRUE;
444 }
445
446 return TRUE;
447 }
448
449 wxString wxTextCtrl::GetLineText( long lineNo ) const
450 {
451 if (m_windowStyle & wxTE_MULTILINE)
452 {
453 gint len = gtk_text_get_length( GTK_TEXT(m_text) );
454 char *text = gtk_editable_get_chars( GTK_EDITABLE(m_text), 0, len );
455
456 if (text)
457 {
458 wxString buf("");
459 long i;
460 int currentLine = 0;
461 for (i = 0; currentLine != lineNo && text[i]; i++ )
462 if (text[i] == '\n')
463 currentLine++;
464 // Now get the text
465 int j;
466 for (j = 0; text[i] && text[i] != '\n'; i++, j++ )
467 buf += text[i];
468
469 g_free( text );
470 return buf;
471 }
472 else
473 return wxEmptyString;
474 }
475 else
476 {
477 if (lineNo == 0) return GetValue();
478 return wxEmptyString;
479 }
480 }
481
482 void wxTextCtrl::OnDropFiles( wxDropFilesEvent &WXUNUSED(event) )
483 {
484 /* If you implement this, don't forget to update the documentation!
485 * (file docs/latex/wx/text.tex) */
486 wxFAIL_MSG( "wxTextCtrl::OnDropFiles not implemented" );
487 }
488
489 long wxTextCtrl::PositionToXY(long pos, long *x, long *y ) const
490 {
491 if ( m_windowStyle & wxTE_MULTILINE )
492 {
493 wxString text = GetValue();
494
495 // cast to prevent warning. But pos really should've been unsigned.
496 if( (unsigned long)pos > text.Len() )
497 return FALSE;
498
499 *x=0; // First Col
500 *y=0; // First Line
501
502 const char* stop = text.c_str() + pos;
503 for ( const char *p = text.c_str(); p < stop; p++ )
504 {
505 if (*p == '\n')
506 {
507 (*y)++;
508 *x=0;
509 }
510 else
511 (*x)++;
512 }
513 }
514 else // single line control
515 {
516 if ( pos <= GTK_ENTRY(m_text)->text_length )
517 {
518 *y = 0;
519 *x = pos;
520 }
521 else
522 {
523 // index out of bounds
524 return FALSE;
525 }
526 }
527
528 return TRUE;
529 }
530
531 long wxTextCtrl::XYToPosition(long x, long y ) const
532 {
533 if (!(m_windowStyle & wxTE_MULTILINE)) return 0;
534
535 long pos=0;
536 for( int i=0; i<y; i++ ) pos += GetLineLength(i) + 1; // one for '\n'
537
538 pos += x;
539 return pos;
540 }
541
542 int wxTextCtrl::GetLineLength(long lineNo) const
543 {
544 wxString str = GetLineText (lineNo);
545 return (int) str.Length();
546 }
547
548 int wxTextCtrl::GetNumberOfLines() const
549 {
550 if (m_windowStyle & wxTE_MULTILINE)
551 {
552 gint len = gtk_text_get_length( GTK_TEXT(m_text) );
553 char *text = gtk_editable_get_chars( GTK_EDITABLE(m_text), 0, len );
554
555 if (text)
556 {
557 int currentLine = 0;
558 for (int i = 0; i < len; i++ )
559 {
560 if (text[i] == '\n')
561 currentLine++;
562 }
563 g_free( text );
564
565 // currentLine is 0 based, add 1 to get number of lines
566 return currentLine + 1;
567 }
568 else
569 {
570 return 0;
571 }
572 }
573 else
574 {
575 return 1;
576 }
577 }
578
579 void wxTextCtrl::SetInsertionPoint( long pos )
580 {
581 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
582
583 if (m_windowStyle & wxTE_MULTILINE)
584 {
585 /* seems to be broken in GTK 1.0.X:
586 gtk_text_set_point( GTK_TEXT(m_text), (int)pos ); */
587
588 gtk_signal_disconnect_by_func( GTK_OBJECT(m_text),
589 GTK_SIGNAL_FUNC(gtk_text_changed_callback), (gpointer)this);
590
591 /* we fake a set_point by inserting and deleting. as the user
592 isn't supposed to get to know about thos non-sense, we
593 disconnect so that no events are sent to the user program. */
594
595 gint tmp = (gint)pos;
596 gtk_editable_insert_text( GTK_EDITABLE(m_text), " ", 1, &tmp );
597 gtk_editable_delete_text( GTK_EDITABLE(m_text), tmp-1, tmp );
598
599 gtk_signal_connect( GTK_OBJECT(m_text), "changed",
600 GTK_SIGNAL_FUNC(gtk_text_changed_callback), (gpointer)this);
601
602 /* bring editable's cursor uptodate. another bug in GTK. */
603
604 GTK_EDITABLE(m_text)->current_pos = gtk_text_get_point( GTK_TEXT(m_text) );
605 }
606 else
607 {
608 gtk_entry_set_position( GTK_ENTRY(m_text), (int)pos );
609
610 /* bring editable's cursor uptodate. bug in GTK. */
611
612 GTK_EDITABLE(m_text)->current_pos = pos;
613 }
614 }
615
616 void wxTextCtrl::SetInsertionPointEnd()
617 {
618 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
619
620 if (m_windowStyle & wxTE_MULTILINE)
621 SetInsertionPoint(gtk_text_get_length(GTK_TEXT(m_text)));
622 else
623 gtk_entry_set_position( GTK_ENTRY(m_text), -1 );
624 }
625
626 void wxTextCtrl::SetEditable( bool editable )
627 {
628 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
629
630 if (m_windowStyle & wxTE_MULTILINE)
631 gtk_text_set_editable( GTK_TEXT(m_text), editable );
632 else
633 gtk_entry_set_editable( GTK_ENTRY(m_text), editable );
634 }
635
636 void wxTextCtrl::SetSelection( long from, long to )
637 {
638 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
639
640 gtk_editable_select_region( GTK_EDITABLE(m_text), (gint)from, (gint)to );
641 }
642
643 void wxTextCtrl::ShowPosition( long WXUNUSED(pos) )
644 {
645 wxFAIL_MSG( "wxTextCtrl::ShowPosition not implemented" );
646 }
647
648 long wxTextCtrl::GetInsertionPoint() const
649 {
650 wxCHECK_MSG( m_text != NULL, 0, "invalid text ctrl" );
651
652 return (long) GTK_EDITABLE(m_text)->current_pos;
653 }
654
655 long wxTextCtrl::GetLastPosition() const
656 {
657 wxCHECK_MSG( m_text != NULL, 0, "invalid text ctrl" );
658
659 int pos = 0;
660 if (m_windowStyle & wxTE_MULTILINE)
661 pos = gtk_text_get_length( GTK_TEXT(m_text) );
662 else
663 pos = GTK_ENTRY(m_text)->text_length;
664
665 return (long)pos;
666 }
667
668 void wxTextCtrl::Remove( long from, long to )
669 {
670 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
671
672 gtk_editable_delete_text( GTK_EDITABLE(m_text), (gint)from, (gint)to );
673 }
674
675 void wxTextCtrl::Replace( long from, long to, const wxString &value )
676 {
677 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
678
679 gtk_editable_delete_text( GTK_EDITABLE(m_text), (gint)from, (gint)to );
680 if (value.IsNull()) return;
681 gint pos = (gint)from;
682 gtk_editable_insert_text( GTK_EDITABLE(m_text), value, value.Length(), &pos );
683 }
684
685 void wxTextCtrl::Cut()
686 {
687 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
688
689 #if (GTK_MINOR_VERSION > 0)
690 gtk_editable_cut_clipboard( GTK_EDITABLE(m_text) );
691 #else
692 gtk_editable_cut_clipboard( GTK_EDITABLE(m_text), 0 );
693 #endif
694 }
695
696 void wxTextCtrl::Copy()
697 {
698 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
699
700 #if (GTK_MINOR_VERSION > 0)
701 gtk_editable_copy_clipboard( GTK_EDITABLE(m_text) );
702 #else
703 gtk_editable_copy_clipboard( GTK_EDITABLE(m_text), 0 );
704 #endif
705 }
706
707 void wxTextCtrl::Paste()
708 {
709 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
710
711 #if (GTK_MINOR_VERSION > 0)
712 gtk_editable_paste_clipboard( GTK_EDITABLE(m_text) );
713 #else
714 gtk_editable_paste_clipboard( GTK_EDITABLE(m_text), 0 );
715 #endif
716 }
717
718 bool wxTextCtrl::CanCopy() const
719 {
720 // Can copy if there's a selection
721 long from, to;
722 GetSelection(& from, & to);
723 return (from != to) ;
724 }
725
726 bool wxTextCtrl::CanCut() const
727 {
728 // Can cut if there's a selection
729 long from, to;
730 GetSelection(& from, & to);
731 return (from != to) ;
732 }
733
734 bool wxTextCtrl::CanPaste() const
735 {
736 return IsEditable() ;
737 }
738
739 // Undo/redo
740 void wxTextCtrl::Undo()
741 {
742 // TODO
743 wxFAIL_MSG( "wxTextCtrl::Undo not implemented" );
744 }
745
746 void wxTextCtrl::Redo()
747 {
748 // TODO
749 wxFAIL_MSG( "wxTextCtrl::Redo not implemented" );
750 }
751
752 bool wxTextCtrl::CanUndo() const
753 {
754 // TODO
755 wxFAIL_MSG( "wxTextCtrl::CanUndo not implemented" );
756 return FALSE;
757 }
758
759 bool wxTextCtrl::CanRedo() const
760 {
761 // TODO
762 wxFAIL_MSG( "wxTextCtrl::CanRedo not implemented" );
763 return FALSE;
764 }
765
766 // If the return values from and to are the same, there is no
767 // selection.
768 void wxTextCtrl::GetSelection(long* from, long* to) const
769 {
770 // TODO
771 *from = 0;
772 *to = 0;
773 wxFAIL_MSG( "wxTextCtrl::GetSelection not implemented" );
774 }
775
776 bool wxTextCtrl::IsEditable() const
777 {
778 // TODO
779 wxFAIL_MSG( "wxTextCtrl::IsEditable not implemented" );
780 return FALSE;
781 }
782
783 void wxTextCtrl::Clear()
784 {
785 SetValue( "" );
786 }
787
788 void wxTextCtrl::OnChar( wxKeyEvent &key_event )
789 {
790 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
791
792 if ((key_event.KeyCode() == WXK_RETURN) && (m_windowStyle & wxPROCESS_ENTER))
793 {
794 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
795 event.SetEventObject(this);
796 if (GetEventHandler()->ProcessEvent(event)) return;
797 }
798
799 key_event.Skip();
800 }
801
802 #ifndef NO_TEXT_WINDOW_STREAM
803 int wxTextCtrl::overflow( int WXUNUSED(c) )
804 {
805 int len = pptr() - pbase();
806 char *txt = new char[len+1];
807 strncpy(txt, pbase(), len);
808 txt[len] = '\0';
809 (*this) << txt;
810 setp(pbase(), epptr());
811 delete[] txt;
812 return EOF;
813 }
814
815 int wxTextCtrl::sync()
816 {
817 int len = pptr() - pbase();
818 char *txt = new char[len+1];
819 strncpy(txt, pbase(), len);
820 txt[len] = '\0';
821 (*this) << txt;
822 setp(pbase(), epptr());
823 delete[] txt;
824 return 0;
825 }
826
827 int wxTextCtrl::underflow()
828 {
829 return EOF;
830 }
831
832 wxTextCtrl& wxTextCtrl::operator<<(const wxString& s)
833 {
834 AppendText(s);
835 return *this;
836 }
837
838 wxTextCtrl& wxTextCtrl::operator<<(float f)
839 {
840 static char buf[100];
841 sprintf(buf, "%.2f", f);
842 AppendText(buf);
843 return *this;
844 }
845
846 wxTextCtrl& wxTextCtrl::operator<<(double d)
847 {
848 static char buf[100];
849 sprintf(buf, "%.2f", d);
850 AppendText(buf);
851 return *this;
852 }
853
854 wxTextCtrl& wxTextCtrl::operator<<(int i)
855 {
856 static char buf[100];
857 sprintf(buf, "%i", i);
858 AppendText(buf);
859 return *this;
860 }
861
862 wxTextCtrl& wxTextCtrl::operator<<(long i)
863 {
864 static char buf[100];
865 sprintf(buf, "%ld", i);
866 AppendText(buf);
867 return *this;
868 }
869
870 wxTextCtrl& wxTextCtrl::operator<<(const char c)
871 {
872 char buf[2];
873
874 buf[0] = c;
875 buf[1] = 0;
876 AppendText(buf);
877 return *this;
878 }
879 #endif
880
881 GtkWidget* wxTextCtrl::GetConnectWidget()
882 {
883 return GTK_WIDGET(m_text);
884 }
885
886 bool wxTextCtrl::IsOwnGtkWindow( GdkWindow *window )
887 {
888 if (m_windowStyle & wxTE_MULTILINE)
889 return (window == GTK_TEXT(m_text)->text_area);
890 else
891 return (window == GTK_ENTRY(m_text)->text_area);
892 }
893
894 void wxTextCtrl::SetFont( const wxFont &WXUNUSED(font) )
895 {
896 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
897
898 // doesn't work
899 }
900
901 void wxTextCtrl::SetForegroundColour( const wxColour &WXUNUSED(colour) )
902 {
903 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
904
905 // doesn't work
906 }
907
908 void wxTextCtrl::SetBackgroundColour( const wxColour &colour )
909 {
910 wxCHECK_RET( m_text != NULL, "invalid text ctrl" );
911
912 wxControl::SetBackgroundColour( colour );
913
914 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
915 if (sysbg.Red() == colour.Red() &&
916 sysbg.Green() == colour.Green() &&
917 sysbg.Blue() == colour.Blue())
918 {
919 return;
920 }
921
922 if (!m_backgroundColour.Ok()) return;
923
924 if (m_windowStyle & wxTE_MULTILINE)
925 {
926 GdkWindow *window = GTK_TEXT(m_text)->text_area;
927 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
928 gdk_window_set_background( window, m_backgroundColour.GetColor() );
929 gdk_window_clear( window );
930 }
931 }
932
933 void wxTextCtrl::ApplyWidgetStyle()
934 {
935 if (m_windowStyle & wxTE_MULTILINE)
936 {
937 // how ?
938 }
939 else
940 {
941 SetWidgetStyle();
942 gtk_widget_set_style( m_text, m_widgetStyle );
943 }
944 }
945
946 void wxTextCtrl::OnCut(wxCommandEvent& WXUNUSED(event))
947 {
948 Cut();
949 }
950
951 void wxTextCtrl::OnCopy(wxCommandEvent& WXUNUSED(event))
952 {
953 Copy();
954 }
955
956 void wxTextCtrl::OnPaste(wxCommandEvent& WXUNUSED(event))
957 {
958 Paste();
959 }
960
961 void wxTextCtrl::OnUndo(wxCommandEvent& WXUNUSED(event))
962 {
963 Undo();
964 }
965
966 void wxTextCtrl::OnRedo(wxCommandEvent& WXUNUSED(event))
967 {
968 Redo();
969 }
970
971 void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
972 {
973 event.Enable( CanCut() );
974 }
975
976 void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event)
977 {
978 event.Enable( CanCopy() );
979 }
980
981 void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event)
982 {
983 event.Enable( CanPaste() );
984 }
985
986 void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event)
987 {
988 event.Enable( CanUndo() );
989 }
990
991 void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
992 {
993 event.Enable( CanRedo() );
994 }