source@mandoc.bsd.lv
 help / color / mirror / Atom feed
From: schwarze@mdocml.bsd.lv
To: source@mdocml.bsd.lv
Subject: mdocml: Correct indentation for lists and displays inside lists.
Date: Sun, 18 Nov 2012 13:02:23 -0500 (EST)	[thread overview]
Message-ID: <201211181802.qAII2NVF031841@krisdoz.my.domain> (raw)

Log Message:
-----------
Correct indentation for lists and displays inside lists.

Inspired by a diff from millert@, but implemented rather
differently and with slightly better functionality.
In particular, this one respects -offset and -width
arguments found in the input file.

Modified Files:
--------------
    mdocml:
        mdoc_man.c

Revision Data
-------------
Index: mdoc_man.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/mdoc_man.c,v
retrieving revision 1.42
retrieving revision 1.43
diff -Lmdoc_man.c -Lmdoc_man.c -u -p -r1.42 -r1.43
--- mdoc_man.c
+++ mdoc_man.c
@@ -254,6 +254,11 @@ static	int		outflags;
 #define	MMAN_An_split	(1 << 8)  /* author mode is "split" */
 #define	MMAN_An_nosplit	(1 << 9)  /* author mode is "nosplit" */
 
+#define	BL_STACK_MAX	32
+
+static	size_t		Bl_stack[BL_STACK_MAX];  /* offsets [chars] */
+static	int		Bl_stack_post[BL_STACK_MAX];  /* add final .RE */
+static	int		Bl_stack_len;  /* number of nested Bl blocks */
 static	int		TPremain;  /* characters before tag is full */
 
 static	struct {
@@ -390,6 +395,7 @@ print_offs(const char *v)
 	struct roffsu	  su;
 	size_t		  sz;
 
+	/* Convert v into a number (of characters). */
 	if (NULL == v || '\0' == *v || 0 == strcmp(v, "left"))
 		sz = 0;
 	else if (0 == strcmp(v, "indent"))
@@ -397,11 +403,29 @@ print_offs(const char *v)
 	else if (0 == strcmp(v, "indent-two"))
 		sz = 12;
 	else if (a2roffsu(v, &su, SCALE_MAX)) {
-		print_word(v);
-		return;
+		if (SCALE_EN == su.unit)
+			sz = su.scale;
+		else {
+			/*
+			 * XXX
+			 * If we are inside an enclosing list,
+			 * there is no easy way to add the two
+			 * indentations because they are provided
+			 * in terms of different units.
+			 */
+			print_word(v);
+			return;
+		}
 	} else
 		sz = strlen(v);
 
+	/*
+	 * We are inside an enclosing list.
+	 * Add the two indentations.
+	 */
+	if (Bl_stack_len)
+		sz += Bl_stack[Bl_stack_len - 1];
+
 	snprintf(buf, sizeof(buf), "%ldn", sz);
 	print_word(buf);
 }
@@ -416,6 +440,8 @@ print_width(const char *v, const struct 
 
 	numeric = 1;
 	remain = 0;
+
+	/* Convert v into a number (of characters). */
 	if (NULL == v)
 		sz = defsz;
 	else if (a2roffsu(v, &su, SCALE_MAX)) {
@@ -432,6 +458,24 @@ print_width(const char *v, const struct 
 	chsz = (NULL != child && MDOC_TEXT == child->type) ?
 			strlen(child->string) : 0;
 
+	/*
+	 * If we are inside an enclosing list,
+	 * preserve its indentation.
+	 */
+	if (Bl_stack_len && Bl_stack[Bl_stack_len - 1]) {
+		print_line(".RS", 0);
+		snprintf(buf, sizeof(buf), "%ldn",
+				Bl_stack[Bl_stack_len - 1]);
+		print_word(buf);
+	}
+
+	/*
+	 * Save our own indentation,
+	 * such that child lists can use it.
+	 */
+	Bl_stack[Bl_stack_len++] = sz + 2;
+
+	/* Set up the current list. */
 	if (defsz && chsz > sz)
 		print_block(".HP", 0);
 	else {
@@ -767,11 +811,28 @@ pre_bd(DECL_ARGS)
 static void
 post_bd(DECL_ARGS)
 {
+	char		 buf[24];
 
+	/* Close out this display. */
 	print_line(".RE", MMAN_nl);
 	if (DISP_unfilled == n->norm->Bd.type ||
 	    DISP_literal  == n->norm->Bd.type)
 		print_line(".fi", MMAN_nl);
+
+	/*
+	 * If we are inside an enclosing list and the current
+	 * list item is not yet finished, restore the correct
+	 * indentation for what remains of that item.
+	 */
+	if (NULL != n->parent->next &&
+	    Bl_stack_len && Bl_stack[Bl_stack_len - 1]) {
+		print_line(".RS", 0);
+		snprintf(buf, sizeof(buf), "%ldn",
+				Bl_stack[Bl_stack_len - 1]);
+		print_word(buf);
+		/* Remeber to close out this .RS block later. */
+		Bl_stack_post[Bl_stack_len - 1] = 1;
+	}
 }
 
 static int
@@ -1197,10 +1258,46 @@ post_it(DECL_ARGS)
 		}
 		break;
 	case (MDOC_BODY):
-		if (LIST_column == bln->norm->Bl.type &&
-		    NULL != n->next) {
-			putchar('\t');
-			outflags &= ~MMAN_spc;
+		switch (bln->norm->Bl.type) {
+		case (LIST_bullet):
+			/* FALLTHROUGH */
+		case (LIST_dash):
+			/* FALLTHROUGH */
+		case (LIST_hyphen):
+			/* FALLTHROUGH */
+		case (LIST_enum):
+			/* FALLTHROUGH */
+		case (LIST_hang):
+			/* FALLTHROUGH */
+		case (LIST_tag):
+			assert(Bl_stack_len);
+			Bl_stack[--Bl_stack_len] = 0;
+
+			/*
+			 * Our indentation had to be restored
+			 * after a child display.
+			 * Close out that indentation block now.
+			 */
+			if (Bl_stack_post[Bl_stack_len]) {
+				print_line(".RE", MMAN_nl);
+				Bl_stack_post[Bl_stack_len] = 0;
+			}
+
+			/*
+			 * We are inside an enclosing list.
+			 * Restore the indentation of that list.
+			 */
+			if (Bl_stack_len && Bl_stack[Bl_stack_len - 1])
+				print_line(".RE", MMAN_nl);
+			break;
+		case (LIST_column):
+			if (NULL != n->next) {
+				putchar('\t');
+				outflags &= ~MMAN_spc;
+			}
+			break;
+		default:
+			break;
 		}
 		break;
 	default:
--
 To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv

                 reply	other threads:[~2012-11-18 18:02 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=201211181802.qAII2NVF031841@krisdoz.my.domain \
    --to=schwarze@mdocml.bsd.lv \
    --cc=source@mdocml.bsd.lv \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).