Browse Source

Add support for indented tables in ODT export

* etc/styles/OrgOdtContentTemplate.xml
(OrgIndentedSection-Level-*): New section styles. These
sections are indented to the same level as the corresponding
list entries.  These sections hold tables that occur within a
list.
(OrgTable): Increased relative width from 90% to 96% for
aesthetic reasons.

* lisp/org-odt.el (org-odt-table-indentedp): New variable
(org-odt-begin-table): Modified.  If the table is within a
list, temporarily leave the list and begin an indented section
before emitting the table.
(org-odt-end-table): Modified.  If the table was within a
list, close the indented section and re-open the list
immediately after ending the table.
(org-odt-continue-list, org-odt-discontinue-list): Helper
routines to temporarily discontinue and continue a list.
(org-odt-list-stack-stashed): New variable to hold the state
of a pending list.
(org-odt-begin-list, org-odt-begin-list-item)
(org-odt-end-list-item): Modified. Handle nitty-gritties for
continuing a list and list item.
(org-odt-section-count): New variable that keeps track of
section count.  Used in conjunction with naming of sections.
(org-odt-begin-section, org-odt-end-section): New defuns.
(org-odt-init-outfile): Initialize
`org-odt-list-stack-stashed' and `org-odt-section-count'.

* lisp/org-lparse.el (org-lparse-list-item-count): Removed. Was a
superfluous variable.
(org-lparse-list-level): Removed.  Now derived from
`org-lparse-list-stack'.
(org-lparse-list-stack): New.  List that records the list
types - ordered, unordered or descriptive - in the following
order: self, parent, grand-parent etc.
(org-do-lparse): Added, removed above let-bound vars.
Disallowed regular tables within list-table block.
(org-lparse-begin-list, org-lparse-end-list)
(org-lparse-begin-list-item, org-lparse-end-list-item):
Propagate above changes.

OpenDocument doesn't permit tables to occur in the middle of a
list.  Use list continuations and indented sections to typeset
indented tables.

Fixes the following bug:
http://lists.gnu.org/archive/html/emacs-orgmode/2012-01/msg00515.html
Jambunathan K 8 years ago
parent
commit
bf1d5cfe95
3 changed files with 172 additions and 77 deletions
  1. 54 1
      etc/styles/OrgOdtContentTemplate.xml
  2. 60 69
      lisp/org-lparse.el
  3. 58 7
      lisp/org-odt.el

+ 54 - 1
etc/styles/OrgOdtContentTemplate.xml

@@ -46,8 +46,61 @@
 
   <!-- automatic styles -->
   <office:automatic-styles>
+    <!-- Section styles -->
+    <style:style style:name="OrgIndentedSection-Level-1" style:family="section">
+      <style:section-properties text:dont-balance-text-columns="false" fo:margin-left="1.281cm" fo:margin-right="0cm" style:editable="false">
+	<style:columns fo:column-count="1" fo:column-gap="0cm"/>
+      </style:section-properties>
+    </style:style>
+    <style:style style:name="OrgIndentedSection-Level-2" style:family="section">
+      <style:section-properties text:dont-balance-text-columns="false" fo:margin-left="1.905cm" fo:margin-right="0cm" style:editable="false">
+	<style:columns fo:column-count="1" fo:column-gap="0cm"/>
+      </style:section-properties>
+    </style:style>
+    <style:style style:name="OrgIndentedSection-Level-3" style:family="section">
+      <style:section-properties text:dont-balance-text-columns="false" fo:margin-left="2.54cm" fo:margin-right="0cm" style:editable="false">
+	<style:columns fo:column-count="1" fo:column-gap="0cm"/>
+      </style:section-properties>
+    </style:style>
+    <style:style style:name="OrgIndentedSection-Level-4" style:family="section">
+      <style:section-properties text:dont-balance-text-columns="false" fo:margin-left="3.175cm" fo:margin-right="0cm" style:editable="false">
+	<style:columns fo:column-count="1" fo:column-gap="0cm"/>
+      </style:section-properties>
+    </style:style>
+    <style:style style:name="OrgIndentedSection-Level-5" style:family="section">
+      <style:section-properties text:dont-balance-text-columns="false" fo:margin-left="3.81cm" fo:margin-right="0cm" style:editable="false">
+	<style:columns fo:column-count="1" fo:column-gap="0cm"/>
+      </style:section-properties>
+    </style:style>
+    <style:style style:name="OrgIndentedSection-Level-6" style:family="section">
+      <style:section-properties text:dont-balance-text-columns="false" fo:margin-left="4.445cm" fo:margin-right="0cm" style:editable="false">
+	<style:columns fo:column-count="1" fo:column-gap="0cm"/>
+      </style:section-properties>
+    </style:style>
+    <style:style style:name="OrgIndentedSection-Level-7" style:family="section">
+      <style:section-properties text:dont-balance-text-columns="false" fo:margin-left="5.08cm" fo:margin-right="0cm" style:editable="false">
+	<style:columns fo:column-count="1" fo:column-gap="0cm"/>
+      </style:section-properties>
+    </style:style>
+    <style:style style:name="OrgIndentedSection-Level-8" style:family="section">
+      <style:section-properties text:dont-balance-text-columns="false" fo:margin-left="5.715cm" fo:margin-right="0cm" style:editable="false">
+	<style:columns fo:column-count="1" fo:column-gap="0cm"/>
+      </style:section-properties>
+    </style:style>
+    <style:style style:name="OrgIndentedSection-Level-9" style:family="section">
+      <style:section-properties text:dont-balance-text-columns="false" fo:margin-left="6.35cm" fo:margin-right="0cm" style:editable="false">
+	<style:columns fo:column-count="1" fo:column-gap="0cm"/>
+      </style:section-properties>
+    </style:style>
+    <style:style style:name="OrgIndentedSection-Level-10" style:family="section">
+      <style:section-properties text:dont-balance-text-columns="false" fo:margin-left="6.985cm" fo:margin-right="0cm" style:editable="false">
+	<style:columns fo:column-count="1" fo:column-gap="0cm"/>
+      </style:section-properties>
+    </style:style>
+
+    <!-- Table styles -->
     <style:style style:name="OrgTable" style:family="table">
-      <style:table-properties style:rel-width="90%" fo:margin-top="0cm" fo:margin-bottom="0.20cm" table:align="center"/>
+      <style:table-properties style:rel-width="96%" fo:margin-top="0cm" fo:margin-bottom="0.20cm" table:align="center"/>
     </style:style>
 
     <style:style style:name="OrgTableColumn" style:family="table-column">

+ 60 - 69
lisp/org-lparse.el

@@ -598,11 +598,7 @@ version."
 	 (org-lparse-par-open-stashed 0)
 
 	 ;; list related vars
-	 (org-lparse-list-level 0)	; list level starts at 1. A
-					; value of 0 implies we are
-					; outside of any list
-	 (org-lparse-list-item-count 0)
-	 org-lparse-list-stack
+	 (org-lparse-list-stack '())
 
 	 ;; list-table related vars
 	 org-lparse-list-table-p
@@ -1081,10 +1077,11 @@ version."
 		    table-buffer (nreverse table-buffer)
 		    table-orig-buffer (nreverse table-orig-buffer))
 	      (org-lparse-end-paragraph)
+	      (when org-lparse-list-table-p
+		(error "Regular tables are not allowed in a list-table block"))
 	      (org-lparse-insert 'TABLE table-buffer table-orig-buffer)))
 
 	   ;; Normal lines
-
 	   (t
 	    ;; This line either is list item or end a list.
 	    (when (get-text-property 0 'list-item line)
@@ -2104,8 +2101,6 @@ When TITLE is nil, just close all open levels."
 		      ("d" . description)))))
 
 ;; following vars are bound during `org-do-lparse'
-(defvar org-lparse-list-level)
-(defvar org-lparse-list-item-count)
 (defvar org-lparse-list-stack)
 (defvar org-lparse-list-table:table-row)
 (defvar org-lparse-list-table:lines)
@@ -2147,73 +2142,69 @@ When TITLE is nil, just close all open levels."
 ;; https://lists.gnu.org/archive/html/emacs-orgmode/2011-03/msg01101.html
 
 (defun org-lparse-begin-list (ltype)
-  (incf org-lparse-list-level)
-  (push org-lparse-list-item-count org-lparse-list-stack)
-  (setq org-lparse-list-item-count 0)
-  (cond
-   ((not org-lparse-list-table-p)
-    (org-lparse-begin 'LIST ltype))
-   ;; process LIST-TABLE
-   ((= 1 org-lparse-list-level)
-    ;; begin LIST-TABLE
-    (setq org-lparse-list-table:lines nil)
-    (setq org-lparse-list-table:table-row nil))
-   ((= 2 org-lparse-list-level)
-    (ignore))
-   (t
-    (org-lparse-begin 'LIST ltype))))
+  (push ltype org-lparse-list-stack)
+  (let ((list-level (length org-lparse-list-stack)))
+    (cond
+     ((not org-lparse-list-table-p)
+      (org-lparse-begin 'LIST ltype))
+     ;; process LIST-TABLE
+     ((= 1 list-level)
+      ;; begin LIST-TABLE
+      (setq org-lparse-list-table:lines nil)
+      (setq org-lparse-list-table:table-row nil))
+     ((= 2 list-level)
+      (ignore))
+     (t
+      (org-lparse-begin 'LIST ltype)))))
 
 (defun org-lparse-end-list (ltype)
-  (setq org-lparse-list-item-count (pop org-lparse-list-stack))
-  (decf org-lparse-list-level)
-  (cond
-   ((not org-lparse-list-table-p)
-    (org-lparse-end 'LIST ltype))
-   ;; process LIST-TABLE
-   ((= 0 org-lparse-list-level)
-    ;; end LIST-TABLE
-    (insert (org-lparse-format-list-table
-	     (nreverse org-lparse-list-table:lines))))
-   ((= 1 org-lparse-list-level)
-    (ignore))
-   (t
-    (org-lparse-end 'LIST ltype))))
+  (pop org-lparse-list-stack)
+  (let ((list-level (length org-lparse-list-stack)))
+    (cond
+     ((not org-lparse-list-table-p)
+      (org-lparse-end 'LIST ltype))
+     ;; process LIST-TABLE
+     ((= 0 list-level)
+      ;; end LIST-TABLE
+      (insert (org-lparse-format-list-table
+	       (nreverse org-lparse-list-table:lines))))
+     ((= 1 list-level)
+      (ignore))
+     (t
+      (org-lparse-end 'LIST ltype)))))
 
 (defun org-lparse-begin-list-item (ltype &optional arg headline)
-  (incf org-lparse-list-item-count)
-  (cond
-   ((not org-lparse-list-table-p)
-    (org-lparse-begin 'LIST-ITEM ltype arg headline))
-   ;; process LIST-TABLE
-   ((and (= 1 org-lparse-list-level)
-	 (= 1 org-lparse-list-item-count))
-    ;; begin TABLE-ROW for LIST-TABLE
-    (setq org-lparse-list-table:table-row nil)
-    (org-lparse-begin-list-table:table-cell))
-   ((and (= 2 org-lparse-list-level)
-	 (= 1 org-lparse-list-item-count))
-    ;; begin TABLE-CELL for LIST-TABLE
-    (org-lparse-begin-list-table:table-cell))
-   (t
-    (org-lparse-begin 'LIST-ITEM ltype arg headline))))
+  (let ((list-level (length org-lparse-list-stack)))
+    (cond
+     ((not org-lparse-list-table-p)
+      (org-lparse-begin 'LIST-ITEM ltype arg headline))
+     ;; process LIST-TABLE
+     ((= 1 list-level)
+      ;; begin TABLE-ROW for LIST-TABLE
+      (setq org-lparse-list-table:table-row nil)
+      (org-lparse-begin-list-table:table-cell))
+     ((= 2 list-level)
+      ;; begin TABLE-CELL for LIST-TABLE
+      (org-lparse-begin-list-table:table-cell))
+     (t
+      (org-lparse-begin 'LIST-ITEM ltype arg headline)))))
 
 (defun org-lparse-end-list-item (ltype)
-  (decf org-lparse-list-item-count)
-  (cond
-   ((not org-lparse-list-table-p)
-    (org-lparse-end 'LIST-ITEM ltype))
-   ;; process LIST-TABLE
-   ((and (= 1 org-lparse-list-level)
-	 (= 0 org-lparse-list-item-count))
-    ;; end TABLE-ROW for LIST-TABLE
-    (org-lparse-end-list-table:table-cell)
-    (push (nreverse org-lparse-list-table:table-row)
-	  org-lparse-list-table:lines))
-   ((= 2 org-lparse-list-level)
-    ;; end TABLE-CELL for LIST-TABLE
-    (org-lparse-end-list-table:table-cell))
-   (t
-    (org-lparse-end 'LIST-ITEM ltype))))
+  (let ((list-level (length org-lparse-list-stack)))
+    (cond
+     ((not org-lparse-list-table-p)
+      (org-lparse-end 'LIST-ITEM ltype))
+     ;; process LIST-TABLE
+     ((= 1 list-level)
+      ;; end TABLE-ROW for LIST-TABLE
+      (org-lparse-end-list-table:table-cell)
+      (push (nreverse org-lparse-list-table:table-row)
+	    org-lparse-list-table:lines))
+     ((= 2 list-level)
+      ;; end TABLE-CELL for LIST-TABLE
+      (org-lparse-end-list-table:table-cell))
+     (t
+      (org-lparse-end 'LIST-ITEM ltype)))))
 
 (defvar org-lparse-list-table:table-cell-open)
 (defun org-lparse-begin-list-table:table-cell ()

+ 58 - 7
lisp/org-odt.el

@@ -646,6 +646,15 @@ PUB-DIR is set, use this as the publishing directory."
 (defun org-odt-end-outline-text ()
   (ignore))
 
+(defvar org-odt-section-count 0)
+(defun org-odt-begin-section (style &optional name)
+  (setq name (or name (format "Section-%d" (incf org-odt-section-count))))
+  (org-lparse-insert-tag
+   "<text:section text:style-name=\"%s\" text:name=\"%s\">" style name))
+
+(defun org-odt-end-section ()
+  (org-lparse-insert-tag "</text:section>"))
+
 (defun org-odt-begin-paragraph (&optional style)
   (org-lparse-insert-tag
    "<text:p%s>" (org-odt-get-extra-attrs-for-paragraph-style style)))
@@ -729,13 +738,17 @@ PUB-DIR is set, use this as the publishing directory."
      (list))
     (t (error "Unknown environment %s" style))))
 
-(defvar org-lparse-list-level) ; dynamically bound in org-do-lparse
+(defvar org-lparse-list-stack) ; dynamically bound in org-do-lparse
+(defvar org-odt-list-stack-stashed)
 (defun org-odt-begin-list (ltype)
   (setq ltype (or (org-lparse-html-list-type-to-canonical-list-type ltype)
 		  ltype))
   (let* ((style-name (org-odt-get-style-name-for-entity 'list ltype))
-	 (extra (concat (when (= org-lparse-list-level 1)
-			  " text:continue-numbering=\"false\"")
+	 (extra (concat (if (or org-lparse-list-table-p
+				(and (= 1 (length org-lparse-list-stack))
+				     (null org-odt-list-stack-stashed)))
+			    " text:continue-numbering=\"false\""
+			  " text:continue-numbering=\"true\"")
 			(when style-name
 			  (format " text:style-name=\"%s\""  style-name)))))
     (case ltype
@@ -758,11 +771,15 @@ PUB-DIR is set, use this as the publishing directory."
     (ordered
      (assert (not headline) t)
      (let* ((counter arg) (extra ""))
-       (org-lparse-insert-tag "<text:list-item>")
+       (org-lparse-insert-tag (if (= (length org-lparse-list-stack)
+				     (length org-odt-list-stack-stashed))
+				  "<text:list-header>" "<text:list-item>"))
        (org-lparse-begin-paragraph)))
     (unordered
      (let* ((id arg) (extra ""))
-       (org-lparse-insert-tag "<text:list-item>")
+       (org-lparse-insert-tag (if (= (length org-lparse-list-stack)
+				     (length org-odt-list-stack-stashed))
+				  "<text:list-header>" "<text:list-item>"))
        (org-lparse-begin-paragraph)
        (insert (if headline (org-odt-format-target headline id)
 		 (org-odt-format-bookmark "" id)))))
@@ -783,13 +800,30 @@ PUB-DIR is set, use this as the publishing directory."
 		  ltype))
   (case ltype
     ((ordered unordered)
-     (org-lparse-insert-tag "</text:list-item>"))
+     (org-lparse-insert-tag (if (= (length org-lparse-list-stack)
+				   (length org-odt-list-stack-stashed))
+				(prog1 "</text:list-header>"
+				  (setq org-odt-list-stack-stashed nil))
+			      "</text:list-item>")))
     (description
      (org-lparse-end-list-item-1)
      (org-lparse-end-list 'description)
      (org-lparse-end-list-item-1))
     (t (error "Unknown list type"))))
 
+(defun org-odt-discontinue-list ()
+  (let ((stashed-stack org-lparse-list-stack))
+    (loop for list-type in stashed-stack
+	  do (org-lparse-end-list-item-1 list-type)
+	  (org-lparse-end-list list-type))
+    (setq org-odt-list-stack-stashed stashed-stack)))
+
+(defun org-odt-continue-list ()
+  (setq org-odt-list-stack-stashed (nreverse org-odt-list-stack-stashed))
+  (loop for list-type in org-odt-list-stack-stashed
+	do (org-lparse-begin-list list-type)
+	(org-lparse-begin-list-item list-type)))
+
 ;; Following variables are let bound when table emission is in
 ;; progress. See org-lparse.el.
 (defvar org-lparse-table-begin-marker)
@@ -897,7 +931,19 @@ style from the list."
 			       :key-type symbol
 			       :value-type (const :tag "True" t))))))
 
+(defvar org-odt-table-indentedp nil)
 (defun org-odt-begin-table (caption label attributes)
+  (setq org-odt-table-indentedp (not (null org-lparse-list-stack)))
+  (when org-odt-table-indentedp
+    ;; Within the Org file, the table is appearing within a list item.
+    ;; OpenDocument doesn't allow table to appear within list items.
+    ;; Temporarily terminate the list, emit the table and then
+    ;; re-continue the list.
+    (org-odt-discontinue-list)
+    ;; Put the Table in an indented section.
+    (let ((level (length org-odt-list-stack-stashed)))
+      (org-odt-begin-section (format "OrgIndentedSection-Level-%d" level))))
+
   (setq org-odt-table-style attributes)
   (setq org-odt-table-style-spec
 	(assoc org-odt-table-style org-export-odt-table-styles))
@@ -940,7 +986,10 @@ style from the list."
 	 ((equal spec "table-cell:style-name")
 	  (replace-match table-cell-style t t))))))
   (goto-char (point-max))
-  (org-lparse-insert-tag "</table:table>"))
+  (org-lparse-insert-tag "</table:table>")
+  (when org-odt-table-indentedp
+    (org-odt-end-section)
+    (org-odt-continue-list)))
 
 (defun org-odt-begin-table-rowgroup (&optional is-header-row)
   (when org-lparse-table-rowgrp-open
@@ -2053,7 +2102,9 @@ CATEGORY-HANDLE is used.  See
     (setq org-odt-manifest-file-entries nil
 	  org-odt-embedded-images-count 0
 	  org-odt-embedded-formulas-count 0
+	  org-odt-section-count 0
 	  org-odt-entity-labels-alist nil
+	  org-odt-list-stack-stashed nil
 	  org-odt-entity-counts-plist nil)
     content-file))