Browse Source

Plan 9 from Bell Labs 2004-03-23

David du Colombier 20 years ago
parent
commit
5668ef3d18

+ 10 - 7
dist/replica/plan9.db

@@ -2974,7 +2974,7 @@ power/mkfile - 664 sys sys 948141304 46
 rc - 20000000775 sys sys 944959447 0
 rc - 20000000775 sys sys 944959447 0
 rc/bin - 20000000775 sys sys 1018637942 0
 rc/bin - 20000000775 sys sys 1018637942 0
 rc/bin/9fat: - 775 sys sys 1015089559 354
 rc/bin/9fat: - 775 sys sys 1015089559 354
-rc/bin/9fs - 775 sys sys 1042305252 869
+rc/bin/9fs - 775 sys sys 1079969823 948
 rc/bin/B - 775 sys sys 945617206 645
 rc/bin/B - 775 sys sys 945617206 645
 rc/bin/C - 775 sys sys 1045493437 788
 rc/bin/C - 775 sys sys 1045493437 788
 rc/bin/Kill - 775 sys sys 1018637942 115
 rc/bin/Kill - 775 sys sys 1018637942 115
@@ -3030,7 +3030,7 @@ rc/bin/mousereset - 775 sys sys 1015089542 37
 rc/bin/nroff - 775 sys sys 945617208 27
 rc/bin/nroff - 775 sys sys 945617208 27
 rc/bin/patch - 20000000775 sys sys 1067803227 0
 rc/bin/patch - 20000000775 sys sys 1067803227 0
 rc/bin/patch/apply - 775 sys sys 1067804403 1234
 rc/bin/patch/apply - 775 sys sys 1067804403 1234
-rc/bin/patch/create - 775 sys sys 1067804404 1129
+rc/bin/patch/create - 775 sys sys 1079969485 1126
 rc/bin/patch/diff - 775 sys sys 1067804404 466
 rc/bin/patch/diff - 775 sys sys 1067804404 466
 rc/bin/patch/list - 775 sys sys 1067804541 321
 rc/bin/patch/list - 775 sys sys 1067804541 321
 rc/bin/patch/note - 664 sys sys 1067804405 593
 rc/bin/patch/note - 664 sys sys 1067804405 593
@@ -4650,7 +4650,7 @@ sys/man/1/diff - 664 sys sys 969499884 2793
 sys/man/1/doc2txt - 664 sys sys 954089516 1095
 sys/man/1/doc2txt - 664 sys sys 954089516 1095
 sys/man/1/doctype - 664 sys sys 944959673 849
 sys/man/1/doctype - 664 sys sys 944959673 849
 sys/man/1/du - 664 sys sys 1017166323 1410
 sys/man/1/du - 664 sys sys 1017166323 1410
-sys/man/1/echo - 664 sys sys 944959673 279
+sys/man/1/echo - 664 sys sys 1079969656 430
 sys/man/1/ed - 664 sys sys 961259286 13916
 sys/man/1/ed - 664 sys sys 961259286 13916
 sys/man/1/emacs - 664 sys sys 944959673 199
 sys/man/1/emacs - 664 sys sys 944959673 199
 sys/man/1/eqn - 664 sys sys 944959675 5655
 sys/man/1/eqn - 664 sys sys 944959675 5655
@@ -4675,7 +4675,7 @@ sys/man/1/hoc - 664 sys sys 944959676 2357
 sys/man/1/idiff - 664 sys sys 1018386774 927
 sys/man/1/idiff - 664 sys sys 1018386774 927
 sys/man/1/join - 664 sys sys 957920006 2562
 sys/man/1/join - 664 sys sys 957920006 2562
 sys/man/1/jpg - 664 sys sys 1074280543 4758
 sys/man/1/jpg - 664 sys sys 1074280543 4758
-sys/man/1/kbmap - 664 sys sys 1079545417 841
+sys/man/1/kbmap - 664 sys sys 1079969760 845
 sys/man/1/kill - 664 sys sys 1018369246 1193
 sys/man/1/kill - 664 sys sys 1018369246 1193
 sys/man/1/ktrace - 664 sys sys 957920006 1330
 sys/man/1/ktrace - 664 sys sys 957920006 1330
 sys/man/1/leak - 664 sys sys 1017423522 2871
 sys/man/1/leak - 664 sys sys 1017423522 2871
@@ -4686,7 +4686,7 @@ sys/man/1/lp - 664 sys sys 1015024739 3304
 sys/man/1/ls - 664 sys sys 1079372922 2897
 sys/man/1/ls - 664 sys sys 1079372922 2897
 sys/man/1/mail - 664 sys sys 1050078464 2158
 sys/man/1/mail - 664 sys sys 1050078464 2158
 sys/man/1/man - 664 sys sys 1059484724 1740
 sys/man/1/man - 664 sys sys 1059484724 1740
-sys/man/1/marshal - 664 sys sys 1050078464 3307
+sys/man/1/marshal - 664 sys sys 1079970326 3150
 sys/man/1/mc - 664 sys sys 1045501392 508
 sys/man/1/mc - 664 sys sys 1045501392 508
 sys/man/1/mk - 664 sys sys 964455061 13154
 sys/man/1/mk - 664 sys sys 964455061 13154
 sys/man/1/mkdir - 664 sys sys 944959673 443
 sys/man/1/mkdir - 664 sys sys 944959673 443
@@ -9560,17 +9560,20 @@ sys/src/cmd/ip/traceroute.c - 664 sys sys 1032060124 9370
 sys/src/cmd/ip/udpecho.c - 664 sys sys 1050714674 855
 sys/src/cmd/ip/udpecho.c - 664 sys sys 1050714674 855
 sys/src/cmd/join.c - 664 sys sys 944961364 7488
 sys/src/cmd/join.c - 664 sys sys 944961364 7488
 sys/src/cmd/jpg - 20000000775 sys sys 988249983 0
 sys/src/cmd/jpg - 20000000775 sys sys 988249983 0
+sys/src/cmd/jpg/bmp.c - 664 sys sys 1079970078 4217
+sys/src/cmd/jpg/bmp.h - 664 sys sys 1079970081 975
 sys/src/cmd/jpg/close.c - 664 sys sys 944961292 1930
 sys/src/cmd/jpg/close.c - 664 sys sys 944961292 1930
 sys/src/cmd/jpg/gif.c - 664 sys sys 1045505400 8844
 sys/src/cmd/jpg/gif.c - 664 sys sys 1045505400 8844
 sys/src/cmd/jpg/ico.c - 664 sys sys 1072107030 8799
 sys/src/cmd/jpg/ico.c - 664 sys sys 1072107030 8799
 sys/src/cmd/jpg/imagefile.h - 664 sys sys 988225303 2246
 sys/src/cmd/jpg/imagefile.h - 664 sys sys 988225303 2246
 sys/src/cmd/jpg/jpegdump.c - 664 sys sys 1018802871 7161
 sys/src/cmd/jpg/jpegdump.c - 664 sys sys 1018802871 7161
 sys/src/cmd/jpg/jpg.c - 664 sys sys 1014926432 7389
 sys/src/cmd/jpg/jpg.c - 664 sys sys 1014926432 7389
-sys/src/cmd/jpg/mkfile - 664 sys sys 1072107030 1014
+sys/src/cmd/jpg/mkfile - 664 sys sys 1079970080 1056
 sys/src/cmd/jpg/multichan.c - 664 sys sys 1039753047 825
 sys/src/cmd/jpg/multichan.c - 664 sys sys 1039753047 825
 sys/src/cmd/jpg/onechan.c - 664 sys sys 1039753044 3732
 sys/src/cmd/jpg/onechan.c - 664 sys sys 1039753044 3732
 sys/src/cmd/jpg/png.c - 664 sys sys 1014926432 4655
 sys/src/cmd/jpg/png.c - 664 sys sys 1014926432 4655
 sys/src/cmd/jpg/ppm.c - 664 sys sys 944961292 4190
 sys/src/cmd/jpg/ppm.c - 664 sys sys 944961292 4190
+sys/src/cmd/jpg/readbmp.c - 664 sys sys 1079970079 13697
 sys/src/cmd/jpg/readgif.c - 664 sys sys 1014926433 10306
 sys/src/cmd/jpg/readgif.c - 664 sys sys 1014926433 10306
 sys/src/cmd/jpg/readjpg.c - 664 sys sys 1032060302 33009
 sys/src/cmd/jpg/readjpg.c - 664 sys sys 1032060302 33009
 sys/src/cmd/jpg/readpng.c - 664 sys sys 1068773222 6914
 sys/src/cmd/jpg/readpng.c - 664 sys sys 1068773222 6914
@@ -11171,7 +11174,7 @@ sys/src/cmd/wikifs/io.c - 664 sys sys 1018387004 11469
 sys/src/cmd/wikifs/lookup.c - 664 sys sys 1018211093 182
 sys/src/cmd/wikifs/lookup.c - 664 sys sys 1018211093 182
 sys/src/cmd/wikifs/map.c - 664 sys sys 1018211093 109
 sys/src/cmd/wikifs/map.c - 664 sys sys 1018211093 109
 sys/src/cmd/wikifs/mkfile - 664 sys sys 1045503591 468
 sys/src/cmd/wikifs/mkfile - 664 sys sys 1045503591 468
-sys/src/cmd/wikifs/parse.c - 664 sys sys 1018211093 4929
+sys/src/cmd/wikifs/parse.c - 664 sys sys 1079969446 4989
 sys/src/cmd/wikifs/parsehist.c - 664 sys sys 1018211093 1906
 sys/src/cmd/wikifs/parsehist.c - 664 sys sys 1018211093 1906
 sys/src/cmd/wikifs/testwrite.c - 664 sys sys 1018211093 818
 sys/src/cmd/wikifs/testwrite.c - 664 sys sys 1018211093 818
 sys/src/cmd/wikifs/tohtml.c - 664 sys sys 1079380577 13998
 sys/src/cmd/wikifs/tohtml.c - 664 sys sys 1079380577 13998

+ 10 - 0
dist/replica/plan9.log

@@ -14714,3 +14714,13 @@
 1079811022 0 c sys/src/cmd/vnc/kbds.c - 664 sys sys 1079809881 3256
 1079811022 0 c sys/src/cmd/vnc/kbds.c - 664 sys sys 1079809881 3256
 1079877634 0 c sys/src/cmd/ramfs.c - 664 sys sys 1079877660 15377
 1079877634 0 c sys/src/cmd/ramfs.c - 664 sys sys 1079877660 15377
 1079919045 0 c sys/src/cmd/ndb/dn.c - 664 sys sys 1079918815 26961
 1079919045 0 c sys/src/cmd/ndb/dn.c - 664 sys sys 1079918815 26961
+1079969469 0 c rc/bin/patch/create - 775 sys sys 1079969485 1126
+1079969469 1 c sys/src/cmd/wikifs/parse.c - 664 sys sys 1079969446 4989
+1079971270 0 c rc/bin/9fs - 775 sys sys 1079969823 948
+1079971270 1 c sys/man/1/echo - 664 sys sys 1079969656 430
+1079971270 2 c sys/man/1/kbmap - 664 sys sys 1079969760 845
+1079971270 3 c sys/man/1/marshal - 664 sys sys 1079970326 3150
+1079971270 4 a sys/src/cmd/jpg/bmp.c - 664 sys sys 1079970078 4217
+1079971270 5 a sys/src/cmd/jpg/bmp.h - 664 sys sys 1079970081 975
+1079971270 6 c sys/src/cmd/jpg/mkfile - 664 sys sys 1079970080 1056
+1079971270 7 a sys/src/cmd/jpg/readbmp.c - 664 sys sys 1079970079 13697

+ 3 - 0
rc/bin/9fs

@@ -27,6 +27,9 @@ case sourcesdump
 case sourcessnap
 case sourcessnap
 	9fs sources
 	9fs sources
 	mount /srv/sources /n/sourcessnap main/snapshot
 	mount /srv/sources /n/sourcessnap main/snapshot
+case wiki
+	srv 'net!plan9.bell-labs.com!wiki' wiki	
+	mount /srv/wiki /mnt/wiki
 case *
 case *
 	switch($#*){
 	switch($#*){
 	case 1
 	case 1

+ 1 - 1
rc/bin/patch/create

@@ -17,7 +17,7 @@ if(! test -d /n/sources/patch){
 
 
 d=/n/sources/patch/$1
 d=/n/sources/patch/$1
 if(! mkdir $d){
 if(! mkdir $d){
-	echo mkdir $d/$1 failed >[1=2]
+	echo mkdir $d failed >[1=2]
 	exit mkdir
 	exit mkdir
 }
 }
 
 

+ 6 - 0
sys/man/1/echo

@@ -18,3 +18,9 @@ Option
 suppresses the newline.
 suppresses the newline.
 .SH SOURCE
 .SH SOURCE
 .B /sys/src/cmd/echo.c
 .B /sys/src/cmd/echo.c
+.SH DIAGNOSTICS
+If
+.I echo
+draws an error while writing to standard output, the exit status is
+.LR "write error" .
+Otherwise the exit status is empty.

+ 4 - 4
sys/man/1/kbmap

@@ -8,15 +8,15 @@ kbmap \- show a list of available keyboard maps and switch between them.
 ]
 ]
 .SH DESCRIPTION
 .SH DESCRIPTION
 .I Kbmap
 .I Kbmap
-shows a single column consisting of the names keyboard maps for different
+shows a single column consisting of the names of keyboard maps for different
 alphabets available on the system. With no arguments 
 alphabets available on the system. With no arguments 
 .B kbmap
 .B kbmap
 will look for files in 
 will look for files in 
-.B /lib/kbmap/.
+.BR /sys/lib/kbmap .
 .PP
 .PP
-Clicking the right mouse button will highlight the name and force the
+Clicking the right mouse button will highlight the entry and force the
 keyboard mapping defined in the corresponding file to become current
 keyboard mapping defined in the corresponding file to become current
-one for the system.  Typing 'q' quits.
+for the system; typing 'q' quits.
 .PP
 .PP
 .I Kbmap
 .I Kbmap
 requires that the file
 requires that the file

+ 0 - 9
sys/man/1/marshal

@@ -136,15 +136,6 @@ are all passed as command line options to the
 that
 that
 .I marshal
 .I marshal
 invokes.
 invokes.
-.TP
-.BI -C recipient
-specifies that a copy of the mail should also be sent to
-.I recipient
-and that
-.I recipient
-should be included in a
-.B CC:
-header line.
 .PD
 .PD
 .PP
 .PP
 .I Marshal
 .I Marshal

+ 210 - 0
sys/src/cmd/jpg/bmp.c

@@ -0,0 +1,210 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <draw.h>
+#include <event.h>
+#include "imagefile.h"
+
+int		cflag = 0;
+int		dflag = 0;
+int		eflag = 0;
+int		nineflag = 0;
+int		threeflag = 0;
+int		output = 0;
+ulong		outchan = CMAP8;
+int		defaultcolor = 1;
+Image		*image;
+
+enum{
+	Border	= 2,
+	Edge	= 5
+};
+
+char	*show(int, char*);
+
+Rawimage** readbmp(int fd, int colorspace);
+
+void
+eresized(int new)
+{
+	Rectangle r;
+
+	if(new && getwindow(display, Refnone) < 0){
+		fprint(2, "bmp: can't reattach to window\n");
+		exits("resize");
+	}
+	if(image == nil)
+		return;
+	r = insetrect(screen->clipr, Edge+Border);
+	r.max.x = r.min.x+Dx(image->r);
+	r.max.y = r.min.y+Dy(image->r);
+	border(screen, r, -Border, nil, ZP);
+	draw(screen, r, image, nil, image->r.min);
+	flushimage(display, 1);
+}
+
+void
+main(int argc, char *argv[])
+{
+	int fd, i;
+	char *err;
+
+	ARGBEGIN{
+	case '3':		/* produce encoded, compressed, three-color bitmap file; no display by default */
+		threeflag++;
+		/* fall through */
+	case 't':		/* produce encoded, compressed, true-color bitmap file; no display by default */
+		cflag++;
+		dflag++;
+		output++;
+		defaultcolor = 0;
+		outchan = RGB24;
+		break;
+	case 'c':		/* produce encoded, compressed, bitmap file; no display by default */
+		cflag++;
+		dflag++;
+		output++;
+		if(defaultcolor)
+			outchan = CMAP8;
+		break;
+	case 'd':		/* suppress display of image */
+		dflag++;
+		break;
+	case 'e':		/* disable floyd-steinberg error diffusion */
+		eflag++;
+		break;
+	case 'k':		/* force black and white */
+		defaultcolor = 0;
+		outchan = GREY8;
+		break;
+	case 'v':		/* force RGBV */
+		defaultcolor = 0;
+		outchan = CMAP8;
+		break;
+	case '9':		/* produce plan 9, uncompressed, bitmap file; no display by default */
+		nineflag++;
+		dflag++;
+		output++;
+		if(defaultcolor)
+			outchan = CMAP8;
+		break;
+	default:
+		fprint(2, "usage: bmp -39cdektv  [file.bmp ...]\n");
+		exits("usage");
+	}ARGEND;
+
+	err = nil;
+	if(argc == 0)
+		err = show(0, "<stdin>");
+	else{
+		for(i=0; i<argc; i++){
+			fd = open(argv[i], OREAD);
+			if(fd < 0){
+				fprint(2, "bmp: can't open %s: %r\n", argv[i]);
+				err = "open";
+			}else{
+				err = show(fd, argv[i]);
+				close(fd);
+			}
+			if((nineflag || cflag) && argc>1 && err==nil){
+				fprint(2, "bmp: exiting after one file\n");
+				break;
+			}
+		}
+	}
+	exits(err);
+}
+
+int
+init(void)
+{
+	static int inited;
+
+	if(inited == 0){
+		if(initdraw(0, 0, 0) < 0){
+			fprint(2, "bmp: initdraw failed: %r");
+			return -1;
+		}
+		einit(Ekeyboard|Emouse);
+		inited++;
+	}
+	return 1;
+}
+
+char*
+show(int fd, char *name)
+{
+	Rawimage **array, *r, *c;
+	Image *i;
+	int j, ch;
+	char buf[32];
+
+	array = readbmp(fd, CRGB);
+	if(array == nil || array[0]==nil){
+		fprint(2, "bmp: decode %s failed: %r\n", name);
+		return "decode";
+	}
+	if(!dflag){
+		if(init() < 0)
+			return "initdraw";
+		if(defaultcolor && screen->depth>8)
+			outchan = RGB24;
+	}
+	r = array[0];
+	if(outchan == CMAP8)
+		c = torgbv(r, !eflag);
+	else{
+		if(outchan==GREY8 || (r->chandesc==CY && threeflag==0))
+			c = totruecolor(r, CY);
+		else
+			c = totruecolor(r, CRGB24);
+	}
+	if(c == nil){
+		fprint(2, "bmp: converting %s to local format failed: %r\n", name);
+		return "torgbv";
+	}
+	if(!dflag){
+		if(r->chandesc == CY)
+			i = allocimage(display, c->r, GREY8, 0, 0);
+		else
+			i = allocimage(display, c->r, outchan, 0, 0);
+		if(i == nil){
+			fprint(2, "bmp: allocimage %s failed: %r\n", name);
+			return "allocimage";
+		}
+		if(loadimage(i, i->r, c->chans[0], c->chanlen) < 0){
+			fprint(2, "bmp: loadimage %s failed: %r\n", name);
+			return "loadimage";
+		}
+		image = i;
+		eresized(0);
+		if((ch=ekbd())=='q' || ch==0x7F || ch==0x04)
+			exits(nil);
+		draw(screen, screen->clipr, display->white, nil, ZP);
+		image = nil;
+		freeimage(i);
+	}
+	if(nineflag){
+		chantostr(buf, outchan);
+		print("%11s %11d %11d %11d %11d ", buf,
+			c->r.min.x, c->r.min.y, c->r.max.x, c->r.max.y);
+		if(write(1, c->chans[0], c->chanlen) != c->chanlen){
+			fprint(2, "bmp: %s: write error %r\n", name);
+			return "write";
+		}
+	}else if(cflag){
+		if(writerawimage(1, c) < 0){
+			fprint(2, "bmp: %s: write error: %r\n", name);
+			return "write";
+		}
+	}
+	for(j=0; j<r->nchans; j++)
+		free(r->chans[j]);
+	free(r);
+	free(array);
+	if(c){
+		free(c->chans[0]);
+		free(c);
+	}
+	return nil;
+}

+ 37 - 0
sys/src/cmd/jpg/bmp.h

@@ -0,0 +1,37 @@
+
+#define BMP_RGB      	0
+#define BMP_RLE8     	1
+#define BMP_RLE4     	2
+#define BMP_BITFIELDS	3
+
+typedef struct {
+	uchar red;
+	uchar green;
+	uchar blue;
+	uchar alpha;
+} Rgb;
+
+typedef struct {
+        short	type;
+        long	size;
+        short	reserved1;
+        short	reserved2;
+        long	offbits;
+} Filehdr;
+
+typedef struct {
+	long	size;		/* Size of the Bitmap-file */
+	long	lReserved;	/* Reserved */
+	long	dataoff;	/* Picture data location */
+	long	hsize;		/* Header-Size */
+	long	width;		/* Picture width (pixels) */
+	long	height;		/* Picture height (pixels) */
+	short	planes;		/* Planes (must be 1) */
+	short	bpp;		/* Bits per pixel (1, 4, 8 or 24) */
+	long	compression;	/* Compression mode */
+	long	imagesize;	/* Image size (bytes) */
+	long	hres;		/* Horizontal Resolution (pels/meter) */
+	long	vres;		/* Vertical Resolution (pels/meter) */
+	long	colours;	/* Used Colours (Col-Table index) */
+	long	impcolours;	/* Important colours (Col-Table index) */
+} Infohdr;

+ 2 - 0
sys/src/cmd/jpg/mkfile

@@ -10,6 +10,7 @@ TARG=jpg\
 	yuv\
 	yuv\
 	ico\
 	ico\
 	toico\
 	toico\
+	bmp\
 
 
 IMFILES=\
 IMFILES=\
 	torgbv.$O\
 	torgbv.$O\
@@ -48,6 +49,7 @@ $O.toppm:	writeppm.$O multichan.$O toppm.$O
 $O.png:		$IMFILES readpng.$O png.$O
 $O.png:		$IMFILES readpng.$O png.$O
 $O.topng:	writepng.$O topng.$O
 $O.topng:	writepng.$O topng.$O
 $O.yuv:		$IMFILES readyuv.$O yuv.$O
 $O.yuv:		$IMFILES readyuv.$O yuv.$O
+$O.bmp:		$IMFILES readbmp.$O bmp.$O
 
 
 torgbv.$O:	ycbcr.h rgbv.h
 torgbv.$O:	ycbcr.h rgbv.h
 
 

+ 626 - 0
sys/src/cmd/jpg/readbmp.c

@@ -0,0 +1,626 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <draw.h>
+#include "imagefile.h"
+#include "bmp.h"
+
+/*
+ MS-BMP file reader
+ (c) 2003, I.P.Keller
+
+ aims to decode *all* valid bitmap formats, although some of the
+ flavours couldn't be verified due to lack of suitable test-files.
+ the following flavours are supported:
+
+	Bit/Pix	Orientation	Compression	Tested?
+	  1	top->bottom	n/a		yes
+	  1	bottom->top	n/a		yes
+	  4	top->bottom	no		yes
+	  4	bottom->top	no		yes
+	  4	top->bottom	RLE4		yes, but not with displacement
+	  8	top->bottom	no		yes
+	  8	bottom->top	no		yes
+	  8	top->bottom	RLE8		yes, but not with displacement
+	 16	top->bottom	no		no
+	 16	bottom->top	no		no
+	 16	top->bottom	BITMASK		no
+	 16	bottom->top	BITMASK		no
+	 24	top->bottom	n/a		yes
+	 24	bottom->top	n/a		yes
+	 32	top->bottom	no		no
+	 32	bottom->top	no		no
+	 32	top->bottom	BITMASK		no
+	 32	bottom->top	BITMASK		no
+
+ OS/2 1.x bmp files are recognised as well, but testing was very limited.
+
+ verifying was done with a number of test files, generated by
+ different tools. nevertheless, the tests were in no way exhaustive
+ enough to guarantee bug-free decoding. caveat emptor!
+*/
+
+static short
+r16(Biobuf*b)
+{
+	short s;
+
+	s = Bgetc(b);
+	s |= ((short)Bgetc(b)) << 8;
+	return s;
+}
+
+
+static long
+r32(Biobuf*b)
+{
+	long l;
+
+	l = Bgetc(b);
+	l |= ((long)Bgetc(b)) << 8;
+	l |= ((long)Bgetc(b)) << 16;
+	l |= ((long)Bgetc(b)) << 24;
+	return l;
+}
+
+
+/* get highest bit set */
+static int
+msb(ulong x)
+{
+	int i;
+	for(i = 32; i; i--, x <<= 1)
+		if(x & 0x80000000L)
+			return i;
+	return 0;
+}
+
+/* Load a 1-Bit encoded BMP file (uncompressed) */
+static int
+load_1T(Biobuf *b, long width, long height, Rgb* buf, Rgb* clut)
+{
+	long ix, iy, i = 0, step_up = 0, padded_width = ((width + 31) / 32) * 32;
+	int val = 0, n;
+
+	if(height > 0) {	/* bottom-up */
+		i = (height - 1) * width;
+		step_up = -2 * width;
+	} else
+		height = -height;
+
+	for(iy = height; iy; iy--, i += step_up)
+		for(ix = 0, n = 0; ix < padded_width; ix++, n--) {
+			if(!n) {
+				val = Bgetc(b);
+				n = 8;
+			}
+			if(ix < width) {
+				buf[i] = clut[val & 0x80 ? 1 : 0];
+				i++;
+			}
+			val <<= 1;
+		}
+	return 0;
+}
+
+/* Load a 4-Bit encoded BMP file (uncompressed) */
+static int
+load_4T(Biobuf* b, long width, long height, Rgb* buf, Rgb* clut)
+{
+	long ix, iy, i = 0, step_up = 0, skip = (4 - (((width % 8) + 1) / 2)) & 3;
+	uint valH, valL;
+
+	if(height > 0) {	/* bottom-up */
+		i = (height - 1) * width;
+		step_up = -2 * width;
+	} else
+		height = -height;
+
+	for(iy = height; iy; iy--, i += step_up) {
+		for(ix = 0; ix < width; ) {
+			valH = valL = Bgetc(b) & 0xff;
+			valH >>= 4;
+
+			buf[i] = clut[valH];
+			i++; ix++;
+
+			if(ix < width) {
+				valL &= 0xf;
+				buf[i] = clut[valL];
+				i++; ix++;
+			}
+		}
+		Bseek(b, skip, 1);
+	}
+	return 0;
+}
+
+/* Load a 4-Bit encoded BMP file (RLE4-compressed) */
+static int
+load_4C(Biobuf *b, long width, long height, Rgb* buf, Rgb* clut)
+{
+	long ix, iy = height -1;
+	uint val, valS, skip;
+	Rgb* p;
+
+	while(iy >= 0) {
+		ix = 0;
+		while(ix < width) {
+			val = Bgetc(b);
+
+			if(0 != val) {
+				valS = (uint)Bgetc(b);
+				p = &buf[ix + iy * width];
+				while(val--) {
+					*p = clut[0xf & (valS >> 4)];
+					p++;
+					ix++;
+					if(0 < val) {
+						*p = clut[0xf & valS];
+						p++;
+						ix++;
+						val--;
+					}
+				}
+			} else {
+				/* Special modes... */
+				val = Bgetc(b);
+				switch(val) {
+					case 0:	/* End-Of-Line detected */
+						ix = width;
+						iy--;
+						break;
+					case 1:	/* End-Of-Picture detected -->> abort */
+						ix = width;
+						iy = -1;
+						break;
+					case 2:	/* Position change detected */
+						val = Bgetc(b);
+						ix += val;
+						val = Bgetc(b);
+						iy -= val;
+						break;
+
+					default:/* Transparent data sequence detected */
+						p = &buf[ix + iy * width];
+						if((1 == (val & 3)) || (2 == (val & 3)))
+							skip = 1;
+						else 
+							skip = 0;
+
+						while(val--) {
+							valS = (uint)Bgetc(b);
+							*p = clut[0xf & (valS >> 4)];
+							p++;
+							ix++;
+							if(0 < val) {
+								*p = clut[0xf & valS];
+								p++;
+								ix++;
+								val--;
+							}
+						}
+						if(skip)
+							Bgetc(b);
+						break;
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+/* Load a 8-Bit encoded BMP file (uncompressed) */
+static int
+load_8T(Biobuf *b, long width, long height, Rgb* buf, Rgb* clut)
+{
+	long ix, iy, i = 0, step_up = 0, skip = (4 - (width % 4)) & 3;
+
+	if(height > 0) {	/* bottom-up */
+		i = (height - 1) * width;
+		step_up = -2 * width;
+	} else
+		height = -height;
+
+	for(iy = height; iy; iy--, i += step_up) {
+		for(ix = 0; ix < width; ix++, i++)
+			buf[i] = clut[Bgetc(b) & 0xff];
+		Bseek(b, skip, 1);
+	}
+	return 0;
+}
+
+/* Load a 8-Bit encoded BMP file (RLE8-compressed) */
+static int
+load_8C(Biobuf *b, long width, long height, Rgb* buf, Rgb* clut)
+{
+	long ix, iy = height -1;
+	int val, valS, skip;
+	Rgb* p;
+
+	while(iy >= 0) {
+		ix = 0;
+		while(ix < width) {
+			val = Bgetc(b);
+
+			if(0 != val) {
+				valS = Bgetc(b);
+				p = &buf[ix + iy * width];
+				while(val--) {
+					*p = clut[valS];
+					p++;
+					ix++;
+				}
+			} else {
+				/* Special modes... */
+				val = Bgetc(b);
+				switch(val) {
+					case 0: /* End-Of-Line detected */
+						ix = width;
+						iy--;
+						break;
+					case 1: /* End-Of-Picture detected */
+						ix = width;
+						iy = -1;
+						break;
+					case 2: /* Position change detected */
+						val = Bgetc(b);
+						ix += val;
+						val = Bgetc(b);
+						iy -= val;
+						break;
+					default: /* Transparent (not compressed) sequence detected */
+						p = &buf[ix + iy * width];
+						if(val & 1)
+							skip = 1;
+						else 
+							skip = 0;
+
+						while(val--) {
+							valS = Bgetc(b);
+							*p = clut[valS];
+							p++;
+							ix++;
+						}
+						if(skip)
+							/* Align data stream */
+							Bgetc(b);
+						break;
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+/* Load a 16-Bit encoded BMP file (uncompressed) */
+static int
+load_16(Biobuf *b, long width, long height, Rgb* buf, Rgb* clut)
+{
+	uchar c[2];
+	long ix, iy, i = 0, step_up = 0;
+
+	if(height > 0) {	/* bottom-up */
+		i = (height - 1) * width;
+		step_up = -2 * width;
+	} else
+		height = -height;
+
+	if(clut) {
+		unsigned mask_blue =  (unsigned)clut[0].blue +
+		                     ((unsigned)clut[0].green << 8);
+		unsigned mask_green =  (unsigned)clut[1].blue +
+		                      ((unsigned)clut[1].green << 8);
+		unsigned mask_red =  (unsigned)clut[2].blue +
+		                    ((unsigned)clut[2].green << 8);
+		int shft_blue = msb((ulong)mask_blue) - 8;
+		int shft_green = msb((ulong)mask_green) - 8;
+		int shft_red = msb((ulong)mask_red) - 8;
+
+		for(iy = height; iy; iy--, i += step_up)
+			for(ix = 0; ix < width; ix++, i++) {
+				unsigned val;
+				Bread(b, c, sizeof(c));
+				val = (unsigned)c[0] + ((unsigned)c[1] << 8);
+
+				buf[i].alpha = 0;
+				if(shft_blue >= 0)
+					buf[i].blue = (uchar)((val & mask_blue) >> shft_blue);
+				else
+					buf[i].blue = (uchar)((val & mask_blue) << -shft_blue);
+				if(shft_green >= 0)
+					buf[i].green = (uchar)((val & mask_green) >> shft_green);
+				else
+					buf[i].green = (uchar)((val & mask_green) << -shft_green);
+				if(shft_red >= 0)
+					buf[i].red = (uchar)((val & mask_red) >> shft_red);
+				else
+					buf[i].red = (uchar)((val & mask_red) << -shft_red);
+			}
+	} else
+		for(iy = height; iy; iy--, i += step_up)
+			for(ix = 0; ix < width; ix++, i++) {
+				Bread(b, c, sizeof(c));
+				buf[i].blue = (uchar)((c[0] << 3) & 0xf8);
+				buf[i].green = (uchar)(((((unsigned)c[1] << 6) +
+				                        (((unsigned)c[0]) >> 2))) & 0xf8);
+				buf[i].red = (uchar)((c[1] << 1) & 0xf8);
+			}
+	return 0;
+}
+
+/* Load a 24-Bit encoded BMP file (uncompressed) */
+static int
+load_24T(Biobuf* b, long width, long height, Rgb* buf)
+{
+	long ix, iy, i = 0, step_up = 0, skip = (4 - ((width * 3) % 4)) & 3;
+
+	if(height > 0) {	/* bottom-up */
+		i = (height - 1) * width;
+		step_up = -2 * width;
+	} else
+		height = -height;
+
+	for(iy = height; iy; iy--, i += step_up) {
+		for(ix = 0; ix < width; ix++, i++) {
+			buf[i].alpha = 0;
+			buf[i].blue = Bgetc(b);
+			buf[i].green = Bgetc(b);
+			buf[i].red = Bgetc(b);
+		}
+		Bseek(b, skip, 1);
+	}
+	return 0;
+}
+
+/* Load a 32-Bit encoded BMP file (uncompressed) */
+static int
+load_32(Biobuf *b, long width, long height, Rgb* buf, Rgb* clut)
+{
+	uchar c[4];
+	long ix, iy, i = 0, step_up = 0;
+
+	if(height > 0) {	/* bottom-up */
+		i = (height - 1) * width;
+		step_up = -2 * width;
+	} else
+		height = -height;
+
+	if(clut) {
+		ulong mask_blue =  (ulong)clut[0].blue +
+		                          ((ulong)clut[0].green << 8) +
+		                          ((ulong)clut[0].red << 16) +
+		                          ((ulong)clut[0].alpha << 24);
+		ulong mask_green =  (ulong)clut[1].blue +
+		                           ((ulong)clut[1].green << 8) +
+		                           ((ulong)clut[1].red << 16) +
+		                           ((ulong)clut[1].alpha << 24);
+		ulong mask_red =  (ulong)clut[2].blue +
+		                         ((ulong)clut[2].green << 8) +
+		                         ((ulong)clut[2].red << 16) +
+		                         ((ulong)clut[2].alpha << 24);
+		int shft_blue = msb(mask_blue) - 8;
+		int shft_green = msb(mask_green) - 8;
+		int shft_red = msb(mask_red) - 8;
+
+		for(iy = height; iy; iy--, i += step_up)
+			for(ix = 0; ix < width; ix++, i++) {
+				ulong val;
+				Bread(b, c, sizeof(c));
+				val =  (ulong)c[0] + ((ulong)c[1] << 8) +
+				      ((ulong)c[2] << 16) + ((ulong)c[1] << 24);
+
+				buf[i].alpha = 0;
+				if(shft_blue >= 0)
+					buf[i].blue = (uchar)((val & mask_blue) >> shft_blue);
+				else
+					buf[i].blue = (uchar)((val & mask_blue) << -shft_blue);
+				if(shft_green >= 0)
+					buf[i].green = (uchar)((val & mask_green) >> shft_green);
+				else
+					buf[i].green = (uchar)((val & mask_green) << -shft_green);
+				if(shft_red >= 0)
+					buf[i].red = (uchar)((val & mask_red) >> shft_red);
+				else
+					buf[i].red = (uchar)((val & mask_red) << -shft_red);
+			}
+	} else
+		for(iy = height; iy; iy--, i += step_up)
+			for(ix = 0; ix < width; ix++, i++) {
+				Bread(b, c, nelem(c));
+				buf[i].blue = c[0];
+				buf[i].green = c[1];
+				buf[i].red = c[2];
+			}
+	return 0;
+}
+
+
+static Rgb*
+ReadBMP(Biobuf *b, int *width, int *height)
+{
+	int colours, num_coltab = 0;
+	Filehdr bmfh;
+	Infohdr bmih;
+	Rgb clut[256];
+	Rgb* buf;
+
+	bmfh.type = r16(b);
+	if(bmfh.type != 0x4d42) 	/* signature must be 'BM' */
+		sysfatal("bad magic number, not a BMP file");
+
+	bmfh.size = r32(b);
+	bmfh.reserved1 = r16(b);
+	bmfh.reserved2 = r16(b);
+	bmfh.offbits = r32(b);
+
+	memset(&bmih, 0, sizeof(bmih));
+	bmih.size = r32(b);
+
+	if(bmih.size == 0x0c) {			/* OS/2 1.x version */
+		bmih.width = r16(b);
+		bmih.height = r16(b);
+		bmih.planes = r16(b);
+		bmih.bpp = r16(b);
+		bmih.compression = BMP_RGB;
+	} else {				/* Windows */
+		bmih.width = r32(b);
+		bmih.height = r32(b);
+		bmih.planes = r16(b);
+		bmih.bpp = r16(b);
+		bmih.compression = r32(b);
+		bmih.imagesize = r32(b);
+		bmih.hres = r32(b);
+		bmih.vres = r32(b);
+		bmih.colours = r32(b);
+		bmih.impcolours = r32(b);
+	}
+
+	if(bmih.bpp < 16) {
+		/* load colour table */
+		if(bmih.impcolours)
+			num_coltab = (int)bmih.impcolours;
+		else
+			num_coltab = 1 << bmih.bpp;
+	} else if(bmih.compression == BMP_BITFIELDS &&
+	          (bmih.bpp == 16 || bmih.bpp == 32))
+		/* load bitmasks */
+		num_coltab = 3;
+
+	if(num_coltab) {
+		int i; 
+		Bseek(b, bmih.size + sizeof(Infohdr), 0);
+
+		for(i = 0; i < num_coltab; i++) {
+			clut[i].blue  = (uchar)Bgetc(b);
+			clut[i].green = (uchar)Bgetc(b);
+			clut[i].red   = (uchar)Bgetc(b);
+			clut[i].alpha = (uchar)Bgetc(b);
+		}
+	}
+
+	*width = bmih.width;
+	*height = bmih.height;
+	colours = bmih.bpp;
+
+	Bseek(b, bmfh.offbits, 0);
+
+	if ((buf = calloc(sizeof(Rgb), *width * abs(*height))) == nil)
+		sysfatal("no memory");
+
+	switch(colours) {
+		case 1:
+			load_1T(b, *width, *height, buf, clut);
+			break;
+		case 4:
+			if(bmih.compression == BMP_RLE4)
+				load_4C(b, *width, *height, buf, clut);
+			else
+				load_4T(b, *width, *height, buf, clut);
+			break;
+		case 8:
+			if(bmih.compression == BMP_RLE8)
+				load_8C(b, *width, *height, buf, clut);
+			else
+				load_8T(b, *width, *height, buf, clut);
+			break;
+		case 16:
+			load_16(b, *width, *height, buf,
+			        bmih.compression == BMP_BITFIELDS ? clut : nil);
+			break;
+		case 24:
+			load_24T(b, *width, *height, buf);
+			break;
+		case 32:
+			load_32(b, *width, *height, buf,
+			        bmih.compression == BMP_BITFIELDS ? clut : nil);
+			break;
+	}
+	return buf;
+}
+
+Rawimage**
+Breadbmp(Biobuf *bp, int colourspace)
+{
+	Rawimage *a, **array;
+	int c, width, height;
+	uchar *r, *g, *b;
+	Rgb *s, *e;
+	Rgb *bmp;
+	char ebuf[128];
+
+	a = nil;
+	bmp = nil;
+	array = nil;
+	USED(a);
+	USED(bmp);
+	if (colourspace != CRGB) {
+		errstr(ebuf, sizeof ebuf);	/* throw it away */
+		werrstr("ReadRGB: unknown colour space %d", colourspace);
+		return nil;
+	}
+
+	if ((bmp = ReadBMP(bp, &width, &height)) == nil)
+		return nil;
+
+	if ((a = calloc(sizeof(Rawimage), 1)) == nil)
+		goto Error;
+
+	for (c = 0; c  < 3; c++)
+		if ((a->chans[c] = calloc(width, height)) == nil)
+			goto Error;
+
+	if ((array = calloc(sizeof(Rawimage *), 2)) == nil)
+		goto Error;
+	array[0] = a;
+	array[1] = nil;
+
+	a->nchans = 3;
+	a->chandesc = CRGB;
+	a->chanlen = width * height;
+	a->r = Rect(0, 0, width, height);
+
+	s = bmp;
+	e = s + width * height;
+	r = a->chans[0];
+	g = a->chans[1];
+	b = a->chans[2];
+
+	do {
+		*r++ = s->red;
+		*g++ = s->green;
+		*b++ = s->blue;
+	}while(++s < e);
+
+	free(bmp);
+	return array;
+
+Error:
+	if (a)
+		for (c = 0; c < 3; c++)
+			if (a->chans[c])
+				free(a->chans[c]);
+	if (a)
+		free(a);
+	if (array)
+		free(array);
+	if (bmp)
+		free(bmp);
+	return nil;
+
+}
+
+Rawimage**
+readbmp(int fd, int colorspace)
+{
+	Rawimage * *a;
+	Biobuf b;
+
+	if (Binit(&b, fd, OREAD) < 0)
+		return nil;
+	a = Breadbmp(&b, colorspace);
+	Bterm(&b);
+	return a;
+}
+
+

+ 14 - 3
sys/src/cmd/wikifs/parse.c

@@ -211,8 +211,19 @@ wman(Wpage *wtxt)
 	return wtxt;	
 	return wtxt;	
 }
 }
 
 
-static char *lower = "abcdefghijklmnopqrstuvwxyz";
-static char *upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+static int isheading(char *p) {
+	Rune r;
+	int hasupper=0;
+	while(*p) {
+		p+=chartorune(&r,p);
+		if(isupperrune(r))
+			hasupper=1;
+		else if(islowerrune(r))
+			return 0;
+	}
+	return hasupper;
+}
+
 Wpage*
 Wpage*
 Brdpage(char *(*rdline)(void*,int), void *b)
 Brdpage(char *(*rdline)(void*,int), void *b)
 {
 {
@@ -247,7 +258,7 @@ Brdpage(char *(*rdline)(void*,int), void *b)
 			pw = &(*pw)->next;
 			pw = &(*pw)->next;
 			break;
 			break;
 		default:
 		default:
-			if(strpbrk(p, lower)==nil && strpbrk(p, upper)){
+			if(isheading(p)){
 				*pw = mkwtxt(Wheading, estrdup(p));
 				*pw = mkwtxt(Wheading, estrdup(p));
 				pw = &(*pw)->next;
 				pw = &(*pw)->next;
 				continue;
 				continue;