[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#809739: marked as done (cdebconf: text frontend: having a way to scroll among choices)



Your message dated Fri, 29 Jan 2016 05:19:07 +0000
with message-id <E1aP1Sd-0003s4-Ol@franck.debian.org>
and subject line Bug#809739: fixed in cdebconf 0.203
has caused the Debian Bug report #809739,
regarding cdebconf: text frontend: having a way to scroll among choices
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
809739: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=809739
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Source: cdebconf
Version: 0.201
Severity: normal
Tags: patch

Hello,

In the text frontend, when there are more choices than can fit in the
screen, the question and the first choices get lost in the backlog.
When lucky, the available backscroll is long enough, but that's not
guaranteed, notably with the every-increasing list of supported
languages :)

I have come up with some changes in the text frontend to make it only
display what can fit on the screen and provide shortcuts to circulate
among the list of available choices.  I have attached the patch, and put
a sample built image on
https://people.debian.org/~sthibault/tmp/mini-cdebconf-text-choices.iso
(select the "speech" boot menu entry to easy select the text frontend).

The idea is to make all functions that print text return the number of
printed lines, so that the printlist() function can be given the number
of lines it is allowed to print.  That works quite nicely.

For now I have used '(' and ')' as shortcuts for previous and next
choices, probably better shortcuts could be found ('<' is already
taken).  Also the banners "Other/Previous/Next choices are available
with" can probably be improved.

How do debian-boot people think about this?

Samuel

-- System Information:
Debian Release: stretch/sid
  APT prefers unstable-debug
  APT policy: (500, 'unstable-debug'), (500, 'oldoldstable'), (500, 'buildd-unstable'), (500, 'unstable'), (500, 'testing'), (500, 'stable'), (500, 'oldstable'), (1, 'experimental-debug'), (1, 'buildd-experimental'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.3.0-1-amd64 (SMP w/4 CPU cores)
Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

-- 
Samuel
In mutt, type cthis
Dans mutt, taper cceci
diff --git a/src/modules/frontend/text/cdebconf_text.h b/src/modules/frontend/text/cdebconf_text.h
index 7f7088d..a4ce753 100644
--- a/src/modules/frontend/text/cdebconf_text.h
+++ b/src/modules/frontend/text/cdebconf_text.h
@@ -5,6 +5,8 @@
 #define CHAR_GOBACK '<'
 #define CHAR_HELP '?'
 #define CHAR_CLEAR '!'
+#define CHAR_PREV '('
+#define CHAR_NEXT ')'
 
 int cdebconf_text_get_width(const char *text);
 
diff --git a/src/modules/frontend/text/text.c b/src/modules/frontend/text/text.c
index e90b837..d7a1da8 100644
--- a/src/modules/frontend/text/text.c
+++ b/src/modules/frontend/text/text.c
@@ -64,7 +64,7 @@ struct frontend_data {
 	char *previous_title;
 };
 
-typedef int (text_handler)(struct frontend *obj, struct question *q);
+typedef int (text_handler)(struct frontend *obj, unsigned printed, struct question *q);
 
 #define MAKE_UPPER(C) do { if (islower((int) C)) { C = (char) toupper((int) C); } } while(0)
 
@@ -102,13 +102,40 @@ static int getwidth(void)
 }
 
 /*
+ * Function: getheight
+ * Input: none
+ * Output: int - height of screen
+ * Description: get the height of the current terminal
+ * Assumptions: doesn't handle resizing; caches value on first call
+ */
+static int getheight(void)
+{
+	static int res = 25;
+	static int inited = 0;
+	int fd;
+	struct winsize ws;
+
+	if (inited == 0)
+	{
+		inited = 1;
+		if ((fd = open("/dev/tty", O_RDONLY)) > 0)
+		{
+			if (ioctl(fd, TIOCGWINSZ, &ws) == 0 && ws.ws_row > 0)
+				res = ws.ws_row;
+			close(fd);
+		}
+	}
+	return res;
+}
+
+/*
  * Function: wrap_print
  * Input: const char *str - string to display
- * Output: none
+ * Output: unsigned printed - number of printed lines
  * Description: prints a string to the screen with word wrapping 
  * Assumptions: string fits in <500 lines
  */
-static void wrap_print(const char *str)
+static unsigned wrap_print(const char *str)
 {
 	/* Simple greedy line-wrapper */
 	int i, lc;
@@ -121,20 +148,23 @@ static void wrap_print(const char *str)
 		printf("%s\n", lines[i]);
 		DELETE(lines[i]);
 	}
+	return lc;
 }
 
 /*
  * Function: text_handler_displaydesc
  * Input: struct frontend *obj - UI object
+ *        unsigned printed - number of already printed lines
  *        struct question *q - question for which to display the description
- * Output: none
+ * Output: unsigned - number of printed lines
  * Description: displays the description for a given question 
  * Assumptions: none
  */
-static void text_handler_displaydesc(struct frontend *obj, struct question *q) 
+static unsigned text_handler_displaydesc(struct frontend *obj, unsigned printed, struct question *q) 
 {
 	char *descr = q_get_description(obj, q);
 	char *ext_descr = q_get_extended_description(obj, q);
+	printed = 0;
 	if (strcmp(q->template->type, "note") == 0 ||
 	    strcmp(q->template->type, "error") == 0)
 	{
@@ -143,17 +173,19 @@ static void text_handler_displaydesc(struct frontend *obj, struct question *q)
 		else
 			printf("%s", descr);
 		printf("\n\n");
+		printed += 2;
 		if (*ext_descr)
-			wrap_print(ext_descr);
+			printed += wrap_print(ext_descr);
 	}
 	else
 	{
 		if (*ext_descr)
-			wrap_print(ext_descr);
-		wrap_print(descr);
+			printed += wrap_print(ext_descr);
+		printed += wrap_print(descr);
 	}
 	free(descr);
 	free(ext_descr);
+	return printed;
 }
 
 static void
@@ -163,21 +195,24 @@ get_answer(char *answer, int size)
 	CHOMP(answer);
 }
 
-static void
+static unsigned
 show_help (struct frontend *obj, struct question *q)
 {
 	char *descr = q_get_description(obj, q);
 	char *help = q_get_help(obj, q);
+	unsigned printed = 0;
 	if (*help) {
 		struct question *help_q = obj->qdb->methods.get(obj->qdb, help);
 		if (help_q) {
 			char *help_descr = q_get_description(obj, help_q);
 			char *help_ext_descr = q_get_extended_description(obj, help_q);
-			wrap_print(help_descr);
+			printed += wrap_print(help_descr);
 			printf("\n");
+			printed++;
 			if (*help_ext_descr) {
-				wrap_print(help_ext_descr);
+				printed += wrap_print(help_ext_descr);
 				printf("\n");
+				printed++;
 			}
 			free(help_ext_descr);
 			free(help_descr);
@@ -186,13 +221,16 @@ show_help (struct frontend *obj, struct question *q)
 		free(help);
 	}
 	printf("%s\n", question_get_text(obj, "debconf/text-help-keystrokes", "KEYSTROKES:"));
+	printed++;
 	printf(" ");
 	printf(question_get_text(obj, "debconf/text-help-keystroke", "'%c'"), CHAR_HELP);
 	printf(" %s\n", question_get_text(obj, "debconf/text-help-help", "Display this help message"));
+	printed++;
 	if (obj->methods.can_go_back (obj, q)) {
 		printf(" ");
 		printf(question_get_text(obj, "debconf/text-help-keystroke", "'%c'"), CHAR_GOBACK);
 		printf(" %s\n", question_get_text(obj, "debconf/text-help-goback", "Go back to previous question"));
+		printed++;
 	}
 	if (strcmp(q->template->type, "string") == 0 ||
 	    strcmp(q->template->type, "password") == 0 ||
@@ -200,9 +238,11 @@ show_help (struct frontend *obj, struct question *q)
 		printf(" ");
 		printf(question_get_text(obj, "debconf/text-help-keystroke", "'%c'"), CHAR_CLEAR);
 		printf(" %s\n", question_get_text(obj, "debconf/text-help-clear", "Select an empty entry"));
+		printed++;
 	}
-	wrap_print(descr);
+	printed += wrap_print(descr);
 	free(descr);
+	return printed;
 }
 
 struct choices {
@@ -213,8 +253,21 @@ struct choices {
 	int *tindex;
 };
 
-static void
-printlist (struct frontend *obj, struct question *q, const struct choices *choices)
+/*
+ * Function: printlist
+ * Input: struct frontend *obj - UI object
+ *        unsigned max_lines - maximum number of lines to print
+ *        unsigned start - which line of choices should be printed first.
+ *        struct question *q - question for which to display the description
+ * Output: bool - whether we managed to print all choices from 'start' to last or not
+ * Description: displays the description for a given question
+ * Assumptions: none
+ *
+ * If it didn't fit, it will have printed a one-line comment about it, thus one
+ * line of choices less.
+ */
+static unsigned
+printlist (struct frontend *obj, unsigned max_lines, unsigned start, struct question *q, const struct choices *choices)
 {
 	int choice_min = -1;
 	int num_cols, num_lines;
@@ -229,6 +282,7 @@ printlist (struct frontend *obj, struct question *q, const struct choices *choic
 	int width = getwidth();
 	char **fchoices = malloc(sizeof(char *) * choices->count);
 	int horiz = 0;
+	bool all = false;
 
 	if (getenv("DEBCONF_TEXT_HORIZ"))
 		horiz = 1;
@@ -304,6 +358,7 @@ printlist (struct frontend *obj, struct question *q, const struct choices *choic
 		num_lines = choices->count;
 		num_cols = 1;
 	}
+
 	output = malloc(sizeof(char *) * num_lines);
 	for (i = 0; i < num_lines; i++)
 	{
@@ -337,27 +392,57 @@ printlist (struct frontend *obj, struct question *q, const struct choices *choic
 			max_len = 0;
 		}
 	}
-	for (l = 0; l < num_lines; l++)
+
+	if (max_lines >= num_lines - start)
+	{
+		/* More than enough room */
+		max_lines = num_lines - start;
+		all = true;
+	}
+	else
+		/* Keep one line for the "more choices" prompt */
+		max_lines--;
+	/* Don't display the beginning */
+	for (l = 0; l < start; l++)
+		free(output[l]);
+	/* Display only what fits in the screen */
+	for ( ; l < start + max_lines; l++)
 	{
 		printf("%s\n", output[l]);
 		free(output[l]);
 	}
+	/* Don't display the end */
+	for ( ; l < num_lines; l++)
+		free(output[l]);
+
 	free(output);
 	free(col_width);
 	for (i = 0; i < choices->count; i++)
 		free(fchoices[i]);
 	free(fchoices);
+
+	if (start > 0 && !all)
+		printf(question_get_text(obj, "debconf/text-help-otherchoices", "Other choices are available with '%c' and '%c'"), CHAR_PREV, CHAR_NEXT);
+	if (start > 0 && all)
+		printf(question_get_text(obj, "debconf/text-help-prevchoices", "Previous choices are available with '%c'"), CHAR_PREV);
+	if (start == 0 && !all)
+		printf(question_get_text(obj, "debconf/text-help-nextchoices", "Next choices are available with '%c'"), CHAR_NEXT);
+	if (start > 0 || !all)
+		printf("\n");
+
+	return all;
 }
 
 /*
  * Function: text_handler_boolean
  * Input: struct frontend *obj - frontend object
+ *        unsigned printed - number of already printed lines
  *        struct question *q - question to ask
  * Output: int - DC_OK, DC_NOTOK, DC_GOBACK
  * Description: handler for the boolean question type
  * Assumptions: none
  */
-static int text_handler_boolean(struct frontend *obj, struct question *q)
+static int text_handler_boolean(struct frontend *obj, unsigned printed, struct question *q)
 {
 	char buf[30];
 	int ans = 0;
@@ -385,7 +470,7 @@ static int text_handler_boolean(struct frontend *obj, struct question *q)
 					"Prompt: '%c' for help> "), CHAR_HELP);
 		get_answer(buf, sizeof(buf));
 		if (buf[0] == CHAR_HELP && buf[1] == 0)
-			show_help(obj, q);
+			printed += show_help(obj, q);
 		else if (obj->methods.can_go_back (obj, q) &&
 		         buf[0] == CHAR_GOBACK && buf[1] == 0)
 			return DC_GOBACK;
@@ -433,6 +518,7 @@ static void choices_delete(struct choices *c)
 /*
  * Function: choices_get
  * Input: struct frontend *obj - frontend object
+ *        unsigned printed - number of already printed lines
  *        struct question *q - question to ask
  * Output: struct choices * - choices values, translations, indices, and select
  * Description: retrieve question choices, translations, indices
@@ -480,12 +566,13 @@ static struct choices *choices_get(struct frontend *obj, struct question *q)
 /*
  * Function: text_handler_multiselect
  * Input: struct frontend *obj - frontend object
+ *        unsigned printed - number of already printed lines
  *        struct question *q - question to ask
  * Output: int - DC_OK, DC_NOTOK
  * Description: handler for the multiselect question type
  * Assumptions: none
  */
-static int text_handler_multiselect(struct frontend *obj, struct question *q)
+static int text_handler_multiselect(struct frontend *obj, unsigned printed, struct question *q)
 {
 	struct choices *choices = NULL;
 	char **defaults;
@@ -493,6 +580,8 @@ static int text_handler_multiselect(struct frontend *obj, struct question *q)
 	char answer[4096] = {0};
 	int i, j, dcount, choice;
 	int ret = DC_OK;
+	unsigned start = 0;
+	bool all;
 
 	choices = choices_get(obj, q);
 	if (choices == NULL)
@@ -525,13 +614,14 @@ static int text_handler_multiselect(struct frontend *obj, struct question *q)
 		}
 
   DISPLAY:
-	printlist (obj, q, choices);
+	all = printlist (obj, getheight() - printed - 1, start, q, choices);
 	printf(question_get_text(obj, "debconf/text-prompt-default-string", 
 		"Prompt: '%c' for help, default=%s> "), CHAR_HELP, defval);
 	get_answer(answer, sizeof(answer));
 	if (answer[0] == CHAR_HELP && answer[1] == 0)
 	{
-		show_help(obj, q);
+		printed = 0;
+		printed += show_help(obj, q);
 		goto DISPLAY;
 	}
 	else if (answer[0] == CHAR_CLEAR && answer[1] == 0)
@@ -545,6 +635,27 @@ static int text_handler_multiselect(struct frontend *obj, struct question *q)
 		ret = DC_GOBACK;
 		goto CleanUp_DEFVAL;
 	}
+	else if (answer[0] == CHAR_NEXT && answer[1] == 0)
+	{
+		if (!all)
+			start += getheight() - printed - 2;
+		printed = 0;
+		goto DISPLAY;
+	}
+	else if (answer[0] == CHAR_PREV && answer[1] == 0)
+	{
+		/* Note: 'printed' may not always contain the same value, when
+		 * the title banner is not printed again notably.  This however
+		 * only happens once, the second time the question in answered,
+		 * and start will have then been 0 already so this does not
+		 * pose problem.  */
+		if (start <= getheight() - printed - 2)
+			start = 0;
+		else
+			start -= getheight() - printed - 2;
+		printed = 0;
+		goto DISPLAY;
+	}
 
 	if (!(ISEMPTY(answer)))
 	{
@@ -580,6 +691,7 @@ static int text_handler_multiselect(struct frontend *obj, struct question *q)
 /*
  * Function: text_handler_select
  * Input: struct frontend *obj - frontend object
+ *        unsigned printed - number of already printed lines
  *        struct question *q - question to ask
  * Output: int - DC_OK, DC_NOTOK
  * Description: handler for the select question type
@@ -587,13 +699,15 @@ static int text_handler_multiselect(struct frontend *obj, struct question *q)
  *
  * TODO: factor common code with multiselect
  */
-static int text_handler_select(struct frontend *obj, struct question *q)
+static int text_handler_select(struct frontend *obj, unsigned printed, struct question *q)
 {
 	struct choices *choices = NULL;
 	char answer[128];
 	int i, choice, def = -1;
 	const char *defval;
 	int ret = DC_OK;
+	unsigned start = 0;
+	bool all;
 
 	choices = choices_get(obj, q);
 	if (choices == NULL)
@@ -617,7 +731,7 @@ static int text_handler_select(struct frontend *obj, struct question *q)
 	i = 0;
 	choice = -1;
 	do {
-		printlist (obj, q, choices);
+		all = printlist (obj, getheight() - printed - 1, start, q, choices);
 		if (def >= 0 && choices->choices_translated[def]) {
 			printf(question_get_text(obj, "debconf/text-prompt-default", 
 				"Prompt: '%c' for help, default=%d> "),
@@ -629,7 +743,7 @@ static int text_handler_select(struct frontend *obj, struct question *q)
 		get_answer(answer, sizeof(answer));
 		if (answer[0] == CHAR_HELP)
 		{
-			show_help(obj, q);
+			printed += show_help(obj, q);
 			continue;
 		}
 		if (obj->methods.can_go_back (obj, q) &&
@@ -638,6 +752,27 @@ static int text_handler_select(struct frontend *obj, struct question *q)
 			ret = DC_GOBACK;
 			goto CleanUp_SELECTED;
 		}
+		else if (answer[0] == CHAR_NEXT && answer[1] == 0)
+		{
+			if (!all)
+				start += getheight() - printed - 2;
+			printed = 0;
+			continue;
+		}
+		else if (answer[0] == CHAR_PREV && answer[1] == 0)
+		{
+			/* Note: 'printed' may not always contain the same value, when
+			 * the title banner is not printed again notably.  This however
+			 * only happens once, the second time the question in answered,
+			 * and start will have then been 0 already so this does not
+			 * pose problem.  */
+			if (start < getheight() - printed - 2)
+				start = 0;
+			else
+				start -= getheight() - printed - 2;
+			printed = 0;
+			continue;
+		}
 		if (ISEMPTY(answer))
 			choice = def;
 		else {
@@ -653,6 +788,7 @@ static int text_handler_select(struct frontend *obj, struct question *q)
 				}
 			}
 		}
+		printed = 0;
 	} while (choice < 0 || choice >= choices->count);
 	question_setvalue(q, choices->choices[choices->tindex[choice]]);
 
@@ -665,12 +801,13 @@ static int text_handler_select(struct frontend *obj, struct question *q)
 /*
  * Function: text_handler_note
  * Input: struct frontend *obj - frontend object
+ *        unsigned printed - number of already printed lines
  *        struct question *q - question to ask
  * Output: int - DC_OK, DC_NOTOK, DC_GOBACK
  * Description: handler for the note question type
  * Assumptions: none
  */
-static int text_handler_note(struct frontend *obj, struct question *q)
+static int text_handler_note(struct frontend *obj, unsigned printed, struct question *q)
 {
 	char buf[100] = {0};
 	printf("%s ", question_get_text(obj, "debconf/cont-prompt",
@@ -680,7 +817,7 @@ static int text_handler_note(struct frontend *obj, struct question *q)
 	{
 		get_answer(buf, sizeof(buf));
 		if (buf[0] == CHAR_HELP && buf[1] == 0)
-			show_help(obj, q);
+			printed += show_help(obj, q);
 		else if (obj->methods.can_go_back (obj, q) &&
 		         buf[0] == CHAR_GOBACK && buf[1] == 0)
 			return DC_GOBACK;
@@ -693,6 +830,7 @@ static int text_handler_note(struct frontend *obj, struct question *q)
 /*
  * Function: text_handler_password
  * Input: struct frontend *obj - frontend object
+ *        unsigned printed - number of already printed lines
  *        struct question *q - question to ask
  * Output: int - DC_OK, DC_NOTOK
  * Description: handler for the password question type
@@ -700,7 +838,7 @@ static int text_handler_note(struct frontend *obj, struct question *q)
  *
  * TODO: this can be *MUCH* improved. no editing is possible right now
  */
-static int text_handler_password(struct frontend *obj, struct question *q)
+static int text_handler_password(struct frontend *obj, unsigned printed, struct question *q)
 {
 	struct termios oldt, newt;
 	char passwd[256] = {0};
@@ -729,7 +867,7 @@ static int text_handler_password(struct frontend *obj, struct question *q)
 		passwd[i] = 0;
 		tcsetattr(0, TCSANOW, &oldt);
 		if (passwd[0] == CHAR_HELP && passwd[1] == 0)
-			show_help(obj, q);
+			printed += show_help(obj, q);
 		else
 			break;
 	}
@@ -746,12 +884,13 @@ static int text_handler_password(struct frontend *obj, struct question *q)
 /*
  * Function: text_handler_string
  * Input: struct frontend *obj - frontend object
+ *        unsigned printed - number of already printed lines
  *        struct question *q - question to ask
  * Output: int - DC_OK, DC_NOTOK
  * Description: handler for the string question type
  * Assumptions: none
  */
-static int text_handler_string(struct frontend *obj, struct question *q)
+static int text_handler_string(struct frontend *obj, unsigned printed, struct question *q)
 {
 	char buf[1024] = {0};
 	const char *defval = question_getvalue(q, "");
@@ -763,7 +902,7 @@ static int text_handler_string(struct frontend *obj, struct question *q)
 		fflush(stdout);
 		get_answer(buf, sizeof(buf));
 		if (buf[0] == CHAR_HELP && buf[1] == 0)
-			show_help(obj, q);
+			printed += show_help(obj, q);
 		else
 			break;
 	}
@@ -784,27 +923,29 @@ static int text_handler_string(struct frontend *obj, struct question *q)
 /*
  * Function: text_handler_text
  * Input: struct frontend *obj - frontend object
+ *        unsigned printed - number of already printed lines
  *        struct question *q - question to ask
  * Output: int - DC_OK, DC_NOTOK, DC_GOBACK
  * Description: handler for the text question type
  * Assumptions: none
  */
-static int text_handler_text(struct frontend *obj, struct question *q)
+static int text_handler_text(struct frontend *obj, unsigned printed, struct question *q)
 {
-	return text_handler_note(obj, q);
+	return text_handler_note(obj, printed, q);
 }
 
 /*
  * Function: text_handler_error
  * Input: struct frontend *obj - frontend object
+ *        unsigned printed - number of already printed lines
  *        struct question *q - question to ask
  * Output: int - DC_OK, DC_NOTOK, DC_GOBACK
  * Description: handler for the error question type. Currently equal to _note
  * Assumptions: none
  */
-static int text_handler_error(struct frontend *obj, struct question *q)
+static int text_handler_error(struct frontend *obj, unsigned printed, struct question *q)
 {
-	return text_handler_note(obj, q);
+	return text_handler_note(obj, printed, q);
 }
 
 /* ----------------------------------------------------------------------- */
@@ -867,6 +1008,7 @@ static int text_shutdown(struct frontend *obj)
 /*
  * Function: text_can_go_back
  * Input: struct frontend *obj - frontend object
+ *        unsigned printed - number of already printed lines
  *        struct question *q - question object
  * Output: int - DC_OK, DC_NOTOK
  * Description: tells whether confmodule supports backing up
@@ -881,6 +1023,7 @@ text_can_go_back(struct frontend *obj, struct question *q)
 /*
  * Function: text_can_align
  * Input: struct frontend *obj - frontend object
+ *        unsigned printed - number of already printed lines
  *        struct question *q - question object
  * Output: int - DC_OK, DC_NOTOK
  * Description: tells whether confmodule supports aligning columns
@@ -929,12 +1072,14 @@ static int text_go(struct frontend *obj)
 	struct question *q = obj->questions;
 	int i;
 	int ret = DC_OK;
+	unsigned printed;
 
 	while (q != NULL) {
 		for (i = 0; i < DIM(question_handlers); i++) {
 			text_handler *handler;
 			struct plugin *plugin = NULL;
 
+			printed = 0;
 			if (*question_handlers[i].type)
 				handler = question_handlers[i].handler;
 			else {
@@ -968,12 +1113,13 @@ static int text_go(struct frontend *obj)
 					memset(underline, '-', underline_len);
 					underline[underline_len] = '\0';
 					printf("%s\n%s\n\n", obj->title, underline);
+					printed += 3;
 					free(underline);
 					free(data->previous_title);
 					data->previous_title = strdup(obj->title);
 				}
-				text_handler_displaydesc(obj, q);
-				ret = handler(obj, q);
+				printed += text_handler_displaydesc(obj, printed, q);
+				ret = handler(obj, printed, q);
 				putchar('\n');
 				if (ret == DC_OK)
 					frontend_qdb_set(obj->qdb, q, 0);

--- End Message ---
--- Begin Message ---
Source: cdebconf
Source-Version: 0.203

We believe that the bug you reported is fixed in the latest version of
cdebconf, which is due to be installed in the Debian FTP archive.

A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to 809739@bugs.debian.org,
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Christian Perrier <bubulle@debian.org> (supplier of updated cdebconf package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing ftpmaster@ftp-master.debian.org)


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Format: 1.8
Date: Thu, 28 Jan 2016 15:40:45 +0100
Source: cdebconf
Binary: cdebconf cdebconf-gtk libdebconfclient0 libdebconfclient0-dev cdebconf-udeb cdebconf-priority libdebconfclient0-udeb cdebconf-text-udeb cdebconf-newt-udeb cdebconf-gtk-udeb
Architecture: source i386 all
Version: 0.203
Distribution: unstable
Urgency: medium
Maintainer: Debian Install System Team <debian-boot@lists.debian.org>
Changed-By: Christian Perrier <bubulle@debian.org>
Description:
 cdebconf   - Debian Configuration Management System (C-implementation)
 cdebconf-gtk - Gtk+ frontend for Debian Configuration Management System
 cdebconf-gtk-udeb - Gtk+ frontend for Debian Configuration Management System (udeb)
 cdebconf-newt-udeb - Newt frontend for Debian Configuration Management System (udeb)
 cdebconf-priority - Change debconf priority (udeb)
 cdebconf-text-udeb - Plain text frontend for Debian Configuration Management System (udeb)
 cdebconf-udeb - Debian Configuration Management System (C-implementation) (udeb)
 libdebconfclient0 - Debian Configuration Management System (C-implementation library)
 libdebconfclient0-dev - Development files for cdebconf
 libdebconfclient0-udeb - Debian Configuration Management System (C-implementation) (udeb)
Closes: 809739
Changes:
 cdebconf (0.203) unstable; urgency=medium
 .
   [ Regis Boudin ]
   * Remove conditional code to handle glib pre-2.31, which is pre-wheezy.
     Add versioned Build-Depends accordingly.
   * Updake GTK+ plugin to not use deprecated GDK symbols.
   * Add the possibility to target GTK+2 or GTK+3. Stick to GTK+2 for now.
 .
   [ Samuel Thibault ]
   * text: Print one screen worth of choices, and use +/- to switch between
     choices screens. Closes: #809739.
Checksums-Sha1:
 d4d56efa70209c5eb3ac97c4e5bf3c6c0474fc5e 2660 cdebconf_0.203.dsc
 e12f45e2ba05b6b7376b571fbc976d538d9c39ab 271248 cdebconf_0.203.tar.xz
 9835e8e0263a1d66fa72bf46ce251add39198d63 215630 cdebconf-dbgsym_0.203_i386.deb
 153688ddf1b8a09ce347a3a2b5b8889ded2a8ab6 81864 cdebconf-gtk-dbgsym_0.203_i386.deb
 2b30246ed7b66a24f255002316c375e8b0f33aba 32188 cdebconf-gtk-udeb_0.203_i386.udeb
 a579ade3c724f4d42adab32149d340c103858851 74732 cdebconf-gtk_0.203_i386.deb
 01b2b38cb0ace5b7b0d6dd343503480531e1df41 21244 cdebconf-newt-udeb_0.203_i386.udeb
 6aeef55aed5aae997584b6504db9f733b2fc0a1b 3152 cdebconf-priority_0.203_all.udeb
 6fab3f98231f416b6e9d5bd0f8a98e23a79b9843 24358 cdebconf-text-udeb_0.203_i386.udeb
 20bb2462da793ef9aac5690522b101a543f9a184 82614 cdebconf-udeb_0.203_i386.udeb
 bca825774294a1d16413fd5e15b5c19582bac74e 182026 cdebconf_0.203_i386.deb
 93c76a632ea885615b30309a27582992bb46ac55 5280 libdebconfclient0-dbgsym_0.203_i386.deb
 f6704cd9aceef34b93987120cd062abd7d2e6c3d 51510 libdebconfclient0-dev_0.203_i386.deb
 b5d181d225fd1e555a9314f72913f14776f965c8 3388 libdebconfclient0-udeb_0.203_i386.udeb
 b5a2b757a9966a8b7a96ef67d3e380e56932d167 47122 libdebconfclient0_0.203_i386.deb
Checksums-Sha256:
 95b149c378e564cabf4e0f8bdc95bc546dc5ba1bc80b5069050f5806438ac540 2660 cdebconf_0.203.dsc
 e7e38e20059fa7e0bd6233ead5d2e203ca9d683067a94668db501ea148efcf9f 271248 cdebconf_0.203.tar.xz
 53032506fcd81b97045ec200265b8998ccc29968fa864a0a3fd97823e2ab8aed 215630 cdebconf-dbgsym_0.203_i386.deb
 148bd34431d0bb7a6c2f93840fba038927858c521915b9439bc5709cad01b227 81864 cdebconf-gtk-dbgsym_0.203_i386.deb
 35a822a6e22951466971491d447e880b6e7ee1b96ac40b57a39cfd1213a327b8 32188 cdebconf-gtk-udeb_0.203_i386.udeb
 3134764431771d6319aa28149db23ee1e2f082c94675ab543cb79bd06a0d3673 74732 cdebconf-gtk_0.203_i386.deb
 28e357ab39cd55e4ac315294846bf1a22a9d50892191785d60482d42b5b207db 21244 cdebconf-newt-udeb_0.203_i386.udeb
 212ee380fb1cf010304c862a9fad6792e4b14cf2f785ee26bcf9d6e63e2c14ff 3152 cdebconf-priority_0.203_all.udeb
 a7afb34e389162e76d6c294c0bc52e96d3069fdedd2735b49d252246b90352c8 24358 cdebconf-text-udeb_0.203_i386.udeb
 68ae11aef6969a99e5c5be593181f9a665bf2580b919a1f8e8350cf7e7870cf7 82614 cdebconf-udeb_0.203_i386.udeb
 18d88bff78481caf01a41e2b3fdb2ec8a367dfa61da7963c6cb245ed52e8b81d 182026 cdebconf_0.203_i386.deb
 6bba1b63db32843539be24e470ede400436143b6a8d7ad31149945d497835c07 5280 libdebconfclient0-dbgsym_0.203_i386.deb
 502c6b1d571b9ca0a365a807cc5659c35888912d62c7f9828f3598a7ab7a904c 51510 libdebconfclient0-dev_0.203_i386.deb
 fcf1fb4f70499b44376882834a47deae6a4bc7e927fa4f33650f84bb7b09bdb9 3388 libdebconfclient0-udeb_0.203_i386.udeb
 78aef2259e55eb924fa6602e166c588e42d151805fecb1783f3ee3f5a143c39e 47122 libdebconfclient0_0.203_i386.deb
Files:
 ca1ab93b3813aeae00ad6352b94169b9 2660 utils optional cdebconf_0.203.dsc
 e0f14019dd6b35637fe03893612e3746 271248 utils optional cdebconf_0.203.tar.xz
 93289491e62798ea2a1a9d976ed925d4 215630 debug extra cdebconf-dbgsym_0.203_i386.deb
 96ffa42739a9b8a66477260bd3bce238 81864 debug extra cdebconf-gtk-dbgsym_0.203_i386.deb
 e278a550f680aadc61f1431d829fd58d 32188 debian-installer optional cdebconf-gtk-udeb_0.203_i386.udeb
 4ea3efcaa449773f5f5ac47bb32b8b78 74732 admin extra cdebconf-gtk_0.203_i386.deb
 65ae535ef97adebfc60f420904df8f7c 21244 debian-installer optional cdebconf-newt-udeb_0.203_i386.udeb
 387f1993897ff325b3317025d0bda8f2 3152 debian-installer standard cdebconf-priority_0.203_all.udeb
 fc2425676dc92a015ec9360736ef3bd9 24358 debian-installer optional cdebconf-text-udeb_0.203_i386.udeb
 c06e519fc7f823937bca1f806eb31ffc 82614 debian-installer standard cdebconf-udeb_0.203_i386.udeb
 8282729cbd6edfc0dcc83f4bd5472233 182026 utils extra cdebconf_0.203_i386.deb
 34c9e2be1be58c0f960a65fbfce67c01 5280 debug extra libdebconfclient0-dbgsym_0.203_i386.deb
 e4a94c2750eecf74e708227eefd5d795 51510 libdevel optional libdebconfclient0-dev_0.203_i386.deb
 8cf17949e345d71e51843746be44dbe9 3388 debian-installer optional libdebconfclient0-udeb_0.203_i386.udeb
 0de973c3c19c9071940f0ae06792af8f 47122 libs optional libdebconfclient0_0.203_i386.deb

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQIcBAEBCAAGBQJWqvQRAAoJEIcvcCxNbiWoXG4P+wUvQaerPUS4zFhZTOLYV0Ci
OV4P5C3yICLucvyrHU0u6HhHgsGMCGtOXBQ9iw2MNRdxPuhscKnoQ8A2j6lIQjxu
+LhSwuMhHsSUBF1rnOKlctHiXEeWZkF3Gy9W9KrSyv1RUHTx0ZY64f4Lua/8WNdK
SCeh1TMwy3ibIpVQRu9vcZgtYrtr/GH3SBj2ODy/PbMGI+2za/iVY76NldhtdzRv
jxMusxkDjs7NfCbNYNO2px+A3s9/iM9mlo4bA1FaN8jCsNQJJf+r9QQW/1lXy/R0
New5A6QHdjI7haTbxxS+t++LSl76hG8t6fMZyYeG1gvkw6F/BJF51mOiyzrHbo23
Ojakz3rPXhL6Fb/RxVuYrg4y1KxLbPGwfs5uWK4gm9HI60srL8geiKMNV0paGdh/
SZ5J9EuSuFXGQ0Xu2JaJM/YHltkUq6Q9iHyD99CHnqmfg1WbQdrGDFx9wt/2sxB7
MFiM3RQNxqLjAg8ZOHYgQAPZo45nyKN7fE/MrgxWvRKVLED7mh8PdUETQYWS7WOv
66I3GRSTPqn+1FHtGzCSNCA1EtL8JmbRD4129qNW+XjwLvvz3fK1NTFg0y3wcPKg
fLOvLMMeh6EC9MvNaYQ2iLrtbLIHU9YhBItLqq9gExmQGEpT69vYClWPoxx1Q+Ge
ekBPMFULfEB/hfOJhrl9
=jikg
-----END PGP SIGNATURE-----

--- End Message ---

Reply to: