Example #1
0
DOMNode* DeltaReverse( DOMNode *deltaElement, DOMDocument *reversedDoc ) {
	
	vddprintf(("    reversing time-version header\n"));

	DOMNode* reversedElement = reversedDoc->importNode( deltaElement, false );

	//DOMString from = deltaElement.getAttributes().getNamedItem("from").getNodeValue() ;
        //DOMString to   = deltaElement.getAttributes().getNamedItem("to"  ).getNodeValue() ;
        const XMLCh* from = deltaElement->getAttributes()->getNamedItem(XMLString::transcode("from"))->getNodeValue() ;
        const XMLCh* to = deltaElement->getAttributes()->getNamedItem(XMLString::transcode("to"))->getNodeValue() ;
        
	reversedElement->getAttributes()->getNamedItem(XMLString::transcode("to"))->setNodeValue( from );
	reversedElement->getAttributes()->getNamedItem(XMLString::transcode("from"))->setNodeValue( to );

	DOMNode* fromXidMap = deltaElement->getAttributes()->getNamedItem(XMLString::transcode("fromXidMap"));
	DOMNode* toXidMap   = deltaElement->getAttributes()->getNamedItem(XMLString::transcode("toXidMap"));
	if (fromXidMap!=NULL) {
          //DOMString from = fromXidMap.getNodeValue();
		reversedElement->getAttributes()->getNamedItem(XMLString::transcode("toXidMap"))->setNodeValue( fromXidMap->getNodeValue() );
	}
	if (toXidMap!=NULL) {
          //DOMString to = toXidMap.getNodeValue();
		reversedElement->getAttributes()->getNamedItem(XMLString::transcode("fromXidMap"))->setNodeValue( toXidMap->getNodeValue() );
	}

	// No chanhges in the delta -> ok
	if (!deltaElement->hasChildNodes()) return( reversedElement );
	
	// Input : read Elementary Operation
	DOMNode* child = deltaElement->getFirstChild() ;
	
	// Output : precedent will be used to write Elementary Operation in reverse order
	DOMNode* precedent = NULL; // =NULL by default

	while (child != NULL) {
		if (child->getNodeType()!=DOMNode::ELEMENT_NODE) THROW_AWAY(("Bad type (%d) for Delta Operation Node", (int)child->getNodeType()));
		DOMElement* operationNode = (DOMElement*) child ;
		XyLatinStr operation(child->getLocalName());
		
		// Reverse DELETE into INSERT
		
		if (strcmp(operation, "d")==0) {
			vddprintf(("    reversing delete into insert\n"));
			DOMElement* iElement = reversedDoc->createElementNS(XYDIFF_XYDELTA_NS, XMLString::transcode("xy:i")) ;
			CopyAttr(iElement, operationNode, XMLString::transcode("par"), true);
			CopyAttr(iElement, operationNode, XMLString::transcode("pos"), true);
			CopyAttr(iElement, operationNode, XMLString::transcode("xm"), true);
			CopyAttr(iElement, operationNode, XMLString::transcode("move"), false);
			CopyAttr(iElement, operationNode, XMLString::transcode("update"), false);
			CopyContent(iElement, operationNode);
			reversedElement->insertBefore( iElement, precedent ) ;
			precedent = iElement ;
			}

		// Reverse INSERT into DELETE
		
		else if (strcmp(operation, "i")==0) {
	    		vddprintf(("    reversing insert into delete\n")); 
			DOMElement *iElement = reversedDoc->createElementNS(XYDIFF_XYDELTA_NS, XMLString::transcode("xy:d")) ;
			CopyAttr(iElement, operationNode, XMLString::transcode("par"), true);
			CopyAttr(iElement, operationNode, XMLString::transcode("pos"), true);
			CopyAttr(iElement, operationNode, XMLString::transcode("xm"), true);
			CopyAttr(iElement, operationNode, XMLString::transcode("move"), false);
			CopyAttr(iElement, operationNode, XMLString::transcode("update"), false);
			CopyContent(iElement, operationNode);
			reversedElement->insertBefore( iElement, precedent ) ;
			precedent = iElement ;
		  }
	// Attribute Update
		else if (strcmp(operation, "au")==0) {
			vddprintf(("    reversing attribute update\n"));
			
			//DOMString xidElem  = operationNode.getAttributes().getNamedItem("xid").getNodeValue();
			//DOMString attrName = operationNode.getAttributes().getNamedItem("a").getNodeValue();
			//DOMString oldValue = operationNode.getAttributes().getNamedItem("ov").getNodeValue();
			//DOMString newValue = operationNode.getAttributes().getNamedItem("nv").getNodeValue();
			const XMLCh* xidElem = operationNode->getAttributes()->getNamedItem(XMLString::transcode("xid"))->getNodeValue();
                        const XMLCh* attrName = operationNode->getAttributes()->getNamedItem(XMLString::transcode("a"))->getNodeValue();
                        const XMLCh* oldValue = operationNode->getAttributes()->getNamedItem(XMLString::transcode("ov"))->getNodeValue();
                        const XMLCh* newValue = operationNode->getAttributes()->getNamedItem(XMLString::transcode("nv"))->getNodeValue();
                        

			DOMElement* auElement = reversedDoc->createElementNS(XYDIFF_XYDELTA_NS, XMLString::transcode("xy:au"));
			auElement->setAttribute(XMLString::transcode("xid"), xidElem);
			auElement->setAttribute(XMLString::transcode("a"),   attrName);
			auElement->setAttribute(XMLString::transcode("nv"),  oldValue);
			auElement->setAttribute(XMLString::transcode("ov"),  newValue);
			
			reversedElement->insertBefore(auElement, precedent);
			precedent = auElement ;
		}
	// Attribute Delete
		else if (strcmp(operation, "ad")==0) {
			vddprintf(("    reversing attribute insert into attribute delete\n"));

			//DOMString xidElem  = operationNode.getAttributes().getNamedItem("xid").getNodeValue();
			//DOMString attrName = operationNode.getAttributes().getNamedItem("a").getNodeValue();
			//DOMString attrVal  = operationNode.getAttributes().getNamedItem("v").getNodeValue();
			const XMLCh* xidElem  = operationNode->getAttributes()->getNamedItem(XMLString::transcode("xid"))->getNodeValue();
			const XMLCh* attrName = operationNode->getAttributes()->getNamedItem(XMLString::transcode("a"))->getNodeValue();
			const XMLCh* attrVal  = operationNode->getAttributes()->getNamedItem(XMLString::transcode("v"))->getNodeValue();
			
			DOMElement* aiElement = reversedDoc->createElementNS(XYDIFF_XYDELTA_NS, XMLString::transcode("xy:ai"));
			aiElement->setAttribute(XMLString::transcode("xid"), xidElem);
			aiElement->setAttribute(XMLString::transcode("a"), attrName);
			aiElement->setAttribute(XMLString::transcode("v"), attrVal);
			
			reversedElement->insertBefore(aiElement, precedent);
			precedent = aiElement ;
		}
	// Attribute Insert
		else if (strcmp(operation, "ai")==0) {
			vddprintf(("    reversing attribute delete into attribute insert\n"));

			//DOMString xidElem  = operationNode.getAttributes().getNamedItem("xid").getNodeValue();
			//DOMString attrName = operationNode.getAttributes().getNamedItem("a").getNodeValue();
			//DOMString attrVal  = operationNode.getAttributes().getNamedItem("v").getNodeValue();
                        const XMLCh* xidElem  = operationNode->getAttributes()->getNamedItem(XMLString::transcode("xid"))->getNodeValue();
			const XMLCh* attrName = operationNode->getAttributes()->getNamedItem(XMLString::transcode("a"))->getNodeValue();
			const XMLCh* attrVal  = operationNode->getAttributes()->getNamedItem(XMLString::transcode("v"))->getNodeValue();
			
			DOMElement* adElement = reversedDoc->createElementNS(XYDIFF_XYDELTA_NS, XMLString::transcode("xy:ad"));
			adElement->setAttribute(XMLString::transcode("xid"), xidElem);
			adElement->setAttribute(XMLString::transcode("a"), attrName);
			adElement->setAttribute(XMLString::transcode("v"), attrVal);
			
			reversedElement->insertBefore(adElement, precedent);
			precedent = adElement ;
		}
		
    // Reverse UPDATE to UPDATE
		
		else if (strcmp(operation, "u")==0) {
			vddprintf(("    reversing update\n"));
		  
			DOMNode* oldValue = child->getFirstChild() ;
			if ( oldValue==NULL ) throw ReverseUpdateException("<update> has no child!");
			
			DOMNode* newValue = oldValue->getNextSibling() ;
			if ( newValue==NULL ) throw ReverseUpdateException("<update> has only one child!");
			
			//DOMString xid= child.getAttributes().getNamedItem("xid").getNodeValue() ;
                        const XMLCh* xid= child->getAttributes()->getNamedItem(XMLString::transcode("xid"))->getNodeValue() ;
			
			DOMElement *uElement = reversedDoc->createElementNS(XYDIFF_XYDELTA_NS, XMLString::transcode("xy:u")) ;
			uElement->setAttribute(XMLString::transcode("xid"), xid);
			
			DOMElement* uOld = reversedDoc->createElementNS(XYDIFF_XYDELTA_NS, XMLString::transcode("xy:ov"));
			DOMNode* uOldText = reversedDoc->importNode( newValue->getFirstChild(), true );
			uOld->appendChild( uOldText );
			
			DOMElement* uNew = reversedDoc->createElementNS(XYDIFF_XYDELTA_NS, XMLString::transcode("xy:nv"));
			DOMNode* uNewText = reversedDoc->importNode( oldValue->getFirstChild(), true );
			uNew->appendChild( uNewText );
			
			uElement->appendChild( uOld ) ;
			uElement->appendChild( uNew ) ;
			
		  reversedElement->insertBefore( uElement, precedent ) ;
			precedent = uElement ;
			}
		else if (strcmp(operation, "renameRoot")==0) {
			vddprintf(("    reversing renameRoot operation\n"));

			const XMLCh* rFrom = operationNode->getAttributes()->getNamedItem(XMLString::transcode("from"))->getNodeValue();
			const XMLCh* rTo   = operationNode->getAttributes()->getNamedItem(XMLString::transcode("to"))->getNodeValue();
			
			DOMElement *rrElement = reversedDoc->createElementNS(XYDIFF_XYDELTA_NS, XMLString::transcode("xy:renameRoot"));
			rrElement->setAttribute(XMLString::transcode("from"), rTo);
			rrElement->setAttribute(XMLString::transcode("to"), rFrom);
			
			reversedElement->insertBefore(rrElement, precedent);
			precedent = rrElement ;			
		}
		
		else {
			throw DeltaReverseException("Invalid Data", "main", "Unknown operation <" + std::string(operation) + ">")  ;
		}
				
		child = child->getNextSibling();
		}
	
	return ( reversedElement ) ;
	}
// the formatter's core, wraps the line and justifies it if needed
int TextFormatter::WrapLine(CFDC& dc, Paragraph& pp,
    FilePos& pos, LineArray& la,
    int top, int maxh)
{
    if (maxh <= 0)
        return 0;
    // process images separately
    if (pp.flags&Paragraph::image)
        return WrapImage(dc, pp, pos, la, top, maxh);
    if (pp.len == 0 || (pp.len == 1 && pp.str[0] == L' '))
    {
        dc.SelectFont(0, 0);
        int fh, fa;
        dc.GetFontSize(fh, fa);
        if (fh > maxh)
            return -1;
        Line l;
        l.pos = pos;
        l.flags = Line::first | Line::last | Line::defstyle;
        l.height = fh;
        l.base = fa;
        la.Add(l);
        pos.off = pp.len;
        return l.height;
    }
    if (m_hyphenate)
        pp.Hyphenate();
    const wchar_t *str = pp.str;
    int len = pp.len;
    Buffer<int> dx(len + 1);
    int toth = 0;
    while (toth < maxh && pos.off < len)
    {
        // 1. get text size
        int nch = len;
        int curwidth = m_width;
        int ispace = 0;
        if (pos.off == 0 && (pp.flags&(Paragraph::center | Paragraph::right)) == 0)
            AdjustIndent(curwidth, ispace, pp.lindent, pp.rindent, pp.findent, dc.GetLPX());
        else
            AdjustIndent(curwidth, ispace, pp.lindent, pp.rindent, 0, dc.GetLPX());
        dx[0] = 0;
        int lh = 1, lbase = 1;
        GetTextExtent(dc, pp, pos.off, curwidth, nch, dx + 1, lh, lbase);
        if (toth + lh > maxh)
            return -1;
        if (nch == 0)
            nch = 1;
        // 2. do word wrap
        bool addhyp = false;
        if (nch + pos.off < pp.str.size())
        {
            int i;
            for (i = nch; i > 0 && str[pos.off + i] != L' '; --i)
            {
                // wrap at existing dashes
                if (i < nch && (str[pos.off + i] == L'-' || str[pos.off + i] == 0x2013 ||
                    str[pos.off + i] == 0x2014) && i < len - 1 && (str[pos.off + i + 1] == L' ' ||
                    iswalpha(str[pos.off + i + 1])))
                {
                    ++i;
                    break;
                }
                // or at possible hyphenation points
                if (m_hyphenate && pp.cflags[pos.off + i].hyphen &&
                    dx[i] + dc.GetHypWidth() <= curwidth)
                {
                    addhyp = true;
                    break;
                }
            }
            if (i > 0)
                nch = i;
            else
                addhyp = false;
        }
        // insert it into line list
        if (pos.off == 0 && nch == pp.str.size())
        {
            // got full line
            Line l(str, len, false);
            l.pos = pos;
            l.flags = Line::first | Line::last;
            l.ispace = ispace;
            l.height = lh;
            l.base = lbase;
            if (dx[nch] < curwidth)
            {
                if (pp.flags&Paragraph::center)
                    l.ispace += (curwidth - dx[nch]) / 2;
                else if (pp.flags&Paragraph::right)
                    l.ispace += curwidth - dx[nch];
            }
            CopyAttr(l.attr, pp.cflags, len);
            for (int j = 0; j < len; ++j)
                l.dx[j] = dx[j + 1] - dx[j];
            la.Add(l);
            pos.off = len;
        }
        else
        {
            Line l(str + pos.off, nch, addhyp);
            if (addhyp)
                l.str[nch] = L'-';
            l.pos = pos;
            l.ispace = ispace;
            l.height = lh;
            l.base = lbase;
            l.flags = 0;
            if (pos.off == 0)
                l.flags |= Line::first;
            if (pos.off + nch == pp.str.size())
                l.flags |= Line::last;
            for (int j = 0; j < nch; ++j)
                l.dx[j] = dx[j + 1] - dx[j];
            int extra_width = 0;
            if (addhyp)
                l.dx[nch] = extra_width = dc.GetHypWidth();
            // 3. justify/center text if needed
            if (dx[nch] < curwidth)
            {
                if (addhyp)
                    curwidth -= extra_width;
                if (pp.flags&Paragraph::center)
                {
                    l.ispace += (curwidth - dx[nch]) / 2;
                }
                else if (pp.flags&Paragraph::right)
                {
                    l.ispace += curwidth - dx[nch];
                }
                else if ((m_justified || pp.flags&Paragraph::justify) &&
                    !(l.flags&Line::last))
                {
                    // count spaces in string
                    int nspc = 0, i;
                    for (i = 0; i < nch; ++i)
                        if (L' ' == str[pos.off + i])
                            ++nspc;
                    // and distribute extra width to them
                    if (nspc > 0)
                    {
                        int addw = (curwidth - dx[nch]) / nspc;
                        int extraddw = curwidth - dx[nch] - addw*nspc;
                        for (i = 0; i < nch; ++i)
                        {
                            if (str[pos.off + i] == L' ')
                            {
                                l.dx[i] += addw;
                                if (extraddw)
                                {
                                    ++l.dx[i];
                                    --extraddw;
                                }
                            }
                        }
                    }
                }
            }
            CopyAttr(l.attr, pp.cflags + pos.off, nch);
            if (addhyp)
                l.attr[nch] = l.attr[nch - 1];
            la.Add(l);
            pos.off += nch;
            while (pos.off < len && str[pos.off] == L' ')
                ++pos.off;
        }
        toth += lh;
    }
    return toth;
}
void GenesisCopyWindow::CopyDirectory(const char *dirname, const char *destination, const char *destdirname)
////////////////////////////////////////////////////////////////////////
{
	BEntry srcentry(dirname);
	BEntry dstentry;
	char name[B_FILE_NAME_LENGTH];
	BString fulldestdir;
	
	if (srcentry.InitCheck()!=B_OK)
		return;
		
	if (!srcentry.Exists())
		return;
		
	srcentry.GetName(name);	
	
	fulldestdir.SetTo(destination);
	if (destdirname)
		fulldestdir << "/" << destdirname;
	else
		fulldestdir << "/" << name;

	dstentry.SetTo(fulldestdir.String());
	
	if (dstentry.InitCheck()!=B_OK)
		return;
		
	if (!dstentry.Exists())
	{
		if (create_directory(fulldestdir.String(), 0777)!=B_OK)		// TODO: jo a 0777?
			return;
	}

	BDirectory dir;
	
	dir.SetTo(dirname);
	if (dir.InitCheck()==B_OK)
	{
		BEntry entry;
		
		if (dir.GetEntry(&entry)==B_OK)
		{	
			while (dir.GetNextEntry(&entry)==B_OK)			
			{
				entry.GetName(name);
								
				if (entry.IsDirectory())
				{
					BString fullname;
					
					fullname.SetTo(dirname);
					fullname << "/" << name;
					CopyDirectory(fullname.String(), fulldestdir.String());
				}
				else if (entry.IsSymLink())
				{
					BString fullname;
					
					fullname.SetTo(dirname);
					fullname << "/" << name;
					CopyLink(fullname.String(), fulldestdir.String());
				}
				else 
				{
					BString fullname;
					
					fullname.SetTo(dirname);
					fullname << "/" << name;
					CopyFile(fullname.String(), fulldestdir.String());
				}
			}
		}
	}

	// Copy attributes...
	CopyAttr(dirname, fulldestdir.String());
}
bool GenesisCopyWindow::CopyLink(const char *linkname, const char *destination, const char *destfilename)
////////////////////////////////////////////////////////////////////////
{
	BSymLink srclink;
	BSymLink dstlink;
	BDirectory dstdir;
	BEntry srcentry;
	BEntry symlinkentry;
	BPath LinkPath;
	char name[B_FILE_NAME_LENGTH];
	struct stat statbuf;
	entry_ref ref;
		
	srcentry.SetTo(linkname);
	srcentry.GetName(name);
	srcentry.GetRef(&ref);
	symlinkentry.SetTo(&ref, true);
	symlinkentry.GetPath(&LinkPath);

	if (destfilename)
		sprintf(name,"%s",destfilename);
	
	if (srcentry.GetStat(&statbuf)!=B_OK)
		return false;

	dstdir.SetTo(destination);
	
	if (dstdir.InitCheck()!=B_OK)
		return false;

	Lock();
	m_FileBar->Update(-m_FileBar->CurrentValue());	// Reset to 0.0
	m_FileBar->SetMaxValue(1);
	m_FileBar->SetTrailingText(name);
	Unlock();

	if (dstdir.CreateSymLink(name, LinkPath.Path(), &dstlink)!=B_OK && !m_SkipSymLinkCreationError)
	{
		BString text;
		
		text << "Cannot create '" << name << "' symbolic link in '" << LinkPath.Path() << "'";
		
		BAlert *myAlert = new BAlert("Copy",text.String(),"Abort","Skip all","Skip",B_WIDTH_AS_USUAL,B_OFFSET_SPACING,B_WARNING_ALERT);
		myAlert->SetShortcut(0, B_ESCAPE);
		switch (myAlert->Go())
		{
			case 0:
				Close();
				kill_thread(m_CopyThread);
				break;
			case 1:
				m_SkipSymLinkCreationError = true;
				break;
		}	

		return false;
	}

	Lock();
	m_FileBar->Update(1);
	Unlock();
		
	dstlink.SetPermissions(statbuf.st_mode);
	dstlink.SetOwner(statbuf.st_uid);
	dstlink.SetGroup(statbuf.st_gid);
	dstlink.SetModificationTime(statbuf.st_mtime);
	dstlink.SetCreationTime(statbuf.st_crtime);

	// Copy attributes...
	BString destlinkname;
	destlinkname.SetTo("");
	destlinkname << destination << "/" << name;
	CopyAttr(linkname, destlinkname.String());

	return true;
}
bool GenesisCopyWindow::CopyFile(const char *filename, const char *destination, const char *destfilename)
////////////////////////////////////////////////////////////////////////
{
	char name[B_FILE_NAME_LENGTH];
	BString destname;
	BEntry srcentry(filename);
	BEntry dstentry(destination);
	struct stat statbuf;
	ssize_t len;

	srcentry.GetName(name);

	destname.SetTo(destination);
	destname += "/";
	if (destfilename)
		destname += destfilename;
	else
		destname += name;

	BEntry dstfileentry(destname.String());
	if (dstfileentry.InitCheck()!=B_OK)
		return false;
	if (dstfileentry.Exists() && !m_OverwriteAll)
	{
		BString text;
		
		text << "File '" << name << "' already exists. Do you want to overwrite it?";
		
		BAlert *myAlert = new BAlert("Copy",text.String(),"Abort","Overwrite all","Overwrite",B_WIDTH_AS_USUAL,B_OFFSET_SPACING,B_WARNING_ALERT);
		myAlert->SetShortcut(0, B_ESCAPE);
		switch (myAlert->Go())
		{
			case 0:
				Close();
				kill_thread(m_CopyThread);
				break;
			case 1:
				m_OverwriteAll = true;
				break;
		}	
	}

	BFile srcfile(filename, B_READ_ONLY);
	BFile dstfile(destname.String(), B_WRITE_ONLY | B_CREATE_FILE);

	if (srcentry.InitCheck()!=B_OK)
		return false;
	
	if (dstentry.InitCheck()!=B_OK)
		return false;
		
	if (!srcentry.Exists())
		return false;
		
	if (!dstentry.Exists())
	{
		return false;
	}
	
	if (srcentry.GetStat(&statbuf)!=B_OK)
	{
		return false;
	}
		
	unsigned char *buf = new unsigned char[statbuf.st_blksize];
	if (!buf)
	{
		return false;
	}	

	Lock();
	m_FileBar->Update(-m_FileBar->CurrentValue());	// Reset to 0.0
	m_FileBar->SetMaxValue(statbuf.st_size);
	m_FileBar->SetTrailingText(name);
	Unlock();

	while (true)
	{
		len = srcfile.Read(buf, statbuf.st_blksize);
		if (len>0)
		{
			dstfile.Write(buf, len);
			Lock();
			m_FileBar->Update(len);
			Unlock();
		}
		else if (len<0) // error
		{
			delete [] buf;
			return false;
		}
		else	// No more bytes to copy, we are done...
			break;
	}

	dstfile.SetPermissions(statbuf.st_mode);
	dstfile.SetOwner(statbuf.st_uid);
	dstfile.SetGroup(statbuf.st_gid);
	dstfile.SetModificationTime(statbuf.st_mtime);
	dstfile.SetCreationTime(statbuf.st_crtime);

	delete [] buf;

	// Copy attributes...
	CopyAttr(filename, destname.String());

	return true;
}