1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "textctrl.h"
16 #include <sys/types.h>
20 #include "wx/textctrl.h"
21 #include "wx/settings.h"
22 #include "wx/filefn.h"
25 #if defined(__BORLANDC__) && !defined(__WIN32__)
34 #include <sys/types.h>
38 #include "wx/motif/private.h"
41 wxTextWindowChangedProc (Widget w
, XtPointer clientData
, XtPointer ptr
);
43 wxTextWindowModifyProc (Widget w
, XtPointer clientData
, XmTextVerifyCallbackStruct
*cbs
);
45 wxTextWindowGainFocusProc (Widget w
, XtPointer clientData
, XmAnyCallbackStruct
*cbs
);
47 wxTextWindowLoseFocusProc (Widget w
, XtPointer clientData
, XmAnyCallbackStruct
*cbs
);
49 #if !USE_SHARED_LIBRARY
50 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl
, wxControl
)
52 BEGIN_EVENT_TABLE(wxTextCtrl
, wxControl
)
53 EVT_DROP_FILES(wxTextCtrl::OnDropFiles
)
54 EVT_CHAR(wxTextCtrl::OnChar
)
59 wxTextCtrl::wxTextCtrl()
60 #ifndef NO_TEXT_WINDOW_STREAM
65 m_tempCallbackStruct
= (void*) NULL
;
69 bool wxTextCtrl::Create(wxWindow
*parent
, wxWindowID id
,
70 const wxString
& value
,
72 const wxSize
& size
, long style
,
73 const wxValidator
& validator
,
76 m_tempCallbackStruct
= (void*) NULL
;
81 SetValidator(validator
);
82 if (parent
) parent
->AddChild(this);
84 m_windowStyle
= style
;
87 m_windowId
= (int)NewControlId();
91 Widget parentWidget
= (Widget
) parent
->GetClientWidget();
93 bool wantHorizScrolling
= ((m_windowStyle
& wxHSCROLL
) != 0);
95 // If we don't have horizontal scrollbars, we want word wrap.
96 bool wantWordWrap
= !wantHorizScrolling
;
98 if (m_windowStyle
& wxTE_MULTILINE
)
101 XtSetArg (args
[0], XmNscrollHorizontal
, wantHorizScrolling
? True
: False
);
102 XtSetArg (args
[1], XmNwordWrap
, wantWordWrap
? True
: False
);
104 m_mainWidget
= (WXWidget
) XmCreateScrolledText (parentWidget
, (char*) (const char*) name
, args
, 2);
106 XtVaSetValues ((Widget
) m_mainWidget
,
107 XmNeditable
, ((style
& wxTE_READONLY
) ? False
: True
),
108 XmNeditMode
, XmMULTI_LINE_EDIT
,
110 XtManageChild ((Widget
) m_mainWidget
);
114 m_mainWidget
= (WXWidget
) XtVaCreateManagedWidget ((char*) (const char*) name
,
115 xmTextWidgetClass
, parentWidget
,
118 // TODO: Is this relevant? What does it do?
120 if (!value
.IsNull() && (value
.Length() > (unsigned int) noCols
))
121 noCols
= value
.Length();
122 XtVaSetValues ((Widget
) m_mainWidget
,
128 XmTextSetString ((Widget
) m_mainWidget
, (char*) (const char*) value
);
130 XtAddCallback((Widget
) m_mainWidget
, XmNvalueChangedCallback
, (XtCallbackProc
)wxTextWindowChangedProc
, (XtPointer
)this);
132 XtAddCallback((Widget
) m_mainWidget
, XmNmodifyVerifyCallback
, (XtCallbackProc
)wxTextWindowModifyProc
, (XtPointer
)this);
134 // XtAddCallback((Widget) m_mainWidget, XmNactivateCallback, (XtCallbackProc)wxTextWindowModifyProc, (XtPointer)this);
136 XtAddCallback((Widget
) m_mainWidget
, XmNfocusCallback
, (XtCallbackProc
)wxTextWindowGainFocusProc
, (XtPointer
)this);
138 XtAddCallback((Widget
) m_mainWidget
, XmNlosingFocusCallback
, (XtCallbackProc
)wxTextWindowLoseFocusProc
, (XtPointer
)this);
140 SetCanAddEventHandler(TRUE
);
141 AttachWidget (parent
, m_mainWidget
, (WXWidget
) NULL
, pos
.x
, pos
.y
, size
.x
, size
.y
);
143 SetFont(* parent
->GetFont());
144 ChangeColour(m_mainWidget
);
149 WXWidget
wxTextCtrl::GetTopWidget() const
151 return ((m_windowStyle
& wxTE_MULTILINE
) ? (WXWidget
) XtParent((Widget
) m_mainWidget
) : m_mainWidget
);
154 wxString
wxTextCtrl::GetValue() const
160 void wxTextCtrl::SetValue(const wxString
& value
)
165 // Clipboard operations
166 void wxTextCtrl::Copy()
171 void wxTextCtrl::Cut()
176 void wxTextCtrl::Paste()
181 void wxTextCtrl::SetEditable(bool editable
)
186 void wxTextCtrl::SetInsertionPoint(long pos
)
191 void wxTextCtrl::SetInsertionPointEnd()
193 long pos
= GetLastPosition();
194 SetInsertionPoint(pos
);
197 long wxTextCtrl::GetInsertionPoint() const
203 long wxTextCtrl::GetLastPosition() const
209 void wxTextCtrl::Replace(long from
, long to
, const wxString
& value
)
214 void wxTextCtrl::Remove(long from
, long to
)
219 void wxTextCtrl::SetSelection(long from
, long to
)
224 bool wxTextCtrl::LoadFile(const wxString
& file
)
226 if (!wxFileExists(file
))
233 ifstream
input((char*) (const char*) file
, ios::nocreate
| ios::in
);
237 struct stat stat_buf
;
238 if (stat(file
, &stat_buf
) < 0)
240 // This may need to be a bigger buffer than the file size suggests,
241 // if it's a UNIX file. Give it an extra 1000 just in case.
242 char *tmp_buffer
= (char*)malloc((size_t)(stat_buf
.st_size
+1+1000));
245 while (!input
.eof() && input
.peek() != EOF
)
247 input
.getline(wxBuffer
, 500);
248 int len
= strlen(wxBuffer
);
250 wxBuffer
[len
+1] = 10;
252 strcpy(tmp_buffer
+pos
, wxBuffer
);
253 pos
+= strlen(wxBuffer
);
266 // If file is null, try saved file name first
267 // Returns TRUE if succeeds.
268 bool wxTextCtrl::SaveFile(const wxString
& file
)
270 wxString
theFile(file
);
272 theFile
= m_fileName
;
275 m_fileName
= theFile
;
277 ofstream
output((char*) (const char*) theFile
);
281 // TODO get and save text
286 void wxTextCtrl::WriteText(const wxString
& text
)
288 // TODO write text to control
291 void wxTextCtrl::Clear()
293 XmTextSetString ((Widget
) m_mainWidget
, "");
294 // TODO: do we need position flag?
295 // m_textPosition = 0;
299 bool wxTextCtrl::IsModified() const
304 // Makes 'unmodified'
305 void wxTextCtrl::DiscardEdits()
310 int wxTextCtrl::GetNumberOfLines() const
316 long wxTextCtrl::XYToPosition(long x
, long y
) const
322 void wxTextCtrl::PositionToXY(long pos
, long *x
, long *y
) const
327 void wxTextCtrl::ShowPosition(long pos
)
332 int wxTextCtrl::GetLineLength(long lineNo
) const
338 wxString
wxTextCtrl::GetLineText(long lineNo
) const
348 void wxTextCtrl::Command(wxCommandEvent
& event
)
350 SetValue (event
.GetString());
351 ProcessCommand (event
);
354 void wxTextCtrl::OnDropFiles(wxDropFilesEvent
& event
)
356 // By default, load the first file into the text window.
357 if (event
.GetNumberOfFiles() > 0)
359 LoadFile(event
.GetFiles()[0]);
363 // The streambuf code was partly taken from chapter 3 by Jerry Schwarz of
364 // AT&T's "C++ Lanuage System Release 3.0 Library Manual" - Stein Somers
366 //=========================================================================
367 // Called then the buffer is full (gcc 2.6.3)
368 // or when "endl" is output (Borland 4.5)
369 //=========================================================================
370 // Class declaration using multiple inheritance doesn't work properly for
371 // Borland. See note in wb_text.h.
372 #ifndef NO_TEXT_WINDOW_STREAM
373 int wxTextCtrl::overflow(int c
)
375 // Make sure there is a holding area
376 if ( allocate()==EOF
)
378 wxError("Streambuf allocation failed","Internal error");
382 // Verify that there are no characters in get area
383 if ( gptr() && gptr() < egptr() )
385 wxError("Who's trespassing my get area?","Internal error");
392 // Make sure there is a put area
395 /* This doesn't seem to be fatal so comment out error message */
396 // wxError("Put area not opened","Internal error");
397 setp( base(), base() );
400 // Determine how many characters have been inserted but no consumed
401 int plen
= pptr() - pbase();
403 // Now Jerry relies on the fact that the buffer is at least 2 chars
404 // long, but the holding area "may be as small as 1" ???
405 // And we need an additional \0, so let's keep this inefficient but
408 // If c!=EOF, it is a character that must also be comsumed
409 int xtra
= c
==EOF
? 0 : 1;
411 // Write temporary C-string to wxTextWindow
413 char *txt
= new char[plen
+xtra
+1];
414 memcpy(txt
, pbase(), plen
);
415 txt
[plen
] = (char)c
; // append c
416 txt
[plen
+xtra
] = '\0'; // append '\0' or overwrite c
417 // If the put area already contained \0, output will be truncated there
423 setp(pbase(), epptr());
425 #if defined(__WATCOMC__)
427 #elif defined(zapeof) // HP-UX (all cfront based?)
430 return c
!=EOF
? c
: 0; // this should make everybody happy
434 //=========================================================================
435 // called then "endl" is output (gcc) or then explicit sync is done (Borland)
436 //=========================================================================
437 int wxTextCtrl::sync()
439 // Verify that there are no characters in get area
440 if ( gptr() && gptr() < egptr() )
442 wxError("Who's trespassing my get area?","Internal error");
446 if ( pptr() && pptr() > pbase() ) return overflow(EOF
);
450 int len = pptr() - pbase();
451 char *txt = new char[len+1];
452 strncpy(txt, pbase(), len);
455 setp(pbase(), epptr());
461 //=========================================================================
462 // Should not be called by a "ostream". Used by a "istream"
463 //=========================================================================
464 int wxTextCtrl::underflow()
470 wxTextCtrl
& wxTextCtrl::operator<<(const wxString
& s
)
476 wxTextCtrl
& wxTextCtrl::operator<<(float f
)
479 str
.Printf("%.2f", f
);
484 wxTextCtrl
& wxTextCtrl::operator<<(double d
)
487 str
.Printf("%.2f", d
);
492 wxTextCtrl
& wxTextCtrl::operator<<(int i
)
500 wxTextCtrl
& wxTextCtrl::operator<<(long i
)
503 str
.Printf("%ld", i
);
508 wxTextCtrl
& wxTextCtrl::operator<<(const char c
)
518 void wxTextCtrl::OnChar(wxKeyEvent
& event
)
520 if (m_tempCallbackStruct
)
522 XmTextVerifyCallbackStruct
*textStruct
=
523 (XmTextVerifyCallbackStruct
*) m_tempCallbackStruct
;
524 textStruct
->doit
= True
;
525 if (isascii(event
.m_keyCode
) && (textStruct
->text
->length
== 1))
527 textStruct
->text
->ptr
[0] = ((event
.m_keyCode
== WXK_RETURN
) ? 10 : event
.m_keyCode
);
533 wxTextWindowChangedProc (Widget w
, XtPointer clientData
, XtPointer ptr
)
535 if (!wxGetWindowFromTable(w
))
536 // Widget has been deleted!
539 wxTextCtrl
*tw
= (wxTextCtrl
*) clientData
;
540 tw
->SetModified(TRUE
);
544 wxTextWindowModifyProc (Widget w
, XtPointer clientData
, XmTextVerifyCallbackStruct
*cbs
)
546 wxTextCtrl
*tw
= (wxTextCtrl
*) clientData
;
548 // If we're already within an OnChar, return: probably
549 // a programmatic insertion.
550 if (tw
->m_tempCallbackStruct
)
553 // Check for a backspace
554 if (cbs
->startPos
== (cbs
->currInsert
- 1))
556 tw
->m_tempCallbackStruct
= (void*) cbs
;
558 wxKeyEvent
event (wxEVT_CHAR
);
559 event
.SetId(tw
->GetId());
560 event
.m_keyCode
= WXK_DELETE
;
561 event
.SetEventObject(tw
);
563 // Only if wxTextCtrl::OnChar is called
564 // will this be set to True (and the character
568 tw
->GetEventHandler()->ProcessEvent(event
);
570 tw
->m_tempCallbackStruct
= NULL
;
575 // Pasting operation: let it through without
577 if (cbs
->text
->length
> 1)
580 // Something other than text
581 if (cbs
->text
->ptr
== NULL
)
584 tw
->m_tempCallbackStruct
= (void*) cbs
;
586 wxKeyEvent
event (wxEVT_CHAR
);
587 event
.SetId(tw
->GetId());
588 event
.SetEventObject(tw
);
589 event
.m_keyCode
= (cbs
->text
->ptr
[0] == 10 ? 13 : cbs
->text
->ptr
[0]);
591 // Only if wxTextCtrl::OnChar is called
592 // will this be set to True (and the character
596 tw
->GetEventHandler()->ProcessEvent(event
);
598 tw
->m_tempCallbackStruct
= NULL
;
602 wxTextWindowGainFocusProc (Widget w
, XtPointer clientData
, XmAnyCallbackStruct
*cbs
)
604 if (!wxGetWindowFromTable(w
))
607 wxTextCtrl
*tw
= (wxTextCtrl
*) clientData
;
608 wxFocusEvent
event(wxEVT_SET_FOCUS
, tw
->GetId());
609 event
.SetEventObject(tw
);
610 tw
->GetEventHandler()->ProcessEvent(event
);
614 wxTextWindowLoseFocusProc (Widget w
, XtPointer clientData
, XmAnyCallbackStruct
*cbs
)
616 if (!wxGetWindowFromTable(w
))
619 wxTextCtrl
*tw
= (wxTextCtrl
*) clientData
;
620 wxFocusEvent
event(wxEVT_KILL_FOCUS
, tw
->GetId());
621 event
.SetEventObject(tw
);
622 tw
->GetEventHandler()->ProcessEvent(event
);