/* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */ /* AbiWord * Copyright (C) 2003 Francis James Franklin * Copyright (C) 2003 AbiSource, Inc. * * 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include #include "ut_exception.h" #include "pd_AbiWord_2.h" PD_AbiWord_2::PD_AbiWord_2 (PD_Document * doc) : m_document(doc), m_tree(0) { // } PD_AbiWord_2::~PD_AbiWord_2 () { if (m_tree) delete m_tree; } /* easy tree construction */ bool PD_AbiWord_2::a (const char * _href) { if (!m_document || !m_tree) return false; // TODO: validation Element * el = m_stack.top (); if (el == 0) return false; if (el->type () != et_p) return false; El_P * P = static_cast(el); El_A * A = 0; UT_TRY { A = new El_A(_href); } UT_CATCH(...) { A = 0; } if (A) { if (!P->ins (P->count (), A)) A = 0; } if (A == 0) return false; return m_stack.push (A); } bool PD_AbiWord_2::abiword (const char * _fileformat, const char * _template, const char * _styles, const char * _version, const char * _style) { if (!m_document) return false; if (m_tree) return false; // TODO: validation UT_TRY { m_tree = new El_AbiWord(_fileformat,_template,_styles,_version,_style); } UT_CATCH(...) { m_tree = 0; } if (m_tree == 0) return false; return true; } void PD_AbiWord_2::abiword () { // TODO } bool PD_AbiWord_2::bookmark (const char * _id) { if (!m_document || !m_tree) return false; // TODO: validation Element * el = m_stack.top (); if (el == 0) return false; bool okay = false; switch (el->type ()) { case et_a: case et_p: okay = true; break; default: break; } if (!okay) return false; El_BookMark * BookMark = 0; UT_TRY { BookMark = new El_BookMark(_id,NewID()); // TODO: handle user-defined bookmark IDs } UT_CATCH(...) { BookMark = 0; } if (BookMark == 0) return false; switch (el->type ()) { case et_a: { El_A * A = static_cast(el); okay = A->ins (A->count (), BookMark); } break; case et_p: { El_P * P = static_cast(el); okay = P->ins (P->count (), BookMark); } break; default: break; } if (!okay) return false; return true; } bool PD_AbiWord_2::br () { if (!m_document || !m_tree) return false; Element * el = m_stack.top (); if (el == 0) return false; bool okay = false; switch (el->type ()) { case et_a: case et_p: okay = true; break; default: break; } if (!okay) return false; El_Br * Br = 0; UT_TRY { Br = new El_Br; } UT_CATCH(...) { Br = 0; } if (Br == 0) return false; switch (el->type ()) { case et_a: { El_A * A = static_cast(el); okay = A->ins (A->count (), Br); } break; case et_p: { El_P * P = static_cast(el); okay = P->ins (P->count (), Br); } break; default: break; } if (!okay) return false; return true; } bool PD_AbiWord_2::cbr () { if (!m_document || !m_tree) return false; Element * el = m_stack.top (); if (el == 0) return false; bool okay = false; switch (el->type ()) { case et_a: case et_p: okay = true; break; default: break; } if (!okay) return false; El_CBr * CBr = 0; UT_TRY { CBr = new El_CBr; } UT_CATCH(...) { CBr = 0; } if (CBr == 0) return false; switch (el->type ()) { case et_a: { El_A * A = static_cast(el); okay = A->ins (A->count (), CBr); } break; case et_p: { El_P * P = static_cast(el); okay = P->ins (P->count (), CBr); } break; default: break; } if (!okay) return false; return true; } bool PD_AbiWord_2::CDATA (const UT_UTF8String & text) { if (!m_document || !m_tree) return false; Element * el = m_stack.top (); if (el == 0) return false; bool okay = false; switch (el->type ()) { case et_a: case et_field: case et_noteanchor: case et_notelink: case et_p: case et_span: okay = true; break; default: break; } if (!okay) return false; /* if the final child of the current element is CDATA then append rather than create */ if (el->count ()) if ((*el)[el->count()-1]->type () == et_CDATA) { El_CDATA * CDATA = static_cast((*el)[el->count()-1]); CDATA->m_cdata += text; return true; } El_CDATA * CDATA = 0; UT_TRY { CDATA = new El_CDATA(text); } UT_CATCH(...) { CDATA = 0; } if (CDATA == 0) return false; switch (el->type ()) { case et_a: { El_A * A = static_cast(el); okay = A->ins (A->count (), CDATA); } break; case et_field: { El_Field * Field = static_cast(el); okay = Field->ins (Field->count (), CDATA); } break; case et_p: { El_P * P = static_cast(el); okay = P->ins (P->count (), CDATA); } break; case et_span: { El_Span * Span = static_cast(el); okay = Span->ins (Span->count (), CDATA); } break; default: break; } if (!okay) return false; return true; } bool PD_AbiWord_2::cell (const char * _style, const char * _colspan, const char * _rowspan) // TODO: FIXME { if (!m_document || !m_tree) return false; // TODO: validation Element * el = m_stack.top (); if (el == 0) return false; if (el->type () != et_table) return false; El_Table * Table = static_cast(el); El_Cell * Cell = 0; UT_TRY { Cell = new El_Cell(_style); } UT_CATCH(...) { Cell = 0; } if (Cell) { if (!Table->ins (Table->count (), Cell)) Cell = 0; } if (Cell == 0) return false; return m_stack.push (Cell); } bool PD_AbiWord_2::col (UT_uint32 column, const char * _style) { // TODO } PD_AbiWord_2::El_D * PD_AbiWord_2::d (const char * _id, const char * _type) { if (!m_document || !m_tree) return 0; // TODO: validation El_Data * Data = m_tree->getData (); if (Data == 0) return 0; El_D * D = Data->insert (_id, NewID (), _type); return D; } bool PD_AbiWord_2::endnote (const char * _id) { if (!m_document || !m_tree) return false; // TODO: validation El_EndNotes * EndNotes = m_tree->getEndNotes (); if (EndNotes == 0) return false; El_EndNote * EndNote = EndNotes->insert (_id, NewID ()); if (EndNote == 0) return false; return m_stack.push (EndNote); } bool PD_AbiWord_2::field (const char * _class, const char * _style, const char * _type) { if (!m_document || !m_tree) return false; // TODO: validation Element * el = m_stack.top (); if (el == 0) return false; bool okay = false; switch (el->type ()) { case et_a: case et_p: okay = true; break; default: break; } if (!okay) return false; El_Field * Field = 0; UT_TRY { Field = new El_Field(_class,_style,_type); } UT_CATCH(...) { Field = 0; } if (Field == 0) return false; switch (el->type ()) { case et_a: { El_A * A = static_cast(el); okay = A->ins (A->count (), Field); } break; case et_p: { El_P * P = static_cast(el); okay = P->ins (P->count (), Field); } break; default: break; } if (!okay) return false; return m_stack.push (Field); } bool PD_AbiWord_2::footnote (const char * _id) { if (!m_document || !m_tree) return false; // TODO: validation El_FootNotes * FootNotes = m_tree->getFootNotes (); if (FootNotes == 0) return false; El_FootNote * FootNote = FootNotes->insert (_id, NewID ()); if (FootNote == 0) return false; return m_stack.push (FootNote); } bool PD_AbiWord_2::image (const char * _href, const char * _style) { if (!m_document || !m_tree) return false; // TODO: validation Element * el = m_stack.top (); if (el == 0) return false; bool okay = false; switch (el->type ()) { case et_a: case et_p: okay = true; break; default: break; } if (!okay) return false; El_Image * Image = 0; UT_TRY { Image = new El_Image(_href,_style); } UT_CATCH(...) { Image = 0; } if (Image == 0) return false; switch (el->type ()) { case et_a: { El_A * A = static_cast(el); okay = A->ins (A->count (), Image); } break; case et_p: { El_P * P = static_cast(el); okay = P->ins (P->count (), Image); } break; default: break; } if (!okay) return false; return true; } bool PD_AbiWord_2::iw (const char * _word) { if (!m_document || !m_tree) return false; // TODO: validation El_IgnoredWords * IgnoredWords = m_tree->getIgnoredWords (); if (IgnoredWords == 0) return false; El_IW * IW = IgnoredWords->insert (_word); if (IW == 0) return false; return true; } bool PD_AbiWord_2::l (const char * _id, const char * _parent_id, const char * _type, const char * _start_value, const char * _list_decimal, const char * _list_delim) { if (!m_document || !m_tree) return false; // TODO: validation El_Lists * Lists = m_tree->getLists (); if (Lists == 0) return false; El_L * L = Lists->insert (_id, NewID (), _parent_id, _type, _start_value, _list_decimal, _list_delim); if (L == 0) return false; return true; } bool PD_AbiWord_2::m (const char * _key, const char * _value) { if (!m_document || !m_tree) return false; // TODO: validation El_MetaData * MetaData = m_tree->getMetaData (); if (MetaData == 0) return false; El_M * M = MetaData->insert (_key, _value); if (M == 0) return false; return true; } bool PD_AbiWord_2::noteanchor (const char * _class, const char * _style) { if (!m_document || !m_tree) return false; // TODO: validation Element * el = m_stack.top (); if (el == 0) return false; El_NoteAnchor * NoteAnchor = 0; switch (el->type ()) { case et_endnote: { El_EndNote * EndNote = static_cast(el); NoteAnchor = &(el->m_note_anchor); } break; case et_footnote: { El_FootNote * FootNote = static_cast(el); NoteAnchor = &(el->m_note_anchor); } break; default: break; } if (NoteAnchor == 0) return false; NoteAnchor->m_style_class = _class; NoteAnchor->m_style = _style; return m_stack.push (NoteAnchor); } bool PD_AbiWord_2::notelink (const char * _href, const char * _class, const char * _style, const char * _type) { if (!m_document || !m_tree) return false; // TODO: validation Element * el = m_stack.top (); if (el == 0) return false; bool okay = false; switch (el->type ()) { case et_a: case et_p: okay = true; break; default: break; } if (!okay) return false; El_NoteLink * NoteLink = 0; UT_TRY { NoteLink = new El_NoteLink(_href,_class,_style,_type); } UT_CATCH(...) { NoteLink = 0; } if (NoteLink == 0) return false; switch (el->type ()) { case et_a: { El_A * A = static_cast(el); okay = A->ins (A->count (), NoteLink); } break; case et_p: { El_P * P = static_cast(el); okay = P->ins (P->count (), NoteLink); } break; default: break; } if (!okay) return false; return m_stack.push (NoteLink); } bool PD_AbiWord_2::p (const char * _class, const char * _style, const char * _list_id, const char * _level) { if (!m_document || !m_tree) return false; // TODO: validation Element * el = m_stack.top (); if (el == 0) return false; bool okay = false; switch (el->type ()) { case et_cell: case et_endnote: case et_footnote: case et_section: okay = true; break; default: break; } if (!okay) return false; El_P * P = 0; UT_TRY { P = new El_P(_class,_style,_list_id,_level); } UT_CATCH(...) { P = 0; } if (P == 0) return false; switch (el->type ()) { case et_cell: { El_Cell * Cell = static_cast(el); okay = Cell->ins (Cell->count (), P); } break; case et_endnote: { El_EndNote * EndNote = static_cast(el); okay = EndNote->ins (EndNote->count (), P); } break; case et_footnote: { El_FootNote * FootNote = static_cast(el); okay = FootNote->ins (FootNote->count (), P); } break; case et_section: { El_Section * Section = static_cast(el); okay = Section->ins (Section->count (), P); } break; default: break; } if (!okay) return false; return m_stack.push (P); } bool PD_AbiWord_2::pagesize (const char * _page_type, const char * _page_scale, const char * _width, const char * _height, const char * _orientation, const char * _units) { if (!m_document || !m_tree) return false; // TODO: validation El_PageSize * PageSize = m_tree->insert (_page_type, _page_scale, _width, _height, _orientation, _units); if (PageSize == 0) return false; return true; } bool PD_AbiWord_2::pbr () { if (!m_document || !m_tree) return false; Element * el = m_stack.top (); if (el == 0) return false; bool okay = false; switch (el->type ()) { case et_a: case et_p: okay = true; break; default: break; } if (!okay) return false; El_PBr * PBr = 0; UT_TRY { PBr = new El_PBr; } UT_CATCH(...) { PBr = 0; } if (PBr == 0) return false; switch (el->type ()) { case et_a: { El_A * A = static_cast(el); okay = A->ins (A->count (), PBr); } break; case et_p: { El_P * P = static_cast(el); okay = P->ins (P->count (), PBr); } break; default: break; } if (!okay) return false; return true; } bool PD_AbiWord_2::r (const char * _id, const char * _reviewer) { if (!m_document || !m_tree) return false; // TODO: validation El_Revisions * Revisions = m_tree->getRevisions (); if (Revisions == 0) return false; El_R * R = Revisions->insert (_id, NewID (), _reviewer); if (R == 0) return false; return true; } bool PD_AbiWord_2::row (const char * _style) { // TODO } bool PD_AbiWord_2::s (const char * _name, const char * _type, const char * _style, const char * _based_on, const char * _followed_by) { if (!m_document || !m_tree) return false; // TODO: validation El_Styles * Styles = m_tree->getStyles (); if (Styles == 0) return false; El_S * S = Styles->insert (_name, _type, _style, _based_on, _followed_by); if (S == 0) return false; return true; } bool PD_AbiWord_2::section (const char * _id, const char * _type, const char * _style, const char * _header_id, const char * _footer_id, const char * _columns, const char * _column_gap) { if (!m_document || !m_tree) return false; // TODO: validation El_Section * Section = m_tree->insert (_id, NewID (), _type, _style, _header_id, _footer_id, _columns, _column_gap); if (Section == 0) return false; return m_stack.push (Section); } bool PD_AbiWord_2::span (const char * _class, const char * _style) { if (!m_document || !m_tree) return false; // TODO: validation Element * el = m_stack.top (); if (el == 0) return false; bool okay = false; switch (el->type ()) { case et_a: case et_field: case et_noteanchor: case et_notelink: case et_p: okay = true; break; default: break; } if (!okay) return false; El_Span * Span = 0; UT_TRY { Span = new El_Span(_class,_style); } UT_CATCH(...) { Span = 0; } if (Span == 0) return false; switch (el->type ()) { case et_a: { El_A * A = static_cast(el); okay = A->ins (A->count (), Span); } break; case et_field: { El_Field * Field = static_cast(el); okay = Field->ins (Field->count (), Span); } break; case et_p: { El_P * P = static_cast(el); okay = P->ins (P->count (), Span); } break; default: break; } if (!okay) return false; return m_stack.push (Span); } bool PD_AbiWord_2::table (const char * _style, UT_uint32 rows, UT_uint32 cols) // TODO: FIXME { if (!m_document || !m_tree) return false; if (rows == 0) return false; if (cols == 0) return false; // TODO: validation Element * el = m_stack.top (); if (el == 0) return false; bool okay = false; switch (el->type ()) { case et_section: { El_Section * Section = static_cast(el); okay = (Section->m_type == "flow"); } break; case et_cell: okay = true; break; default: break; } if (!okay) return false; El_Table * Table = El_Table::table (NewID(),_style,rows,cols); if (Table == 0) return false; switch (el->type ()) { case et_section: { El_Section * Section = static_cast(el); okay = Section->ins (Section->count (), Table); } break; case et_cell: { El_Cell * Cell = static_cast(el); okay = Cell->ins (Cell->count (), Table); } break; default: break; } if (!okay) return false; return m_stack.push (Table); } /* import */ bool PD_AbiWord_2::appendToDocument (); bool PD_AbiWord_2::insertInDocument (); // for adding to open document /* export */ bool PD_AbiWord_2::writeDocument (Writer * writer, bool include_meta_data, bool embed_object_data, bool strip) { if (!writer) return false; if (!m_tree) return false; UT_UTF8String cache; cache = "\n"; if (!writer->A2_write (cache)) return false; cache = "\n"; if (!writer->A2_write (cache)) return false; return m_tree->write (writer, cache, include_meta_data, embed_object_data, strip); } /* PL_Listener implementation */ bool PD_AbiWord_2::populate (PL_StruxFmtHandle sfh, const PX_ChangeRecord * pcr) { if (!m_tree) return false; Element * el = m_stack.top (); if (el == 0) return false; ElementType et = el->type (); bool okay = true; switch (pcr->getType ()) { case PX_ChangeRecord::PXT_InsertSpan: { const PX_ChangeRecord_Span * pcrs = static_cast(pcr); bool bField = pcrs->getField () ? true : false; switch (et) { case et_a: case et_p: okay = !bField; break; case et_field: case et_noteanchor: // noteanchor & notelink are field-elements case et_notelink: if (!bField) // drop out of field element { m_stack.pop (); el = m_stack.top (); if (el == 0) { okay = false; break; } et = el->type (); } break; default: okay = false; break; } if (!okay) break; if (!span (pcr->getIndexAP ())) { okay = false; break; } if (!CDATA (m_document->getPointer (pcrs->getBufIndex ()), pcrs->getLength ())) { okay = false; break; } if (m_stack.top()->type () == et_span) { // drop out of span [TODO: need to clean up spans / text later - or even here?] span (); } } break; case PX_ChangeRecord::PXT_InsertObject: { const PX_ChangeRecord_Object * pcro = static_cast(pcr); switch (et) { case et_a: case et_p: break; case et_field: case et_noteanchor: // noteanchor & notelink are field-elements case et_notelink: { m_stack.pop (); el = m_stack.top (); if (el == 0) { okay = false; break; } et = el->type (); } break; default: okay = false; break; } if (!okay) break; switch (pcro->getObjectType ()) { case PTO_Image: okay = image (pcr->getIndexAP ()); break; case PTO_Field: okay = field (pcr->getIndexAP ()); break; case PTO_Bookmark: okay = bookmark (pcr->getIndexAP ()); break; case PTO_Hyperlink: { if (et == et_a) a (); const PP_AttrProp * pAP = 0; if (m_pDocument->getAttrProp (api, &pAP)) { const XML_Char * href = 0; if (pAP->getAttribute ("xlink:href", href)) { okay = a (reinterpret_cast(href)); } } } break; default: okay = false; // shouldn't happen break; } } break; case PX_ChangeRecord::PXT_InsertFmtMark: { /* What is this supposed to be? An empty ?? * ?? - in which case, do we need a new element? * * TODO? */ } break; default: okay = false; // shouldn't happen break; } return okay; } bool PD_AbiWord_2::populateStrux (PL_StruxDocHandle sdh, const PX_ChangeRecord * pcr, PL_StruxFmtHandle * psfh) { *psfh = 0; // we don't need this if (!m_tree) return false; if (pcr->getType () != PX_ChangeRecord::PXT_InsertStrux) return false; const PX_ChangeRecord_Strux * pcrx = static_cast(pcr); bool okay = true; switch (pcrx->getStruxType ()) { case PTX_Section: case PTX_SectionHdrFtr: { m_stack.clear (); okay = section (pcr->getIndexAP ()); } break; case PTX_SectionTable: { okay = m_stack.popTo (et_section, et_cell); if (!okay) break; okay = table (pcr->getIndexAP ()); } break; case PTX_SectionCell: { okay = m_stack.popTo (et_table); if (!okay) break; okay = cell (pcr->getIndexAP ()); } break; case PTX_SectionFootnote: { okay = footnote (pcr->getIndexAP ()); } break; case PTX_SectionEndnote: { okay = endnote (pcr->getIndexAP ()); } break; case PTX_SectionMarginnote: { // TODO: okay = marginnote (pcr->getIndexAP ()); } break; case PTX_SectionFrame: { // TODO: okay = frame (pcr->getIndexAP ()); } break; case PTX_EndTable: { okay = m_stack.popTo (et_table); if (!okay) break; table (); } break; case PTX_EndCell: { okay = m_stack.popTo (et_cell); if (!okay) break; cell (); } break; case PTX_EndFootnote: { okay = m_stack.popTo (et_footnote); if (!okay) break; footnote (); } break; case PTX_EndEndnote: { okay = m_stack.popTo (et_endnote); if (!okay) break; endnote (); } break; case PTX_EndMarginnote: { /* TODO: * okay = m_stack.popTo (et_endnote); * if (!okay) break; * * endnote (); */ } break; case PTX_EndFrame: { /* TODO: * okay = m_stack.popTo (et_frame); * if (!okay) break; * * frame (); */ } break; case PTX_Block: { if (m_stack.popTo (et_p)) m_stack.pop (); Element * el = m_stack.top (); if (el == 0) return false; ElementType et = el->type (); switch (et) { case et_cell: case et_endnote: case et_footnote: case et_section: break; default: okay = false; break; } if (!okay) break; okay = p (pcr->getIndexAP ()); } break; default: okay = false; break; } return okay; } /* empty method */ bool PD_AbiWord_2::change (PL_StruxFmtHandle sfh, const PX_ChangeRecord * pcr) { return true; } /* empty method */ bool PD_AbiWord_2::insertStrux (PL_StruxFmtHandle sfh, const PX_ChangeRecord * pcr, PL_StruxDocHandle sdhNew, PL_ListenerId lid, void (* pfnBindHandles) (PL_StruxDocHandle sdhNew, PL_ListenerId lid, PL_StruxFmtHandle sfhNew)) { return true; } /* empty method */ bool PD_AbiWord_2::signal (UT_uint32 iSignal) { return true; } bool PD_AbiWord_2::CDATA (const UT_UCSChar * buffer, UT_uint32 length) { return CDATA (UT_UTF8String(buffer,length)); } bool PD_AbiWord_2::bookmark (PT_AttrPropIndex api) { const PP_AttrProp * pAP = 0; bool bHaveAP = m_pDocument->getAttrProp (api, &pAP); if (!bHaveAP) return false; const XML_Char * type = = 0; if (!pAP->getAttribute ("type", type)) return false; if (UT_strcmp (type, "start") != 0) return true; // ignore non-start bookmarks const XML_Char * name = 0; if (!pAP->getAttribute ("name", name)) return false; return bookmark (reinterpret_cast(name)); } bool PD_AbiWord_2::cell (PT_AttrPropIndex api) { const PP_AttrProp * pAP = 0; bool bHaveAP = m_pDocument->getAttrProp (api, &pAP); // TODO return true; } bool PD_AbiWord_2::endnote (PT_AttrPropIndex api) { const PP_AttrProp * pAP = 0; bool bHaveAP = m_pDocument->getAttrProp (api, &pAP); // TODO return true; } bool PD_AbiWord_2::footnote (PT_AttrPropIndex api) { const PP_AttrProp * pAP = 0; bool bHaveAP = m_pDocument->getAttrProp (api, &pAP); // TODO return true; } bool PD_AbiWord_2::field (PT_AttrPropIndex api) { const PP_AttrProp * pAP = 0; bool bHaveAP = m_pDocument->getAttrProp (api, &pAP); // TODO: handle end/footnote anchor/ref separation return true; } bool PD_AbiWord_2::image (PT_AttrPropIndex api) { const PP_AttrProp * pAP = 0; bool bHaveAP = m_pDocument->getAttrProp (api, &pAP); // TODO // const XML_Char* image_name = getObjectKey(api, (const XML_Char*) "dataid"); // if (image_name) // m_pUsedImages.insert(image_name); return true; } bool PD_AbiWord_2::p (PT_AttrPropIndex api) { const PP_AttrProp * pAP = 0; bool bHaveAP = m_pDocument->getAttrProp (api, &pAP); // TODO return true; } bool PD_AbiWord_2::section (PT_AttrPropIndex api) { const PP_AttrProp * pAP = 0; bool bHaveAP = m_pDocument->getAttrProp (api, &pAP); // TODO return true; } bool PD_AbiWord_2::span (PT_AttrPropIndex api) { const PP_AttrProp * pAP = 0; bool bHaveAP = m_pDocument->getAttrProp (api, &pAP); // TODO return false; } bool PD_AbiWord_2::table (PT_AttrPropIndex api) { const PP_AttrProp * pAP = 0; bool bHaveAP = m_pDocument->getAttrProp (api, &pAP); // TODO return true; } UT_UTF8String styleFromProps (const PP_AttrProp * pAP) { UT_UTF8String style; if (pAP == 0) return style; // TODO // if (style.byteLength ()) style += "; "; return style; } #if 0 General: Property Name CSS Equiv Name Values in AbiWord ------------------------------------------------------------------------------------------------ bgcolor background-color <6-digit hex (no #)> | transparent color color <6-digit hex (no #)> dir-override dir ltr | rtl dom-dir ?? ltr | rtl field-font ?? (?) font-family font-family generic | font-size font-size (?) font-stretch ?? normal | (?) font-style font-style normal | italic font-variant font-variant (?) font-weight font-weight normal | bold height height (?) keep-together ?? (?) keep-with-next ?? (?) lang ?? (?) line-height ?? (?) list-tag ?? (?) margin-bottom margin-bottom (?) margin-left margin-left (?) margin-right margin-right (?) margin-top margin-top (?) orphans orphans (?) tabstops ?? (?) text-align text-align left | right | center | justify text-decoration text-decoration [underline || overline || line-through || topline || bottomline] | none text-indent text-indent (?) text-position vertical-align [superscript || subscript] | normal widows widows (?) width width (?) Section: Property Name CSS Equiv Name Values in AbiWord ------------------------------------------------------------------------------------------------ page-margin-footer ?? (?) page-margin-header ?? (?) Cells: Property Name CSS Equiv Name Values in AbiWord ------------------------------------------------------------------------------------------------ bot-attach ?? (?) left-attach ?? (?) right-attach ?? (?) top-attach ?? (?) Tables: Property Name CSS Equiv Name Values in AbiWord ------------------------------------------------------------------------------------------------ table-col-spacing ?? (?) table-column-leftpos ?? (?) table-column-props ?? (?) ?? >> Secondly, what is the meaning of the table property "table-col-spacing"? > The spacing between left edge of text of one column and the right edge of > the next in the next column in a table. Note: see http://www.w3.org/TR/2003/WD-CSS21-20030128/tables.html #endif