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: textbuf.cpp 38570 2006-04-05 14:37:47Z VZ $ 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 42const 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 56const 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 70wxString 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 135wxString wxTextBuffer::ms_eof; 136 137// ---------------------------------------------------------------------------- 138// ctors & dtor 139// ---------------------------------------------------------------------------- 140 141wxTextBuffer::wxTextBuffer(const wxString& strBufferName) 142 : m_strBufferName(strBufferName) 143{ 144 m_nCurLine = 0; 145 m_isOpened = false; 146} 147 148wxTextBuffer::~wxTextBuffer() 149{ 150 // required here for Darwin 151} 152 153// ---------------------------------------------------------------------------- 154// buffer operations 155// ---------------------------------------------------------------------------- 156 157bool wxTextBuffer::Exists() const 158{ 159 return OnExists(); 160} 161 162bool wxTextBuffer::Create(const wxString& strBufferName) 163{ 164 m_strBufferName = strBufferName; 165 166 return Create(); 167} 168 169bool 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 184bool wxTextBuffer::Open(const wxString& strBufferName, const wxMBConv& conv) 185{ 186 m_strBufferName = strBufferName; 187 188 return Open(conv); 189} 190 191bool 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. 210wxTextFileType 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.Count() / 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(_("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 271bool wxTextBuffer::Close() 272{ 273 Clear(); 274 m_isOpened = false; 275 276 return true; 277} 278 279bool wxTextBuffer::Write(wxTextFileType typeNew, const wxMBConv& conv) 280{ 281 return OnWrite(typeNew, conv); 282} 283 284#endif // wxUSE_TEXTBUFFER 285