summaryrefslogtreecommitdiff
path: root/sys/src/cmd/getmap.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/getmap.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/getmap.c')
-rwxr-xr-xsys/src/cmd/getmap.c155
1 files changed, 155 insertions, 0 deletions
diff --git a/sys/src/cmd/getmap.c b/sys/src/cmd/getmap.c
new file mode 100755
index 000000000..3db180160
--- /dev/null
+++ b/sys/src/cmd/getmap.c
@@ -0,0 +1,155 @@
+#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);
+}