X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e9576ca53db96b462ed4c0b4bdf47d64c40203e4..15ba5c2731f1c4a7555408b35c7d593b1cb1a590:/src/mac/textctrl.cpp diff --git a/src/mac/textctrl.cpp b/src/mac/textctrl.cpp index 4171b868b6..dd35860824 100644 --- a/src/mac/textctrl.cpp +++ b/src/mac/textctrl.cpp @@ -36,85 +36,251 @@ #endif #endif +#include "wx/mac/uma.h" + #if !USE_SHARED_LIBRARY IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl) BEGIN_EVENT_TABLE(wxTextCtrl, wxControl) EVT_DROP_FILES(wxTextCtrl::OnDropFiles) + EVT_CHAR(wxTextCtrl::OnChar) + EVT_MENU(wxID_CUT, wxTextCtrl::OnCut) + EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy) + EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste) + EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo) + EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo) + + EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut) + EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy) + EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste) + EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo) + EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo) END_EVENT_TABLE() #endif // Text item wxTextCtrl::wxTextCtrl() -#ifndef NO_TEXT_WINDOW_STREAM - :streambuf() -#endif { - m_fileName = ""; } +const short kVerticalMargin = 2 ; +const short kHorizontalMargin = 2 ; + bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, - const wxString& value, + const wxString& st, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator, const wxString& name) { - m_fileName = ""; - SetName(name); - SetValidator(validator); - if (parent) parent->AddChild(this); - - m_windowStyle = style; - - if ( id == -1 ) - m_windowId = (int)NewControlId(); - else - m_windowId = id; + // base initialization + if ( !CreateBase(parent, id, pos, size, style, validator, name) ) + return FALSE; - return TRUE; + wxSize mySize = size ; + if ( UMAHasAppearance() ) + { + m_macHorizontalBorder = 5 ; // additional pixels around the real control + m_macVerticalBorder = 5 ; + } + else + { + m_macHorizontalBorder = 0 ; // additional pixels around the real control + m_macVerticalBorder = 0 ; + } + + + Rect bounds ; + Str255 title ; + + if ( mySize.y == -1 ) + { + if ( UMAHasAppearance() ) + mySize.y = 13 ; + else + mySize.y = 24 ; + + mySize.y += 2 * m_macVerticalBorder ; + } + + MacPreControlCreate( parent , id , "" , pos , mySize ,style, validator , name , &bounds , title ) ; + + m_macControl = UMANewControl( parent->GetMacRootWindow() , &bounds , "\p" , true , 0 , 0 , 1, + ( style & wxTE_PASSWORD ) ? kControlEditTextPasswordProc : kControlEditTextProc , (long) this ) ; + MacPostControlCreate() ; + + wxString value ; + + { + TEHandle teH ; + long size ; + + UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; + (*teH)->lineHeight = -1 ; + } + + if( wxApp::s_macDefaultEncodingIsPC ) + value = wxMacMakeMacStringFromPC( st ) ; + else + value = st ; + UMASetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , value.Length() , (char*) ((const char*)value) ) ; + + return TRUE; } wxString wxTextCtrl::GetValue() const { - // TODO - return wxString(""); + Size actualsize; + UMAGetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 32767 , wxBuffer , &actualsize) ; + wxBuffer[actualsize] = 0 ; + if( wxApp::s_macDefaultEncodingIsPC ) + return wxMacMakePCStringFromMac( wxBuffer ) ; + else + return wxString(wxBuffer); } -void wxTextCtrl::SetValue(const wxString& value) +void wxTextCtrl::GetSelection(long* from, long* to) const { - // TODO + ControlEditTextSelectionRec selection ; + TEHandle teH ; + long size ; + + UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; + + *from = (**teH).selStart; + *to = (**teH).selEnd; } -void wxTextCtrl::SetSize(int x, int y, int width, int height, int sizeFlags) +void wxTextCtrl::SetValue(const wxString& st) { - // TODO + wxString value ; + + if( wxApp::s_macDefaultEncodingIsPC ) + value = wxMacMakeMacStringFromPC( st ) ; + else + value = st ; + UMASetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , value.Length() , (char*) ((const char*)value) ) ; + UMADrawControl( m_macControl ) ; } // Clipboard operations void wxTextCtrl::Copy() { - // TODO + if (CanCopy()) + { + TEHandle teH ; + long size ; + + UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; + TECopy( teH ) ; +#if TARGET_CARBON + OSStatus err ; + err = ClearCurrentScrap( ); +#else + OSErr err ; + err = ZeroScrap( ); +#endif + TEToScrap() ; + } } void wxTextCtrl::Cut() { - // TODO + if (CanCut()) + { + TEHandle teH ; + long size ; + + UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; + TECut( teH ) ; +#if TARGET_CARBON + OSStatus err ; + err = ClearCurrentScrap( ); +#else + OSErr err ; + err = ZeroScrap( ); +#endif + TEToScrap() ; + // MacInvalidateControl() ; + } } void wxTextCtrl::Paste() { - // TODO + if (CanPaste()) + { + TEHandle teH ; + long size ; + + UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; + TEFromScrap() ; + TEPaste( teH ) ; + UMADrawControl( m_macControl ) ; + } +} + +bool wxTextCtrl::CanCopy() const +{ + // Can copy if there's a selection + long from, to; + GetSelection(& from, & to); + return (from != to); +} + +bool wxTextCtrl::CanCut() const +{ + // Can cut if there's a selection + long from, to; + GetSelection(& from, & to); + return (from != to); +} + +bool wxTextCtrl::CanPaste() const +{ + if (!IsEditable()) + return FALSE; + + long offset ; +#if TARGET_CARBON + OSStatus err = noErr; + ScrapRef scrapRef; + + err = GetCurrentScrap( &scrapRef ); + if ( err != noTypeErr && err != memFullErr ) + { + ScrapFlavorFlags flavorFlags; + Size byteCount; + + if (( err = GetScrapFlavorFlags( scrapRef, 'TEXT', &flavorFlags )) == noErr) + { + if (( err = GetScrapFlavorSize( scrapRef, 'TEXT', &byteCount )) == noErr) + { + return TRUE ; + } + } + } + return FALSE; + +#else + if ( GetScrap( NULL , 'TEXT' , &offset ) > 0 ) + { + return TRUE ; + } +#endif + return FALSE ; } void wxTextCtrl::SetEditable(bool editable) { - // TODO + if ( editable ) + UMAActivateControl( m_macControl ) ; + else + UMADeactivateControl( m_macControl ) ; } void wxTextCtrl::SetInsertionPoint(long pos) { - // TODO + SetSelection( pos , pos ) ; } void wxTextCtrl::SetInsertionPointEnd() @@ -125,110 +291,181 @@ void wxTextCtrl::SetInsertionPointEnd() long wxTextCtrl::GetInsertionPoint() const { - // TODO - return 0; + ControlEditTextSelectionRec selection ; + TEHandle teH ; + long size ; + + UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; +// UMAGetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection , &size ) ; + return (**teH).selStart ; } long wxTextCtrl::GetLastPosition() const { - // TODO - return 0; + ControlEditTextSelectionRec selection ; + TEHandle teH ; + long size ; + + UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; + +// UMAGetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection , &size ) ; + return (**teH).teLength ; } void wxTextCtrl::Replace(long from, long to, const wxString& value) { - // TODO + TEHandle teH ; + long size ; + + ControlEditTextSelectionRec selection ; + + selection.selStart = from ; + selection.selEnd = to ; + UMASetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ; + UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; + TESetSelect( from , to , teH ) ; + TEDelete( teH ) ; + TEInsert( value , value.Length() , teH ) ; +// MacInvalidateControl() ; } void wxTextCtrl::Remove(long from, long to) { - // TODO + TEHandle teH ; + long size ; + + ControlEditTextSelectionRec selection ; + + selection.selStart = from ; + selection.selEnd = to ; + UMASetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ; + UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; + TEDelete( teH ) ; +// MacInvalidateControl() ; } void wxTextCtrl::SetSelection(long from, long to) { - // TODO + ControlEditTextSelectionRec selection ; + TEHandle teH ; + long size ; + + UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; + + selection.selStart = from ; + selection.selEnd = to ; + + UMASetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ; + TESetSelect( selection.selStart , selection.selEnd , teH ) ; } bool wxTextCtrl::LoadFile(const wxString& file) { - if (!wxFileExists(file)) - return FALSE; - - m_fileName = file; - - Clear(); - -#ifndef __WXMAC__ - ifstream input((char*) (const char*) file, ios::nocreate | ios::in); -#else - ifstream input((char*) (const char*) file, ios::in); -#endif - if (!input.bad()) + if ( wxTextCtrlBase::LoadFile(file) ) { - struct stat stat_buf; - if (stat(file, &stat_buf) < 0) - return FALSE; - // This may need to be a bigger buffer than the file size suggests, - // if it's a UNIX file. Give it an extra 1000 just in case. - char *tmp_buffer = (char*)malloc((size_t)(stat_buf.st_size+1+1000)); - long no_lines = 0; - long pos = 0; - while (!input.eof() && input.peek() != EOF) - { - input.getline(wxBuffer, 500); - int len = strlen(wxBuffer); - wxBuffer[len] = 13; - wxBuffer[len+1] = 10; - wxBuffer[len+2] = 0; - strcpy(tmp_buffer+pos, wxBuffer); - pos += strlen(wxBuffer); - no_lines++; - } - - // TODO add line - - free(tmp_buffer); - - return TRUE; + return TRUE; } + return FALSE; } -// If file is null, try saved file name first -// Returns TRUE if succeeds. -bool wxTextCtrl::SaveFile(const wxString& file) +void wxTextCtrl::WriteText(const wxString& text) { - wxString theFile(file); - if (theFile == "") - theFile = m_fileName; - if (theFile == "") - return FALSE; - m_fileName = theFile; + TEHandle teH ; + long size ; + + memcpy( wxBuffer, text , text.Length() ) ; + wxBuffer[text.Length() ] = 0 ; +// wxMacConvertNewlines( wxBuffer , wxBuffer ) ; + + UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; + + TEInsert( wxBuffer , strlen( wxBuffer) , teH ) ; + Refresh() ; +} - ofstream output((char*) (const char*) theFile); - if (output.bad()) - return FALSE; +void wxTextCtrl::AppendText(const wxString& text) +{ + SetInsertionPointEnd(); + WriteText(text); +} - // TODO get and save text +void wxTextCtrl::Clear() +{ + UMASetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 0 , (char*) ((const char*)NULL) ) ; + Refresh() ; +} - return FALSE; +bool wxTextCtrl::IsModified() const +{ + return TRUE; } -void wxTextCtrl::WriteText(const wxString& text) +bool wxTextCtrl::IsEditable() const { - // TODO write text to control + return IsEnabled(); } -void wxTextCtrl::Clear() +bool wxTextCtrl::AcceptsFocus() const { - // TODO + // we don't want focus if we can't be edited + return IsEditable() && wxControl::AcceptsFocus(); } -bool wxTextCtrl::IsModified() const +wxSize wxTextCtrl::DoGetBestSize() const { - // TODO - return FALSE; + int wText = 100 ; + + int hText ; + if ( UMAHasAppearance() ) + hText = 13 ; + else + hText = 24 ; + hText += 2 * m_macHorizontalBorder ; +/* + int cx, cy; + wxGetCharSize(GetHWND(), &cx, &cy, &GetFont()); + + int wText = DEFAULT_ITEM_WIDTH; + + int hText = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy); + + return wxSize(wText, hText); +*/ + if ( m_windowStyle & wxTE_MULTILINE ) + { + hText *= wxMin(GetNumberOfLines(), 5); + } + //else: for single line control everything is ok + return wxSize(wText, hText); +} + +// ---------------------------------------------------------------------------- +// Undo/redo +// ---------------------------------------------------------------------------- + +void wxTextCtrl::Undo() +{ + if (CanUndo()) + { + } +} + +void wxTextCtrl::Redo() +{ + if (CanRedo()) + { + } +} + +bool wxTextCtrl::CanUndo() const +{ + return FALSE ; +} + +bool wxTextCtrl::CanRedo() const +{ + return FALSE ; } // Makes 'unmodified' @@ -249,9 +486,9 @@ long wxTextCtrl::XYToPosition(long x, long y) const return 0; } -void wxTextCtrl::PositionToXY(long pos, long *x, long *y) const +bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const { - // TODO + return FALSE ; } void wxTextCtrl::ShowPosition(long pos) @@ -261,14 +498,12 @@ void wxTextCtrl::ShowPosition(long pos) int wxTextCtrl::GetLineLength(long lineNo) const { - // TODO - return 0; + return GetValue().Length(); } wxString wxTextCtrl::GetLineText(long lineNo) const { - // TODO - return wxString(""); + return GetValue(); } /* @@ -290,158 +525,127 @@ void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event) } } -// The streambuf code was partly taken from chapter 3 by Jerry Schwarz of -// AT&T's "C++ Lanuage System Release 3.0 Library Manual" - Stein Somers - -//========================================================================= -// Called then the buffer is full (gcc 2.6.3) -// or when "endl" is output (Borland 4.5) -//========================================================================= -// Class declaration using multiple inheritance doesn't work properly for -// Borland. See note in wb_text.h. -#ifndef NO_TEXT_WINDOW_STREAM -int wxTextCtrl::overflow(int c) -{ - // Make sure there is a holding area - if ( allocate()==EOF ) - { - wxError("Streambuf allocation failed","Internal error"); - return EOF; - } - - // Verify that there are no characters in get area - if ( gptr() && gptr() < egptr() ) - { - wxError("Who's trespassing my get area?","Internal error"); - return EOF; - } - - // Reset get area - setg(0,0,0); - - // Make sure there is a put area - if ( ! pptr() ) - { -/* This doesn't seem to be fatal so comment out error message */ -// wxError("Put area not opened","Internal error"); - setp( base(), base() ); - } - - // Determine how many characters have been inserted but no consumed - int plen = pptr() - pbase(); - - // Now Jerry relies on the fact that the buffer is at least 2 chars - // long, but the holding area "may be as small as 1" ??? - // And we need an additional \0, so let's keep this inefficient but - // safe copy. - - // If c!=EOF, it is a character that must also be comsumed - int xtra = c==EOF? 0 : 1; - - // Write temporary C-string to wxTextWindow - { - char *txt = new char[plen+xtra+1]; - memcpy(txt, pbase(), plen); - txt[plen] = (char)c; // append c - txt[plen+xtra] = '\0'; // append '\0' or overwrite c - // If the put area already contained \0, output will be truncated there - WriteText(txt); - delete[] txt; - } - - // Reset put area - setp(pbase(), epptr()); - -#if defined(__WATCOMC__) - return __NOT_EOF; -#elif defined(zapeof) // HP-UX (all cfront based?) - return zapeof(c); -#else - return c!=EOF ? c : 0; // this should make everybody happy -#endif +void wxTextCtrl::OnChar(wxKeyEvent& event) +{ + switch ( event.KeyCode() ) + { + case WXK_RETURN: + if (m_windowStyle & wxPROCESS_ENTER) + { + wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId); + event.SetEventObject( this ); + if ( GetEventHandler()->ProcessEvent(event) ) + return; + } + if ( !(m_windowStyle & wxTE_MULTILINE) ) + { + wxWindow *parent = GetParent(); + wxPanel *panel = wxDynamicCast(parent, wxPanel); + while ( parent != NULL && panel == NULL ) + { + parent = parent->GetParent() ; + panel = wxDynamicCast(parent, wxPanel); + } + if ( panel && panel->GetDefaultItem() ) + { + wxButton *def = panel->GetDefaultItem() ; + wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() ); + event.SetEventObject(def); + def->Command(event); + event.Skip() ; + return ; + } + } + //else: multiline controls need Enter for themselves + + break; + + case WXK_TAB: + // always produce navigation event - even if we process TAB + // ourselves the fact that we got here means that the user code + // decided to skip processing of this TAB - probably to let it + // do its default job. + { + wxNavigationKeyEvent eventNav; + eventNav.SetDirection(!event.ShiftDown()); + eventNav.SetWindowChange(event.ControlDown()); + eventNav.SetEventObject(this); + + if ( GetParent()->GetEventHandler()->ProcessEvent(eventNav) ) + return; + event.Skip() ; + return ; + } + break; + } + + EventRecord *ev = wxTheApp->MacGetCurrentEvent() ; + short keycode ; + short keychar ; + keychar = short(ev->message & charCodeMask); + keycode = short(ev->message & keyCodeMask) >> 8 ; + UMAHandleControlKey( m_macControl , keycode , keychar , ev->modifiers ) ; + if ( keychar >= 0x20 || event.KeyCode() == WXK_RETURN) + { + wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId); + event.SetString( GetValue() ) ; + event.SetEventObject( this ); + GetEventHandler()->ProcessEvent(event); + } + } -//========================================================================= -// called then "endl" is output (gcc) or then explicit sync is done (Borland) -//========================================================================= -int wxTextCtrl::sync() -{ - // Verify that there are no characters in get area - if ( gptr() && gptr() < egptr() ) - { - wxError("Who's trespassing my get area?","Internal error"); - return EOF; - } - - if ( pptr() && pptr() > pbase() ) return overflow(EOF); - - return 0; -/* OLD CODE - int len = pptr() - pbase(); - char *txt = new char[len+1]; - strncpy(txt, pbase(), len); - txt[len] = '\0'; - (*this) << txt; - setp(pbase(), epptr()); - delete[] txt; - return 0; -*/ +// ---------------------------------------------------------------------------- +// standard handlers for standard edit menu events +// ---------------------------------------------------------------------------- + +void wxTextCtrl::OnCut(wxCommandEvent& event) +{ + Cut(); } -//========================================================================= -// Should not be called by a "ostream". Used by a "istream" -//========================================================================= -int wxTextCtrl::underflow() +void wxTextCtrl::OnCopy(wxCommandEvent& event) { - return EOF; + Copy(); } -#endif -wxTextCtrl& wxTextCtrl::operator<<(const wxString& s) +void wxTextCtrl::OnPaste(wxCommandEvent& event) { - WriteText(s); - return *this; + Paste(); } -wxTextCtrl& wxTextCtrl::operator<<(float f) +void wxTextCtrl::OnUndo(wxCommandEvent& event) { - wxString str; - str.Printf("%.2f", f); - WriteText(str); - return *this; + Undo(); } -wxTextCtrl& wxTextCtrl::operator<<(double d) +void wxTextCtrl::OnRedo(wxCommandEvent& event) { - wxString str; - str.Printf("%.2f", d); - WriteText(str); - return *this; + Redo(); } -wxTextCtrl& wxTextCtrl::operator<<(int i) +void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event) { - wxString str; - str.Printf("%d", i); - WriteText(str); - return *this; + event.Enable( CanCut() ); } -wxTextCtrl& wxTextCtrl::operator<<(long i) +void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event) { - wxString str; - str.Printf("%ld", i); - WriteText(str); - return *this; + event.Enable( CanCopy() ); } -wxTextCtrl& wxTextCtrl::operator<<(const char c) +void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event) { - char buf[2]; + event.Enable( CanPaste() ); +} - buf[0] = c; - buf[1] = 0; - WriteText(buf); - return *this; +void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event) +{ + event.Enable( CanUndo() ); +} + +void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event) +{ + event.Enable( CanRedo() ); }