]> git.saurik.com Git - wxWidgets.git/blob - src/common/textbuf.cpp
small fixes
[wxWidgets.git] / src / common / textbuf.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        src/common/textbuf.cpp
3 // Purpose:     implementation of wxTextBuffer class
4 // Created:     14.11.01
5 // Author:      Morten Hanssen, Vadim Zeitlin
6 // RCS-ID:      $Id$
7 // Copyright:   (c) 1998-2001 wxWidgets team
8 // Licence:     wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // headers
13 // ============================================================================
14
15 #include  "wx/wxprec.h"
16
17 #ifdef __BORLANDC__
18     #pragma hdrstop
19 #endif  //__BORLANDC__
20
21 #ifndef WX_PRECOMP
22     #include  "wx/string.h"
23     #include  "wx/intl.h"
24     #include  "wx/log.h"
25 #endif
26
27 #include "wx/textbuf.h"
28
29 // ============================================================================
30 // wxTextBuffer class implementation
31 // ============================================================================
32
33 // ----------------------------------------------------------------------------
34 // static methods (always compiled in)
35 // ----------------------------------------------------------------------------
36
37 // default type is the native one
38 // the native type under Mac OS X is:
39 //   - Unix when compiling with the Apple Developer Tools (__UNIX__)
40 //   - Mac when compiling with CodeWarrior (__WXMAC__)
41
42 const wxTextFileType wxTextBuffer::typeDefault =
43 #if defined(__WINDOWS__) || defined(__DOS__) || defined(__PALMOS__)
44   wxTextFileType_Dos;
45 #elif defined(__UNIX__)
46   wxTextFileType_Unix;
47 #elif defined(__WXMAC__)
48   wxTextFileType_Mac;
49 #elif defined(__OS2__)
50   wxTextFileType_Os2;
51 #else
52   wxTextFileType_None;
53   #error  "wxTextBuffer: unsupported platform."
54 #endif
55
56 const wxChar *wxTextBuffer::GetEOL(wxTextFileType type)
57 {
58     switch ( type ) {
59         default:
60             wxFAIL_MSG(wxT("bad buffer type in wxTextBuffer::GetEOL."));
61             // fall through nevertheless - we must return something...
62
63         case wxTextFileType_None: return wxEmptyString;
64         case wxTextFileType_Unix: return wxT("\n");
65         case wxTextFileType_Dos:  return wxT("\r\n");
66         case wxTextFileType_Mac:  return wxT("\r");
67     }
68 }
69
70 wxString wxTextBuffer::Translate(const wxString& text, wxTextFileType type)
71 {
72     // don't do anything if there is nothing to do
73     if ( type == wxTextFileType_None )
74         return text;
75
76     // nor if it is empty
77     if ( text.empty() )
78         return text;
79
80     wxString eol = GetEOL(type), result;
81
82     // optimization: we know that the length of the new string will be about
83     // the same as the length of the old one, so prealloc memory to aviod
84     // unnecessary relocations
85     result.Alloc(text.Len());
86
87     wxChar chLast = 0;
88     for ( const wxChar *pc = text.c_str(); *pc; pc++ )
89     {
90         wxChar ch = *pc;
91         switch ( ch ) {
92             case _T('\n'):
93                 // Dos/Unix line termination
94                 result += eol;
95                 chLast = 0;
96                 break;
97
98             case _T('\r'):
99                 if ( chLast == _T('\r') ) {
100                     // Mac empty line
101                     result += eol;
102                 }
103                 else {
104                     // just remember it: we don't know whether it is just "\r"
105                     // or "\r\n" yet
106                     chLast = _T('\r');
107                 }
108                 break;
109
110             default:
111                 if ( chLast == _T('\r') ) {
112                     // Mac line termination
113                     result += eol;
114
115                     // reset chLast to avoid inserting another eol before the
116                     // next character
117                     chLast = 0;
118                 }
119
120                 // add to the current line
121                 result += ch;
122         }
123     }
124
125     if ( chLast ) {
126         // trailing '\r'
127         result += eol;
128     }
129
130     return result;
131 }
132
133 #if wxUSE_TEXTBUFFER
134
135 wxString wxTextBuffer::ms_eof;
136
137 // ----------------------------------------------------------------------------
138 // ctors & dtor
139 // ----------------------------------------------------------------------------
140
141 wxTextBuffer::wxTextBuffer(const wxString& strBufferName)
142             : m_strBufferName(strBufferName)
143 {
144     m_nCurLine = 0;
145     m_isOpened = false;
146 }
147
148 wxTextBuffer::~wxTextBuffer()
149 {
150     // required here for Darwin
151 }
152
153 // ----------------------------------------------------------------------------
154 // buffer operations
155 // ----------------------------------------------------------------------------
156
157 bool wxTextBuffer::Exists() const
158 {
159     return OnExists();
160 }
161
162 bool wxTextBuffer::Create(const wxString& strBufferName)
163 {
164     m_strBufferName = strBufferName;
165
166     return Create();
167 }
168
169 bool wxTextBuffer::Create()
170 {
171     // buffer name must be either given in ctor or in Create(const wxString&)
172     wxASSERT( !m_strBufferName.empty() );
173
174     // if the buffer already exists do nothing
175     if ( Exists() ) return false;
176
177     if ( !OnOpen(m_strBufferName, WriteAccess) )
178         return false;
179
180     OnClose();
181     return true;
182 }
183
184 bool wxTextBuffer::Open(const wxString& strBufferName, const wxMBConv& conv)
185 {
186     m_strBufferName = strBufferName;
187
188     return Open(conv);
189 }
190
191 bool wxTextBuffer::Open(const wxMBConv& conv)
192 {
193     // buffer name must be either given in ctor or in Open(const wxString&)
194     wxASSERT( !m_strBufferName.empty() );
195
196     // open buffer in read-only mode
197     if ( !OnOpen(m_strBufferName, ReadAccess) )
198         return false;
199
200     // read buffer into memory
201     m_isOpened = OnRead(conv);
202
203     OnClose();
204
205     return m_isOpened;
206 }
207
208 // analyse some lines of the buffer trying to guess it's type.
209 // if it fails, it assumes the native type for our platform.
210 wxTextFileType wxTextBuffer::GuessType() const
211 {
212     wxASSERT( IsOpened() );
213
214     // scan the buffer lines
215     size_t nUnix = 0,     // number of '\n's alone
216            nDos  = 0,     // number of '\r\n'
217            nMac  = 0;     // number of '\r's
218
219     // we take MAX_LINES_SCAN in the beginning, middle and the end of buffer
220     #define MAX_LINES_SCAN    (10)
221     size_t nCount = m_aLines.GetCount() / 3,
222         nScan =  nCount > 3*MAX_LINES_SCAN ? MAX_LINES_SCAN : nCount / 3;
223
224     #define   AnalyseLine(n)              \
225         switch ( m_aTypes[n] ) {            \
226             case wxTextFileType_Unix: nUnix++; break;   \
227             case wxTextFileType_Dos:  nDos++;  break;   \
228             case wxTextFileType_Mac:  nMac++;  break;   \
229             default: wxFAIL_MSG(_T("unknown line terminator")); \
230         }
231
232     size_t n;
233     for ( n = 0; n < nScan; n++ )     // the beginning
234         AnalyseLine(n);
235     for ( n = (nCount - nScan)/2; n < (nCount + nScan)/2; n++ )
236         AnalyseLine(n);
237     for ( n = nCount - nScan; n < nCount; n++ )
238         AnalyseLine(n);
239
240     #undef   AnalyseLine
241
242     // interpret the results (FIXME far from being even 50% fool proof)
243     if ( nScan > 0 && nDos + nUnix + nMac == 0 ) {
244         // no newlines at all
245         wxLogWarning(_("'%s' is probably a binary buffer."), m_strBufferName.c_str());
246     }
247     else {
248         #define   GREATER_OF(t1, t2) n##t1 == n##t2 ? typeDefault               \
249                                                 : n##t1 > n##t2             \
250                                                     ? wxTextFileType_##t1   \
251                                                     : wxTextFileType_##t2
252
253 #if !defined(__WATCOMC__) || wxCHECK_WATCOM_VERSION(1,4)
254         if ( nDos > nUnix )
255             return GREATER_OF(Dos, Mac);
256         else if ( nDos < nUnix )
257             return GREATER_OF(Unix, Mac);
258         else {
259             // nDos == nUnix
260             return nMac > nDos ? wxTextFileType_Mac : typeDefault;
261         }
262 #endif // __WATCOMC__
263
264         #undef    GREATER_OF
265     }
266
267     return typeDefault;
268 }
269
270
271 bool wxTextBuffer::Close()
272 {
273     Clear();
274     m_isOpened = false;
275
276     return true;
277 }
278
279 bool wxTextBuffer::Write(wxTextFileType typeNew, const wxMBConv& conv)
280 {
281     return OnWrite(typeNew, conv);
282 }
283
284 #endif // wxUSE_TEXTBUFFER