1/*
2** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
3**
4** This file is part of TACK.
5**
6** TACK is free software; you can redistribute it and/or modify
7** it under the terms of the GNU General Public License as published by
8** the Free Software Foundation; either version 2, or (at your option)
9** any later version.
10**
11** TACK is distributed in the hope that it will be useful,
12** but WITHOUT ANY WARRANTY; without even the implied warranty of
13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14** GNU General Public License for more details.
15**
16** You should have received a copy of the GNU General Public License
17** along with TACK; see the file COPYING.  If not, write to
18** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19** Boston, MA 02110-1301, USA
20*/
21
22#include <tack.h>
23
24MODULE_ID("$Id: crum.c,v 1.4 2005/09/17 19:49:16 tom Exp $")
25
26/*
27 * Test cursor movement.
28 */
29
30static void crum_clear(struct test_list *t, int *state, int *ch);
31static void crum_home(struct test_list *t, int *state, int *ch);
32static void crum_ll(struct test_list *t, int *state, int *ch);
33static void crum_move(struct test_list *t, int *state, int *ch);
34static void crum_os(struct test_list *t, int *state, int *ch);
35
36static char crum_text[5][80];
37
38struct test_list crum_test_list[] = {
39	{0, 0, 0, 0, "e) edit terminfo", 0, &edit_menu},
40	{MENU_NEXT, 0, "clear", 0, 0, crum_clear, 0},
41	{MENU_NEXT, 0, "home", 0, 0, crum_home, 0},
42	{MENU_NEXT, 0, "ll", 0, 0, crum_ll, 0},
43	{MENU_NEXT, 0, crum_text[0], "home cuu1", 0, crum_move, 0},
44	{MENU_NEXT + 1, 0, crum_text[1], "cub1 cud1 cuf1 cuu1", 0, crum_move, 0},
45	{MENU_NEXT + 2, 0, crum_text[2], "cub cud cuf cuu", 0, crum_move, 0},
46	{MENU_NEXT + 3, 0, crum_text[3], "vpa hpa", 0, crum_move, 0},
47	{MENU_NEXT + 4, 0, crum_text[4], "cup", 0, crum_move, 0},
48	{MENU_NEXT, 0, "cup", "os", 0, crum_os, 0},
49	{MENU_LAST, 0, 0, 0, 0, 0, 0}
50};
51
52/*
53**	move_to(from-row, from-column, to-row, to-column, selection)
54**
55**	move the cursor from (rf, cf) to (rt, ct) using sel
56*/
57static void
58move_to(
59	int rf,
60	int cf,
61	int rt,
62	int ct,
63	int sel)
64{
65	char *s;
66
67	if (sel & 16) {	/* use (cup) */
68		s = tparm(cursor_address, rt, ct);
69		tputs(s, lines, tc_putch);
70		return;
71	}
72	if (sel & 8) {	/* use (hpa) (vpa) */
73		if (column_address) {
74			s = tparm(column_address, ct);
75			tputs(s, 1, tc_putch);
76			cf = ct;
77		}
78		if (row_address) {
79			s = tparm(row_address, rt);
80			tputs(s, 1, tc_putch);
81			rf = rt;
82		}
83	}
84	if (sel & 4) {	/* parameterized relative cursor movement */
85		if (parm_right_cursor)
86			if (cf < ct) {
87				s = tparm(parm_right_cursor, ct - cf);
88				tputs(s, ct - cf, tc_putch);
89				cf = ct;
90			}
91		if (parm_left_cursor)
92			if (cf > ct) {
93				s = tparm(parm_left_cursor, cf - ct);
94				tputs(s, cf - ct, tc_putch);
95				cf = ct;
96			}
97		if (parm_down_cursor)
98			if (rf < rt) {
99				s = tparm(parm_down_cursor, rt - rf);
100				tputs(s, rt - rf, tc_putch);
101				rf = rt;
102			}
103		if (parm_up_cursor)
104			if (rf > rt) {
105				s = tparm(parm_up_cursor, rf - rt);
106				tputs(s, rf - rt, tc_putch);
107				rf = rt;
108			}
109	}
110	if (sel & 2) {
111		if (cursor_left)
112			while (cf > ct) {
113				tc_putp(cursor_left);
114				cf--;
115			}
116		/*
117		   do vertical motion next.  Just in case cursor_down has a
118		   side effect of changing the column.  This could happen if
119		   the tty handler translates NL to CRNL.
120		*/
121		if (cursor_down)
122			while (rf < rt) {
123				tc_putp(cursor_down);
124				rf++;
125			}
126		if (cursor_up)
127			while (rf > rt) {
128				tc_putp(cursor_up);
129				rf--;
130			}
131		if (cursor_right)
132			while (cf < ct) {
133				tc_putp(cursor_right);
134				cf++;
135			}
136	}
137	/* last chance */
138	if (rf > rt) {
139		if (can_go_home) {	/* a bit drastic but ... */
140			go_home();
141			cf = 0;
142			rf = 0;
143		} else if (cursor_up) {
144			while (rf > rt) {
145				tc_putp(cursor_up);
146				rf--;
147			}
148		}
149	}
150	if (ct == 0 && rt > rf) {
151		put_crlf();
152		cf = 0;
153		rf++;
154	}
155	if (ct == 0 && cf != 0) {
156		put_cr();
157		cf = 0;
158	}
159	while (rf < rt) {
160		put_lf();
161		rf++;
162	}
163	while (cf > ct) {
164		put_str("\b");
165		cf--;
166	}
167	if (cursor_right) {
168		while (cf < ct) {
169			tc_putp(cursor_right);
170			cf++;
171		}
172	} else {
173		/* go ahead and trash my display */
174		while (cf < ct) {
175			putchp(' ');
176			cf++;
177		}
178	}
179}
180
181/*
182**	display_it(selection, text)
183**
184**	print the display using sel
185*/
186static void
187display_it(
188	int sel,
189	char *txt)
190{
191	int i, done_line;
192
193	put_clear();
194	go_home();
195	put_newlines(2);
196	ptextln("    The top line should be alternating <'s and >'s");
197	ptextln("    The left side should be alternating A's and V's");
198	ptext("    Testing ");
199	ptext(txt);
200	put_cr();
201
202	/* horizontal */
203	move_to(done_line = line_count, 0, 0, 2, sel);
204	for (i = 4; i < columns - 2; i += 2) {
205		putchp('>');
206		move_to(0, i - 1, 0, i, sel);
207	}
208	putchp('>');
209	i -= 2;
210	move_to(0, i + 1, 0, i - 1, sel);
211	for (; i > 2; i -= 2) {
212		putchp('<');
213		move_to(0, i, 0, i - 3, sel);
214	}
215	putchp('<');
216
217	/* vertical */
218	move_to(0, 2, 0, 0, sel);
219	for (i = 2; i < lines - 1; i += 2) {
220		putchp('V');
221		move_to(i - 2, 1, i, 0, sel);
222	}
223	putchp('V');
224	i -= 2;
225	move_to(i, 1, i + 1, 0, sel);
226	for (; i > 0; i -= 2) {
227		putchp('A');
228		move_to(i + 1, 1, i - 1, 0, sel);
229	}
230	putchp('A');
231	move_to(i + 1, 1, 0, 0, sel);	/* go home first */
232	move_to(0, 0, done_line + 1, 3, sel);
233	put_str(txt);
234	put_str(" Done. ");
235}
236
237/*
238**	crum_clear(test_list, status, ch)
239**
240**	(clear) test Clear screen
241*/
242static void
243crum_clear(
244	struct test_list *t,
245	int *state,
246	int *ch)
247{
248	int i;
249
250	if (clear_screen) {
251		for (i = lines; i > 1; i--) {
252			putln("garbage");
253		}
254		put_clear();
255		ptextln("This line should start in the home position.");
256		ptext("The rest of the screen should be clear.  ");
257	} else {
258		ptextln("(clear) Clear screen is not defined.  ");
259	}
260	generic_done_message(t, state, ch);
261}
262
263/*
264**	crum_home(test_list, status, ch)
265**
266**	(home) test Home cursor
267*/
268static void
269crum_home(
270	struct test_list *t,
271	int *state,
272	int *ch)
273{
274	if (cursor_home) {
275		put_clear();
276		put_newlines(lines / 2);
277		go_home();
278		put_crlf();
279		ptext("The bottom line should have text.");
280		go_home();
281		put_newlines(lines - 1);
282		ptext("This line is on the bottom.");
283		go_home();
284		ptextln("This line starts in the home position.");
285		put_crlf();
286	} else {
287		ptextln("(home) Home cursor is not defined.  ");
288	}
289	generic_done_message(t, state, ch);
290}
291
292/*
293**	crum_ll(test_list, status, ch)
294**
295**	(ll) test Last line
296*/
297static void
298crum_ll(
299	struct test_list *t,
300	int *state,
301	int *ch)
302{
303	/*
304	   (ll) may be simulated with (cup).  Don't complain if (cup) is present.
305	*/
306	if (cursor_to_ll) {
307		put_clear();
308		put_str("This line could be anywhere.");
309		tc_putp(cursor_to_ll);
310		ptext("This line should be on the bottom");
311		go_home();
312		put_crlf();
313	} else
314	if (cursor_address) {
315		return;
316	} else {
317		ptextln("(ll) Move to last line is not defined.  ");
318	}
319	generic_done_message(t, state, ch);
320}
321
322/*
323**	crum_move(test_list, status, ch)
324**
325**	(*) test all cursor move commands
326*/
327static void
328crum_move(
329	struct test_list *t,
330	int *state,
331	int *ch)
332{
333	char buf[80];
334	int n;
335
336	switch (n = (t->flags & 15)) {
337	case 0:
338		sprintf(buf, " (cr) (nel) (cub1)%s",
339			cursor_home ? " (home)" : (cursor_up ? " (cuu1)" : ""));
340		break;
341	case 1:
342		sprintf(buf, "%s%s%s%s", cursor_left ? " (cub1)" : "",
343			cursor_down ? " (cud1)" : "", cursor_right ? " (cuf1)" : "",
344			cursor_up ? " (cuu1)" : "");
345		if (buf[0] == '\0') {
346			ptext("    (cub1) (cud1) (cuf1) (cuu1) not defined.");
347		}
348		break;
349	case 2:
350		sprintf(buf, "%s%s%s%s", parm_left_cursor ? " (cub)" : "",
351			parm_down_cursor ? " (cud)" : "",
352			parm_right_cursor ? " (cuf)" : "",
353			parm_up_cursor ? " (cuu)" : "");
354		if (buf[0] == '\0') {
355			ptext("    (cub) (cud) (cuf) (cuu) not defined.");
356		}
357		break;
358	case 3:
359		sprintf(buf, "%s%s", row_address ? " (vpa)" : "",
360			column_address ? " (hpa)" : "");
361		if (buf[0] == '\0') {
362			ptext("    (vpa) (hpa) not defined.");
363		}
364		break;
365	case 4:
366		if (!cursor_address) {
367			ptext("    (cup) not defined.  ");
368			generic_done_message(t, state, ch);
369			return;
370		}
371		strcpy(buf, " (cup)");
372		break;
373	}
374	if (buf[0] == '\0') {
375		put_str("  Done. ");
376	} else {
377		can_test(buf, FLAG_TESTED);
378		strcpy(crum_text[n], &buf[2]);
379		crum_text[n][strlen(buf) - 3] = '\0';
380
381		display_it(1 << n, buf);
382	}
383	*ch = wait_here();
384	if (*ch != 'r') {
385		put_clear();
386	}
387}
388
389/*
390**	crum_os(test_list, status, ch)
391**
392**	(cup) test Cursor position on overstrike terminals
393*/
394static void
395crum_os(
396	struct test_list *t,
397	int *state,
398	int *ch)
399{
400	int i;
401
402	if (cursor_address && over_strike) {
403		put_clear();
404		for (i = 0; i < columns - 2; i++) {
405			tc_putch('|');
406		}
407		for (i = 1; i < lines - 2; i++) {
408			put_crlf();
409			tc_putch('_');
410		}
411		for (i = 0; i < columns - 2; i++) {
412			tputs(tparm(cursor_address, 0, i), lines, tc_putch);
413			tc_putch('+');
414		}
415		for (i = 0; i < lines - 2; i++) {
416			tputs(tparm(cursor_address, i, 0), lines, tc_putch);
417			tc_putch(']');
418			tc_putch('_');
419		}
420		go_home();
421		put_newlines(3);
422		ptext("    All the characters should look the same.  ");
423		generic_done_message(t, state, ch);
424		put_clear();
425	}
426}
427