1 /****************************************************************************
2  * Copyright 2019,2020 Thomas E. Dickey                                     *
3  * Copyright 2000-2013,2017 Free Software Foundation, Inc.                  *
4  *                                                                          *
5  * Permission is hereby granted, free of charge, to any person obtaining a  *
6  * copy of this software and associated documentation files (the            *
7  * "Software"), to deal in the Software without restriction, including      *
8  * without limitation the rights to use, copy, modify, merge, publish,      *
9  * distribute, distribute with modifications, sublicense, and/or sell       *
10  * copies of the Software, and to permit persons to whom the Software is    *
11  * furnished to do so, subject to the following conditions:                 *
12  *                                                                          *
13  * The above copyright notice and this permission notice shall be included  *
14  * in all copies or substantial portions of the Software.                   *
15  *                                                                          *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
19  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
20  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
21  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
23  *                                                                          *
24  * Except as contained in this notice, the name(s) of the above copyright   *
25  * holders shall not be used in advertising or otherwise to promote the     *
26  * sale, use or other dealings in this Software without prior written       *
27  * authorization.                                                           *
28  ****************************************************************************/
29 
30 /*
31  * Author: Thomas E. Dickey - 2000
32  *
33  * $Id: railroad.c,v 1.25 2020/09/05 21:43:37 tom Exp $
34  *
35  * A simple demo of the termcap interface.
36  */
37 #define USE_TINFO
38 #include <test.priv.h>
39 
40 #if HAVE_TGETENT
41 
42 static char *wipeit;
43 static char *moveit;
44 static int length;
45 static int height;
46 
47 static char *finisC;
48 static char *finisS;
49 static char *finisU;
50 
51 static char *startC;
52 static char *startS;
53 static char *startU;
54 
55 static char *backup;
56 
57 static bool interrupted = FALSE;
58 
59 static
TPUTS_PROTO(outc,c)60 TPUTS_PROTO(outc, c)
61 {
62     int rc = OK;
63 
64     if (interrupted) {
65 	char tmp = (char) c;
66 	if (write(STDOUT_FILENO, &tmp, (size_t) 1) == -1)
67 	    rc = ERR;
68     } else {
69 	if (putc(c, stdout) == EOF)
70 	    rc = ERR;
71     }
72     TPUTS_RETURN(rc);
73 }
74 
75 static void
PutChar(int ch)76 PutChar(int ch)
77 {
78     putchar(ch);
79     fflush(stdout);
80     napms(moveit ? 10 : 50);	/* not really termcap... */
81 }
82 
83 static void
Backup(void)84 Backup(void)
85 {
86     tputs(backup != 0 ? backup : "\b", 1, outc);
87 }
88 
89 static void
MyShowCursor(int flag)90 MyShowCursor(int flag)
91 {
92     if (startC != 0 && finisC != 0) {
93 	tputs(flag ? startC : finisC, 1, outc);
94     }
95 }
96 
97 static void
StandOut(int flag)98 StandOut(int flag)
99 {
100     if (startS != 0 && finisS != 0) {
101 	tputs(flag ? startS : finisS, 1, outc);
102     }
103 }
104 
105 static void
Underline(int flag)106 Underline(int flag)
107 {
108     if (startU != 0 && finisU != 0) {
109 	tputs(flag ? startU : finisU, 1, outc);
110     }
111 }
112 
113 static void
ShowSign(char * string)114 ShowSign(char *string)
115 {
116     char *base = string;
117     int first, last;
118 
119     if (moveit != 0) {
120 	tputs(tgoto(moveit, 0, height - 1), 1, outc);
121 	tputs(wipeit, 1, outc);
122     }
123 
124     while (*string != 0) {
125 	int ch = *string;
126 	if (ch != ' ') {
127 	    if (moveit != 0) {
128 		for (first = length - 2; first >= (string - base); first--) {
129 		    if (first < length - 1) {
130 			tputs(tgoto(moveit, first + 1, height - 1), 1, outc);
131 			PutChar(' ');
132 		    }
133 		    tputs(tgoto(moveit, first, height - 1), 1, outc);
134 		    PutChar(ch);
135 		}
136 	    } else {
137 		last = ch;
138 		if (isalpha(ch)) {
139 		    first = isupper(ch) ? 'A' : 'a';
140 		} else if (isdigit(ch)) {
141 		    first = '0';
142 		} else {
143 		    first = ch;
144 		}
145 		if (first < last) {
146 		    Underline(1);
147 		    while (first < last) {
148 			PutChar(first);
149 			Backup();
150 			first++;
151 		    }
152 		    Underline(0);
153 		}
154 	    }
155 	    if (moveit != 0)
156 		Backup();
157 	}
158 	StandOut(1);
159 	PutChar(ch);
160 	StandOut(0);
161 	fflush(stdout);
162 	string++;
163     }
164     if (moveit != 0)
165 	tputs(wipeit, 1, outc);
166     putchar('\n');
167 }
168 
169 static void
cleanup(void)170 cleanup(void)
171 {
172     Underline(0);
173     StandOut(0);
174     MyShowCursor(1);
175 }
176 
177 static void
onsig(int n GCC_UNUSED)178 onsig(int n GCC_UNUSED)
179 {
180     interrupted = TRUE;
181     cleanup();
182     ExitProgram(EXIT_FAILURE);
183 }
184 
185 static void
railroad(char ** args)186 railroad(char **args)
187 {
188     NCURSES_CONST char *name = getenv("TERM");
189     char buffer[1024];
190     char area[1024], *ap = area;
191     int z;
192 
193     if (name == 0)
194 #ifdef EXP_WIN32_DRIVER
195 	name = "ms-terminal";
196 #else
197 	name = "dumb";
198 #endif
199 
200     InitAndCatch(z = tgetent(buffer, name), onsig);
201     if (z >= 0) {
202 
203 	wipeit = tgetstr("ce", &ap);
204 	height = tgetnum("li");
205 	length = tgetnum("co");
206 	moveit = tgetstr("cm", &ap);
207 
208 	if (wipeit == 0
209 	    || moveit == 0
210 	    || height <= 0
211 	    || length <= 0) {
212 	    wipeit = 0;
213 	    moveit = 0;
214 	    height = 0;
215 	    length = 0;
216 	}
217 
218 	startS = tgetstr("so", &ap);
219 	finisS = tgetstr("se", &ap);
220 
221 	startU = tgetstr("us", &ap);
222 	finisU = tgetstr("ue", &ap);
223 
224 	backup = tgetstr("le", &ap);
225 
226 	startC = tgetstr("ve", &ap);
227 	finisC = tgetstr("vi", &ap);
228 
229 	MyShowCursor(0);
230 
231 	while (*args) {
232 	    ShowSign(*args++);
233 	}
234 	MyShowCursor(1);
235     }
236 }
237 
238 int
main(int argc,char * argv[])239 main(int argc, char *argv[])
240 {
241     if (argc > 1) {
242 	railroad(argv + 1);
243     } else {
244 	static char world[] = "Hello World";
245 	static char *hello[] =
246 	{world, 0};
247 	railroad(hello);
248     }
249     ExitProgram(EXIT_SUCCESS);
250 }
251 
252 #else
253 int
main(int argc GCC_UNUSED,char * argv[]GCC_UNUSED)254 main(int argc GCC_UNUSED,
255      char *argv[]GCC_UNUSED)
256 {
257     printf("This program requires termcap\n");
258     exit(EXIT_FAILURE);
259 }
260 #endif
261