diff --git a/odcread.cc b/odcread.cc
index e790fdd36bcdc3b211d3c4d277cf9462ee6db3dd..d2aa025e12713d516fa5355d7d4751a03c5a1a50 100644 (file)
--- a/odcread.cc
+++ b/odcread.cc
#include <textmodel.h>
#include <visitor.h>
+// Character encoding conversions
+#include <langinfo.h> // determine the current charset
+#include <locale.h> // locale support
+#include <iconv.h> // charset conversions
+#include <errno.h> // error codes
+#include <string.h> // string descriptions of error codes
+
namespace odc {
class Context {
public:
virtual void foldRight() {
terminateContext();
}
+ char *getCharSet() {
+ return nl_langinfo(CODESET);
+ }
virtual void textShortPiece(const ShortPiece *piece) {
- std::string text = piece->getText();
- d_context.top()->addPiece(text);
+ std::string str = convert((char *)piece->getBuffer(), piece->size() + 1, (char *)"ISO-8859-1", 1);
+ d_context.top()->addPiece(str);
}
virtual void textLongPiece(const LongPiece *piece) {
- throw "Long Piece not handled";
- //std::string text = piece->getText();
- //d_context.top()->addPiece(text);
+ std::string str = convert((char *)piece->getBuffer(), piece->size() + 2, (char *)"UCS-2", 2);
+ d_context.top()->addPiece(str);
+ }
+
+ /**
+ * Convert an input character buffer in the given encoding to the
+ * locale's encoding.
+ */
+ std::string convert(char *in, size_t bytesIn, char *encodingIn, size_t inBytesPerChar) {
+ // Convert from the input encoding to the locale's encoding
+ iconv_t conv = iconv_open(getCharSet(), encodingIn);
+
+ // Handle errors by throwing a readable message
+ if (conv == (iconv_t)-1) {
+ std::string str("iconv initialization error: ");
+ str += strerror(errno);
+ throw str.c_str();
+ }
+
+ // Assume at most 4 bytes per character are needed
+ size_t bytesOut = 4 * bytesIn / inBytesPerChar;
+
+ // Allocate the output buffer
+ char *out = new char[bytesOut];
+ char *outPtr = out;
+
+ // Perform conversion
+ size_t rval = iconv(conv, &in, &bytesIn, &outPtr, &bytesOut);
+ if (rval == (size_t)-1) {
+ std::string str("iconv error: ");
+ str += strerror(errno);
+ throw str.c_str();
+ }
+
+ // Free the iconv state
+ iconv_close(conv);
+
+ // Copy result into a std::string
+ std::string str(out);
+ delete out;
+
+ // Convert newlines
+ for (std::string::iterator it = str.begin(); it < str.end(); ++it) {
+ if (*it == '\r') *it = '\n';
+ }
+
+ return str;
}
};
if (argc < 2) {
return 1;
}
+
+ // Set the locale according to the terminal's environment
+ setlocale(LC_ALL, "");
+
std::ifstream in(argv[1], std::ios::in | std::ios::binary);
- odc::Store* s = odc::importDocument(in);
+
+ odc::Store* s;
+ try {
+ s = odc::importDocument(in);
+ } catch (int trap) {
+ std::cerr << "Exception in parsing file: BlackBox trap no. " << trap << std::endl;
+ return 2;
+ } catch (const char * exception) {
+ std::cerr << "Exception in parsing file: " << exception << std::endl;
+ return 2;
+ }
// std::cout << s->toPlainText() << std::endl;
// std::cout << std::endl << std::endl;
- odc::MyVisitor visitor;
- s->accept(visitor);
+ try {
+ odc::MyVisitor visitor;
+ s->accept(visitor);
+ } catch (const char * exception) {
+ std::cerr << "Exception in processing document: " << exception << std::endl;
+ return 3;
+ }
// std::cout << s->toString() << std::endl;
// std::cout << in.tellg() << " " << in.eof() << std::endl;