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 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 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 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 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