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