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.11 1998/09/17 19:40:30 sos 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 53 /* Who is the author of this ASCII pic? */ 54 55 static char *daemon_pic[] = { 56 " , ,", 57 " /( )`", 58 " \\ \\___ / |", 59 " /- _ `-/ '", 60 " (/\\/ \\ \\ /\\", 61 " / / | ` \\", 62 " O O ) / |", 63 " `-^--'`< '", 64 " (_.) _ ) /", 65 " `.___/` /", 66 " `-----' /", 67 "<----. __ / __ \\", 68 "<----|====O)))==) \\) /====", 69 "<----' `--' `.__,' \\", 70 " | |", 71 " \\ / /\\", 72 " ______( (_ / \\______/", 73 " ,' ,-----' |", 74 " `--{__________)", 75 NULL 76 }; 77 78 static char *daemon_attr[] = { 79 " R R", 80 " RR RR", 81 " R RRRR R R", 82 " RR W RRR R", 83 " RWWW W R RR", 84 " W W W R R", 85 " B B W R R", 86 " WWWWWWRR R", 87 " RRRR R R R", 88 " RRRRRRR R", 89 " RRRRRRR R", 90 "YYYYYY RR R RR R", 91 "YYYYYYYYYYRRRRYYR RR RYYYY", 92 "YYYYYY RRRR RRRRRR R", 93 " R R", 94 " R R RR", 95 " CCCCCCR RR R RRRRRRRR", 96 " CC CCCCCCC C", 97 " CCCCCCCCCCCCCCC", 98 NULL 99 }; 100 101 /* 102 * Reverse a graphics character, or return unaltered if no mirror; 103 * should do alphanumerics too, but I'm too lazy. <cshenton@it.hq.nasa.gov> 104 */ 105 106 static char 107 xflip_symbol(char symbol) 108 { 109 static const char lchars[] = "`'(){}[]\\/<>"; 110 static const char rchars[] = "'`)(}{][/\\><"; 111 int pos; 112 113 for (pos = 0; lchars[pos] != '\0'; pos++) 114 if (lchars[pos] == symbol) 115 return rchars[pos]; 116 117 return symbol; 118 } 119 120 static void 121 clear_daemon(int xpos, int ypos, int dxdir, int xoff, int yoff, 122 int xlen, int ylen) 123 { 124 int y; 125 126 if (xlen <= 0) 127 return; 128 for (y = yoff; y < ylen; y++) 129 fillw(((FG_LIGHTGREY|BG_BLACK) << 8) | scr_map[0x20], 130 CONSOLE_VECT(xpos + xoff, ypos + y), xlen - xoff); 131 } 132 133 static void 134 draw_daemon(int xpos, int ypos, int dxdir, int xoff, int yoff, 135 int xlen, int ylen) 136 { 137 int x, y; 138 int px; 139 int attr; 140 141 for (y = yoff; y < ylen; y++) { 142 if (dxdir < 0) 143 px = xoff; 144 else 145 px = DAEMON_MAX_WIDTH - xlen; 146 if (px >= strlen(daemon_pic[y])) 147 continue; 148 for (x = xoff; (x < xlen) && (daemon_pic[y][px] != '\0'); x++, px++) { 149 switch (daemon_attr[y][px]) { 150 case 'R': attr = (FG_LIGHTRED|BG_BLACK)<<8; break; 151 case 'Y': attr = (FG_YELLOW|BG_BLACK)<<8; break; 152 case 'B': attr = (FG_LIGHTBLUE|BG_BLACK)<<8; break; 153 case 'W': attr = (FG_LIGHTGREY|BG_BLACK)<<8; break; 154 case 'C': attr = (FG_CYAN|BG_BLACK)<<8; break; 155 default: attr = (FG_WHITE|BG_BLACK)<<8; break; 156 } 157 if (dxdir < 0) { /* Moving left */ 158 *CONSOLE_VECT(xpos + x, ypos + y) = 159 scr_map[daemon_pic[y][px]]|attr; 160 } else { /* Moving right */ 161 *CONSOLE_VECT(xpos + DAEMON_MAX_WIDTH - px - 1, ypos + y) = 162 scr_map[xflip_symbol(daemon_pic[y][px])]|attr; 163 } 164 } 165 } 166 } 167 168 static void 169 clear_string(int xpos, int ypos, int xoff, char *s, int len) 170 { 171 if (len <= 0) 172 return; 173 fillw(((FG_LIGHTGREY|BG_BLACK) << 8) | scr_map[0x20], 174 CONSOLE_VECT(xpos + xoff, ypos), len - xoff); 175 } 176 177 static void 178 draw_string(int xpos, int ypos, int xoff, char *s, int len) 179 { 180 int x; 181 182 for (x = xoff; x < len; x++) 183 *CONSOLE_VECT(xpos + x, ypos) = 184 scr_map[s[x]]|(FG_LIGHTGREEN|BG_BLACK)<<8; 185 } 186 187 static void 188 daemon_saver(int blank) 189 { 190 static int txpos = 10, typos = 10; 191 static int txdir = -1, tydir = -1; 192 static int dxpos = 0, dypos = 0; 193 static int dxdir = 1, dydir = 1; 194 static int moved_daemon = 0; 195 static int xoff, yoff, toff; 196 static int xlen, ylen, tlen; 197 scr_stat *scp = cur_console; 198 int min, max; 199 200 if (blank) { 201 if (!ISTEXTSC(scp)) 202 return; 203 if (scrn_blanked == 0) { 204 scp->status |= SAVER_RUNNING; 205 window = (u_short *)(*biosvidsw.adapter)(scp->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 (scrn_blanked++ < 2) 213 return; 214 scrn_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 if (scrn_blanked > 0) { 326 set_border(scp, scp->border); 327 scrn_blanked = 0; 328 scp->status &= ~SAVER_RUNNING; 329 } 330 } 331 } 332 333 static int 334 daemon_saver_load(void) 335 { 336 int err; 337 338 messagelen = strlen(hostname) + 3 + strlen(ostype) + 1 + 339 strlen(osrelease); 340 message = malloc(messagelen + 1, M_DEVBUF, M_WAITOK); 341 sprintf(message, "%s - %s %s", hostname, ostype, osrelease); 342 343 err = add_scrn_saver(daemon_saver); 344 if (err != 0) 345 free(message, M_DEVBUF); 346 return err; 347 } 348 349 static int 350 daemon_saver_unload(void) 351 { 352 int err; 353 354 err = remove_scrn_saver(daemon_saver); 355 if (err == 0) 356 free(message, M_DEVBUF); 357 return err; 358 } 359 360 SAVER_MODULE(daemon_saver); 361