plan9fox/sys/src/cmd/getmap.c
Ori Bernstein 5bc9b0c3ca improve usage messages (thanks henesy)
Fix inconsistencies between programs and their usage
messages,  correct instances where information seems
to be missing or lost. This  includes missing arguments,
making usage consistent with manuals, and so on.
2020-03-10 10:09:34 -07:00

156 lines
3.2 KiB
C

#include <u.h>
#include <libc.h>
#include <draw.h>
/*
* int getcmap(int id, char *file, unsigned char *buf)
* Read a colormap from the given file into the buffer.
* Returns 1 on success, 0 otherwise.
* Goes to unglaublich length to figure out what the file name means:
* If the name is "screen" or "display" or "vga", reads the colormap from /dev/draw/id/colormap.
* If the name is "gamma",returns gamma=2.3 colormap
* If the name is "gamma###", returns gamma=#### colormap
* Ditto for rgamma, for reverse video.
* Looks for the file in a list of directories (given below).
*/
char *cmapdir[] = {
"",
"/lib/cmap/",
0
};
int
getcmap(int id, char *f, unsigned char *buf)
{
char name[512];
char *s, *lines[256], *fields[4];
int cmap, i, j, n, v, rev;
double gamma;
cmap = -1;
for(i=0; cmapdir[i]!=nil ;i++){
snprint(name, sizeof name, "%s%s", cmapdir[i], f);
if((cmap = open(name, OREAD)) >= 0)
break;
}
if(cmap == -1){
if(strcmp(name, "screen")==0 || strcmp(name, "display")==0 || strcmp(name, "vga")==0){
snprint(name, sizeof name, "/dev/draw/%d/colormap", id);
cmap = open(name, OREAD);
if(cmap < 0)
return 0;
}
}
if(cmap==-1){ /* could be gamma or gamma<number> or fb */
if(strncmp(f, "gamma", 5)==0){
rev=0;
f+=5;
}else if(strncmp(f, "rgamma", 6)==0){
rev = 1;
f+=6;
}else
return 0;
if(*f == '\0')
gamma=2.3;
else{
if(strspn(f, "0123456789.") != strlen(f))
return 0;
gamma = atof(f);
}
for(i=0; i!=256; i++){
v=255.*pow(i/255., 1./gamma);
if(rev)
v=255-v;
buf[0] = buf[1] = buf[2] = v;
buf += 3;
}
return 1;
}
s = malloc(20000);
n = readn(cmap, s, 20000-1);
if(n <= 0)
return 0;
s[n] = '\0';
if(getfields(s, lines, 256, 0, "\n") != 256)
return 0;
for(i=0; i<256; i++){
if(getfields(lines[i], fields, 4, 1, " \t") != 4)
return 0;
if(atoi(fields[0]) != i)
return 0;
for(j=0; j<3; j++)
buf[3*i+j] = atoi(fields[j+1]);
}
return 1;
}
/* replicate (from top) value in v (n bits) until it fills a ulong */
ulong
rep(ulong v, int n)
{
int o;
ulong rv;
rv = 0;
for(o=32-n; o>=0; o-=n)
rv |= v<<o;
if(o != -n)
rv |= v>>-o;
return rv;
}
void
putcmap(int id, uchar cmap[256*3])
{
char *s, *t;
int i, fd;
char name[64];
snprint(name, sizeof name, "/dev/draw/%d/colormap", id);
fd = open(name, OWRITE);
if(fd < 0)
sysfatal("can't open colormap file: %r");
s = malloc(20000);
t = s;
for(i = 0; i<256; i++)
t += sprint(t, "%d %d %d %d\n", i, cmap[3*i+0], cmap[3*i+1], cmap[3*i+2]);
if(write(fd, s, t-s) != t-s)
sysfatal("writing color map: %r");
close(fd);
}
void
main(int argc, char *argv[])
{
uchar cmapbuf[256*3];
char *map, buf[12*12+1];
int fd, id;
if(argc>2){
fprint(2, "usage: %s colormap\n", argv[0]);
exits("usage");
}
map = "rgbv";
if(argc > 1)
map = argv[1];
fd = open("/dev/draw/new", OREAD);
if(fd < 0 || read(fd, buf, sizeof buf) != 12*12)
sysfatal("can't connect to display: %r");
id = atoi(buf+0*12);
if(strncmp(buf+2*12, " m8 ", 12) != 0)
sysfatal("can't set colormap except on CMAP8 (m8) displays; this one is %.12s", buf+2*12);
if(getcmap(id, map, cmapbuf) == 0){
fprint(2, "%s: can't find %s\n", argv[0], map);
exits("not found");
}
putcmap(id, cmapbuf);
exits(0);
}