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