Mercurial > dillo_port1.3
view src/plain.cc @ 1918:55af06da5523
merge in recent changes from main repo
author | corvid <corvid@lavabit.com> |
---|---|
date | Fri, 25 Feb 2011 08:37:13 +0000 |
parents | 2c90a2e90866 |
children |
line wrap: on
line source
/* * File: plain.cc * * Copyright (C) 2005-2007 Jorge Arellano Cid <jcid@dillo.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. */ /* * Module for decoding a text/plain object into a dw widget. */ #include "msg.h" #include "prefs.h" #include "cache.h" #include "bw.h" #include "web.hh" #include "misc.h" #include "styleengine.hh" #include "uicmd.hh" #include "dw/core.hh" #include "dw/textblock.hh" // Dw to Textblock #define DW2TB(dw) ((Textblock*)dw) using namespace dw; using namespace dw::core; class DilloPlain { private: class PlainLinkReceiver: public dw::core::Layout::LinkReceiver { public: DilloPlain *plain; bool press(dw::core::Widget *widget, int link, int img, int x, int y, dw::core::EventButton *event); }; PlainLinkReceiver plainReceiver; void addLine(char *Buf, uint_t BufSize); public: BrowserWindow *bw; Widget *dw; style::Style *widgetStyle; size_t Start_Ofs; /* Offset of where to start reading next */ int state; DilloPlain(BrowserWindow *bw); ~DilloPlain(); void write(void *Buf, uint_t BufSize, int Eof); }; /* FSM states */ enum { ST_SeekingEol, ST_Eol, ST_Eof }; /* * Exported function with C linkage. */ extern "C" { void *a_Plain_text(const char *type, void *P, CA_Callback_t *Call,void **Data); } /* * Forward declarations */ static void Plain_callback(int Op, CacheClient_t *Client); void a_Plain_free(void *data); /* * Diplain constructor. */ DilloPlain::DilloPlain(BrowserWindow *p_bw) { /* Init event receiver */ plainReceiver.plain = this; /* Init internal variables */ bw = p_bw; dw = new Textblock (prefs.limit_text_width); Start_Ofs = 0; state = ST_SeekingEol; Layout *layout = (Layout*) bw->render_layout; StyleEngine styleEngine (layout); styleEngine.startElement ("body"); styleEngine.startElement ("pre"); widgetStyle = styleEngine.wordStyle (); widgetStyle->ref (); /* The context menu */ layout->connectLink (&plainReceiver); /* Hook destructor to the dw delete call */ dw->setDeleteCallback(a_Plain_free, this); } /* * Free memory used by the DilloPlain class. */ DilloPlain::~DilloPlain() { _MSG("::~DilloPlain()\n"); widgetStyle->unref(); } /* * Receive the mouse button press event */ bool DilloPlain::PlainLinkReceiver::press (Widget *widget, int, int, int, int, EventButton *event) { _MSG("DilloPlain::PlainLinkReceiver::buttonPress\n"); if (event->button == 3) { a_UIcmd_page_popup(plain->bw, FALSE, NULL); return true; } return false; } void DilloPlain::addLine(char *Buf, uint_t BufSize) { int len; char buf[128]; char *end = Buf + BufSize; if (BufSize > 0) { // Limit word length to avoid X11 coordinate // overflow with extremely long lines. while ((len = a_Misc_expand_tabs(&Buf, end, buf, sizeof(buf)))) DW2TB(dw)->addText(buf, len, widgetStyle); } else { // Add dummy word for empty lines - otherwise the parbreak is ignored. DW2TB(dw)->addText("", 0, widgetStyle); } DW2TB(dw)->addParbreak(0, widgetStyle); } /* * Here we parse plain text and put it into the page structure. * (This function is called by Plain_callback whenever there's new data) */ void DilloPlain::write(void *Buf, uint_t BufSize, int Eof) { char *Start; uint_t i, len, MaxBytes; _MSG("DilloPlain::write Eof=%d\n", Eof); Start = (char*)Buf + Start_Ofs; MaxBytes = BufSize - Start_Ofs; i = len = 0; while ( i < MaxBytes ) { switch ( state ) { case ST_SeekingEol: if (Start[i] == '\n' || Start[i] == '\r') state = ST_Eol; else { ++i; ++len; } break; case ST_Eol: addLine(Start + i - len, len); if (Start[i] == '\r' && Start[i + 1] == '\n') ++i; if (i < MaxBytes) ++i; state = ST_SeekingEol; len = 0; break; } } Start_Ofs += i - len; if (Eof && len) { addLine(Start + i - len, len); Start_Ofs += len; } DW2TB(dw)->flush(); } /* * Set callback function and callback data for "text/" MIME major-type. */ void *a_Plain_text(const char *type, void *P, CA_Callback_t *Call, void **Data) { DilloWeb *web = (DilloWeb*)P; DilloPlain *plain = new DilloPlain(web->bw); *Call = (CA_Callback_t)Plain_callback; *Data = (void*)plain; return (void*)plain->dw; } void a_Plain_free(void *data) { _MSG("a_Plain_free! %p\n", data); delete ((DilloPlain *)data); } /* * This function is a cache client */ static void Plain_callback(int Op, CacheClient_t *Client) { DilloPlain *plain = (DilloPlain*)Client->CbData; if (Op) { /* Do the last line: */ plain->write(Client->Buf, Client->BufSize, 1); /* remove this client from our active list */ a_Bw_close_client(plain->bw, Client->Key); } else { plain->write(Client->Buf, Client->BufSize, 0); } }