]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/textctrl.cpp
d553477f93b6aa315fda8a05f98fa0d075a306d2
[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 END_EVENT_TABLE()
48 #endif
49
50 // Text item
51 wxTextCtrl::wxTextCtrl()
52 #ifndef NO_TEXT_WINDOW_STREAM
53 :streambuf()
54 #endif
55 {
56 m_fileName = "";
57 }
58
59 bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
60 const wxString& st,
61 const wxPoint& pos,
62 const wxSize& size, long style,
63 const wxValidator& validator,
64 const wxString& name)
65 {
66 m_macHorizontalBorder = 2 ; // additional pixels around the real control
67 m_macVerticalBorder = 2 ;
68
69 wxSize mySize = size ;
70
71 Rect bounds ;
72 Str255 title ;
73
74 if ( mySize.y == -1 )
75 {
76 if ( UMAHasAppearance() )
77 mySize.y = 16 ;
78 else
79 mySize.y = 24 ;
80 }
81 MacPreControlCreate( parent , id , "" , pos , mySize ,style, validator , name , &bounds , title ) ;
82
83 m_macControl = UMANewControl( parent->GetMacRootWindow() , &bounds , "\p" , true , 0 , 0 , 1,
84 kControlEditTextProc , (long) this ) ;
85 MacPostControlCreate() ;
86
87 wxString value ;
88
89 if( wxApp::s_macDefaultEncodingIsPC )
90 value = wxMacMakeMacStringFromPC( st ) ;
91 else
92 value = st ;
93 UMASetControlData( m_macControl, 0, kControlEditTextTextTag , value.Length() , (char*) ((const char*)value) ) ;
94
95 return TRUE;
96 }
97
98 wxString wxTextCtrl::GetValue() const
99 {
100 Size actualsize;
101 UMAGetControlData( m_macControl, 0, kControlEditTextTextTag , 32767 , wxBuffer , &actualsize) ;
102 wxBuffer[actualsize] = 0 ;
103 if( wxApp::s_macDefaultEncodingIsPC )
104 return wxMacMakePCStringFromMac( wxBuffer ) ;
105 else
106 return wxString(wxBuffer);
107 }
108
109 void wxTextCtrl::SetValue(const wxString& st)
110 {
111 wxString value ;
112
113 if( wxApp::s_macDefaultEncodingIsPC )
114 value = wxMacMakeMacStringFromPC( st ) ;
115 else
116 value = st ;
117 UMASetControlData( m_macControl, 0, kControlEditTextTextTag , value.Length() , (char*) ((const char*)value) ) ;
118 Refresh() ;
119 // MacInvalidateControl() ;
120 }
121
122 void wxTextCtrl::SetSize(int x, int y, int width, int height, int sizeFlags)
123 {
124 wxControl::SetSize( x , y , width , height , sizeFlags ) ;
125 }
126
127 // Clipboard operations
128 void wxTextCtrl::Copy()
129 {
130 TEHandle teH ;
131 long size ;
132
133 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
134 TECopy( teH ) ;
135 }
136
137 void wxTextCtrl::Cut()
138 {
139 TEHandle teH ;
140 long size ;
141
142 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
143 TECut( teH ) ;
144 // MacInvalidateControl() ;
145 }
146
147 void wxTextCtrl::Paste()
148 {
149 TEHandle teH ;
150 long size ;
151
152 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
153 TEPaste( teH ) ;
154 // MacInvalidateControl() ;
155 }
156
157 void wxTextCtrl::SetEditable(bool editable)
158 {
159 if ( editable )
160 UMAActivateControl( m_macControl ) ;
161 else
162 UMADeactivateControl( m_macControl ) ;
163 }
164
165 void wxTextCtrl::SetInsertionPoint(long pos)
166 {
167 SetSelection( pos , pos ) ;
168 }
169
170 void wxTextCtrl::SetInsertionPointEnd()
171 {
172 long pos = GetLastPosition();
173 SetInsertionPoint(pos);
174 }
175
176 long wxTextCtrl::GetInsertionPoint() const
177 {
178 ControlEditTextSelectionRec selection ;
179 TEHandle teH ;
180 long size ;
181
182 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
183 // UMAGetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection , &size ) ;
184 return (**teH).selStart ;
185 }
186
187 long wxTextCtrl::GetLastPosition() const
188 {
189 ControlEditTextSelectionRec selection ;
190 TEHandle teH ;
191 long size ;
192
193 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
194
195 // UMAGetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection , &size ) ;
196 return (**teH).teLength ;
197 }
198
199 void wxTextCtrl::Replace(long from, long to, const wxString& value)
200 {
201 TEHandle teH ;
202 long size ;
203
204 ControlEditTextSelectionRec selection ;
205
206 selection.selStart = from ;
207 selection.selEnd = to ;
208 UMASetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
209 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
210 TESetSelect( from , to , teH ) ;
211 TEDelete( teH ) ;
212 TEInsert( value , value.Length() , teH ) ;
213 // MacInvalidateControl() ;
214 }
215
216 void wxTextCtrl::Remove(long from, long to)
217 {
218 TEHandle teH ;
219 long size ;
220
221 ControlEditTextSelectionRec selection ;
222
223 selection.selStart = from ;
224 selection.selEnd = to ;
225 UMASetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
226 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
227 TEDelete( teH ) ;
228 // MacInvalidateControl() ;
229 }
230
231 void wxTextCtrl::SetSelection(long from, long to)
232 {
233 ControlEditTextSelectionRec selection ;
234 TEHandle teH ;
235 long size ;
236
237 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
238
239 selection.selStart = from ;
240 selection.selEnd = to ;
241
242 UMASetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
243 TESetSelect( selection.selStart , selection.selEnd , teH ) ;
244 }
245
246 bool wxTextCtrl::LoadFile(const wxString& file)
247 {
248 if (!wxFileExists(file))
249 return FALSE;
250
251 m_fileName = file;
252
253 Clear();
254
255 #ifndef __WXMAC__
256 ifstream input((char*) (const char*) file, ios::nocreate | ios::in);
257 #else
258 ifstream input((char*) (const char*) file, ios::in);
259 #endif
260 if (!input.bad())
261 {
262 struct stat stat_buf;
263 if (stat(file, &stat_buf) < 0)
264 return FALSE;
265 // This may need to be a bigger buffer than the file size suggests,
266 // if it's a UNIX file. Give it an extra 1000 just in case.
267 char *tmp_buffer = (char*)malloc((size_t)(stat_buf.st_size+1+1000));
268 long no_lines = 0;
269 long pos = 0;
270 while (!input.eof() && input.peek() != EOF)
271 {
272 input.getline(wxBuffer, 500);
273 int len = strlen(wxBuffer);
274 wxBuffer[len] = 13;
275 wxBuffer[len+1] = 10;
276 wxBuffer[len+2] = 0;
277 strcpy(tmp_buffer+pos, wxBuffer);
278 pos += strlen(wxBuffer);
279 no_lines++;
280 }
281
282 // TODO add line
283
284 free(tmp_buffer);
285
286 return TRUE;
287 }
288 return FALSE;
289 }
290
291 // If file is null, try saved file name first
292 // Returns TRUE if succeeds.
293 bool wxTextCtrl::SaveFile(const wxString& file)
294 {
295 wxString theFile(file);
296 if (theFile == "")
297 theFile = m_fileName;
298 if (theFile == "")
299 return FALSE;
300 m_fileName = theFile;
301
302 ofstream output((char*) (const char*) theFile);
303 if (output.bad())
304 return FALSE;
305
306 // TODO get and save text
307
308 return FALSE;
309 }
310
311 void wxTextCtrl::WriteText(const wxString& text)
312 {
313 TEHandle teH ;
314 long size ;
315
316 memcpy( wxBuffer, text , text.Length() ) ;
317 wxBuffer[text.Length() ] = 0 ;
318 // wxMacConvertNewlines( wxBuffer , wxBuffer ) ;
319
320 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
321
322 TEInsert( wxBuffer , strlen( wxBuffer) , teH ) ;
323 Refresh() ;
324 }
325
326 void wxTextCtrl::AppendText(const wxString& text)
327 {
328 SetInsertionPointEnd();
329 WriteText(text);
330 }
331
332 void wxTextCtrl::Clear()
333 {
334 TEHandle teH ;
335 long size ;
336 ControlEditTextSelectionRec selection ;
337
338 selection.selStart = 0 ;
339 selection.selEnd = 32767 ;
340
341 UMASetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
342
343 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
344 TECut( teH ) ;
345 // MacInvalidateControl() ;
346 }
347
348 bool wxTextCtrl::IsModified() const
349 {
350 return TRUE;
351 }
352
353 // Makes 'unmodified'
354 void wxTextCtrl::DiscardEdits()
355 {
356 // TODO
357 }
358
359 int wxTextCtrl::GetNumberOfLines() const
360 {
361 // TODO
362 return 0;
363 }
364
365 long wxTextCtrl::XYToPosition(long x, long y) const
366 {
367 // TODO
368 return 0;
369 }
370
371 void wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
372 {
373 // TODO
374 }
375
376 void wxTextCtrl::ShowPosition(long pos)
377 {
378 // TODO
379 }
380
381 int wxTextCtrl::GetLineLength(long lineNo) const
382 {
383 return GetValue().Length();
384 }
385
386 wxString wxTextCtrl::GetLineText(long lineNo) const
387 {
388 return GetValue();
389 }
390
391 /*
392 * Text item
393 */
394
395 void wxTextCtrl::Command(wxCommandEvent & event)
396 {
397 SetValue (event.GetString());
398 ProcessCommand (event);
399 }
400
401 void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
402 {
403 // By default, load the first file into the text window.
404 if (event.GetNumberOfFiles() > 0)
405 {
406 LoadFile(event.GetFiles()[0]);
407 }
408 }
409
410 void wxTextCtrl::OnChar(wxKeyEvent& event)
411 {
412 bool handleIt = true ;
413 switch( event.KeyCode() )
414 {
415 case WXK_RETURN:
416 {
417 /* Oh yes it will, because we also specify DLGC_WANTCHARS
418 wxASSERT_MSG( m_windowStyle & wxTE_PROCESS_ENTER,
419 "this text ctrl should never receive return" );
420 */
421
422 if ( (m_windowStyle & wxTE_MULTILINE) == 0 )
423 {
424 wxWindow* parent = GetParent() ;
425 while( parent )
426 {
427 if ( parent->GetDefaultItem() )
428 {
429 wxButton *defaultBtn = parent->GetDefaultItem() ;
430 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, defaultBtn->GetId() );
431 event.SetEventObject(defaultBtn);
432 defaultBtn->Command(event);
433 return ;
434 }
435 parent = parent->GetParent() ;
436 } ;
437 }
438 break;
439 }
440 case WXK_TAB:
441 // only produce navigation event if we don't process TAB ourself or
442 // if it's a Shift-Tab keypress (we assume nobody will ever need
443 // this key combo for himself)
444 //
445 // NB: Notice that Ctrl-Tab is handled elsewhere and Alt-Tab is
446 // handled by Windows
447 if ( event.ShiftDown() || !(m_windowStyle & wxTE_PROCESS_TAB) )
448 {
449 wxNavigationKeyEvent eventNav;
450 eventNav.SetDirection(!event.ShiftDown());
451 eventNav.SetWindowChange(FALSE);
452 eventNav.SetEventObject(this);
453
454 if ( GetEventHandler()->ProcessEvent(eventNav) )
455 return;
456 }
457 break;
458 }
459 if ( handleIt )
460 {
461 EventRecord *ev = wxTheApp->MacGetCurrentEvent() ;
462 short keycode ;
463 short keychar ;
464 keychar = short(ev->message & charCodeMask);
465 keycode = short(ev->message & keyCodeMask) >> 8 ;
466 UMAHandleControlKey( m_macControl , keycode , keychar , ev->modifiers ) ;
467 if ( keychar >= 0x20 )
468 {
469 {
470 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
471 wxString val(GetValue());
472 if ( !val.IsNull() )
473 event.m_commandString = WXSTRINGCAST val;
474 event.SetEventObject( this );
475 ProcessCommand(event);
476 }
477 }
478 }
479 }
480 // The streambuf code was partly taken from chapter 3 by Jerry Schwarz of
481 // AT&T's "C++ Lanuage System Release 3.0 Library Manual" - Stein Somers
482
483 //=========================================================================
484 // Called then the buffer is full (gcc 2.6.3)
485 // or when "endl" is output (Borland 4.5)
486 //=========================================================================
487 // Class declaration using multiple inheritance doesn't work properly for
488 // Borland. See note in wb_text.h.
489 #ifndef NO_TEXT_WINDOW_STREAM
490 int wxTextCtrl::overflow(int c)
491 {
492 // Make sure there is a holding area
493 if ( allocate()==EOF )
494 {
495 wxError("Streambuf allocation failed","Internal error");
496 return EOF;
497 }
498
499 // Verify that there are no characters in get area
500 if ( gptr() && gptr() < egptr() )
501 {
502 wxError("Who's trespassing my get area?","Internal error");
503 return EOF;
504 }
505
506 // Reset get area
507 setg(0,0,0);
508
509 // Make sure there is a put area
510 if ( ! pptr() )
511 {
512 /* This doesn't seem to be fatal so comment out error message */
513 // wxError("Put area not opened","Internal error");
514 setp( base(), base() );
515 }
516
517 // Determine how many characters have been inserted but no consumed
518 int plen = pptr() - pbase();
519
520 // Now Jerry relies on the fact that the buffer is at least 2 chars
521 // long, but the holding area "may be as small as 1" ???
522 // And we need an additional \0, so let's keep this inefficient but
523 // safe copy.
524
525 // If c!=EOF, it is a character that must also be comsumed
526 int xtra = c==EOF? 0 : 1;
527
528 // Write temporary C-string to wxTextWindow
529 {
530 char *txt = new char[plen+xtra+1];
531 memcpy(txt, pbase(), plen);
532 txt[plen] = (char)c; // append c
533 txt[plen+xtra] = '\0'; // append '\0' or overwrite c
534 // If the put area already contained \0, output will be truncated there
535 AppendText(txt);
536 delete[] txt;
537 }
538
539 // Reset put area
540 setp(pbase(), epptr());
541
542 #if defined(__WATCOMC__)
543 return __NOT_EOF;
544 #elif defined(zapeof) // HP-UX (all cfront based?)
545 return zapeof(c);
546 #else
547 return c!=EOF ? c : 0; // this should make everybody happy
548 #endif
549 }
550
551 //=========================================================================
552 // called then "endl" is output (gcc) or then explicit sync is done (Borland)
553 //=========================================================================
554 int wxTextCtrl::sync()
555 {
556 // Verify that there are no characters in get area
557 if ( gptr() && gptr() < egptr() )
558 {
559 wxError("Who's trespassing my get area?","Internal error");
560 return EOF;
561 }
562
563 if ( pptr() && pptr() > pbase() ) return overflow(EOF);
564
565 return 0;
566 /* OLD CODE
567 int len = pptr() - pbase();
568 char *txt = new char[len+1];
569 strncpy(txt, pbase(), len);
570 txt[len] = '\0';
571 (*this) << txt;
572 setp(pbase(), epptr());
573 delete[] txt;
574 return 0;
575 */
576 }
577
578 //=========================================================================
579 // Should not be called by a "ostream". Used by a "istream"
580 //=========================================================================
581 int wxTextCtrl::underflow()
582 {
583 return EOF;
584 }
585 #endif
586
587 wxTextCtrl& wxTextCtrl::operator<<(const wxString& s)
588 {
589 AppendText(s);
590 return *this;
591 }
592
593 wxTextCtrl& wxTextCtrl::operator<<(float f)
594 {
595 wxString str;
596 str.Printf("%.2f", f);
597 AppendText(str);
598 return *this;
599 }
600
601 wxTextCtrl& wxTextCtrl::operator<<(double d)
602 {
603 wxString str;
604 str.Printf("%.2f", d);
605 AppendText(str);
606 return *this;
607 }
608
609 wxTextCtrl& wxTextCtrl::operator<<(int i)
610 {
611 wxString str;
612 str.Printf("%d", i);
613 AppendText(str);
614 return *this;
615 }
616
617 wxTextCtrl& wxTextCtrl::operator<<(long i)
618 {
619 wxString str;
620 str.Printf("%ld", i);
621 AppendText(str);
622 return *this;
623 }
624
625 wxTextCtrl& wxTextCtrl::operator<<(const char c)
626 {
627 char buf[2];
628
629 buf[0] = c;
630 buf[1] = 0;
631 AppendText(buf);
632 return *this;
633 }
634