2 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
24 #include <console/video_console.h>
25 #include <kdp/kdp_udp.h>
26 #include <kern/debug.h>
27 #include <mach/mach_time.h>
28 #include <sys/errno.h>
32 extern struct vc_info vinfo
;
33 extern boolean_t panicDialogDesired
;
35 #include "panic_image.c"
37 void panic_ui_initialize(const unsigned char * system_clut
);
38 int panic_dialog_set_image( const unsigned char * ptr
, unsigned int size
);
39 void panic_dialog_get_image( unsigned char ** ptr
, unsigned int * size
);
40 void draw_panic_dialog( void );
41 void panic_dialog_test( void );
43 static int panic_dialog_verify( const struct panicimage
* data
, unsigned int size
);
44 static int pixels_needed_to_blit_digit( int digit
);
45 static void blit_digit( int digit
);
46 static char * strnstr(const char * s
, const char * find
, size_t slen
);
47 static void dim_screen(void);
48 static void panic_blit_rect(unsigned int x
, unsigned int y
, unsigned int width
, unsigned int height
,
49 int transparent
, unsigned char * dataPtr
);
51 static int panic_info_x
;
52 static int panic_info_y
;
54 static const unsigned char * active_clut
= NULL
; /* This is a copy of the active clut */
56 static boolean_t panicDialogDrawn
= FALSE
;
58 static const struct panicimage
* panic_dialog
= NULL
; /* the active panic dialog */
59 static const unsigned char * panic_dialog_data
= NULL
; /* where the image data starts */
60 static const unsigned char * panic_dialog_clut
= NULL
; /* where the clut used for the image starts */
62 static unsigned char * curr_image_ptr
= NULL
; /* If NULL, the default panic dialog is active */
63 static unsigned int curr_image_size
= 0;
66 #define FONT_HEIGHT 16
67 static unsigned short rendered_font
[FONT_HEIGHT
][FONT_WIDTH
];
69 static char versionbuf
[20]; /* ####.###~###\0 */
71 #define isdigit(d) ((d) >= '0' && (d) <= '9')
73 #define CLUT_ENTRIES 256
74 #define CLUT_SIZE (CLUT_ENTRIES * 3)
78 * This routine sets up the default panic dialog
81 extern unsigned char iso_font
[];
82 extern const char version
[];
83 extern unsigned int panic_caller
;
86 panic_ui_initialize(const unsigned char * system_clut
)
91 panic_dialog_set_image( NULL
, 0 );
93 active_clut
= system_clut
;
95 strcpy(vstr
, "custom");
97 /* Convert xnu-####.###.obj~### into ####.###~### */
100 char * versionpos
= strnstr(version
, "xnu-", 20);
107 for (i
=0,len
=4;len
<20;len
++) {
108 if (isdigit(versionpos
[len
]) || versionpos
[len
] == '.') { /* extract ####.###. */
109 vstr
[i
++] = versionpos
[len
];
115 if ( versionpos
[len
-1] == '.' ) /* remove trailing period if present */
118 for (;len
<20;len
++) { /* skip to next digit if present */
119 if ( !isdigit(versionpos
[len
]) )
124 if ( versionpos
[len
-1] == '~' ) { /* extract ~### if present */
125 vstr
[i
++] = versionpos
[len
-1];
126 for (;len
<20;len
++) { /* extract ### */
127 if ( isdigit(versionpos
[len
]) ) {
128 vstr
[i
++] = versionpos
[len
];
139 strcpy(versionbuf
, vstr
);
145 panic_dialog_test( void )
147 boolean_t o_panicDialogDrawn
= panicDialogDrawn
;
148 boolean_t o_panicDialogDesired
= panicDialogDesired
;
149 unsigned int o_logPanicDataToScreen
= logPanicDataToScreen
;
150 unsigned int o_panic_caller
= panic_caller
;
151 unsigned int o_panicDebugging
= panicDebugging
;
154 panicDebugging
= TRUE
;
155 panic_caller
= (unsigned int) __builtin_return_address(0);
156 logPanicDataToScreen
= FALSE
;
157 panicDialogDesired
= TRUE
;
158 panicDialogDrawn
= FALSE
;
162 panicDebugging
= o_panicDebugging
;
163 panic_caller
= o_panic_caller
;
164 logPanicDataToScreen
= o_logPanicDataToScreen
;
165 panicDialogDesired
= o_panicDialogDesired
;
166 panicDialogDrawn
= o_panicDialogDrawn
;
171 draw_panic_dialog( void )
173 if (!panicDialogDrawn
&& panicDialogDesired
) {
174 if ( !logPanicDataToScreen
) {
176 int count
, nibble
, indx
;
177 struct ether_addr kdp_mac_addr
;
178 unsigned int panic_dialog_count
, ip_addr
;
179 char panic_num_chars
[13+8+1], mac_addr_chars
[17+1], ip_addr_chars
[15+1];
183 } panic_dialog_info
[3];
186 /* dim the screen 50% before putting up panic dialog */
189 /* set up to draw background box */
190 /* by locating where the upper left corner is placed */
192 pd_x
= (vinfo
.v_width
/2) - panic_dialog
->pd_width
/2;
193 pd_y
= (vinfo
.v_height
/2) - panic_dialog
->pd_height
/2;
195 /* draw panic dialog at pd_x/pd_y */
196 panic_blit_rect( pd_x
, pd_y
, panic_dialog
->pd_width
, panic_dialog
->pd_height
,
197 0, (unsigned char*) panic_dialog_data
);
199 panic_dialog_count
= 0; /* number of info items to display at the bottom of dialog */
201 if (panicDebugging
) {
207 * don't display the panic caller if it is 0
211 if ( panic_caller
!= 0 ) {
212 /* Calculate the pixels need to generate the panic number */
213 panic_dialog_info
[panic_dialog_count
].pixels
= 0;
215 for ( indx
=1, count
=0; count
< 13; count
++ ) {
216 if ( versionbuf
[count
] == '\0' )
219 panic_num_chars
[indx
++] = versionbuf
[count
];
220 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( versionbuf
[count
] );
223 panic_num_chars
[indx
++] = ':';
224 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( ':' );
226 for ( count
=8; count
!= 0; count
-- ) {
227 nibble
= (panic_caller
>> ((count
-1)<<2)) &0xF;
228 panic_num_chars
[indx
++] = nibble
;
229 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( nibble
);
232 panic_num_chars
[0] = indx
;
233 panic_dialog_info
[panic_dialog_count
].chars
= panic_num_chars
;
234 panic_dialog_count
++;
240 * if the mac address is not available, then use ff:ff:ff:ff:ff:ff
244 kdp_mac_addr
= kdp_get_mac_addr();
246 /* If no mac_addr has been set, then force to -1 */
247 if( ! (kdp_mac_addr
.ether_addr_octet
[0] || kdp_mac_addr
.ether_addr_octet
[1] || kdp_mac_addr
.ether_addr_octet
[2]
248 || kdp_mac_addr
.ether_addr_octet
[3] || kdp_mac_addr
.ether_addr_octet
[4] || kdp_mac_addr
.ether_addr_octet
[5])) {
249 for (count
= 0; count
< 6; count
++ )
250 kdp_mac_addr
.ether_addr_octet
[count
] = -1;
253 panic_dialog_info
[panic_dialog_count
].pixels
= 0;
255 for (indx
=1, count
=0; count
< 6; count
++ ) {
256 nibble
= (kdp_mac_addr
.ether_addr_octet
[count
] & 0xf0) >> 4;
257 mac_addr_chars
[indx
++] = nibble
;
258 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( nibble
);
260 nibble
= kdp_mac_addr
.ether_addr_octet
[count
] & 0xf;
261 mac_addr_chars
[indx
++] = nibble
;
262 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( nibble
);
265 mac_addr_chars
[indx
++] = ':';
266 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( ':' );
270 mac_addr_chars
[0] = indx
;
271 panic_dialog_info
[panic_dialog_count
].chars
= mac_addr_chars
;
272 panic_dialog_count
++;
277 * do not display the ip addresses if the machine isn't attachable.
278 * there's no sense in possibly confusing people.
281 if ( (ip_addr
= (unsigned int) ntohl(kdp_get_ip_address())) != 0 ) {
284 panic_dialog_info
[panic_dialog_count
].pixels
= 0;
286 for ( indx
=1, count
=0; count
< 4; count
++ ) {
287 nibble
= (ip_addr
& 0xff000000 ) >> 24;
289 d3
= (nibble
% 10) ; nibble
= nibble
/ 10;
290 d2
= (nibble
% 10) ; nibble
= nibble
/ 10;
294 ip_addr_chars
[indx
++] = d1
;
295 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( d1
);
298 ip_addr_chars
[indx
++] = d2
;
299 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( d2
);
301 ip_addr_chars
[indx
++] = d3
;
302 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( d3
);
305 ip_addr_chars
[indx
++] = '.';
306 panic_dialog_info
[panic_dialog_count
].pixels
+= pixels_needed_to_blit_digit( '.' );
310 ip_addr
= ip_addr
<< 8;
313 ip_addr_chars
[0] = indx
;
314 panic_dialog_info
[panic_dialog_count
].chars
= ip_addr_chars
;
315 panic_dialog_count
++;
319 /* vertical alignment for information to be displayed */
320 panic_info_y
= (vinfo
.v_height
/2) + panic_dialog
->pd_height
/2 - (panic_dialog
->pd_info_height
);
322 /* blit out all the information we gathered */
324 switch ( panic_dialog_count
) {
325 case 1 : /* one item is centered */
326 panic_info_x
= (vinfo
.v_width
/2) - (panic_dialog_info
[0].pixels
/2);
327 for (indx
=1; indx
< panic_dialog_info
[0].chars
[0]; indx
++)
328 blit_digit(panic_dialog_info
[0].chars
[indx
]);
332 case 2 : /* left centered and right centered */
333 x1
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[0].pixels
)/2;
334 panic_info_x
= ((vinfo
.v_width
/2) - (panic_dialog
->pd_width
/2)) + x1
;
336 for (indx
=1; indx
< panic_dialog_info
[0].chars
[0]; indx
++)
337 blit_digit(panic_dialog_info
[0].chars
[indx
]);
339 x2
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[1].pixels
)/2;
340 panic_info_x
= (vinfo
.v_width
/2) + x2
;
342 for (indx
=1; indx
< panic_dialog_info
[1].chars
[0]; indx
++)
343 blit_digit(panic_dialog_info
[1].chars
[indx
]);
347 case 3 : /* left centered, middle and right centered */
348 x1
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[0].pixels
- (panic_dialog_info
[1].pixels
/2))/2;
349 panic_info_x
= ((vinfo
.v_width
/2) - (panic_dialog
->pd_width
/2)) + x1
;
351 for (indx
=1; indx
< panic_dialog_info
[0].chars
[0]; indx
++)
352 blit_digit(panic_dialog_info
[0].chars
[indx
]);
354 panic_info_x
= (vinfo
.v_width
/2) - (panic_dialog_info
[1].pixels
/2);
356 for (indx
=1; indx
< panic_dialog_info
[1].chars
[0]; indx
++)
357 blit_digit(panic_dialog_info
[1].chars
[indx
]);
359 x2
= ((panic_dialog
->pd_width
/2) - panic_dialog_info
[2].pixels
- (panic_dialog_info
[1].pixels
/2))/2;
360 panic_info_x
= (vinfo
.v_width
/2) + x2
+ (panic_dialog_info
[1].pixels
/2);
362 for (indx
=1; indx
< panic_dialog_info
[2].chars
[0]; indx
++)
363 blit_digit(panic_dialog_info
[2].chars
[indx
]);
367 default : /* nothing */
371 } /* if panic_deugging */
372 } /* if ! logPanicDataToScreen */
373 } /* if ! panicDialogDrawn && ! panicDialogDesired */
375 panicDialogDrawn
= TRUE
;
376 panicDialogDesired
= FALSE
;
381 * This routine installs a new panic dialog
382 * If ptr is NULL, then the default "built-in" panic dialog will be installed.
383 * note: It is the caller that must take care of deallocating memory used for the previous panic dialog
387 panic_dialog_set_image( const unsigned char * ptr
, unsigned int size
)
390 unsigned int newsize
;
391 const struct panicimage
* newimage
;
393 /* if ptr is NULL, restore panic image to built-in default */
395 newimage
= &panic_dialog_default
;
396 newsize
= sizeof(struct panicimage
) + newimage
->pd_dataSize
;
399 newimage
= (struct panicimage
*) ptr
;
403 if ( (error
= panic_dialog_verify( newimage
, newsize
)) )
406 panic_dialog
= newimage
;
407 panic_dialog_data
= &panic_dialog
->data
[0];
408 panic_dialog_clut
= &panic_dialog
->data
[panic_dialog
->pd_dataSize
-CLUT_SIZE
];
410 curr_image_ptr
= (unsigned char *) ptr
;
411 curr_image_size
= size
;
418 * This routines returns the current address of the panic dialog
419 * If the default panic dialog is active, then *ptr will be NULL
423 panic_dialog_get_image( unsigned char ** ptr
, unsigned int * size
)
425 *ptr
= curr_image_ptr
;
426 *size
= curr_image_size
;
431 * This routine verifies the panic dialog image is valid.
435 panic_dialog_verify( const struct panicimage
* newimage
, unsigned int size
)
439 if ( size
< (sizeof(struct panicimage
) + newimage
->pd_dataSize
) )
442 if ( newimage
->pd_tag
!= 'RNMp' )
445 size
= newimage
->pd_dataSize
-CLUT_SIZE
;
446 for (sum
=0,i
=0; i
<size
; i
++) {
447 sum
+= newimage
->data
[i
];
451 if ( sum
!= newimage
->pd_sum
)
459 * Service Routines for managing the panic dialog
463 static const struct rendered_num
* find_rendered_digit( int digit
);
464 static void panic_blit_rect_8( unsigned int x
, unsigned int y
, unsigned int width
, unsigned int height
,
465 int transparent
, unsigned char * dataPtr
);
466 static void panic_blit_rect_16( unsigned int x
, unsigned int y
, unsigned int width
, unsigned int height
,
467 int transparent
, unsigned char * dataPtr
);
468 static void panic_blit_rect_32( unsigned int x
, unsigned int y
, unsigned int width
, unsigned int height
,
469 int transparent
, unsigned char * dataPtr
);
470 static int decode_rle( unsigned char * dataPtr
, unsigned int * quantity
, unsigned int * depth
, unsigned char ** value
);
473 /* Utilities to convert 8 bit/gray */
474 static unsigned int make24bitcolor( unsigned int index
, const unsigned char * clut
);
475 static unsigned char findIndexMatch( unsigned char index
);
476 static unsigned char color24togray8( unsigned int color24
);
477 static unsigned char findbestgray( unsigned int color24
);
478 static int isActiveClutOK( void );
481 pixels_needed_to_blit_digit( int digit
)
487 static const struct rendered_num
*
488 find_rendered_digit( int digit
)
490 //extern unsigned char iso_font[];
491 const struct rendered_num
*digitPtr
;
500 digitPtr
= (const struct rendered_num
*) &iso_font
[digit
* 16];
506 blit_digit( int digit
)
508 unsigned char * raw_data
= (unsigned char *) find_rendered_digit( digit
);
509 unsigned width
= FONT_WIDTH
, height
= FONT_HEIGHT
;
512 for (row
=0; row
<FONT_HEIGHT
; row
++) {
516 bits
= raw_data
[row
];
517 for( j
=FONT_WIDTH
-1; j
>=0; j
--) {
520 rendered_font
[row
][j
] = 0x0100 | panic_dialog
->pd_info_color
[0];
522 rendered_font
[row
][j
] = 0x0100 | panic_dialog
->pd_info_color
[1];
527 panic_blit_rect( panic_info_x
, panic_info_y
, width
, height
, 255, (unsigned char *) rendered_font
);
528 panic_info_x
+= width
;
533 panic_blit_rect( unsigned int x
, unsigned int y
,
534 unsigned int width
, unsigned int height
,
535 int transparent
, unsigned char * dataPtr
)
540 switch( vinfo
.v_depth
) {
542 panic_blit_rect_8( x
, y
, width
, height
, transparent
, dataPtr
);
545 panic_blit_rect_16( x
, y
, width
, height
, transparent
, dataPtr
);
548 panic_blit_rect_32( x
, y
, width
, height
, transparent
, dataPtr
);
554 * panic_blit_rect_8 decodes the RLE encoded image data on the fly, looks up the
555 * color by indexing into the clut, or attempts to find the best index.
559 panic_blit_rect_8( unsigned int x
, unsigned int y
,
560 unsigned int width
, unsigned int height
,
561 int transparent
, unsigned char * dataPtr
)
563 volatile unsigned char * dst
;
564 unsigned int line
, col
, i
;
565 static int clutOK
= -1;
566 unsigned int data
, quantity
, depth
;
567 unsigned char * value
;
571 clutOK
= isActiveClutOK();
573 dst
= (volatile unsigned char *) (vinfo
.v_baseaddr
+
574 (y
* vinfo
.v_rowbytes
) +
580 for( line
= 0; line
< height
; line
++) {
581 for( col
= 0; col
< width
; col
++) {
584 dataPtr
+= decode_rle(dataPtr
, &quantity
, &depth
, &value
);
591 data
= findIndexMatch( value
[i
++] );
601 dst
= (volatile unsigned char *) (((int)dst
) + vinfo
.v_rowbytes
);
606 * panic_blit_rect_16 decodes the RLE encoded image data on the fly, looks up the
607 * color by indexing into the clut, uses the top 5 bits to fill in each of the three
608 * pixel values (RGB) and writes each pixel to the screen.
612 panic_blit_rect_16( unsigned int x
, unsigned int y
,
613 unsigned int width
, unsigned int height
,
614 int transparent
, unsigned char * dataPtr
)
617 volatile unsigned short * dst
;
618 unsigned int line
, col
, i
;
619 unsigned int quantity
, index
, data
, depth
;
620 unsigned char * value
;
622 dst
= (volatile unsigned short *) (vinfo
.v_baseaddr
+
623 (y
* vinfo
.v_rowbytes
) +
629 for( line
= 0; line
< height
; line
++) {
630 for( col
= 0; col
< width
; col
++) {
633 dataPtr
+= decode_rle(dataPtr
, &quantity
, &depth
, &value
);
637 index
= value
[i
++] * 3;
639 data
= ( (unsigned short) (0xf8 & (panic_dialog_clut
[index
+ 0])) << 7)
640 | ( (unsigned short) (0xf8 & (panic_dialog_clut
[index
+ 1])) << 2)
641 | ( (unsigned short) (0xf8 & (panic_dialog_clut
[index
+ 2])) >> 3);
651 dst
= (volatile unsigned short *) (((int)dst
) + vinfo
.v_rowbytes
);
656 * panic_blit_rect_32 decodes the RLE encoded image data on the fly, and fills
657 * in each of the three pixel values from the clut (RGB) for each pixel and
658 * writes it to the screen.
662 panic_blit_rect_32( unsigned int x
, unsigned int y
,
663 unsigned int width
, unsigned int height
,
664 int transparent
, unsigned char * dataPtr
)
666 volatile unsigned int * dst
;
667 unsigned int line
, col
, i
;
668 unsigned int quantity
, index
, data
, depth
;
669 unsigned char * value
;
672 dst
= (volatile unsigned int *) (vinfo
.v_baseaddr
+
673 (y
* vinfo
.v_rowbytes
) +
679 for( line
= 0; line
< height
; line
++) {
680 for( col
= 0; col
< width
; col
++) {
683 dataPtr
+= decode_rle(dataPtr
, &quantity
, &depth
, &value
);
687 index
= value
[i
++] * 3;
689 data
= ( (unsigned int) panic_dialog_clut
[index
+ 0] << 16)
690 | ( (unsigned int) panic_dialog_clut
[index
+ 1] << 8)
691 | ( (unsigned int) panic_dialog_clut
[index
+ 2]);
701 dst
= (volatile unsigned int *) (((int)dst
) + vinfo
.v_rowbytes
);
706 decode_rle decodes a single quantity/value run of a "modified-RLE" encoded
707 image. The encoding works as follows:
709 The run is described in the first byte. If the MSB is zero, then the next seven bits
710 are the quantity of bytes that follow that make up the run of value bytes. (see case 0)
712 If the MSB is set, bits 0-3 are the quantity's least significant 4 bits. If bit 5 is set,
713 then the quantity is further described in the next byte, where an additional 7 bits (4-10)
714 worth of quantity will be found. If the MSB of this byte is set, then an additional
715 7 bits (11-17) worth of quantity will be found in the next byte. This repeats until the MSB of
716 a quantity byte is zero, thus ending the run of quantity bytes.
718 Bits 5/6 of the first byte, describe the number of bytes in the value run following the quantity run.
719 These bits describe value runs of 1 to 4 bytes. And the quantity describe the number of value runs.
722 encodings are: (q = quantity, v = value, c = quantity continues)
724 case 0: [ 0 q6-q0 ] [ v7-v0 ] ... [ v7-v0 ]
725 case 1: [ 1 0 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ]
726 case 2: [ 1 0 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ]
727 case 3: [ 1 1 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ]
728 case 4: [ 1 1 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ]
732 decode_rle( unsigned char * dataPtr
, unsigned int * quantity
, unsigned int * depth
, unsigned char ** value
)
735 int i
, runlen
, runsize
;
738 mask
= dataPtr
[i
] & 0xF0;
741 runsize
= ((mask
& 0x60) >> 5) + 1;
742 runlen
= dataPtr
[i
++] & 0x0F;
748 mask
= dataPtr
[i
] & 0x80;
749 runlen
|= ((dataPtr
[i
++] & 0x7F) << shift
);
755 runsize
= dataPtr
[i
++];
760 *value
= &dataPtr
[i
];
769 unsigned long *p
, *endp
, *row
;
770 int col
, rowline
, rowlongs
;
771 register unsigned long mask
;
776 if ( vinfo
.v_depth
== 32 )
778 else if ( vinfo
.v_depth
== 16 )
783 rowline
= vinfo
.v_rowscanbytes
/ 4;
784 rowlongs
= vinfo
.v_rowbytes
/ 4;
786 p
= (unsigned long*) vinfo
.v_baseaddr
;
787 endp
= p
+ (rowlongs
* vinfo
.v_height
);
789 for (row
= p
; row
< endp
; row
+= rowlongs
) {
790 for (p
= &row
[0], col
= 0; col
< rowline
; col
++) {
791 *p
++ = (*p
>> 1) & mask
;
797 /* From user mode Libc - this ought to be in a library */
799 strnstr(const char * s
, const char * find
, size_t slen
)
804 if ((c
= *find
++) != '\0') {
808 if ((sc
= *s
++) == '\0' || slen
-- < 1)
813 } while (strncmp(s
, find
, len
) != 0);
820 * these routines are for converting a color into grayscale
821 * in 8-bit mode, if the active clut is different than the
822 * clut used to create the panic dialog, then we must convert to gray
826 make24bitcolor( unsigned int index
, const unsigned char * clut
)
828 unsigned int color24
= 0;
831 color24
|= clut
[i
+0] << 16;
832 color24
|= clut
[i
+1] << 8;
833 color24
|= clut
[i
+2];
840 findbestgray( unsigned int color24
)
842 unsigned int c24
, rel
, bestindex
=-1, bestgray
= -1;
843 unsigned char gray8
, c8
;
845 #define abs(v) ((v) > 0)?(v):-(v)
847 gray8
= color24togray8( color24
); /* convert the original color into grayscale */
849 for (i
=0; i
<CLUT_ENTRIES
; i
++) {
850 c24
= make24bitcolor( i
, active_clut
);
851 if ( (((c24
>>16)&0xff) != ((c24
>>8)&0xff)) || ((c24
>>8)&0xff) != (c24
& 0xff) )
852 continue; /* only match against grays */
854 c8
= c24
& 0xFF; /* isolate the gray */
856 /* find the gray with the smallest difference */
857 rel
= abs( gray8
- c8
);
858 if ( rel
< bestgray
) {
864 /* Did we fail to find any grays ? */
865 if ( bestindex
== -1 ) {
866 /* someday we should look for the best color match */
867 /* but for now just return the gray as the index */
868 /* at least there might be something readble on the display */
879 color24togray8( unsigned int color24
)
885 R
= (color24
& 0xFF0000) >> 16 ;
886 G
= (color24
& 0xFF00) >> 8 ;
887 B
= (color24
& 0xFF);
889 Gray
= (R
*.30) + (G
*.59) + (B
*.11);
890 gray8
= (unsigned char) ( Gray
+ .5);
896 findIndexMatch( unsigned char index
)
898 static unsigned int last_in_index
= -1;
899 static unsigned char last_index
;
902 if ( index
== last_in_index
)
905 last_in_index
= index
;
906 sc
= make24bitcolor( index
, panic_dialog_clut
);
907 last_index
= findbestgray( sc
); /* find the nearest matching gray in the active clut */
913 isActiveClutOK( void )
916 int r
= 1; /* assume OK */
918 for (i
=0; i
<CLUT_ENTRIES
; i
++) {
919 if ( panic_dialog_clut
[i
] == active_clut
[i
] ) continue;