xref: /minix/external/bsd/less/dist/output.c (revision 84d9c625)
1*84d9c625SLionel Sambuc /*	$NetBSD: output.c,v 1.4 2013/09/04 19:44:21 tron Exp $	*/
2f7cf2976SLionel Sambuc 
3f7cf2976SLionel Sambuc /*
4*84d9c625SLionel Sambuc  * Copyright (C) 1984-2012  Mark Nudelman
5f7cf2976SLionel Sambuc  *
6f7cf2976SLionel Sambuc  * You may distribute under the terms of either the GNU General Public
7f7cf2976SLionel Sambuc  * License or the Less License, as specified in the README file.
8f7cf2976SLionel Sambuc  *
9*84d9c625SLionel Sambuc  * For more information, see the README file.
10f7cf2976SLionel Sambuc  */
11f7cf2976SLionel Sambuc 
12f7cf2976SLionel Sambuc 
13f7cf2976SLionel Sambuc /*
14f7cf2976SLionel Sambuc  * High level routines dealing with the output to the screen.
15f7cf2976SLionel Sambuc  */
16f7cf2976SLionel Sambuc 
17f7cf2976SLionel Sambuc #include "less.h"
18f7cf2976SLionel Sambuc #if MSDOS_COMPILER==WIN32C
19f7cf2976SLionel Sambuc #include "windows.h"
20f7cf2976SLionel Sambuc #endif
21f7cf2976SLionel Sambuc 
22f7cf2976SLionel Sambuc public int errmsgs;	/* Count of messages displayed by error() */
23f7cf2976SLionel Sambuc public int need_clr;
24f7cf2976SLionel Sambuc public int final_attr;
25f7cf2976SLionel Sambuc public int at_prompt;
26f7cf2976SLionel Sambuc 
27f7cf2976SLionel Sambuc extern int sigs;
28f7cf2976SLionel Sambuc extern int sc_width;
29f7cf2976SLionel Sambuc extern int so_s_width, so_e_width;
30f7cf2976SLionel Sambuc extern int screen_trashed;
31f7cf2976SLionel Sambuc extern int any_display;
32f7cf2976SLionel Sambuc extern int is_tty;
33f7cf2976SLionel Sambuc extern int oldbot;
34f7cf2976SLionel Sambuc 
35f7cf2976SLionel Sambuc #if MSDOS_COMPILER==WIN32C || MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
36f7cf2976SLionel Sambuc extern int ctldisp;
37f7cf2976SLionel Sambuc extern int nm_fg_color, nm_bg_color;
38f7cf2976SLionel Sambuc extern int bo_fg_color, bo_bg_color;
39f7cf2976SLionel Sambuc extern int ul_fg_color, ul_bg_color;
40f7cf2976SLionel Sambuc extern int so_fg_color, so_bg_color;
41f7cf2976SLionel Sambuc extern int bl_fg_color, bl_bg_color;
42f7cf2976SLionel Sambuc #endif
43f7cf2976SLionel Sambuc 
44f7cf2976SLionel Sambuc /*
45f7cf2976SLionel Sambuc  * Display the line which is in the line buffer.
46f7cf2976SLionel Sambuc  */
47f7cf2976SLionel Sambuc 	public void
put_line()48f7cf2976SLionel Sambuc put_line()
49f7cf2976SLionel Sambuc {
50f7cf2976SLionel Sambuc 	register int c;
51f7cf2976SLionel Sambuc 	register int i;
52f7cf2976SLionel Sambuc 	int a;
53f7cf2976SLionel Sambuc 
54f7cf2976SLionel Sambuc 	if (ABORT_SIGS())
55f7cf2976SLionel Sambuc 	{
56f7cf2976SLionel Sambuc 		/*
57f7cf2976SLionel Sambuc 		 * Don't output if a signal is pending.
58f7cf2976SLionel Sambuc 		 */
59f7cf2976SLionel Sambuc 		screen_trashed = 1;
60f7cf2976SLionel Sambuc 		return;
61f7cf2976SLionel Sambuc 	}
62f7cf2976SLionel Sambuc 
63f7cf2976SLionel Sambuc 	final_attr = AT_NORMAL;
64f7cf2976SLionel Sambuc 
65f7cf2976SLionel Sambuc 	for (i = 0;  (c = gline(i, &a)) != '\0';  i++)
66f7cf2976SLionel Sambuc 	{
67f7cf2976SLionel Sambuc 		at_switch(a);
68f7cf2976SLionel Sambuc 		final_attr = a;
69f7cf2976SLionel Sambuc 		if (c == '\b')
70f7cf2976SLionel Sambuc 			putbs();
71f7cf2976SLionel Sambuc 		else
72f7cf2976SLionel Sambuc 			putchr(c);
73f7cf2976SLionel Sambuc 	}
74f7cf2976SLionel Sambuc 
75f7cf2976SLionel Sambuc 	at_exit();
76f7cf2976SLionel Sambuc }
77f7cf2976SLionel Sambuc 
78f7cf2976SLionel Sambuc static char obuf[OUTBUF_SIZE];
79f7cf2976SLionel Sambuc static char *ob = obuf;
80f7cf2976SLionel Sambuc 
81f7cf2976SLionel Sambuc /*
82f7cf2976SLionel Sambuc  * Flush buffered output.
83f7cf2976SLionel Sambuc  *
84f7cf2976SLionel Sambuc  * If we haven't displayed any file data yet,
85f7cf2976SLionel Sambuc  * output messages on error output (file descriptor 2),
86f7cf2976SLionel Sambuc  * otherwise output on standard output (file descriptor 1).
87f7cf2976SLionel Sambuc  *
88f7cf2976SLionel Sambuc  * This has the desirable effect of producing all
89f7cf2976SLionel Sambuc  * error messages on error output if standard output
90f7cf2976SLionel Sambuc  * is directed to a file.  It also does the same if
91f7cf2976SLionel Sambuc  * we never produce any real output; for example, if
92f7cf2976SLionel Sambuc  * the input file(s) cannot be opened.  If we do
93f7cf2976SLionel Sambuc  * eventually produce output, code in edit() makes
94f7cf2976SLionel Sambuc  * sure these messages can be seen before they are
95f7cf2976SLionel Sambuc  * overwritten or scrolled away.
96f7cf2976SLionel Sambuc  */
97f7cf2976SLionel Sambuc 	public void
flush()98f7cf2976SLionel Sambuc flush()
99f7cf2976SLionel Sambuc {
100f7cf2976SLionel Sambuc 	register int n;
101f7cf2976SLionel Sambuc 	register int fd;
102f7cf2976SLionel Sambuc 
103f7cf2976SLionel Sambuc 	n = ob - obuf;
104f7cf2976SLionel Sambuc 	if (n == 0)
105f7cf2976SLionel Sambuc 		return;
106f7cf2976SLionel Sambuc 
107f7cf2976SLionel Sambuc #if MSDOS_COMPILER==MSOFTC
108f7cf2976SLionel Sambuc 	if (is_tty && any_display)
109f7cf2976SLionel Sambuc 	{
110f7cf2976SLionel Sambuc 		*ob = '\0';
111f7cf2976SLionel Sambuc 		_outtext(obuf);
112f7cf2976SLionel Sambuc 		ob = obuf;
113f7cf2976SLionel Sambuc 		return;
114f7cf2976SLionel Sambuc 	}
115f7cf2976SLionel Sambuc #else
116f7cf2976SLionel Sambuc #if MSDOS_COMPILER==WIN32C || MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC
117f7cf2976SLionel Sambuc 	if (is_tty && any_display)
118f7cf2976SLionel Sambuc 	{
119f7cf2976SLionel Sambuc 		*ob = '\0';
120f7cf2976SLionel Sambuc 		if (ctldisp != OPT_ONPLUS)
121f7cf2976SLionel Sambuc 			WIN32textout(obuf, ob - obuf);
122f7cf2976SLionel Sambuc 		else
123f7cf2976SLionel Sambuc 		{
124f7cf2976SLionel Sambuc 			/*
125f7cf2976SLionel Sambuc 			 * Look for SGR escape sequences, and convert them
126f7cf2976SLionel Sambuc 			 * to color commands.  Replace bold, underline,
127f7cf2976SLionel Sambuc 			 * and italic escapes into colors specified via
128f7cf2976SLionel Sambuc 			 * the -D command-line option.
129f7cf2976SLionel Sambuc 			 */
130f7cf2976SLionel Sambuc 			char *anchor, *p, *p_next;
131f7cf2976SLionel Sambuc 			unsigned char fg, bg;
132f7cf2976SLionel Sambuc 			static unsigned char at;
133f7cf2976SLionel Sambuc #if MSDOS_COMPILER==WIN32C
134f7cf2976SLionel Sambuc 			/* Screen colors used by 3x and 4x SGR commands. */
135f7cf2976SLionel Sambuc 			static unsigned char screen_color[] = {
136f7cf2976SLionel Sambuc 				0, /* BLACK */
137f7cf2976SLionel Sambuc 				FOREGROUND_RED,
138f7cf2976SLionel Sambuc 				FOREGROUND_GREEN,
139f7cf2976SLionel Sambuc 				FOREGROUND_RED|FOREGROUND_GREEN,
140f7cf2976SLionel Sambuc 				FOREGROUND_BLUE,
141f7cf2976SLionel Sambuc 				FOREGROUND_BLUE|FOREGROUND_RED,
142f7cf2976SLionel Sambuc 				FOREGROUND_BLUE|FOREGROUND_GREEN,
143f7cf2976SLionel Sambuc 				FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED
144f7cf2976SLionel Sambuc 			};
145f7cf2976SLionel Sambuc #else
146f7cf2976SLionel Sambuc 			static enum COLORS screen_color[] = {
147f7cf2976SLionel Sambuc 				BLACK, RED, GREEN, BROWN,
148f7cf2976SLionel Sambuc 				BLUE, MAGENTA, CYAN, LIGHTGRAY
149f7cf2976SLionel Sambuc 			};
150f7cf2976SLionel Sambuc #endif
151f7cf2976SLionel Sambuc 
152f7cf2976SLionel Sambuc 			for (anchor = p_next = obuf;
153f7cf2976SLionel Sambuc 			     (p_next = memchr(p_next, ESC, ob - p_next)) != NULL; )
154f7cf2976SLionel Sambuc 			{
155f7cf2976SLionel Sambuc 				p = p_next;
156f7cf2976SLionel Sambuc 				if (p[1] == '[')  /* "ESC-[" sequence */
157f7cf2976SLionel Sambuc 				{
158f7cf2976SLionel Sambuc 					if (p > anchor)
159f7cf2976SLionel Sambuc 					{
160f7cf2976SLionel Sambuc 						/*
161f7cf2976SLionel Sambuc 						 * If some chars seen since
162f7cf2976SLionel Sambuc 						 * the last escape sequence,
163f7cf2976SLionel Sambuc 						 * write them out to the screen.
164f7cf2976SLionel Sambuc 						 */
165f7cf2976SLionel Sambuc 						WIN32textout(anchor, p-anchor);
166f7cf2976SLionel Sambuc 						anchor = p;
167f7cf2976SLionel Sambuc 					}
168f7cf2976SLionel Sambuc 					p += 2;  /* Skip the "ESC-[" */
169f7cf2976SLionel Sambuc 					if (is_ansi_end(*p))
170f7cf2976SLionel Sambuc 					{
171f7cf2976SLionel Sambuc 						/*
172f7cf2976SLionel Sambuc 						 * Handle null escape sequence
173f7cf2976SLionel Sambuc 						 * "ESC[m", which restores
174f7cf2976SLionel Sambuc 						 * the normal color.
175f7cf2976SLionel Sambuc 						 */
176f7cf2976SLionel Sambuc 						p++;
177f7cf2976SLionel Sambuc 						anchor = p_next = p;
178*84d9c625SLionel Sambuc 						at = 0;
179f7cf2976SLionel Sambuc 						WIN32setcolors(nm_fg_color, nm_bg_color);
180f7cf2976SLionel Sambuc 						continue;
181f7cf2976SLionel Sambuc 					}
182f7cf2976SLionel Sambuc 					p_next = p;
183f7cf2976SLionel Sambuc 
184f7cf2976SLionel Sambuc 					/*
185f7cf2976SLionel Sambuc 					 * Select foreground/background colors
186f7cf2976SLionel Sambuc 					 * based on the escape sequence.
187f7cf2976SLionel Sambuc 					 */
188f7cf2976SLionel Sambuc 					fg = nm_fg_color;
189f7cf2976SLionel Sambuc 					bg = nm_bg_color;
190f7cf2976SLionel Sambuc 					while (!is_ansi_end(*p))
191f7cf2976SLionel Sambuc 					{
192f7cf2976SLionel Sambuc 						char *q;
193f7cf2976SLionel Sambuc 						long code = strtol(p, &q, 10);
194f7cf2976SLionel Sambuc 
195f7cf2976SLionel Sambuc 						if (*q == '\0')
196f7cf2976SLionel Sambuc 						{
197f7cf2976SLionel Sambuc 							/*
198f7cf2976SLionel Sambuc 							 * Incomplete sequence.
199f7cf2976SLionel Sambuc 							 * Leave it unprocessed
200f7cf2976SLionel Sambuc 							 * in the buffer.
201f7cf2976SLionel Sambuc 							 */
202f7cf2976SLionel Sambuc 							int slop = q - anchor;
203f7cf2976SLionel Sambuc 							/* {{ strcpy args overlap! }} */
204f7cf2976SLionel Sambuc 							strcpy(obuf, anchor);
205f7cf2976SLionel Sambuc 							ob = &obuf[slop];
206f7cf2976SLionel Sambuc 							return;
207f7cf2976SLionel Sambuc 						}
208f7cf2976SLionel Sambuc 
209f7cf2976SLionel Sambuc 						if (q == p ||
210f7cf2976SLionel Sambuc 						    code > 49 || code < 0 ||
211f7cf2976SLionel Sambuc 						    (!is_ansi_end(*q) && *q != ';'))
212f7cf2976SLionel Sambuc 						{
213f7cf2976SLionel Sambuc 							p_next = q;
214f7cf2976SLionel Sambuc 							break;
215f7cf2976SLionel Sambuc 						}
216f7cf2976SLionel Sambuc 						if (*q == ';')
217f7cf2976SLionel Sambuc 							q++;
218f7cf2976SLionel Sambuc 
219f7cf2976SLionel Sambuc 						switch (code)
220f7cf2976SLionel Sambuc 						{
221f7cf2976SLionel Sambuc 						default:
222f7cf2976SLionel Sambuc 						/* case 0: all attrs off */
223f7cf2976SLionel Sambuc 							fg = nm_fg_color;
224f7cf2976SLionel Sambuc 							bg = nm_bg_color;
225f7cf2976SLionel Sambuc 							at = 0;
226f7cf2976SLionel Sambuc 							break;
227f7cf2976SLionel Sambuc 						case 1:	/* bold on */
228f7cf2976SLionel Sambuc 							at |= 1;
229f7cf2976SLionel Sambuc 							break;
230f7cf2976SLionel Sambuc 						case 3:	/* italic on */
231f7cf2976SLionel Sambuc 						case 7: /* inverse on */
232f7cf2976SLionel Sambuc 							at |= 2;
233f7cf2976SLionel Sambuc 							break;
234f7cf2976SLionel Sambuc 						case 4:	/* underline on */
235f7cf2976SLionel Sambuc 							at |= 4;
236f7cf2976SLionel Sambuc 							break;
237f7cf2976SLionel Sambuc 						case 5: /* slow blink on */
238f7cf2976SLionel Sambuc 						case 6: /* fast blink on */
239f7cf2976SLionel Sambuc 							at |= 8;
240f7cf2976SLionel Sambuc 							break;
241f7cf2976SLionel Sambuc 						case 8:	/* concealed on */
242f7cf2976SLionel Sambuc 							fg = (bg & 7) | 8;
243f7cf2976SLionel Sambuc 							break;
244f7cf2976SLionel Sambuc 						case 22: /* bold off */
245f7cf2976SLionel Sambuc 							at &= ~1;
246f7cf2976SLionel Sambuc 							break;
247f7cf2976SLionel Sambuc 						case 23: /* italic off */
248f7cf2976SLionel Sambuc 						case 27: /* inverse off */
249f7cf2976SLionel Sambuc 							at &= ~2;
250f7cf2976SLionel Sambuc 							break;
251f7cf2976SLionel Sambuc 						case 24: /* underline off */
252f7cf2976SLionel Sambuc 							at &= ~4;
253f7cf2976SLionel Sambuc 							break;
254f7cf2976SLionel Sambuc 						case 30: case 31: case 32:
255f7cf2976SLionel Sambuc 						case 33: case 34: case 35:
256f7cf2976SLionel Sambuc 						case 36: case 37:
257f7cf2976SLionel Sambuc 							fg = (fg & 8) | (screen_color[code - 30]);
258f7cf2976SLionel Sambuc 							break;
259f7cf2976SLionel Sambuc 						case 39: /* default fg */
260f7cf2976SLionel Sambuc 							fg = nm_fg_color;
261f7cf2976SLionel Sambuc 							break;
262f7cf2976SLionel Sambuc 						case 40: case 41: case 42:
263f7cf2976SLionel Sambuc 						case 43: case 44: case 45:
264f7cf2976SLionel Sambuc 						case 46: case 47:
265f7cf2976SLionel Sambuc 							bg = (bg & 8) | (screen_color[code - 40]);
266f7cf2976SLionel Sambuc 							break;
267f7cf2976SLionel Sambuc 						case 49: /* default fg */
268f7cf2976SLionel Sambuc 							bg = nm_bg_color;
269f7cf2976SLionel Sambuc 							break;
270f7cf2976SLionel Sambuc 						}
271f7cf2976SLionel Sambuc 						p = q;
272f7cf2976SLionel Sambuc 					}
273f7cf2976SLionel Sambuc 					if (!is_ansi_end(*p) || p == p_next)
274f7cf2976SLionel Sambuc 						break;
275f7cf2976SLionel Sambuc 					if (at & 1)
276f7cf2976SLionel Sambuc 					{
277*84d9c625SLionel Sambuc 						/*
278*84d9c625SLionel Sambuc 						 * If \e[1m use defined bold
279*84d9c625SLionel Sambuc 						 * color, else set intensity.
280*84d9c625SLionel Sambuc 						 */
281*84d9c625SLionel Sambuc 						if (p[-2] == '[')
282*84d9c625SLionel Sambuc 						{
283*84d9c625SLionel Sambuc #if MSDOS_COMPILER==WIN32C
284*84d9c625SLionel Sambuc 							fg |= FOREGROUND_INTENSITY;
285*84d9c625SLionel Sambuc 							bg |= BACKGROUND_INTENSITY;
286*84d9c625SLionel Sambuc #else
287f7cf2976SLionel Sambuc 							fg = bo_fg_color;
288f7cf2976SLionel Sambuc 							bg = bo_bg_color;
289*84d9c625SLionel Sambuc #endif
290*84d9c625SLionel Sambuc 						} else
291*84d9c625SLionel Sambuc 							fg |= 8;
292f7cf2976SLionel Sambuc 					} else if (at & 2)
293f7cf2976SLionel Sambuc 					{
294f7cf2976SLionel Sambuc 						fg = so_fg_color;
295f7cf2976SLionel Sambuc 						bg = so_bg_color;
296f7cf2976SLionel Sambuc 					} else if (at & 4)
297f7cf2976SLionel Sambuc 					{
298f7cf2976SLionel Sambuc 						fg = ul_fg_color;
299f7cf2976SLionel Sambuc 						bg = ul_bg_color;
300f7cf2976SLionel Sambuc 					} else if (at & 8)
301f7cf2976SLionel Sambuc 					{
302f7cf2976SLionel Sambuc 						fg = bl_fg_color;
303f7cf2976SLionel Sambuc 						bg = bl_bg_color;
304f7cf2976SLionel Sambuc 					}
305f7cf2976SLionel Sambuc 					fg &= 0xf;
306f7cf2976SLionel Sambuc 					bg &= 0xf;
307f7cf2976SLionel Sambuc 					WIN32setcolors(fg, bg);
308f7cf2976SLionel Sambuc 					p_next = anchor = p + 1;
309f7cf2976SLionel Sambuc 				} else
310f7cf2976SLionel Sambuc 					p_next++;
311f7cf2976SLionel Sambuc 			}
312f7cf2976SLionel Sambuc 
313f7cf2976SLionel Sambuc 			/* Output what's left in the buffer.  */
314f7cf2976SLionel Sambuc 			WIN32textout(anchor, ob - anchor);
315f7cf2976SLionel Sambuc 		}
316f7cf2976SLionel Sambuc 		ob = obuf;
317f7cf2976SLionel Sambuc 		return;
318f7cf2976SLionel Sambuc 	}
319f7cf2976SLionel Sambuc #endif
320f7cf2976SLionel Sambuc #endif
321f7cf2976SLionel Sambuc 	fd = (any_display) ? 1 : 2;
322f7cf2976SLionel Sambuc 	if (write(fd, obuf, n) != n)
323f7cf2976SLionel Sambuc 		screen_trashed = 1;
324f7cf2976SLionel Sambuc 	ob = obuf;
325f7cf2976SLionel Sambuc }
326f7cf2976SLionel Sambuc 
327f7cf2976SLionel Sambuc /*
328f7cf2976SLionel Sambuc  * Output a character.
329f7cf2976SLionel Sambuc  */
330f7cf2976SLionel Sambuc 	public int
putchr(c)331f7cf2976SLionel Sambuc putchr(c)
332f7cf2976SLionel Sambuc 	int c;
333f7cf2976SLionel Sambuc {
334f7cf2976SLionel Sambuc #if 0 /* fake UTF-8 output for testing */
335f7cf2976SLionel Sambuc 	extern int utf_mode;
336f7cf2976SLionel Sambuc 	if (utf_mode)
337f7cf2976SLionel Sambuc 	{
338f7cf2976SLionel Sambuc 		static char ubuf[MAX_UTF_CHAR_LEN];
339f7cf2976SLionel Sambuc 		static int ubuf_len = 0;
340f7cf2976SLionel Sambuc 		static int ubuf_index = 0;
341f7cf2976SLionel Sambuc 		if (ubuf_len == 0)
342f7cf2976SLionel Sambuc 		{
343f7cf2976SLionel Sambuc 			ubuf_len = utf_len(c);
344f7cf2976SLionel Sambuc 			ubuf_index = 0;
345f7cf2976SLionel Sambuc 		}
346f7cf2976SLionel Sambuc 		ubuf[ubuf_index++] = c;
347f7cf2976SLionel Sambuc 		if (ubuf_index < ubuf_len)
348f7cf2976SLionel Sambuc 			return c;
349f7cf2976SLionel Sambuc 		c = get_wchar(ubuf) & 0xFF;
350f7cf2976SLionel Sambuc 		ubuf_len = 0;
351f7cf2976SLionel Sambuc 	}
352f7cf2976SLionel Sambuc #endif
353f7cf2976SLionel Sambuc 	if (need_clr)
354f7cf2976SLionel Sambuc 	{
355f7cf2976SLionel Sambuc 		need_clr = 0;
356f7cf2976SLionel Sambuc 		clear_bot();
357f7cf2976SLionel Sambuc 	}
358f7cf2976SLionel Sambuc #if MSDOS_COMPILER
359f7cf2976SLionel Sambuc 	if (c == '\n' && is_tty)
360f7cf2976SLionel Sambuc 	{
361f7cf2976SLionel Sambuc 		/* remove_top(1); */
362f7cf2976SLionel Sambuc 		putchr('\r');
363f7cf2976SLionel Sambuc 	}
364f7cf2976SLionel Sambuc #else
365f7cf2976SLionel Sambuc #ifdef _OSK
366f7cf2976SLionel Sambuc 	if (c == '\n' && is_tty)  /* In OS-9, '\n' == 0x0D */
367f7cf2976SLionel Sambuc 		putchr(0x0A);
368f7cf2976SLionel Sambuc #endif
369f7cf2976SLionel Sambuc #endif
370f7cf2976SLionel Sambuc 	/*
371f7cf2976SLionel Sambuc 	 * Some versions of flush() write to *ob, so we must flush
372f7cf2976SLionel Sambuc 	 * when we are still one char from the end of obuf.
373f7cf2976SLionel Sambuc 	 */
374f7cf2976SLionel Sambuc 	if (ob >= &obuf[sizeof(obuf)-1])
375f7cf2976SLionel Sambuc 		flush();
376f7cf2976SLionel Sambuc 	*ob++ = c;
377f7cf2976SLionel Sambuc 	at_prompt = 0;
378f7cf2976SLionel Sambuc 	return (c);
379f7cf2976SLionel Sambuc }
380f7cf2976SLionel Sambuc 
381f7cf2976SLionel Sambuc /*
382f7cf2976SLionel Sambuc  * Output a string.
383f7cf2976SLionel Sambuc  */
384f7cf2976SLionel Sambuc 	public void
putstr(s)385f7cf2976SLionel Sambuc putstr(s)
386f7cf2976SLionel Sambuc 	register char *s;
387f7cf2976SLionel Sambuc {
388f7cf2976SLionel Sambuc 	while (*s != '\0')
389f7cf2976SLionel Sambuc 		putchr(*s++);
390f7cf2976SLionel Sambuc }
391f7cf2976SLionel Sambuc 
392f7cf2976SLionel Sambuc 
393f7cf2976SLionel Sambuc /*
394f7cf2976SLionel Sambuc  * Convert an integral type to a string.
395f7cf2976SLionel Sambuc  */
396f7cf2976SLionel Sambuc #define TYPE_TO_A_FUNC(funcname, type) \
397f7cf2976SLionel Sambuc void funcname(num, buf) \
398f7cf2976SLionel Sambuc 	type num; \
399f7cf2976SLionel Sambuc 	char *buf; \
400f7cf2976SLionel Sambuc { \
401f7cf2976SLionel Sambuc 	int neg = (num < 0); \
402f7cf2976SLionel Sambuc 	char tbuf[INT_STRLEN_BOUND(num)+2]; \
403f7cf2976SLionel Sambuc 	register char *s = tbuf + sizeof(tbuf); \
404f7cf2976SLionel Sambuc 	if (neg) num = -num; \
405f7cf2976SLionel Sambuc 	*--s = '\0'; \
406f7cf2976SLionel Sambuc 	do { \
407f7cf2976SLionel Sambuc 		*--s = (num % 10) + '0'; \
408f7cf2976SLionel Sambuc 	} while ((num /= 10) != 0); \
409f7cf2976SLionel Sambuc 	if (neg) *--s = '-'; \
410f7cf2976SLionel Sambuc 	strcpy(buf, s); \
411f7cf2976SLionel Sambuc }
412f7cf2976SLionel Sambuc 
413f7cf2976SLionel Sambuc TYPE_TO_A_FUNC(postoa, POSITION)
414f7cf2976SLionel Sambuc TYPE_TO_A_FUNC(linenumtoa, LINENUM)
415f7cf2976SLionel Sambuc TYPE_TO_A_FUNC(inttoa, int)
416f7cf2976SLionel Sambuc 
417f7cf2976SLionel Sambuc /*
418f7cf2976SLionel Sambuc  * Output an integer in a given radix.
419f7cf2976SLionel Sambuc  */
420f7cf2976SLionel Sambuc 	static int
421f7cf2976SLionel Sambuc iprint_int(num)
422f7cf2976SLionel Sambuc 	int num;
423f7cf2976SLionel Sambuc {
424f7cf2976SLionel Sambuc 	char buf[INT_STRLEN_BOUND(num)];
425f7cf2976SLionel Sambuc 
426f7cf2976SLionel Sambuc 	inttoa(num, buf);
427f7cf2976SLionel Sambuc 	putstr(buf);
428f7cf2976SLionel Sambuc 	return (strlen(buf));
429f7cf2976SLionel Sambuc }
430f7cf2976SLionel Sambuc 
431f7cf2976SLionel Sambuc /*
432f7cf2976SLionel Sambuc  * Output a line number in a given radix.
433f7cf2976SLionel Sambuc  */
434f7cf2976SLionel Sambuc 	static int
iprint_linenum(num)435f7cf2976SLionel Sambuc iprint_linenum(num)
436f7cf2976SLionel Sambuc 	LINENUM num;
437f7cf2976SLionel Sambuc {
438f7cf2976SLionel Sambuc 	char buf[INT_STRLEN_BOUND(num)];
439f7cf2976SLionel Sambuc 
440f7cf2976SLionel Sambuc 	linenumtoa(num, buf);
441f7cf2976SLionel Sambuc 	putstr(buf);
442f7cf2976SLionel Sambuc 	return (strlen(buf));
443f7cf2976SLionel Sambuc }
444f7cf2976SLionel Sambuc 
445f7cf2976SLionel Sambuc /*
446f7cf2976SLionel Sambuc  * This function implements printf-like functionality
447f7cf2976SLionel Sambuc  * using a more portable argument list mechanism than printf's.
448f7cf2976SLionel Sambuc  */
449f7cf2976SLionel Sambuc 	static int
less_printf(fmt,parg)450f7cf2976SLionel Sambuc less_printf(fmt, parg)
451f7cf2976SLionel Sambuc 	register char *fmt;
452f7cf2976SLionel Sambuc 	PARG *parg;
453f7cf2976SLionel Sambuc {
454f7cf2976SLionel Sambuc 	register constant char *s;
455f7cf2976SLionel Sambuc 	register int col;
456f7cf2976SLionel Sambuc 
457f7cf2976SLionel Sambuc 	col = 0;
458f7cf2976SLionel Sambuc 	while (*fmt != '\0')
459f7cf2976SLionel Sambuc 	{
460f7cf2976SLionel Sambuc 		if (*fmt != '%')
461f7cf2976SLionel Sambuc 		{
462f7cf2976SLionel Sambuc 			putchr(*fmt++);
463f7cf2976SLionel Sambuc 			col++;
464f7cf2976SLionel Sambuc 		} else
465f7cf2976SLionel Sambuc 		{
466f7cf2976SLionel Sambuc 			++fmt;
467f7cf2976SLionel Sambuc 			switch (*fmt++)
468f7cf2976SLionel Sambuc 			{
469f7cf2976SLionel Sambuc 			case 's':
470f7cf2976SLionel Sambuc 				s = parg->p_string;
471f7cf2976SLionel Sambuc 				parg++;
472f7cf2976SLionel Sambuc 				while (*s != '\0')
473f7cf2976SLionel Sambuc 				{
474f7cf2976SLionel Sambuc 					putchr(*s++);
475f7cf2976SLionel Sambuc 					col++;
476f7cf2976SLionel Sambuc 				}
477f7cf2976SLionel Sambuc 				break;
478f7cf2976SLionel Sambuc 			case 'd':
479f7cf2976SLionel Sambuc 				col += iprint_int(parg->p_int);
480f7cf2976SLionel Sambuc 				parg++;
481f7cf2976SLionel Sambuc 				break;
482f7cf2976SLionel Sambuc 			case 'n':
483f7cf2976SLionel Sambuc 				col += iprint_linenum(parg->p_linenum);
484f7cf2976SLionel Sambuc 				parg++;
485f7cf2976SLionel Sambuc 				break;
486f7cf2976SLionel Sambuc 			}
487f7cf2976SLionel Sambuc 		}
488f7cf2976SLionel Sambuc 	}
489f7cf2976SLionel Sambuc 	return (col);
490f7cf2976SLionel Sambuc }
491f7cf2976SLionel Sambuc 
492f7cf2976SLionel Sambuc /*
493f7cf2976SLionel Sambuc  * Get a RETURN.
494f7cf2976SLionel Sambuc  * If some other non-trivial char is pressed, unget it, so it will
495f7cf2976SLionel Sambuc  * become the next command.
496f7cf2976SLionel Sambuc  */
497f7cf2976SLionel Sambuc 	public void
get_return()498f7cf2976SLionel Sambuc get_return()
499f7cf2976SLionel Sambuc {
500f7cf2976SLionel Sambuc 	int c;
501f7cf2976SLionel Sambuc 
502f7cf2976SLionel Sambuc #if ONLY_RETURN
503f7cf2976SLionel Sambuc 	while ((c = getchr()) != '\n' && c != '\r')
504f7cf2976SLionel Sambuc 		bell();
505f7cf2976SLionel Sambuc #else
506f7cf2976SLionel Sambuc 	c = getchr();
507f7cf2976SLionel Sambuc 	if (c != '\n' && c != '\r' && c != ' ' && c != READ_INTR)
508f7cf2976SLionel Sambuc 		ungetcc(c);
509f7cf2976SLionel Sambuc #endif
510f7cf2976SLionel Sambuc }
511f7cf2976SLionel Sambuc 
512f7cf2976SLionel Sambuc /*
513f7cf2976SLionel Sambuc  * Output a message in the lower left corner of the screen
514f7cf2976SLionel Sambuc  * and wait for carriage return.
515f7cf2976SLionel Sambuc  */
516f7cf2976SLionel Sambuc 	public void
error(fmt,parg)517f7cf2976SLionel Sambuc error(fmt, parg)
518f7cf2976SLionel Sambuc 	char *fmt;
519f7cf2976SLionel Sambuc 	PARG *parg;
520f7cf2976SLionel Sambuc {
521f7cf2976SLionel Sambuc 	int col = 0;
522f7cf2976SLionel Sambuc 	static char return_to_continue[] = "  (press RETURN)";
523f7cf2976SLionel Sambuc 
524f7cf2976SLionel Sambuc 	errmsgs++;
525f7cf2976SLionel Sambuc 
526f7cf2976SLionel Sambuc 	if (any_display && is_tty)
527f7cf2976SLionel Sambuc 	{
528f7cf2976SLionel Sambuc 		if (!oldbot)
529f7cf2976SLionel Sambuc 			squish_check();
530f7cf2976SLionel Sambuc 		at_exit();
531f7cf2976SLionel Sambuc 		clear_bot();
532f7cf2976SLionel Sambuc 		at_enter(AT_STANDOUT);
533f7cf2976SLionel Sambuc 		col += so_s_width;
534f7cf2976SLionel Sambuc 	}
535f7cf2976SLionel Sambuc 
536f7cf2976SLionel Sambuc 	col += less_printf(fmt, parg);
537f7cf2976SLionel Sambuc 
538f7cf2976SLionel Sambuc 	if (!(any_display && is_tty))
539f7cf2976SLionel Sambuc 	{
540f7cf2976SLionel Sambuc 		putchr('\n');
541f7cf2976SLionel Sambuc 		return;
542f7cf2976SLionel Sambuc 	}
543f7cf2976SLionel Sambuc 
544f7cf2976SLionel Sambuc 	putstr(return_to_continue);
545f7cf2976SLionel Sambuc 	at_exit();
546f7cf2976SLionel Sambuc 	col += sizeof(return_to_continue) + so_e_width;
547f7cf2976SLionel Sambuc 
548f7cf2976SLionel Sambuc 	get_return();
549f7cf2976SLionel Sambuc 	lower_left();
550f7cf2976SLionel Sambuc     clear_eol();
551f7cf2976SLionel Sambuc 
552f7cf2976SLionel Sambuc 	if (col >= sc_width)
553f7cf2976SLionel Sambuc 		/*
554f7cf2976SLionel Sambuc 		 * Printing the message has probably scrolled the screen.
555f7cf2976SLionel Sambuc 		 * {{ Unless the terminal doesn't have auto margins,
556f7cf2976SLionel Sambuc 		 *    in which case we just hammered on the right margin. }}
557f7cf2976SLionel Sambuc 		 */
558f7cf2976SLionel Sambuc 		screen_trashed = 1;
559f7cf2976SLionel Sambuc 
560f7cf2976SLionel Sambuc 	flush();
561f7cf2976SLionel Sambuc }
562f7cf2976SLionel Sambuc 
563f7cf2976SLionel Sambuc static char intr_to_abort[] = "... (interrupt to abort)";
564f7cf2976SLionel Sambuc 
565f7cf2976SLionel Sambuc /*
566f7cf2976SLionel Sambuc  * Output a message in the lower left corner of the screen
567f7cf2976SLionel Sambuc  * and don't wait for carriage return.
568f7cf2976SLionel Sambuc  * Usually used to warn that we are beginning a potentially
569f7cf2976SLionel Sambuc  * time-consuming operation.
570f7cf2976SLionel Sambuc  */
571f7cf2976SLionel Sambuc 	public void
ierror(fmt,parg)572f7cf2976SLionel Sambuc ierror(fmt, parg)
573f7cf2976SLionel Sambuc 	char *fmt;
574f7cf2976SLionel Sambuc 	PARG *parg;
575f7cf2976SLionel Sambuc {
576f7cf2976SLionel Sambuc 	at_exit();
577f7cf2976SLionel Sambuc 	clear_bot();
578f7cf2976SLionel Sambuc 	at_enter(AT_STANDOUT);
579f7cf2976SLionel Sambuc 	(void) less_printf(fmt, parg);
580f7cf2976SLionel Sambuc 	putstr(intr_to_abort);
581f7cf2976SLionel Sambuc 	at_exit();
582f7cf2976SLionel Sambuc 	flush();
583f7cf2976SLionel Sambuc 	need_clr = 1;
584f7cf2976SLionel Sambuc }
585f7cf2976SLionel Sambuc 
586f7cf2976SLionel Sambuc /*
587f7cf2976SLionel Sambuc  * Output a message in the lower left corner of the screen
588f7cf2976SLionel Sambuc  * and return a single-character response.
589f7cf2976SLionel Sambuc  */
590f7cf2976SLionel Sambuc 	public int
query(fmt,parg)591f7cf2976SLionel Sambuc query(fmt, parg)
592f7cf2976SLionel Sambuc 	char *fmt;
593f7cf2976SLionel Sambuc 	PARG *parg;
594f7cf2976SLionel Sambuc {
595f7cf2976SLionel Sambuc 	register int c;
596f7cf2976SLionel Sambuc 	int col = 0;
597f7cf2976SLionel Sambuc 
598f7cf2976SLionel Sambuc 	if (any_display && is_tty)
599f7cf2976SLionel Sambuc 		clear_bot();
600f7cf2976SLionel Sambuc 
601f7cf2976SLionel Sambuc 	(void) less_printf(fmt, parg);
602f7cf2976SLionel Sambuc 	c = getchr();
603f7cf2976SLionel Sambuc 
604f7cf2976SLionel Sambuc 	if (!(any_display && is_tty))
605f7cf2976SLionel Sambuc 	{
606f7cf2976SLionel Sambuc 		putchr('\n');
607f7cf2976SLionel Sambuc 		return (c);
608f7cf2976SLionel Sambuc 	}
609f7cf2976SLionel Sambuc 
610f7cf2976SLionel Sambuc 	lower_left();
611f7cf2976SLionel Sambuc 	if (col >= sc_width)
612f7cf2976SLionel Sambuc 		screen_trashed = 1;
613f7cf2976SLionel Sambuc 	flush();
614f7cf2976SLionel Sambuc 
615f7cf2976SLionel Sambuc 	return (c);
616f7cf2976SLionel Sambuc }
617