// used to build the zone tree // true is returned if the GRect is known for this object, // and false, if the rectangle's size is just the parent size. static bool make_child_layer( DjVuTXT::Zone &parent, const lt_XMLTags &tag, ByteStream &bs, const int height, const double ws, const double hs) { bool retval=true; // the plugin thinks there are only Pages, Lines and Words // so we don't make Paragraphs, Regions and Columns zones // if we did the plugin is not able to search the text but // DjVuToText writes out all the text anyway DjVuTXT::Zone *self_ptr; char sepchar; const GUTF8String name(tag.get_name()); if(name == charactertag) { self_ptr=parent.append_child(); self_ptr->ztype = DjVuTXT::CHARACTER; sepchar=0; }else if(name == wordtag) { self_ptr=parent.append_child(); self_ptr->ztype = DjVuTXT::WORD; sepchar=' '; }else if(name == linetag) { self_ptr=parent.append_child(); self_ptr->ztype = DjVuTXT::LINE; sepchar=DjVuTXT::end_of_line; }else if(name == paragraphtag) { self_ptr=parent.append_child(); self_ptr->ztype = DjVuTXT::PARAGRAPH; sepchar=DjVuTXT::end_of_paragraph; }else if(name == regiontag) { self_ptr=parent.append_child(); self_ptr->ztype = DjVuTXT::REGION; sepchar=DjVuTXT::end_of_region; }else if(name == pagecolumntag) { self_ptr=parent.append_child(); self_ptr->ztype = DjVuTXT::COLUMN; sepchar=DjVuTXT::end_of_column; }else { self_ptr = &parent; self_ptr->ztype = DjVuTXT::PAGE; sepchar=0; } DjVuTXT::Zone &self = *self_ptr; self.text_start = bs.tell(); int &xmin=self.rect.xmin, &ymin=self.rect.ymin, &xmax=self.rect.xmax, &ymax=self.rect.ymax; GRect default_rect; default_rect.xmin=max(parent.rect.xmax,parent.rect.xmin); default_rect.xmax=min(parent.rect.xmax,parent.rect.xmin); default_rect.ymin=max(parent.rect.ymax,parent.rect.ymin); default_rect.ymax=min(parent.rect.ymax,parent.rect.ymin); // Now if there are coordinates, use those. GPosition pos(tag.get_args().contains("coords")); if(pos) { GList<int> rectArgs; intList(tag.get_args()[pos], rectArgs); if((pos=rectArgs)) { xmin=(int)(ws*(double)rectArgs[pos]); if(++pos) { ymin=(height-1)-(int)(hs*(double)rectArgs[pos]); if(++pos) { xmax=(int)(ws*(double)rectArgs[pos]); if(++pos) { ymax=(height-1)-(int)(hs*(double)rectArgs[pos]); if(xmin>xmax) // Make sure xmin is really minimum { const int t=xmin; xmin=xmax; xmax=t; } if(ymin>ymax) // Make sure ymin is really minimum { const int t=ymin; ymin=ymax; ymax=t; } } } } } } if(self.ztype == DjVuTXT::CHARACTER) { if(! pos) { self.rect=default_rect; retval=false; } const GUTF8String raw(tag.get_raw().fromEscaped()); const int i=raw.nextNonSpace(0); bs.writestring(raw.substr(i,raw.firstEndSpace(i)-i)); if(sepchar) bs.write8(sepchar); self.text_length = bs.tell() - self.text_start; }else if(pos) { pos=tag.get_content(); if(pos) { for(pos=tag.get_content(); pos; ++pos) { const GP<lt_XMLTags> t(tag.get_content()[pos].tag); make_child_layer(self, *t, bs, height,ws,hs); } if(sepchar) bs.write8(sepchar); self.text_length = bs.tell() - self.text_start; }else { const GUTF8String raw(tag.get_raw().fromEscaped()); const int i=raw.nextNonSpace(0); bs.writestring(raw.substr(i,raw.firstEndSpace(i)-i)); if(sepchar) bs.write8(sepchar); self.text_length = bs.tell() - self.text_start; } }else { self.rect=default_rect; if((pos=tag.get_content())) { do { const GP<lt_XMLTags> t(tag.get_content()[pos].tag); const GRect save_rect(self.rect); self.rect=default_rect; if ((retval = make_child_layer(self, *t, bs, height, ws, hs))) { xmin=min(save_rect.xmin,xmin); xmax=max(save_rect.xmax,xmax); ymin=min(save_rect.ymin,ymin); ymax=max(save_rect.ymax,ymax); }else { // If the child doesn't have coordinates, we need to use a box // at least as big as the parent's coordinates. xmin=min(save_rect.xmin,default_rect.xmax); xmax=max(save_rect.xmax,default_rect.xmin); ymin=min(save_rect.ymin,default_rect.ymax); ymax=max(save_rect.ymax,default_rect.ymin); for(; pos; ++pos) { const GP<lt_XMLTags> t(tag.get_content()[pos].tag); make_child_layer(self, *t, bs, height,ws,hs); } break; } } while(++pos); if(sepchar) bs.write8(sepchar); self.text_length = bs.tell() - self.text_start; }else { const GUTF8String raw(tag.get_raw().fromEscaped()); const int i=raw.nextNonSpace(0); bs.writestring(raw.substr(i,raw.firstEndSpace(i)-i)); if(sepchar) bs.write8(sepchar); self.text_length = bs.tell() - self.text_start; } } parent.rect.xmin=min(xmin,parent.rect.xmin); parent.rect.ymin=min(ymin,parent.rect.ymin); parent.rect.xmax=max(xmax,parent.rect.xmax); parent.rect.ymax=max(ymax,parent.rect.ymax); if(xmin>xmax) { const int t=xmin; xmin=xmax; xmax=t; } if(ymin>ymax) { const int t=ymin; ymin=ymax; ymax=t; } // DjVuPrintMessage("(%d,%d)(%d,%d)<<<\\%o>>>\n", // xmin,ymin,xmax,ymax, sepchar); return retval; }
void Client::start(){ bool hasHeader = false; Packet pak; ByteStream header; ByteStream* read = &header; pak.mData.reserve(1024); header.reserve(16); header.setDataSize(startHandshake()); bool error = false; while(!error){ if(mSocket->canRead()){ int result = mSocket->read(read->data() + read->tell(), read->size() - read->tell()); if(result == -1){ error = true; break; }else if(result > 0){ read->skip(result); if(read->tell() != read->size()) continue; if(mHandshakeStage != HS_COMPLETE){ read->setDataSize(onReceiveHandshake(read)); read->seek(0); continue; } if(!hasHeader){ uint32 hSize = Packet::getHeaderSize(*read); if(read->size() < hSize){ read->setDataSize(hSize); continue; } read->seek(0); pak.deserialise(*read); hasHeader = true; read = &pak.mData; read->seek(0); read->setDataSize(pak.mHeader.mBodySize + pak.mHeader.mBodySize / mChunkSize); }else{ read->dechunk(mChunkSize); read->seek(0); onReceivePacket(&pak); hasHeader = false; read = &header; read->seek(0); read->setDataSize(1); } } if(error) break; } if(mSocket->canWrite() && mSendData.size()){ mSendLock->lock(); while(mSendData.size()){ ByteStream* stream = mSendData.front(); mSocket->write(stream->data(), stream->size()); delete stream; mSendData.pop(); } mSendLock->unlock(); } }; mSocket->getLastError(); disconnect(); }
static toff_t seekproc(thandle_t h, toff_t offset, int mode) { ByteStream *bs = (ByteStream*)h; bs->seek((long)offset, mode); return (toff_t)bs->tell(); }