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