]> git.saurik.com Git - wxWidgets.git/blob - src/mac/textctrl.cpp
adding the notion of cyclic group of radiobutton
[wxWidgets.git] / src / mac / 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 switch( event.KeyCode() )
413 {
414 case WXK_RETURN:
415 {
416 if ( !(m_windowStyle & wxTE_MULTILINE) )
417 {
418 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
419 event.SetEventObject( this );
420 if ( GetEventHandler()->ProcessEvent(event) )
421 return;
422 }
423 //else: multiline controls need Enter for themselves
424
425 break;
426 }
427 case WXK_TAB:
428 // always produce navigation event - even if we process TAB
429 // ourselves the fact that we got here means that the user code
430 // decided to skip processing of this TAB - probably to let it
431 // do its default job.
432 //
433 // NB: Notice that Ctrl-Tab is handled elsewhere and Alt-Tab is
434 // handled by Windows
435 {
436 wxNavigationKeyEvent eventNav;
437 eventNav.SetDirection(!event.ShiftDown());
438 eventNav.SetWindowChange(FALSE);
439 eventNav.SetEventObject(this);
440
441 if ( GetEventHandler()->ProcessEvent(eventNav) )
442 return;
443 }
444 break;
445
446 default:
447 event.Skip();
448 return;
449 }
450
451 // don't just call event.Skip() because this will cause TABs and ENTERs
452 // be passed upwards and we don't always want this - instead process it
453 // right here
454
455 // FIXME
456 event.Skip();
457 }
458 // The streambuf code was partly taken from chapter 3 by Jerry Schwarz of
459 // AT&T's "C++ Lanuage System Release 3.0 Library Manual" - Stein Somers
460
461 //=========================================================================
462 // Called then the buffer is full (gcc 2.6.3)
463 // or when "endl" is output (Borland 4.5)
464 //=========================================================================
465 // Class declaration using multiple inheritance doesn't work properly for
466 // Borland. See note in wb_text.h.
467 #ifndef NO_TEXT_WINDOW_STREAM
468 int wxTextCtrl::overflow(int c)
469 {
470 // Make sure there is a holding area
471 if ( allocate()==EOF )
472 {
473 wxError("Streambuf allocation failed","Internal error");
474 return EOF;
475 }
476
477 // Verify that there are no characters in get area
478 if ( gptr() && gptr() < egptr() )
479 {
480 wxError("Who's trespassing my get area?","Internal error");
481 return EOF;
482 }
483
484 // Reset get area
485 setg(0,0,0);
486
487 // Make sure there is a put area
488 if ( ! pptr() )
489 {
490 /* This doesn't seem to be fatal so comment out error message */
491 // wxError("Put area not opened","Internal error");
492 setp( base(), base() );
493 }
494
495 // Determine how many characters have been inserted but no consumed
496 int plen = pptr() - pbase();
497
498 // Now Jerry relies on the fact that the buffer is at least 2 chars
499 // long, but the holding area "may be as small as 1" ???
500 // And we need an additional \0, so let's keep this inefficient but
501 // safe copy.
502
503 // If c!=EOF, it is a character that must also be comsumed
504 int xtra = c==EOF? 0 : 1;
505
506 // Write temporary C-string to wxTextWindow
507 {
508 char *txt = new char[plen+xtra+1];
509 memcpy(txt, pbase(), plen);
510 txt[plen] = (char)c; // append c
511 txt[plen+xtra] = '\0'; // append '\0' or overwrite c
512 // If the put area already contained \0, output will be truncated there
513 AppendText(txt);
514 delete[] txt;
515 }
516
517 // Reset put area
518 setp(pbase(), epptr());
519
520 #if defined(__WATCOMC__)
521 return __NOT_EOF;
522 #elif defined(zapeof) // HP-UX (all cfront based?)
523 return zapeof(c);
524 #else
525 return c!=EOF ? c : 0; // this should make everybody happy
526 #endif
527 }
528
529 //=========================================================================
530 // called then "endl" is output (gcc) or then explicit sync is done (Borland)
531 //=========================================================================
532 int wxTextCtrl::sync()
533 {
534 // Verify that there are no characters in get area
535 if ( gptr() && gptr() < egptr() )
536 {
537 wxError("Who's trespassing my get area?","Internal error");
538 return EOF;
539 }
540
541 if ( pptr() && pptr() > pbase() ) return overflow(EOF);
542
543 return 0;
544 /* OLD CODE
545 int len = pptr() - pbase();
546 char *txt = new char[len+1];
547 strncpy(txt, pbase(), len);
548 txt[len] = '\0';
549 (*this) << txt;
550 setp(pbase(), epptr());
551 delete[] txt;
552 return 0;
553 */
554 }
555
556 //=========================================================================
557 // Should not be called by a "ostream". Used by a "istream"
558 //=========================================================================
559 int wxTextCtrl::underflow()
560 {
561 return EOF;
562 }
563 #endif
564
565 wxTextCtrl& wxTextCtrl::operator<<(const wxString& s)
566 {
567 AppendText(s);
568 return *this;
569 }
570
571 wxTextCtrl& wxTextCtrl::operator<<(float f)
572 {
573 wxString str;
574 str.Printf("%.2f", f);
575 AppendText(str);
576 return *this;
577 }
578
579 wxTextCtrl& wxTextCtrl::operator<<(double d)
580 {
581 wxString str;
582 str.Printf("%.2f", d);
583 AppendText(str);
584 return *this;
585 }
586
587 wxTextCtrl& wxTextCtrl::operator<<(int i)
588 {
589 wxString str;
590 str.Printf("%d", i);
591 AppendText(str);
592 return *this;
593 }
594
595 wxTextCtrl& wxTextCtrl::operator<<(long i)
596 {
597 wxString str;
598 str.Printf("%ld", i);
599 AppendText(str);
600 return *this;
601 }
602
603 wxTextCtrl& wxTextCtrl::operator<<(const char c)
604 {
605 char buf[2];
606
607 buf[0] = c;
608 buf[1] = 0;
609 AppendText(buf);
610 return *this;
611 }
612