void TextBuffer::setTextCodec (QTextCodec *codec) { m_textCodec = codec; // enforce bom for some encodings int mib = m_textCodec->mibEnum (); if (mib == 1013 || mib == 1014 || mib == 1015) // utf16 setGenerateByteOrderMark (true); if (mib == 1017 || mib == 1018 || mib == 1019) // utf32 setGenerateByteOrderMark (true); }
bool TextBuffer::load (const QString &filename, bool &encodingErrors) { // fallback codec must exist Q_ASSERT (m_fallbackTextCodec); // codec must be set! Q_ASSERT (m_textCodec); /** * first: clear buffer in any case! */ clear (); /** * check if this is a normal file or not, else exit */ KDE_struct_stat sbuf; if (KDE::stat(filename, &sbuf) != 0 || !S_ISREG(sbuf.st_mode)) return false; /** * construct the file loader for the given file, with correct prober type */ Kate::TextLoader file (filename, m_encodingProberType); /** * triple play, maximal three loading rounds * 0) use the given encoding, be done, if no encoding errors happen * 1) use BOM to decided if unicode or if that fails, use encoding prober, if no encoding errors happen, be done * 2) use fallback encoding, be done, if no encoding errors happen * 3) use again given encoding, be done in any case */ for (int i = 0; i < 4; ++i) { /** * kill all blocks beside first one */ for (int b = 1; b < m_blocks.size(); ++b) { TextBlock* block = m_blocks.at(b); block->m_lines.clear (); delete block; } m_blocks.resize (1); /** * remove lines in first block */ m_blocks.last()->m_lines.clear (); m_lines = 0; /** * try to open file, with given encoding * in round 0 + 3 use the given encoding from user * in round 1 use 0, to trigger detection * in round 2 use fallback */ QTextCodec *codec = m_textCodec; if (i == 1) codec = 0; else if (i == 2) codec = m_fallbackTextCodec; if (!file.open (codec)) { // create one dummy textline, in any case m_blocks.last()->appendLine (TextLine (new TextLineData())); m_lines++; return false; } // read in all lines... encodingErrors = false; while ( !file.eof() ) { // read line int offset = 0, length = 0; bool currentError = !file.readLine (offset, length); encodingErrors = encodingErrors || currentError; // bail out on encoding error, if not last round! if (encodingErrors && i < 3) { kDebug (13020) << "Failed try to load file" << filename << "with codec" << (file.textCodec() ? file.textCodec()->name() : "(null)"); break; } // get unicode data for this line const QChar *unicodeData = file.unicode () + offset; // construct new text line with content from file TextLine textLine = TextLine (new TextLineData(QString (unicodeData, length))); // ensure blocks aren't too large if (m_blocks.last()->lines() >= m_blockSize) m_blocks.append (new TextBlock (this, m_blocks.last()->startLine() + m_blocks.last()->lines())); m_blocks.last()->appendLine (textLine); m_lines++; } // if no encoding error, break out of reading loop if (!encodingErrors) { // remember used codec m_textCodec = file.textCodec (); break; } } // remember if BOM was found if (file.byteOrderMarkFound ()) setGenerateByteOrderMark (true); // remember eol mode, if any found in file if (file.eol() != eolUnknown) setEndOfLineMode (file.eol()); // remember mime type for filter device m_mimeTypeForFilterDev = file.mimeTypeForFilterDev (); // assert that one line is there! Q_ASSERT (m_lines > 0); // report CODEC + ERRORS kDebug (13020) << "Loaded file " << filename << "with codec" << m_textCodec->name() << (encodingErrors ? "with" : "without") << "encoding errors"; // report BOM kDebug (13020) << (file.byteOrderMarkFound () ? "Found" : "Didn't find") << "byte order mark"; // report filter device mime-type kDebug (13020) << "used filter device for mime-type" << m_mimeTypeForFilterDev; // emit success emit loaded (filename, encodingErrors); // file loading worked, modulo encoding problems return true; }