xref: /freebsd/sys/dev/syscons/daemon/daemon_saver.c (revision 2da199da53835ee2d9228a60717fd2d0fccf9e50)
1 /*-
2  * Copyright (c) 1997 Sandro Sigala, Brescia, Italy.
3  * Copyright (c) 1997 Chris Shenton
4  * Copyright (c) 1995 S ren Schmidt
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer
12  *    in this position and unchanged.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  *	$Id: daemon_saver.c,v 1.14 1999/01/17 14:25:08 yokota Exp $
29  */
30 
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/module.h>
34 #include <sys/malloc.h>
35 #include <sys/kernel.h>
36 #include <sys/sysctl.h>
37 
38 #include <machine/md_var.h>
39 #include <machine/pc/display.h>
40 
41 #include <saver.h>
42 
43 #define CONSOLE_VECT(x, y) \
44 	(window + (y)*cur_console->xsize + (x))
45 
46 #define DAEMON_MAX_WIDTH	32
47 #define DAEMON_MAX_HEIGHT	19
48 
49 static char *message;
50 static int messagelen;
51 static u_short *window;
52 static int blanked;
53 
54 /* Who is the author of this ASCII pic? */
55 
56 static char *daemon_pic[] = {
57         "             ,        ,",
58 	"            /(        )`",
59 	"            \\ \\___   / |",
60 	"            /- _  `-/  '",
61 	"           (/\\/ \\ \\   /\\",
62 	"           / /   | `    \\",
63 	"           O O   ) /    |",
64 	"           `-^--'`<     '",
65 	"          (_.)  _  )   /",
66 	"           `.___/`    /",
67 	"             `-----' /",
68 	"<----.     __ / __   \\",
69 	"<----|====O)))==) \\) /====",
70 	"<----'    `--' `.__,' \\",
71 	"             |        |",
72 	"              \\       /       /\\",
73 	"         ______( (_  / \\______/",
74 	"       ,'  ,-----'   |",
75 	"       `--{__________)",
76 	NULL
77 };
78 
79 static char *daemon_attr[] = {
80         "             R        R",
81 	"            RR        RR",
82 	"            R RRRR   R R",
83 	"            RR W  RRR  R",
84 	"           RWWW W R   RR",
85 	"           W W   W R    R",
86 	"           B B   W R    R",
87 	"           WWWWWWRR     R",
88 	"          RRRR  R  R   R",
89 	"           RRRRRRR    R",
90 	"             RRRRRRR R",
91 	"YYYYYY     RR R RR   R",
92 	"YYYYYYYYYYRRRRYYR RR RYYYY",
93 	"YYYYYY    RRRR RRRRRR R",
94 	"             R        R",
95 	"              R       R       RR",
96 	"         CCCCCCR RR  R RRRRRRRR",
97 	"       CC  CCCCCCC   C",
98 	"       CCCCCCCCCCCCCCC",
99 	NULL
100 };
101 
102 /*
103  * Reverse a graphics character, or return unaltered if no mirror;
104  * should do alphanumerics too, but I'm too lazy. <cshenton@it.hq.nasa.gov>
105  */
106 
107 static char
108 xflip_symbol(char symbol)
109 {
110 	static const char lchars[] = "`'(){}[]\\/<>";
111 	static const char rchars[] = "'`)(}{][/\\><";
112 	int pos;
113 
114 	for (pos = 0; lchars[pos] != '\0'; pos++)
115 		if (lchars[pos] == symbol)
116 			return rchars[pos];
117 
118 	return symbol;
119 }
120 
121 static void
122 clear_daemon(int xpos, int ypos, int dxdir, int xoff, int yoff,
123 	    int xlen, int ylen)
124 {
125 	int y;
126 
127 	if (xlen <= 0)
128 		return;
129 	for (y = yoff; y < ylen; y++)
130 		fillw(((FG_LIGHTGREY|BG_BLACK) << 8) | scr_map[0x20],
131 		      CONSOLE_VECT(xpos + xoff, ypos + y), xlen - xoff);
132 }
133 
134 static void
135 draw_daemon(int xpos, int ypos, int dxdir, int xoff, int yoff,
136 	    int xlen, int ylen)
137 {
138 	int x, y;
139 	int px;
140 	int attr;
141 
142 	for (y = yoff; y < ylen; y++) {
143 		if (dxdir < 0)
144 			px = xoff;
145 		else
146 			px = DAEMON_MAX_WIDTH - xlen;
147 		if (px >= strlen(daemon_pic[y]))
148 			continue;
149 		for (x = xoff; (x < xlen) && (daemon_pic[y][px] != '\0'); x++, px++) {
150 			switch (daemon_attr[y][px]) {
151 			case 'R': attr = (FG_LIGHTRED|BG_BLACK)<<8; break;
152 			case 'Y': attr = (FG_YELLOW|BG_BLACK)<<8; break;
153 			case 'B': attr = (FG_LIGHTBLUE|BG_BLACK)<<8; break;
154 			case 'W': attr = (FG_LIGHTGREY|BG_BLACK)<<8; break;
155 			case 'C': attr = (FG_CYAN|BG_BLACK)<<8; break;
156 			default: attr = (FG_WHITE|BG_BLACK)<<8; break;
157 			}
158 			if (dxdir < 0) {	/* Moving left */
159 				*CONSOLE_VECT(xpos + x, ypos + y) =
160 					scr_map[daemon_pic[y][px]]|attr;
161 			} else {		/* Moving right */
162 				*CONSOLE_VECT(xpos + DAEMON_MAX_WIDTH - px - 1, ypos + y) =
163 					scr_map[xflip_symbol(daemon_pic[y][px])]|attr;
164 			}
165 		}
166 	}
167 }
168 
169 static void
170 clear_string(int xpos, int ypos, int xoff, char *s, int len)
171 {
172 	if (len <= 0)
173 		return;
174 	fillw(((FG_LIGHTGREY|BG_BLACK) << 8) | scr_map[0x20],
175 	      CONSOLE_VECT(xpos + xoff, ypos), len - xoff);
176 }
177 
178 static void
179 draw_string(int xpos, int ypos, int xoff, char *s, int len)
180 {
181 	int x;
182 
183 	for (x = xoff; x < len; x++)
184 		*CONSOLE_VECT(xpos + x, ypos) =
185 			scr_map[s[x]]|(FG_LIGHTGREEN|BG_BLACK)<<8;
186 }
187 
188 static int
189 daemon_saver(video_adapter_t *adp, int blank)
190 {
191 	static int txpos = 10, typos = 10;
192 	static int txdir = -1, tydir = -1;
193 	static int dxpos = 0, dypos = 0;
194 	static int dxdir = 1, dydir = 1;
195 	static int moved_daemon = 0;
196 	static int xoff, yoff, toff;
197 	static int xlen, ylen, tlen;
198 	scr_stat *scp = cur_console;
199 	int min, max;
200 
201 	if (blank) {
202 		if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
203 			return EAGAIN;
204 		if (blanked == 0) {
205 			window = (u_short *)adp->va_window;
206 			/* clear the screen and set the border color */
207 			fillw(((FG_LIGHTGREY|BG_BLACK) << 8) | scr_map[0x20],
208 			      window, scp->xsize * scp->ysize);
209 			set_border(scp, 0);
210 			xlen = ylen = tlen = 0;
211 		}
212 		if (blanked++ < 2)
213 			return 0;
214 		blanked = 1;
215 
216  		clear_daemon(dxpos, dypos, dxdir, xoff, yoff, xlen, ylen);
217 		clear_string(txpos, typos, toff, (char *)message, tlen);
218 
219 		if (++moved_daemon) {
220 			/*
221 			 * The daemon picture may be off the screen, if
222 			 * screen size is chagened while the screen
223 			 * saver is inactive. Make sure the origin of
224 			 * the picture is between min and max.
225 			 */
226 			if (scp->xsize <= DAEMON_MAX_WIDTH) {
227 				/*
228 				 * If the screen width is too narrow, we
229 				 * allow part of the picture go off
230 				 * the screen so that the daemon won't
231 				 * flip too often.
232 				 */
233 				min = scp->xsize - DAEMON_MAX_WIDTH - 10;
234 				max = 10;
235 			} else {
236 				min = 0;
237 				max = scp->xsize - DAEMON_MAX_WIDTH;
238 			}
239 			if (dxpos <= min) {
240 				dxpos = min;
241 				dxdir = 1;
242 			} else if (dxpos >= max) {
243 				dxpos = max;
244 				dxdir = -1;
245 			}
246 
247 			if (scp->ysize <= DAEMON_MAX_HEIGHT) {
248 				min = scp->ysize - DAEMON_MAX_HEIGHT - 10;
249 				max = 10;
250 			} else {
251 				min = 0;
252 				max = scp->ysize - DAEMON_MAX_HEIGHT;
253 			}
254 			if (dypos <= min) {
255 				dypos = min;
256 				dydir = 1;
257 			} else if (dypos >= max) {
258 				dypos = max;
259 				dydir = -1;
260 			}
261 
262 			moved_daemon = -1;
263 			dxpos += dxdir; dypos += dydir;
264 
265 			/* clip the picture */
266 			xoff = 0;
267 			xlen = DAEMON_MAX_WIDTH;
268 			if (dxpos + xlen <= 0)
269 				xlen = 0;
270 			else if (dxpos < 0)
271 				xoff = -dxpos;
272 			if (dxpos >= scp->xsize)
273 				xlen = 0;
274 			else if (dxpos + xlen > scp->xsize)
275 				xlen = scp->xsize - dxpos;
276 			yoff = 0;
277 			ylen = DAEMON_MAX_HEIGHT;
278 			if (dypos + ylen <= 0)
279 				ylen = 0;
280 			else if (dypos < 0)
281 				yoff = -dypos;
282 			if (dypos >= scp->ysize)
283 				ylen = 0;
284 			else if (dypos + ylen > scp->ysize)
285 				ylen = scp->ysize - dypos;
286 		}
287 
288 		if (scp->xsize <= messagelen) {
289 			min = scp->xsize - messagelen - 10;
290 			max = 10;
291 		} else {
292 			min = 0;
293 			max = scp->xsize - messagelen;
294 		}
295 		if (txpos <= min) {
296 			txpos = min;
297 			txdir = 1;
298 		} else if (txpos >= max) {
299 			txpos = max;
300 			txdir = -1;
301 		}
302 		if (typos <= 0) {
303 			typos = 0;
304 			tydir = 1;
305 		} else if (typos >= scp->ysize - 1) {
306 			typos = scp->ysize - 1;
307 			tydir = -1;
308 		}
309 		txpos += txdir; typos += tydir;
310 
311 		toff = 0;
312 		tlen = messagelen;
313 		if (txpos + tlen <= 0)
314 			tlen = 0;
315 		else if (txpos < 0)
316 			toff = -txpos;
317 		if (txpos >= scp->xsize)
318 			tlen = 0;
319 		else if (txpos + tlen > scp->xsize)
320 			tlen = scp->xsize - txpos;
321 
322  		draw_daemon(dxpos, dypos, dxdir, xoff, yoff, xlen, ylen);
323 		draw_string(txpos, typos, toff, (char *)message, tlen);
324 	} else {
325 		blanked = 0;
326 	}
327 	return 0;
328 }
329 
330 static int
331 daemon_init(video_adapter_t *adp)
332 {
333 	messagelen = strlen(hostname) + 3 + strlen(ostype) + 1 +
334 	    strlen(osrelease);
335 	message = malloc(messagelen + 1, M_DEVBUF, M_WAITOK);
336 	sprintf(message, "%s - %s %s", hostname, ostype, osrelease);
337 	blanked = 0;
338 	return 0;
339 }
340 
341 static int
342 daemon_term(video_adapter_t *adp)
343 {
344 	free(message, M_DEVBUF);
345 	return 0;
346 }
347 
348 static scrn_saver_t daemon_module = {
349 	"daemon_saver", daemon_init, daemon_term, daemon_saver, NULL,
350 };
351 
352 SAVER_MODULE(daemon_saver, daemon_module);
353