From d4dd85679939ff5b1e0dfb2cfedf3d59258c6a85 Mon Sep 17 00:00:00 2001
From: "Pedro A. Aranda" <paranda@it.uc3m.es>
Date: Mon, 30 Dec 2024 13:09:43 +0100
Subject: [PATCH] ox-latex.el: Fix adding unnumbered sections to the ToC

* etc/ORG-NEWS: Announce the fix
* lisp/ox-latex.el: (org-latex-headline): Add the logic to create the
~\\addcontentsline{toc}...~ for unnumbered section headings. This
generates correct LaTeX code that handles including unnumbered
sections in the ToC

---
 etc/ORG-NEWS     |  5 +++++
 lisp/ox-latex.el | 18 +++++++++++++++---
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index b43db549d..7c882b96b 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -436,6 +436,11 @@ For example, given =H:3= and =toc:2= in =#+OPTIONS:=, all headings at
 the 1st and 2nd level appear in the table of contents and those at the
 3rd level do not.

+*** LaTeX exporter now correctly adds unnumbered sections to the ToC
+
+If you add the =:ALT_TITLE:= property to an unnumbered section, it will
+be added to the Table of Contents correctly.
+
 * Version 9.7

 ** Important announcements and breaking changes
diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el
index 4b2e797d0..a4cfe2f2c 100644
--- a/lisp/ox-latex.el
+++ b/lisp/ox-latex.el
@@ -2402,7 +2402,7 @@ holding contextual information."
 				  (string-match-p "\\<local\\>" v)
 				  (format "\\stopcontents[level-%d]" level)))))
 		    info t)))))
-	  (if (and (or (and opt-title (not (equal opt-title full-text)))
+	  (if (and numberedp (or (and opt-title (not (equal opt-title full-text)))
                        ;; Heading contains footnotes.  Add optional title
                        ;; version without footnotes to avoid footnotes in
                        ;; TOC/footers.
@@ -2419,8 +2419,20 @@ holding contextual information."
 		      (concat headline-label pre-blanks contents))
 	    ;; Impossible to add an alternative heading.  Fallback to
 	    ;; regular sectioning format string.
-	    (format section-fmt full-text
-		    (concat headline-label pre-blanks contents))))))))
+            (save-match-data
+              ;; Try to extract the section command from section-fmt
+              ;; This should givee us some protection against unexpeted stuff
+              (let ((matched (string-match "\\\\\\([a-z]+\\)[^a-z]" section-fmt)))
+	        (if (or numberedp (not matched))
+                    ;; Just in case the section header is not a standard \\xyz*{}
+                    (format section-fmt full-text
+		            (concat headline-label pre-blanks contents))
+                  (let* ((section-label (match-string 1 section-fmt))
+                         (add-contents  (format "\\addcontentsline{toc}{%s}{%s}\n" section-label opt-title)))
+                    ;; prepend the addcontentsline as the first element in the generated section
+                    ;; this assures that it will go directly after the section command
+                    (format section-fmt full-text
+		            (concat add-contents headline-label pre-blanks contents))))))))))))

 (defun org-latex-format-headline-default-function
     (todo _todo-type priority text tags _info)
--
2.37.1 (Apple Git-137.1)
