]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/textctrl.cpp
applied (slightly modified) wxToggleButton patch from John Norris and Axel Schlueter
[wxWidgets.git] / src / mac / carbon / textctrl.cpp
CommitLineData
e9576ca5
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: textctrl.cpp
3// Purpose: wxTextCtrl
4// Author: AUTHOR
5// Modified by:
6// Created: ??/??/98
7// RCS-ID: $Id$
8// Copyright: (c) AUTHOR
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "textctrl.h"
14#endif
15
16#ifndef __WXMAC__
17#include <sys/types.h>
18#include <sys/stat.h>
19#else
20#include <stat.h>
21#endif
22#include <fstream.h>
23
24#include "wx/textctrl.h"
25#include "wx/settings.h"
26#include "wx/filefn.h"
27#include "wx/utils.h"
28
29#if defined(__BORLANDC__) && !defined(__WIN32__)
30#include <alloc.h>
31#else
32#ifndef __MWERKS__
33#ifndef __GNUWIN32__
34#include <malloc.h>
35#endif
36#endif
37#endif
38
519cb848
SC
39#include "wx/mac/uma.h"
40
2f1ae414 41#if !USE_SHARED_LIBRARY
e9576ca5
SC
42IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
43
44BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
45 EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
519cb848 46 EVT_CHAR(wxTextCtrl::OnChar)
2f1ae414
SC
47 EVT_MENU(wxID_CUT, wxTextCtrl::OnCut)
48 EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy)
49 EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste)
50 EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo)
51 EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo)
52
53 EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut)
54 EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy)
55 EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste)
56 EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo)
57 EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo)
e9576ca5 58END_EVENT_TABLE()
2f1ae414 59#endif
e9576ca5
SC
60
61// Text item
62wxTextCtrl::wxTextCtrl()
e9576ca5 63{
e9576ca5
SC
64}
65
2f1ae414
SC
66const short kVerticalMargin = 2 ;
67const short kHorizontalMargin = 2 ;
68
e9576ca5 69bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
519cb848 70 const wxString& st,
e9576ca5
SC
71 const wxPoint& pos,
72 const wxSize& size, long style,
73 const wxValidator& validator,
74 const wxString& name)
75{
2f1ae414
SC
76 // base initialization
77 if ( !CreateBase(parent, id, pos, size, style, validator, name) )
78 return FALSE;
519cb848
SC
79
80 wxSize mySize = size ;
2f1ae414
SC
81 if ( UMAHasAppearance() )
82 {
83 m_macHorizontalBorder = 5 ; // additional pixels around the real control
84 m_macVerticalBorder = 5 ;
85 }
86 else
87 {
88 m_macHorizontalBorder = 0 ; // additional pixels around the real control
89 m_macVerticalBorder = 0 ;
90 }
91
519cb848
SC
92
93 Rect bounds ;
94 Str255 title ;
2f1ae414 95
519cb848
SC
96 if ( mySize.y == -1 )
97 {
98 if ( UMAHasAppearance() )
2f1ae414 99 mySize.y = 13 ;
519cb848
SC
100 else
101 mySize.y = 24 ;
2f1ae414
SC
102
103 mySize.y += 2 * m_macVerticalBorder ;
519cb848 104 }
2f1ae414 105
519cb848
SC
106 MacPreControlCreate( parent , id , "" , pos , mySize ,style, validator , name , &bounds , title ) ;
107
108 m_macControl = UMANewControl( parent->GetMacRootWindow() , &bounds , "\p" , true , 0 , 0 , 1,
2f1ae414 109 ( style & wxTE_PASSWORD ) ? kControlEditTextPasswordProc : kControlEditTextProc , (long) this ) ;
519cb848
SC
110 MacPostControlCreate() ;
111
112 wxString value ;
113
114 if( wxApp::s_macDefaultEncodingIsPC )
115 value = wxMacMakeMacStringFromPC( st ) ;
116 else
117 value = st ;
2f1ae414 118 UMASetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , value.Length() , (char*) ((const char*)value) ) ;
519cb848
SC
119
120 return TRUE;
e9576ca5
SC
121}
122
123wxString wxTextCtrl::GetValue() const
124{
519cb848 125 Size actualsize;
2f1ae414 126 UMAGetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 32767 , wxBuffer , &actualsize) ;
519cb848
SC
127 wxBuffer[actualsize] = 0 ;
128 if( wxApp::s_macDefaultEncodingIsPC )
129 return wxMacMakePCStringFromMac( wxBuffer ) ;
130 else
131 return wxString(wxBuffer);
e9576ca5
SC
132}
133
2f1ae414
SC
134void wxTextCtrl::GetSelection(long* from, long* to) const
135{
136 ControlEditTextSelectionRec selection ;
137 TEHandle teH ;
138 long size ;
139
140 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
141
142 *from = (**teH).selStart;
143 *to = (**teH).selEnd;
144}
145
519cb848
SC
146void wxTextCtrl::SetValue(const wxString& st)
147{
148 wxString value ;
149
150 if( wxApp::s_macDefaultEncodingIsPC )
151 value = wxMacMakeMacStringFromPC( st ) ;
152 else
153 value = st ;
2f1ae414 154 UMASetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , value.Length() , (char*) ((const char*)value) ) ;
519cb848
SC
155 Refresh() ;
156// MacInvalidateControl() ;
e9576ca5
SC
157}
158
e9576ca5
SC
159// Clipboard operations
160void wxTextCtrl::Copy()
161{
2f1ae414
SC
162 if (CanCopy())
163 {
164 TEHandle teH ;
165 long size ;
519cb848 166
2f1ae414
SC
167 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
168 TECopy( teH ) ;
169#if TARGET_CARBON
170 OSStatus err ;
171 err = ClearCurrentScrap( );
172#else
173 OSErr err ;
174 err = ZeroScrap( );
175#endif
176 TEToScrap() ;
177 }
e9576ca5
SC
178}
179
180void wxTextCtrl::Cut()
181{
2f1ae414
SC
182 if (CanCut())
183 {
184 TEHandle teH ;
185 long size ;
519cb848 186
2f1ae414
SC
187 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
188 TECut( teH ) ;
189#if TARGET_CARBON
190 OSStatus err ;
191 err = ClearCurrentScrap( );
192#else
193 OSErr err ;
194 err = ZeroScrap( );
195#endif
196 TEToScrap() ;
197 // MacInvalidateControl() ;
198 }
e9576ca5
SC
199}
200
201void wxTextCtrl::Paste()
202{
2f1ae414
SC
203 if (CanPaste())
204 {
205 TEHandle teH ;
206 long size ;
519cb848 207
2f1ae414
SC
208 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
209 TEFromScrap() ;
210 TEPaste( teH ) ;
519cb848 211// MacInvalidateControl() ;
2f1ae414
SC
212 }
213}
214
215bool wxTextCtrl::CanCopy() const
216{
217 // Can copy if there's a selection
218 long from, to;
219 GetSelection(& from, & to);
220 return (from != to);
221}
222
223bool wxTextCtrl::CanCut() const
224{
225 // Can cut if there's a selection
226 long from, to;
227 GetSelection(& from, & to);
228 return (from != to);
229}
230
231bool wxTextCtrl::CanPaste() const
232{
233 if (!IsEditable())
234 return FALSE;
235
236 long offset ;
237#if TARGET_CARBON
238 OSStatus err = noErr;
239 ScrapRef scrapRef;
240
241 err = GetCurrentScrap( &scrapRef );
242 if ( err != noTypeErr && err != memFullErr )
243 {
244 ScrapFlavorFlags flavorFlags;
245 Size byteCount;
246
247 if (( err = GetScrapFlavorFlags( scrapRef, 'TEXT', &flavorFlags )) == noErr)
248 {
249 if (( err = GetScrapFlavorSize( scrapRef, 'TEXT', &byteCount )) == noErr)
250 {
251 return TRUE ;
252 }
253 }
254 }
255 return FALSE;
256
257#else
258 if ( GetScrap( NULL , 'TEXT' , &offset ) > 0 )
259 {
260 return TRUE ;
261 }
262#endif
263 return FALSE ;
e9576ca5
SC
264}
265
266void wxTextCtrl::SetEditable(bool editable)
267{
519cb848
SC
268 if ( editable )
269 UMAActivateControl( m_macControl ) ;
270 else
271 UMADeactivateControl( m_macControl ) ;
e9576ca5
SC
272}
273
274void wxTextCtrl::SetInsertionPoint(long pos)
275{
519cb848 276 SetSelection( pos , pos ) ;
e9576ca5
SC
277}
278
279void wxTextCtrl::SetInsertionPointEnd()
280{
281 long pos = GetLastPosition();
282 SetInsertionPoint(pos);
283}
284
285long wxTextCtrl::GetInsertionPoint() const
286{
519cb848
SC
287 ControlEditTextSelectionRec selection ;
288 TEHandle teH ;
289 long size ;
290
291 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
292// UMAGetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection , &size ) ;
293 return (**teH).selStart ;
e9576ca5
SC
294}
295
296long wxTextCtrl::GetLastPosition() const
297{
519cb848
SC
298 ControlEditTextSelectionRec selection ;
299 TEHandle teH ;
300 long size ;
301
302 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
303
304// UMAGetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection , &size ) ;
305 return (**teH).teLength ;
e9576ca5
SC
306}
307
308void wxTextCtrl::Replace(long from, long to, const wxString& value)
309{
519cb848
SC
310 TEHandle teH ;
311 long size ;
312
313 ControlEditTextSelectionRec selection ;
314
315 selection.selStart = from ;
316 selection.selEnd = to ;
317 UMASetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
318 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
319 TESetSelect( from , to , teH ) ;
320 TEDelete( teH ) ;
321 TEInsert( value , value.Length() , teH ) ;
322// MacInvalidateControl() ;
e9576ca5
SC
323}
324
325void wxTextCtrl::Remove(long from, long to)
326{
519cb848
SC
327 TEHandle teH ;
328 long size ;
329
330 ControlEditTextSelectionRec selection ;
331
332 selection.selStart = from ;
333 selection.selEnd = to ;
334 UMASetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
335 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
336 TEDelete( teH ) ;
337// MacInvalidateControl() ;
e9576ca5
SC
338}
339
340void wxTextCtrl::SetSelection(long from, long to)
341{
519cb848
SC
342 ControlEditTextSelectionRec selection ;
343 TEHandle teH ;
344 long size ;
345
346 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
347
348 selection.selStart = from ;
349 selection.selEnd = to ;
350
351 UMASetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
352 TESetSelect( selection.selStart , selection.selEnd , teH ) ;
e9576ca5
SC
353}
354
355bool wxTextCtrl::LoadFile(const wxString& file)
356{
2f1ae414 357 if ( wxTextCtrlBase::LoadFile(file) )
e9576ca5 358 {
2f1ae414 359 return TRUE;
e9576ca5 360 }
e9576ca5
SC
361
362 return FALSE;
363}
364
365void wxTextCtrl::WriteText(const wxString& text)
366{
519cb848
SC
367 TEHandle teH ;
368 long size ;
369
370 memcpy( wxBuffer, text , text.Length() ) ;
371 wxBuffer[text.Length() ] = 0 ;
372// wxMacConvertNewlines( wxBuffer , wxBuffer ) ;
373
374 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
375
376 TEInsert( wxBuffer , strlen( wxBuffer) , teH ) ;
377 Refresh() ;
e9576ca5
SC
378}
379
13c21be5
HH
380void wxTextCtrl::AppendText(const wxString& text)
381{
519cb848
SC
382 SetInsertionPointEnd();
383 WriteText(text);
13c21be5
HH
384}
385
e9576ca5
SC
386void wxTextCtrl::Clear()
387{
2f1ae414
SC
388 UMASetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 0 , (char*) ((const char*)NULL) ) ;
389 Refresh() ;
e9576ca5
SC
390}
391
392bool wxTextCtrl::IsModified() const
393{
519cb848 394 return TRUE;
e9576ca5
SC
395}
396
2f1ae414
SC
397bool wxTextCtrl::IsEditable() const
398{
399 return IsEnabled();
400}
401
402bool wxTextCtrl::AcceptsFocus() const
403{
404 // we don't want focus if we can't be edited
405 return IsEditable() && wxControl::AcceptsFocus();
406}
407
408wxSize wxTextCtrl::DoGetBestSize() const
409{
410 int wText = 100 ;
411
412 int hText ;
413 if ( UMAHasAppearance() )
414 hText = 13 ;
415 else
416 hText = 24 ;
417 hText += 2 * m_macHorizontalBorder ;
418/*
419 int cx, cy;
420 wxGetCharSize(GetHWND(), &cx, &cy, &GetFont());
421
422 int wText = DEFAULT_ITEM_WIDTH;
423
424 int hText = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy);
425
426 return wxSize(wText, hText);
427*/
428 if ( m_windowStyle & wxTE_MULTILINE )
429 {
430 hText *= wxMin(GetNumberOfLines(), 5);
431 }
432 //else: for single line control everything is ok
433 return wxSize(wText, hText);
434}
435
436// ----------------------------------------------------------------------------
437// Undo/redo
438// ----------------------------------------------------------------------------
439
440void wxTextCtrl::Undo()
441{
442 if (CanUndo())
443 {
444 }
445}
446
447void wxTextCtrl::Redo()
448{
449 if (CanRedo())
450 {
451 }
452}
453
454bool wxTextCtrl::CanUndo() const
455{
456 return FALSE ;
457}
458
459bool wxTextCtrl::CanRedo() const
460{
461 return FALSE ;
462}
463
e9576ca5
SC
464// Makes 'unmodified'
465void wxTextCtrl::DiscardEdits()
466{
467 // TODO
468}
469
470int wxTextCtrl::GetNumberOfLines() const
471{
472 // TODO
473 return 0;
474}
475
476long wxTextCtrl::XYToPosition(long x, long y) const
477{
478 // TODO
479 return 0;
480}
481
2f1ae414 482bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
e9576ca5 483{
2f1ae414 484 return FALSE ;
e9576ca5
SC
485}
486
487void wxTextCtrl::ShowPosition(long pos)
488{
489 // TODO
490}
491
492int wxTextCtrl::GetLineLength(long lineNo) const
493{
519cb848 494 return GetValue().Length();
e9576ca5
SC
495}
496
497wxString wxTextCtrl::GetLineText(long lineNo) const
498{
519cb848 499 return GetValue();
e9576ca5
SC
500}
501
502/*
503 * Text item
504 */
505
506void wxTextCtrl::Command(wxCommandEvent & event)
507{
508 SetValue (event.GetString());
509 ProcessCommand (event);
510}
511
512void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
513{
514 // By default, load the first file into the text window.
515 if (event.GetNumberOfFiles() > 0)
516 {
517 LoadFile(event.GetFiles()[0]);
518 }
519}
520
519cb848
SC
521void wxTextCtrl::OnChar(wxKeyEvent& event)
522{
2f1ae414 523 switch ( event.KeyCode() )
519cb848
SC
524 {
525 case WXK_RETURN:
2f1ae414
SC
526 if (m_windowStyle & wxPROCESS_ENTER)
527 {
e7549107
SC
528 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
529 event.SetEventObject( this );
530 if ( GetEventHandler()->ProcessEvent(event) )
531 return;
2f1ae414
SC
532 }
533 if ( !(m_windowStyle & wxTE_MULTILINE) )
534 {
535 wxWindow *parent = GetParent();
536 wxPanel *panel = wxDynamicCast(parent, wxPanel);
537 while ( parent != NULL && panel == NULL )
538 {
539 parent = parent->GetParent() ;
540 panel = wxDynamicCast(parent, wxPanel);
541 }
542 if ( panel && panel->GetDefaultItem() )
543 {
544 wxButton *def = panel->GetDefaultItem() ;
545 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
546 event.SetEventObject(def);
547 def->Command(event);
548 event.Skip() ;
549 return ;
550 }
519cb848 551 }
e7549107
SC
552 //else: multiline controls need Enter for themselves
553
519cb848 554 break;
2f1ae414 555
519cb848 556 case WXK_TAB:
e7549107
SC
557 // always produce navigation event - even if we process TAB
558 // ourselves the fact that we got here means that the user code
559 // decided to skip processing of this TAB - probably to let it
560 // do its default job.
519cb848
SC
561 {
562 wxNavigationKeyEvent eventNav;
563 eventNav.SetDirection(!event.ShiftDown());
2f1ae414 564 eventNav.SetWindowChange(event.ControlDown());
519cb848 565 eventNav.SetEventObject(this);
e7549107 566
2f1ae414 567 if ( GetParent()->GetEventHandler()->ProcessEvent(eventNav) )
519cb848 568 return;
2f1ae414
SC
569 event.Skip() ;
570 return ;
519cb848
SC
571 }
572 break;
573 }
e7549107 574
2f1ae414
SC
575 EventRecord *ev = wxTheApp->MacGetCurrentEvent() ;
576 short keycode ;
577 short keychar ;
578 keychar = short(ev->message & charCodeMask);
579 keycode = short(ev->message & keyCodeMask) >> 8 ;
580 UMAHandleControlKey( m_macControl , keycode , keychar , ev->modifiers ) ;
581 if ( keychar >= 0x20 || event.KeyCode() == WXK_RETURN)
582 {
583 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
584 event.SetString( GetValue() ) ;
585 event.SetEventObject( this );
586 GetEventHandler()->ProcessEvent(event);
587 }
588
e9576ca5
SC
589}
590
2f1ae414
SC
591// ----------------------------------------------------------------------------
592// standard handlers for standard edit menu events
593// ----------------------------------------------------------------------------
594
595void wxTextCtrl::OnCut(wxCommandEvent& event)
596{
597 Cut();
e9576ca5
SC
598}
599
2f1ae414 600void wxTextCtrl::OnCopy(wxCommandEvent& event)
e9576ca5 601{
2f1ae414 602 Copy();
e9576ca5 603}
e9576ca5 604
2f1ae414 605void wxTextCtrl::OnPaste(wxCommandEvent& event)
e9576ca5 606{
2f1ae414 607 Paste();
e9576ca5
SC
608}
609
2f1ae414 610void wxTextCtrl::OnUndo(wxCommandEvent& event)
e9576ca5 611{
2f1ae414 612 Undo();
e9576ca5
SC
613}
614
2f1ae414 615void wxTextCtrl::OnRedo(wxCommandEvent& event)
e9576ca5 616{
2f1ae414 617 Redo();
e9576ca5
SC
618}
619
2f1ae414 620void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
e9576ca5 621{
2f1ae414 622 event.Enable( CanCut() );
e9576ca5
SC
623}
624
2f1ae414 625void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event)
e9576ca5 626{
2f1ae414 627 event.Enable( CanCopy() );
e9576ca5
SC
628}
629
2f1ae414 630void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event)
e9576ca5 631{
2f1ae414
SC
632 event.Enable( CanPaste() );
633}
e9576ca5 634
2f1ae414
SC
635void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event)
636{
637 event.Enable( CanUndo() );
638}
639
640void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
641{
642 event.Enable( CanRedo() );
e9576ca5
SC
643}
644