xref: /plan9/sys/src/cmd/getmap.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 
5 /*
6  * int getcmap(int id, char *file, unsigned char *buf)
7  *	Read a colormap from the given file into the buffer.
8  *	Returns 1 on success, 0 otherwise.
9  *	Goes to unglaublich length to figure out what the file name means:
10  *	If the name is "screen" or "display" or "vga", reads the colormap from /dev/draw/id/colormap.
11  *	If the name is "gamma",returns gamma=2.3 colormap
12  *	If the name is "gamma###", returns gamma=#### colormap
13  *	Ditto for rgamma, for reverse video.
14  *	Looks for the file in a list of directories (given below).
15  */
16 
17 char *cmapdir[] = {
18 	"",
19 	"/lib/cmap/",
20 	0
21 };
22 
23 int
getcmap(int id,char * f,unsigned char * buf)24 getcmap(int id, char *f, unsigned char *buf)
25 {
26 	char name[512];
27 	char *s, *lines[256], *fields[4];
28 	int cmap, i, j, n, v, rev;
29 	double gamma;
30 
31 	cmap = -1;
32 	for(i=0; cmapdir[i]!=nil ;i++){
33 		snprint(name, sizeof name, "%s%s", cmapdir[i], f);
34 		if((cmap = open(name, OREAD)) >= 0)
35 			break;
36 	}
37 
38 	if(cmap == -1){
39 		if(strcmp(name, "screen")==0 || strcmp(name, "display")==0 || strcmp(name, "vga")==0){
40 			snprint(name, sizeof name, "/dev/draw/%d/colormap", id);
41 			cmap = open(name, OREAD);
42 			if(cmap < 0)
43 				return 0;
44 		}
45 	}
46 
47 	if(cmap==-1){ /* could be gamma or gamma<number> or fb */
48 		if(strncmp(f, "gamma", 5)==0){
49 			rev=0;
50 			f+=5;
51 		}else if(strncmp(f, "rgamma", 6)==0){
52 			rev = 1;
53 			f+=6;
54 		}else
55 			return 0;
56 		if(*f == '\0')
57 			gamma=2.3;
58 		else{
59 			if(strspn(f, "0123456789.") != strlen(f))
60 				return 0;
61 			gamma = atof(f);
62 		}
63 		for(i=0; i!=256; i++){
64 			v=255.*pow(i/255., 1./gamma);
65 			if(rev)
66 				v=255-v;
67 			buf[0] = buf[1] = buf[2] = v;
68 			buf += 3;
69 		}
70 		return 1;
71 	}
72 
73 	s = malloc(20000);
74 	n = readn(cmap, s, 20000-1);
75 	if(n <= 0)
76 		return 0;
77 	s[n] = '\0';
78 	if(getfields(s, lines, 256, 0, "\n") != 256)
79 		return 0;
80 	for(i=0; i<256; i++){
81 		if(getfields(lines[i], fields, 4, 1, " \t") != 4)
82 			return 0;
83 		if(atoi(fields[0]) != i)
84 			return 0;
85 		for(j=0; j<3; j++)
86 			buf[3*i+j] = atoi(fields[j+1]);
87 	}
88 	return 1;
89 }
90 
91 /* replicate (from top) value in v (n bits) until it fills a ulong */
92 ulong
rep(ulong v,int n)93 rep(ulong v, int n)
94 {
95 	int o;
96 	ulong rv;
97 
98 	rv = 0;
99 	for(o=32-n; o>=0; o-=n)
100 		rv |= v<<o;
101 	if(o != -n)
102 		rv |= v>>-o;
103 	return rv;
104 }
105 
106 void
putcmap(int id,uchar cmap[256* 3])107 putcmap(int id, uchar cmap[256*3])
108 {
109 	char *s, *t;
110 	int i, fd;
111 	char name[64];
112 
113 	snprint(name, sizeof name, "/dev/draw/%d/colormap", id);
114 	fd = open(name, OWRITE);
115 	if(fd < 0)
116 		sysfatal("can't open colormap file: %r");
117 	s = malloc(20000);
118 	t = s;
119 	for(i = 0; i<256; i++)
120 		t += sprint(t, "%d %d %d %d\n", i, cmap[3*i+0], cmap[3*i+1], cmap[3*i+2]);
121 	if(write(fd, s, t-s) != t-s)
122 		sysfatal("writing color map: %r");
123 	close(fd);
124 }
125 
126 void
main(int argc,char * argv[])127 main(int argc, char *argv[])
128 {
129 	uchar cmapbuf[256*3];
130 	char *map, buf[12*12+1];
131 	int fd, id;
132 
133 	if(argc>2){
134 		fprint(2, "Usage: %s colormap\n", argv[0]);
135 		exits("usage");
136 	}
137 	map = "rgbv";
138 	if(argc > 1)
139 		map = argv[1];
140 
141 	fd = open("/dev/draw/new", OREAD);
142 	if(fd < 0 || read(fd, buf, sizeof buf) != 12*12)
143 		sysfatal("can't connect to display: %r");
144 	id = atoi(buf+0*12);
145 	if(strncmp(buf+2*12, "         m8 ", 12) != 0)
146 		sysfatal("can't set colormap except on CMAP8 (m8) displays; this one is %.12s", buf+2*12);
147 
148 	if(getcmap(id, map, cmapbuf) == 0){
149 		fprint(2, "%s: can't find %s\n", argv[0], map);
150 		exits("not found");
151 	}
152 
153 	putcmap(id, cmapbuf);
154 	exits(0);
155 }
156