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.8 1998/01/16 17:58:43 bde Exp $ 29 */ 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/exec.h> 34 #include <sys/sysent.h> 35 #include <sys/lkm.h> 36 #include <sys/malloc.h> 37 #include <sys/kernel.h> 38 #include <sys/sysctl.h> 39 40 #include <machine/md_var.h> 41 #include <machine/pc/display.h> 42 43 #include <saver.h> 44 45 #define CONSOLE_VECT(x, y) \ 46 ((u_short*)(Crtat + (y)*cur_console->xsize + (x))) 47 48 #define DAEMON_MAX_WIDTH 32 49 #define DAEMON_MAX_HEIGHT 19 50 51 MOD_MISC(daemon_saver); 52 53 static char *message; 54 static int messagelen; 55 56 /* Who is the author of this ASCII pic? */ 57 58 static char *daemon_pic[] = { 59 " , ,", 60 " /( )`", 61 " \\ \\___ / |", 62 " /- _ `-/ '", 63 " (/\\/ \\ \\ /\\", 64 " / / | ` \\", 65 " O O ) / |", 66 " `-^--'`< '", 67 " (_.) _ ) /", 68 " `.___/` /", 69 " `-----' /", 70 "<----. __ / __ \\", 71 "<----|====O)))==) \\) /====", 72 "<----' `--' `.__,' \\", 73 " | |", 74 " \\ / /\\", 75 " ______( (_ / \\______/", 76 " ,' ,-----' |", 77 " `--{__________)", 78 NULL 79 }; 80 81 static char *daemon_attr[] = { 82 " R R", 83 " RR RR", 84 " R RRRR R R", 85 " RR W RRR R", 86 " RWWW W R RR", 87 " W W W R R", 88 " B B W R R", 89 " WWWWWWRR R", 90 " RRRR R R R", 91 " RRRRRRR R", 92 " RRRRRRR R", 93 "YYYYYY RR R RR R", 94 "YYYYYYYYYYRRRRYYR RR RYYYY", 95 "YYYYYY RRRR RRRRRR R", 96 " R R", 97 " R R RR", 98 " CCCCCCR RR R RRRRRRRR", 99 " CC CCCCCCC C", 100 " CCCCCCCCCCCCCCC", 101 NULL 102 }; 103 104 /* 105 * Reverse a graphics character, or return unaltered if no mirror; 106 * should do alphanumerics too, but I'm too lazy. <cshenton@it.hq.nasa.gov> 107 */ 108 109 static char 110 xflip_symbol(char symbol) 111 { 112 static const char lchars[] = "`'(){}[]\\/<>"; 113 static const char rchars[] = "'`)(}{][/\\><"; 114 int pos; 115 116 for (pos = 0; lchars[pos] != '\0'; pos++) 117 if (lchars[pos] == symbol) 118 return rchars[pos]; 119 120 return symbol; 121 } 122 123 static void 124 clear_daemon(int xpos, int ypos, int dxdir, int xoff, int yoff, 125 int xlen, int ylen) 126 { 127 int y; 128 129 if (xlen <= 0) 130 return; 131 for (y = yoff; y < ylen; y++) 132 fillw(((FG_LIGHTGREY|BG_BLACK) << 8) | scr_map[0x20], 133 CONSOLE_VECT(xpos + xoff, ypos + y), xlen - xoff); 134 } 135 136 static void 137 draw_daemon(int xpos, int ypos, int dxdir, int xoff, int yoff, 138 int xlen, int ylen) 139 { 140 int x, y; 141 int px; 142 int attr; 143 144 for (y = yoff; y < ylen; y++) { 145 if (dxdir < 0) 146 px = xoff; 147 else 148 px = DAEMON_MAX_WIDTH - xlen; 149 if (px >= strlen(daemon_pic[y])) 150 continue; 151 for (x = xoff; (x < xlen) && (daemon_pic[y][px] != '\0'); x++, px++) { 152 switch (daemon_attr[y][px]) { 153 case 'R': attr = (FG_LIGHTRED|BG_BLACK)<<8; break; 154 case 'Y': attr = (FG_YELLOW|BG_BLACK)<<8; break; 155 case 'B': attr = (FG_LIGHTBLUE|BG_BLACK)<<8; break; 156 case 'W': attr = (FG_LIGHTGREY|BG_BLACK)<<8; break; 157 case 'C': attr = (FG_CYAN|BG_BLACK)<<8; break; 158 default: attr = (FG_WHITE|BG_BLACK)<<8; break; 159 } 160 if (dxdir < 0) { /* Moving left */ 161 *CONSOLE_VECT(xpos + x, ypos + y) = 162 scr_map[daemon_pic[y][px]]|attr; 163 } else { /* Moving right */ 164 *CONSOLE_VECT(xpos + DAEMON_MAX_WIDTH - px - 1, ypos + y) = 165 scr_map[xflip_symbol(daemon_pic[y][px])]|attr; 166 } 167 } 168 } 169 } 170 171 static void 172 clear_string(int xpos, int ypos, int xoff, char *s, int len) 173 { 174 if (len <= 0) 175 return; 176 fillw(((FG_LIGHTGREY|BG_BLACK) << 8) | scr_map[0x20], 177 CONSOLE_VECT(xpos + xoff, ypos), len - xoff); 178 } 179 180 static void 181 draw_string(int xpos, int ypos, int xoff, char *s, int len) 182 { 183 int x; 184 185 for (x = xoff; x < len; x++) 186 *CONSOLE_VECT(xpos + x, ypos) = 187 scr_map[s[x]]|(FG_LIGHTGREEN|BG_BLACK)<<8; 188 } 189 190 static void 191 daemon_saver(int blank) 192 { 193 static int txpos = 10, typos = 10; 194 static int txdir = -1, tydir = -1; 195 static int dxpos = 0, dypos = 0; 196 static int dxdir = 1, dydir = 1; 197 static int moved_daemon = 0; 198 static int xoff, yoff, toff; 199 static int xlen, ylen, tlen; 200 scr_stat *scp = cur_console; 201 int min, max; 202 203 if (blank) { 204 if (scrn_blanked == 0) { 205 /* clear the screen and set the border color */ 206 fillw(((FG_LIGHTGREY|BG_BLACK) << 8) | scr_map[0x20], 207 Crtat, scp->xsize * scp->ysize); 208 set_border(0); 209 xlen = ylen = tlen = 0; 210 } 211 if (scrn_blanked++ < 2) 212 return; 213 scrn_blanked = 1; 214 215 clear_daemon(dxpos, dypos, dxdir, xoff, yoff, xlen, ylen); 216 clear_string(txpos, typos, toff, (char *)message, tlen); 217 218 if (++moved_daemon) { 219 /* 220 * The daemon picture may be off the screen, if 221 * screen size is chagened while the screen 222 * saver is inactive. Make sure the origin of 223 * the picture is between min and max. 224 */ 225 if (scp->xsize <= DAEMON_MAX_WIDTH) { 226 /* 227 * If the screen width is too narrow, we 228 * allow part of the picture go off 229 * the screen so that the daemon won't 230 * flip too often. 231 */ 232 min = scp->xsize - DAEMON_MAX_WIDTH - 10; 233 max = 10; 234 } else { 235 min = 0; 236 max = scp->xsize - DAEMON_MAX_WIDTH; 237 } 238 if (dxpos <= min) { 239 dxpos = min; 240 dxdir = 1; 241 } else if (dxpos >= max) { 242 dxpos = max; 243 dxdir = -1; 244 } 245 246 if (scp->ysize <= DAEMON_MAX_HEIGHT) { 247 min = scp->ysize - DAEMON_MAX_HEIGHT - 10; 248 max = 10; 249 } else { 250 min = 0; 251 max = scp->ysize - DAEMON_MAX_HEIGHT; 252 } 253 if (dypos <= min) { 254 dypos = min; 255 dydir = 1; 256 } else if (dypos >= max) { 257 dypos = max; 258 dydir = -1; 259 } 260 261 moved_daemon = -1; 262 dxpos += dxdir; dypos += dydir; 263 264 /* clip the picture */ 265 xoff = 0; 266 xlen = DAEMON_MAX_WIDTH; 267 if (dxpos + xlen <= 0) 268 xlen = 0; 269 else if (dxpos < 0) 270 xoff = -dxpos; 271 if (dxpos >= scp->xsize) 272 xlen = 0; 273 else if (dxpos + xlen > scp->xsize) 274 xlen = scp->xsize - dxpos; 275 yoff = 0; 276 ylen = DAEMON_MAX_HEIGHT; 277 if (dypos + ylen <= 0) 278 ylen = 0; 279 else if (dypos < 0) 280 yoff = -dypos; 281 if (dypos >= scp->ysize) 282 ylen = 0; 283 else if (dypos + ylen > scp->ysize) 284 ylen = scp->ysize - dypos; 285 } 286 287 if (scp->xsize <= messagelen) { 288 min = scp->xsize - messagelen - 10; 289 max = 10; 290 } else { 291 min = 0; 292 max = scp->xsize - messagelen; 293 } 294 if (txpos <= min) { 295 txpos = min; 296 txdir = 1; 297 } else if (txpos >= max) { 298 txpos = max; 299 txdir = -1; 300 } 301 if (typos <= 0) { 302 typos = 0; 303 tydir = 1; 304 } else if (typos >= scp->ysize - 1) { 305 typos = scp->ysize - 1; 306 tydir = -1; 307 } 308 txpos += txdir; typos += tydir; 309 310 toff = 0; 311 tlen = messagelen; 312 if (txpos + tlen <= 0) 313 tlen = 0; 314 else if (txpos < 0) 315 toff = -txpos; 316 if (txpos >= scp->xsize) 317 tlen = 0; 318 else if (txpos + tlen > scp->xsize) 319 tlen = scp->xsize - txpos; 320 321 draw_daemon(dxpos, dypos, dxdir, xoff, yoff, xlen, ylen); 322 draw_string(txpos, typos, toff, (char *)message, tlen); 323 } else { 324 if (scrn_blanked > 0) { 325 set_border(scp->border); 326 scrn_blanked = 0; 327 } 328 } 329 } 330 331 static int 332 daemon_saver_load(struct lkm_table *lkmtp, int cmd) 333 { 334 int err; 335 336 if (cur_console->mode >= M_VESA_BASE) 337 return ENODEV; 338 339 messagelen = strlen(hostname) + 3 + strlen(ostype) + 1 + 340 strlen(osrelease); 341 message = malloc(messagelen + 1, M_DEVBUF, M_WAITOK); 342 sprintf(message, "%s - %s %s", hostname, ostype, osrelease); 343 344 err = add_scrn_saver(daemon_saver); 345 if (err != 0) 346 free(message, M_DEVBUF); 347 return err; 348 } 349 350 static int 351 daemon_saver_unload(struct lkm_table *lkmtp, int cmd) 352 { 353 int err; 354 355 err = remove_scrn_saver(daemon_saver); 356 if (err == 0) 357 free(message, M_DEVBUF); 358 return err; 359 } 360 361 int 362 daemon_saver_mod(struct lkm_table *lkmtp, int cmd, int ver) 363 { 364 MOD_DISPATCH(daemon_saver, lkmtp, cmd, ver, 365 daemon_saver_load, daemon_saver_unload, lkm_nullcmd); 366 } 367