1#!/usr/bin/env perl
2# $XTermId: palettes.pl,v 1.26 2020/07/01 20:13:58 tom Exp $
3# -----------------------------------------------------------------------------
4# this file is part of xterm
5#
6# Copyright 2020 by Thomas E. Dickey
7#
8#                         All Rights Reserved
9#
10# Permission is hereby granted, free of charge, to any person obtaining a
11# copy of this software and associated documentation files (the
12# "Software"), to deal in the Software without restriction, including
13# without limitation the rights to use, copy, modify, merge, publish,
14# distribute, sublicense, and/or sell copies of the Software, and to
15# permit persons to whom the Software is furnished to do so, subject to
16# the following conditions:
17#
18# The above copyright notice and this permission notice shall be included
19# in all copies or substantial portions of the Software.
20#
21# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24# IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
25# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28#
29# Except as contained in this notice, the name(s) of the above copyright
30# holders shall not be used in advertising or otherwise to promote the
31# sale, use or other dealings in this Software without prior written
32# authorization.
33# -----------------------------------------------------------------------------
34# Demonstrate how to set palette colors using xterm's control sequences.
35
36# TODO: add "-n" option, to show tput in dry-run mode
37# TODO: make some way to optimize-out the Tcolors resets, to focus on tput vs hardcoded
38
39use strict;
40use warnings;
41
42use Getopt::Std;
43use Term::ReadKey;
44use FileHandle;
45
46select(STDERR);
47$| = 1;
48select(STDOUT);
49$| = 1;
50
51our (
52    $opt_a, $opt_b, $opt_d, $opt_g, $opt_i,
53    $opt_s, $opt_T, $opt_v, $opt_x, $opt_8
54);
55
56our ( $CSI, $OSC, $ST );
57
58our %colors;
59our @Acolors;
60our %Tcolors;
61our $dump;
62
63our %Tcolor_names = qw(
64  0  foreground
65  1  background
66  2  cursorColor
67  3  pointerForegroundColor
68  4  pointerBackgroundColor
69  5  tektronixForegroundColor
70  6  tektronixBackgroundColor
71  7  highlightColor
72  8  tektronixCursorColor
73  9  highlightForegroundColor
74);
75
76our $DARK;
77
78sub isatty() {
79    my $result = 0;
80    $result = 1 if ( -t 0 and -t 1 and -t 2 );
81    return $result;
82}
83
84# Adapted from
85# https://github.com/altercation/solarized (xresources/solarized)
86sub init_solarized() {
87    $colors{S_yellow}  = 0xb58900;
88    $colors{S_orange}  = 0xcb4b16;
89    $colors{S_red}     = 0xdc322f;
90    $colors{S_magenta} = 0xd33682;
91    $colors{S_violet}  = 0x6c71c4;
92    $colors{S_blue}    = 0x268bd2;
93    $colors{S_cyan}    = 0x2aa198;
94    $colors{S_green}   = 0x859900;
95
96    if ($DARK) {
97        $colors{S_base03} = 0x002b36;
98        $colors{S_base02} = 0x073642;
99        $colors{S_base01} = 0x586e75;
100        $colors{S_base00} = 0x657b83;
101        $colors{S_base0}  = 0x839496;
102        $colors{S_base1}  = 0x93a1a1;
103        $colors{S_base2}  = 0xeee8d5;
104        $colors{S_base3}  = 0xfdf6e3;
105    }
106    else {
107        $colors{S_base03} = 0xfdf6e3;
108        $colors{S_base02} = 0xeee8d5;
109        $colors{S_base01} = 0x93a1a1;
110        $colors{S_base00} = 0x839496;
111        $colors{S_base0}  = 0x657b83;
112        $colors{S_base1}  = 0x586e75;
113        $colors{S_base2}  = 0x073642;
114        $colors{S_base3}  = 0x002b36;
115    }
116
117    $Acolors[0]  = $colors{S_base02};
118    $Acolors[1]  = $colors{S_red};
119    $Acolors[2]  = $colors{S_green};
120    $Acolors[3]  = $colors{S_yellow};
121    $Acolors[4]  = $colors{S_blue};
122    $Acolors[5]  = $colors{S_magenta};
123    $Acolors[6]  = $colors{S_cyan};
124    $Acolors[7]  = $colors{S_base2};
125    $Acolors[9]  = $colors{S_orange};
126    $Acolors[8]  = $colors{S_base03};
127    $Acolors[10] = $colors{S_base01};
128    $Acolors[11] = $colors{S_base00};
129    $Acolors[12] = $colors{S_base0};
130    $Acolors[13] = $colors{S_violet};
131    $Acolors[14] = $colors{S_base1};
132    $Acolors[15] = $colors{S_base3};
133
134    $Tcolors{background}             = $colors{S_base03};
135    $Tcolors{foreground}             = $colors{S_base0};
136    $Tcolors{cursorColor}            = $colors{S_base1};
137    $Tcolors{pointerColorBackground} = $colors{S_base01};
138    $Tcolors{pointerColorForeground} = $colors{S_base1};
139}
140
141# Most of the "themes" are from this source:
142# http://web.archive.org/web/20100329130515/http://phraktured.net:80/terminal-colors
143# in turn, that cites Aaron Griffin (2007) and uses colortheme.sh, referring to
144# https://github.com/Rydgel/archlinux/blob/master/scripts/colortheme.sh
145# https://web.archive.org/web/20060630201817/http://frexx.de/xterm-256-notes/
146sub init_1() {
147    $Tcolors{background} = 0x000000;
148    $Tcolors{foreground} = 0xa8a8a8;
149
150    $Acolors[0]  = 0x000000;
151    $Acolors[1]  = 0xa80000;
152    $Acolors[2]  = 0x00a800;
153    $Acolors[3]  = 0xa85400;
154    $Acolors[4]  = 0x0000a8;
155    $Acolors[5]  = 0xa800a8;
156    $Acolors[6]  = 0x00a8a8;
157    $Acolors[7]  = 0xa8a8a8;
158    $Acolors[8]  = 0x545054;
159    $Acolors[9]  = 0xf85450;
160    $Acolors[10] = 0x50fc50;
161    $Acolors[11] = 0xf8fc50;
162    $Acolors[12] = 0x5054f8;
163    $Acolors[13] = 0xf854f8;
164    $Acolors[14] = 0x50fcf8;
165    $Acolors[15] = 0xf8fcf8;
166}
167
168sub init_2() {
169    $Tcolors{background} = 0x000000;
170    $Tcolors{foreground} = 0x7f7f7f;
171
172    $Acolors[0]  = 0x000000;
173    $Acolors[1]  = 0x9e1828;
174    $Acolors[2]  = 0xaece92;
175    $Acolors[3]  = 0x968a38;
176    $Acolors[4]  = 0x414171;
177    $Acolors[5]  = 0x963c59;
178    $Acolors[6]  = 0x418179;
179    $Acolors[7]  = 0xbebebe;
180    $Acolors[8]  = 0x666666;
181    $Acolors[9]  = 0xcf6171;
182    $Acolors[10] = 0xc5f779;
183    $Acolors[11] = 0xfff796;
184    $Acolors[12] = 0x4186be;
185    $Acolors[13] = 0xcf9ebe;
186    $Acolors[14] = 0x71bebe;
187    $Acolors[15] = 0xffffff;
188}
189
190sub init_3() {
191    $Tcolors{background} = 0x000000;
192    $Tcolors{foreground} = 0xcfcfcf;
193
194    $Acolors[0]  = 0x000000;
195    $Acolors[1]  = 0xe01010;
196    $Acolors[2]  = 0x20ad20;
197    $Acolors[3]  = 0xd4c24f;
198    $Acolors[4]  = 0x231bb8;
199    $Acolors[5]  = 0x9c3885;
200    $Acolors[6]  = 0x1dbdb8;
201    $Acolors[7]  = 0xfefefe;
202    $Acolors[8]  = 0x6a6a6a;
203    $Acolors[9]  = 0xe83a3d;
204    $Acolors[10] = 0x35e956;
205    $Acolors[11] = 0xffff2f;
206    $Acolors[12] = 0x3a53f0;
207    $Acolors[13] = 0xe628ba;
208    $Acolors[14] = 0x1cf5f5;
209    $Acolors[15] = 0xffffff;
210}
211
212sub init_4() {
213    $Tcolors{background} = 0x000000;
214    $Tcolors{foreground} = 0xffffff;
215
216    $Acolors[0]  = 0x000000;
217    $Acolors[1]  = 0xd36265;
218    $Acolors[2]  = 0xaece91;
219    $Acolors[3]  = 0xe7e18c;
220    $Acolors[4]  = 0x7a7ab0;
221    $Acolors[5]  = 0x963c59;
222    $Acolors[6]  = 0x418179;
223    $Acolors[7]  = 0xbebebe;
224    $Acolors[8]  = 0x666666;
225    $Acolors[9]  = 0xef8171;
226    $Acolors[10] = 0xe5f779;
227    $Acolors[11] = 0xfff796;
228    $Acolors[12] = 0x4186be;
229    $Acolors[13] = 0xef9ebe;
230    $Acolors[14] = 0x71bebe;
231    $Acolors[15] = 0xffffff;
232}
233
234sub init_5() {
235    $Tcolors{background} = 0xadaaad;
236    $Tcolors{foreground} = 0x000000;
237
238    $Acolors[0]  = 0x000000;
239    $Acolors[1]  = 0x640f19;
240    $Acolors[2]  = 0x63796b;
241    $Acolors[3]  = 0xad7142;
242    $Acolors[4]  = 0x4f4f89;
243    $Acolors[5]  = 0xb25c7c;
244    $Acolors[6]  = 0x52756b;
245    $Acolors[7]  = 0xadaaad;
246    $Acolors[8]  = 0x525552;
247    $Acolors[9]  = 0xa56163;
248    $Acolors[10] = 0xcec263;
249    $Acolors[11] = 0x73ae70;
250    $Acolors[12] = 0x36709f;
251    $Acolors[13] = 0xaa829c;
252    $Acolors[14] = 0x518989;
253    $Acolors[15] = 0xffffef;
254}
255
256sub init_6() {
257    $Tcolors{background} = 0xbebebe;
258    $Tcolors{foreground} = 0x212121;
259
260    $Acolors[0]  = 0x000000;
261    $Acolors[1]  = 0xbf7276;
262    $Acolors[2]  = 0x86af80;
263    $Acolors[3]  = 0x968a38;
264    $Acolors[4]  = 0x3673b5;
265    $Acolors[5]  = 0x9a70b2;
266    $Acolors[6]  = 0x7abecc;
267    $Acolors[7]  = 0xdbdbdb;
268    $Acolors[8]  = 0x6692af;
269    $Acolors[9]  = 0xe5505f;
270    $Acolors[10] = 0x87bc87;
271    $Acolors[11] = 0xe0d95c;
272    $Acolors[12] = 0x1b85d6;
273    $Acolors[13] = 0xad73ba;
274    $Acolors[14] = 0x338eaa;
275    $Acolors[15] = 0xf4f4f4;
276}
277
278sub init_7() {
279    $Tcolors{background} = 0x676767;
280    $Tcolors{foreground} = 0xffffff;
281
282    $Acolors[0]  = 0x000000;
283    $Acolors[1]  = 0xbf4646;
284    $Acolors[2]  = 0x67b25f;
285    $Acolors[3]  = 0xcfc44e;
286    $Acolors[4]  = 0x516083;
287    $Acolors[5]  = 0xca6eff;
288    $Acolors[6]  = 0x92b2f8;
289    $Acolors[7]  = 0xd5d5d5;
290    $Acolors[8]  = 0x000000;
291    $Acolors[9]  = 0xf48a8a;
292    $Acolors[10] = 0xa5d79f;
293    $Acolors[11] = 0xe1da84;
294    $Acolors[12] = 0xa2bbff;
295    $Acolors[13] = 0xe2b0ff;
296    $Acolors[14] = 0xbacdf8;
297    $Acolors[15] = 0xd5d5d5;
298}
299
300sub init_8() {
301    $Tcolors{background} = 0x101010;
302    $Tcolors{foreground} = 0xd3d3d3;
303
304    $Acolors[0]  = 0x101010;
305    $Acolors[1]  = 0xcd5c5c;
306    $Acolors[2]  = 0x2e8b57;
307    $Acolors[3]  = 0xf0e68c;
308    $Acolors[4]  = 0xb0c4de;
309    $Acolors[5]  = 0xba55d3;
310    $Acolors[6]  = 0x4682b4;
311    $Acolors[7]  = 0xd3d3d3;
312    $Acolors[8]  = 0x4d4d4d;
313    $Acolors[9]  = 0xff6a6a;
314    $Acolors[10] = 0x8fbc8f;
315    $Acolors[11] = 0xfffacd;
316    $Acolors[12] = 0x1e90ff;
317    $Acolors[13] = 0xdb7093;
318    $Acolors[14] = 0x5f9ea0;
319    $Acolors[15] = 0xffffff;
320}
321
322sub init_9() {
323    $Tcolors{background} = 0x1a1a1a;
324    $Tcolors{foreground} = 0xd6d6d6;
325
326    $Acolors[0]  = 0x000000;
327    $Acolors[1]  = 0x9e1828;
328    $Acolors[2]  = 0x008800;
329    $Acolors[3]  = 0x968a38;
330    $Acolors[4]  = 0x414171;
331    $Acolors[5]  = 0x963c59;
332    $Acolors[6]  = 0x418179;
333    $Acolors[7]  = 0xbebebe;
334    $Acolors[8]  = 0x666666;
335    $Acolors[9]  = 0xcf6171;
336    $Acolors[10] = 0x7cbc8c;
337    $Acolors[11] = 0xfff796;
338    $Acolors[12] = 0x4186be;
339    $Acolors[13] = 0xcf9ebe;
340    $Acolors[14] = 0x71bebe;
341    $Acolors[15] = 0xffffff;
342}
343
344sub init_10() {
345    $Tcolors{background} = 0x1a1a1a;
346    $Tcolors{foreground} = 0xd6d6d6;
347
348    $Acolors[0]  = 0x000000;
349    $Acolors[1]  = 0x98565e;
350    $Acolors[2]  = 0x66825d;
351    $Acolors[3]  = 0x969176;
352    $Acolors[4]  = 0x4d6585;
353    $Acolors[5]  = 0x967395;
354    $Acolors[6]  = 0x5f7f7b;
355    $Acolors[7]  = 0xb3b3b3;
356    $Acolors[8]  = 0x737373;
357    $Acolors[9]  = 0xcfa3a9;
358    $Acolors[10] = 0xcaf7bb;
359    $Acolors[11] = 0xfff8bc;
360    $Acolors[12] = 0x83a3be;
361    $Acolors[13] = 0xbba9cf;
362    $Acolors[14] = 0x96cccc;
363    $Acolors[15] = 0xffffff;
364}
365
366sub init_11() {
367    $Tcolors{background} = 0x333333;
368    $Tcolors{foreground} = 0xffffff;
369
370    $Acolors[0]  = 0x333333;
371    $Acolors[1]  = 0xffa0a0;
372    $Acolors[2]  = 0x98fb98;
373    $Acolors[3]  = 0xf0e68c;
374    $Acolors[4]  = 0x87ceeb;
375    $Acolors[5]  = 0xffa0a0;
376    $Acolors[6]  = 0x87ceeb;
377    $Acolors[7]  = 0xffffff;
378    $Acolors[8]  = 0x333333;
379    $Acolors[9]  = 0xffa0a0;
380    $Acolors[10] = 0x9acd32;
381    $Acolors[11] = 0xf0e68c;
382    $Acolors[12] = 0x87ceeb;
383    $Acolors[13] = 0xffa0a0;
384    $Acolors[14] = 0x87ceeb;
385    $Acolors[15] = 0xffffff;
386}
387
388sub init_12() {
389    $Tcolors{foreground} = 0xffffff;
390    $Tcolors{background} = 0x000000;
391
392    $Acolors[0]  = 0x000000;
393    $Acolors[1]  = 0xbf7276;
394    $Acolors[2]  = 0x86af80;
395    $Acolors[3]  = 0x968a38;
396    $Acolors[4]  = 0x3673b5;
397    $Acolors[5]  = 0x9a70b2;
398    $Acolors[6]  = 0x7abecc;
399    $Acolors[7]  = 0xdbdbdb;
400    $Acolors[8]  = 0x6692af;
401    $Acolors[9]  = 0xe5505f;
402    $Acolors[10] = 0x87bc87;
403    $Acolors[11] = 0xe0d95c;
404    $Acolors[12] = 0x1b85d6;
405    $Acolors[13] = 0xad73ba;
406    $Acolors[14] = 0x338eaa;
407    $Acolors[15] = 0xf4f4f4;
408}
409
410sub init_13() {
411    $Tcolors{background} = 0x000000;
412    $Tcolors{foreground} = 0xaaaaaa;
413
414    $Acolors[0]  = 0x000000;
415    $Acolors[1]  = 0x9e1828;
416    $Acolors[2]  = 0xaece92;
417    $Acolors[3]  = 0x968a38;
418    $Acolors[4]  = 0x414171;
419    $Acolors[5]  = 0x963c59;
420    $Acolors[6]  = 0x7f9f7f;
421    $Acolors[7]  = 0xbebebe;
422    $Acolors[8]  = 0x666666;
423    $Acolors[9]  = 0xcf6171;
424    $Acolors[10] = 0xafc5af;
425    $Acolors[11] = 0xf0dfaf;
426    $Acolors[12] = 0x8e9fbc;
427    $Acolors[13] = 0xdca3a3;
428    $Acolors[14] = 0x95c1c5;
429    $Acolors[15] = 0xffffff;
430}
431
432sub init_14() {
433    $Tcolors{background} = 0x959595;
434    $Tcolors{foreground} = 0x000000;
435
436    $Acolors[0]  = 0x7f7f7f;
437    $Acolors[1]  = 0xcd0000;
438    $Acolors[2]  = 0x008b00;
439    $Acolors[3]  = 0xeeee00;
440    $Acolors[4]  = 0x0000cd;
441    $Acolors[5]  = 0xcd00cd;
442    $Acolors[6]  = 0x00eeee;
443    $Acolors[7]  = 0xfaebd7;
444    $Acolors[8]  = 0xe5e5e5;
445    $Acolors[9]  = 0x800000;
446    $Acolors[10] = 0x005020;
447    $Acolors[11] = 0x995500;
448    $Acolors[12] = 0x004080;
449    $Acolors[13] = 0x443300;
450    $Acolors[14] = 0x306080;
451    $Acolors[15] = 0xffffff;
452}
453
454sub init_15() {
455    $Tcolors{background} = 0x1d2b3a;
456    $Tcolors{foreground} = 0xbebebe;
457
458    $Acolors[0]  = 0x000000;
459    $Acolors[1]  = 0xd36265;
460    $Acolors[2]  = 0xaece91;
461    $Acolors[3]  = 0xe7e18c;
462    $Acolors[4]  = 0x7a7ab0;
463    $Acolors[5]  = 0x963c59;
464    $Acolors[6]  = 0x418179;
465    $Acolors[7]  = 0xbebebe;
466    $Acolors[8]  = 0x666666;
467    $Acolors[9]  = 0xef8171;
468    $Acolors[10] = 0xe5f779;
469    $Acolors[11] = 0xfff799;
470    $Acolors[12] = 0x4186be;
471    $Acolors[13] = 0xef9ebe;
472    $Acolors[14] = 0x71bebe;
473    $Acolors[15] = 0xffffff;
474}
475
476sub init_16() {
477    $Tcolors{background} = 0x000000;
478    $Tcolors{foreground} = 0xbebebe;
479
480    $Acolors[0]  = 0x000000;
481    $Acolors[1]  = 0x9e1828;
482    $Acolors[2]  = 0xaece92;
483    $Acolors[3]  = 0x968a38;
484    $Acolors[4]  = 0x414171;
485    $Acolors[5]  = 0x963c59;
486    $Acolors[6]  = 0x418179;
487    $Acolors[7]  = 0xbebebe;
488    $Acolors[8]  = 0x666666;
489    $Acolors[9]  = 0xcf6171;
490    $Acolors[10] = 0xc5f779;
491    $Acolors[11] = 0xfff796;
492    $Acolors[12] = 0x4186be;
493    $Acolors[13] = 0xcf9ebe;
494    $Acolors[14] = 0x71bebe;
495    $Acolors[15] = 0xffffff;
496}
497
498sub init_17() {
499    $Tcolors{background} = 0x000000;
500    $Tcolors{foreground} = 0xe5e5e5;
501
502    $Acolors[0]  = 0x000000;
503    $Acolors[1]  = 0xff0000;
504    $Acolors[2]  = 0x00ff00;
505    $Acolors[3]  = 0xffff00;
506    $Acolors[4]  = 0x0000ff;
507    $Acolors[5]  = 0xff00ff;
508    $Acolors[6]  = 0x00ffff;
509    $Acolors[7]  = 0xffffff;
510    $Acolors[8]  = 0xffd39b;
511    $Acolors[9]  = 0xff8247;
512    $Acolors[10] = 0xff82ab;
513    $Acolors[11] = 0x87cefa;
514    $Acolors[12] = 0xffffff;
515    $Acolors[13] = 0xffffff;
516    $Acolors[14] = 0xffffff;
517    $Acolors[15] = 0xffffff;
518}
519
520sub init_18() {
521    $Acolors[0]  = 0x000000;
522    $Acolors[1]  = 0x9e1828;
523    $Acolors[2]  = 0x5cb247;
524    $Acolors[3]  = 0x968a38;
525    $Acolors[4]  = 0x4161a0;
526    $Acolors[5]  = 0x9b768e;
527    $Acolors[6]  = 0x419189;
528    $Acolors[7]  = 0xbebebe;
529    $Acolors[8]  = 0x666666;
530    $Acolors[9]  = 0xcf6171;
531    $Acolors[10] = 0xc5f779;
532    $Acolors[11] = 0xfff796;
533    $Acolors[12] = 0x4186be;
534    $Acolors[13] = 0xcf9ebe;
535    $Acolors[14] = 0x71bebe;
536    $Acolors[15] = 0xdddddd;
537}
538
539sub init_19() {
540    $Acolors[0]  = 0x000000;
541    $Acolors[1]  = 0xb07050;
542    $Acolors[2]  = 0x12914e;
543    $Acolors[3]  = 0xa0a070;
544    $Acolors[4]  = 0x3e4581;
545    $Acolors[5]  = 0xa070a0;
546    $Acolors[6]  = 0x70a0a0;
547    $Acolors[7]  = 0xa0a0a0;
548    $Acolors[8]  = 0x606060;
549    $Acolors[9]  = 0xb07050;
550    $Acolors[10] = 0x12914e;
551    $Acolors[11] = 0xc0c090;
552    $Acolors[12] = 0x3e4581;
553    $Acolors[13] = 0xc090c0;
554    $Acolors[14] = 0x90c0c0;
555    $Acolors[15] = 0xffffff;
556}
557
558sub init_20() {
559    $Tcolors{foreground} = 0xaaaaaa;
560    $Tcolors{background} = 0x000000;
561
562    $Acolors[0]  = 0x303430;
563    $Acolors[1]  = 0xbf7979;
564    $Acolors[2]  = 0x97b26b;
565    $Acolors[3]  = 0xcdcdc1;
566    $Acolors[4]  = 0x86a2be;
567    $Acolors[5]  = 0xd9b798;
568    $Acolors[6]  = 0xa1b5cd;
569    $Acolors[7]  = 0xffffff;
570    $Acolors[8]  = 0xcdb5cd;
571    $Acolors[9]  = 0xf4a45f;
572    $Acolors[10] = 0xc5f779;
573    $Acolors[11] = 0xffffef;
574    $Acolors[12] = 0x98afd9;
575    $Acolors[13] = 0xd7d998;
576    $Acolors[14] = 0xa1b5cd;
577    $Acolors[15] = 0xdedede;
578}
579
580sub init_21() {
581    $Tcolors{background} = 0x1a1a1a;
582    $Tcolors{foreground} = 0xaaaaaa;
583
584    $Acolors[0]  = 0x000000;
585    $Acolors[1]  = 0x9e1828;
586    $Acolors[2]  = 0x008800;
587    $Acolors[3]  = 0xd2bb4b;
588    $Acolors[4]  = 0x414171;
589    $Acolors[5]  = 0x963c59;
590    $Acolors[6]  = 0x418179;
591    $Acolors[7]  = 0xbebebe;
592    $Acolors[8]  = 0x666666;
593    $Acolors[9]  = 0xbc5766;
594    $Acolors[10] = 0x61a171;
595    $Acolors[11] = 0xe7db52;
596    $Acolors[12] = 0x5085af;
597    $Acolors[13] = 0xa97a99;
598    $Acolors[14] = 0x6ba4a4;
599    $Acolors[15] = 0xffffff;
600}
601
602sub init_22() {
603    $Tcolors{background} = 0x000000;
604    $Tcolors{foreground} = 0xbebebe;
605
606    $Acolors[0]  = 0x000000;
607    $Acolors[1]  = 0xd36265;
608    $Acolors[2]  = 0xaece91;
609    $Acolors[3]  = 0xe7e18c;
610    $Acolors[4]  = 0x7a7ab0;
611    $Acolors[5]  = 0x963c59;
612    $Acolors[6]  = 0x7f9f7f;
613    $Acolors[7]  = 0xbebebe;
614    $Acolors[8]  = 0x666666;
615    $Acolors[9]  = 0xef8171;
616    $Acolors[10] = 0xe5f779;
617    $Acolors[11] = 0xf0dfaf;
618    $Acolors[12] = 0x8e9fbc;
619    $Acolors[13] = 0xef9ebe;
620    $Acolors[14] = 0x71bebe;
621    $Acolors[15] = 0xffffff;
622}
623
624sub init_23() {
625    $Tcolors{background} = 0x0e0e0e;
626    $Tcolors{foreground} = 0x4ad5e1;
627
628    $Acolors[0]  = 0x000000;
629    $Acolors[1]  = 0xdc74d1;
630    $Acolors[2]  = 0x0eb8c7;
631    $Acolors[3]  = 0xdfe37e;
632    $Acolors[4]  = 0x0;        #??
633    $Acolors[5]  = 0x9e88f0;
634    $Acolors[6]  = 0x73f7ff;
635    $Acolors[7]  = 0xe1dddd;
636    $Acolors[8]  = 0x8b8f93;
637    $Acolors[9]  = 0xdc74d1;
638    $Acolors[10] = 0x0eb8c7;
639    $Acolors[11] = 0xdfe37e;
640    $Acolors[13] = 0x9e88f0;
641    $Acolors[14] = 0x73f7ff;
642    $Acolors[15] = 0xe1dddd;
643}
644
645sub init_24() {
646    $Acolors[0]  = 0x000000;
647    $Acolors[1]  = 0xcd5c5c;
648    $Acolors[2]  = 0x8eae71;
649    $Acolors[3]  = 0xd2b48c;
650    $Acolors[4]  = 0x5f7b8a;
651    $Acolors[5]  = 0xcdcdb4;
652    $Acolors[6]  = 0x686868;
653    $Acolors[7]  = 0xffffff;
654    $Acolors[8]  = 0x000000;
655    $Acolors[9]  = 0xee6363;
656    $Acolors[10] = 0x95c749;
657    $Acolors[11] = 0xcdcdc1;
658    $Acolors[12] = 0x6b7b8a;
659    $Acolors[13] = 0xcdcdb4;
660    $Acolors[14] = 0x778798;
661    $Acolors[15] = 0xcacaca;
662}
663
664sub init_25() {
665    $Acolors[0]  = 0x000000;
666    $Acolors[1]  = 0x800000;
667    $Acolors[2]  = 0x008000;
668    $Acolors[3]  = 0xd0d090;
669    $Acolors[4]  = 0x000080;
670    $Acolors[5]  = 0x800080;
671    $Acolors[6]  = 0xa6caf0;
672    $Acolors[7]  = 0xd0d0d0;
673    $Acolors[8]  = 0xb0b0b0;
674    $Acolors[9]  = 0xf08060;
675    $Acolors[10] = 0x60f080;
676    $Acolors[11] = 0xe0c060;
677    $Acolors[12] = 0x80c0e0;
678    $Acolors[13] = 0xf0c0f0;
679    $Acolors[14] = 0xc0d8f8;
680    $Acolors[15] = 0xe0e0e0;
681}
682
683# (Griffin) colors ripped from rezza: http://metawire.org/~rezza/index.php
684sub init_rezza() {
685    $Tcolors{foreground} = 0xdddddd;
686    $Tcolors{background} = 0x222222;
687
688    $Acolors[0]  = 0x191919;
689    $Acolors[1]  = 0x803232;
690    $Acolors[2]  = 0x5b762f;
691    $Acolors[3]  = 0xaa9943;
692    $Acolors[4]  = 0x324c80;
693    $Acolors[5]  = 0x706c9a;
694    $Acolors[6]  = 0x92b19e;
695    $Acolors[7]  = 0xffffff;
696    $Acolors[8]  = 0x252525;
697    $Acolors[9]  = 0x982b2b;
698    $Acolors[10] = 0x89b83f;
699    $Acolors[11] = 0xefef60;
700    $Acolors[12] = 0x2b4f98;
701    $Acolors[13] = 0x826ab1;
702    $Acolors[14] = 0xa1cdcd;
703    $Acolors[15] = 0xdddddd;
704}
705
706sub init_theme($) {
707    my $theme = shift;
708
709    @Acolors = ();
710    %Tcolors = ();
711
712    &init_solarized if ( index( "solarized", $theme ) eq 0 );
713    &init_rezza     if ( index( "rezza",     $theme ) eq 0 );
714
715    &init_1  if ( $theme eq 1 );
716    &init_2  if ( $theme eq 2 );
717    &init_3  if ( $theme eq 3 );
718    &init_4  if ( $theme eq 4 );
719    &init_5  if ( $theme eq 5 );
720    &init_6  if ( $theme eq 6 );
721    &init_7  if ( $theme eq 7 );
722    &init_8  if ( $theme eq 8 );
723    &init_9  if ( $theme eq 9 );
724    &init_10 if ( $theme eq 10 );
725    &init_11 if ( $theme eq 11 );
726    &init_12 if ( $theme eq 12 );
727    &init_13 if ( $theme eq 13 );
728    &init_14 if ( $theme eq 14 );
729    &init_15 if ( $theme eq 15 );
730    &init_16 if ( $theme eq 16 );
731    &init_17 if ( $theme eq 17 );
732    &init_18 if ( $theme eq 18 );
733    &init_19 if ( $theme eq 19 );
734    &init_20 if ( $theme eq 20 );
735    &init_21 if ( $theme eq 21 );
736    &init_22 if ( $theme eq 22 );
737    &init_23 if ( $theme eq 23 );
738    &init_24 if ( $theme eq 24 );
739    &init_25 if ( $theme eq 25 );
740}
741
742sub all_themes() {
743    my @result;
744    push @result, "solarized";
745    push @result, "rezza";
746    for my $n ( 1 .. 25 ) {
747        push @result, $n;
748    }
749    return \@result;
750}
751
752sub raw() {
753    ReadMode 'ultra-raw', 'STDIN';    # allow single-character inputs
754}
755
756sub cooked() {
757    ReadMode 'normal';
758}
759
760sub get_reply($$) {
761    my $command = shift;
762    my $finish  = shift;
763    my $reply   = "";
764
765    &raw;
766    printf STDERR "%s", $command;
767    my $start = time;
768    while ( index( $reply, $finish ) < 0 ) {
769        my $test = ReadKey 0.1;
770        last if ( time > ( $start + 3 ) );
771        next if not defined $test;
772
773        $reply .= $test;
774    }
775    &cooked;
776    return $reply;
777}
778
779sub query_color($$) {
780    my $ansi = shift;
781    my $code = shift;
782    my @result;
783    my $parms;
784    if ($ansi) {
785        $parms = sprintf( "4;%d", $code );
786    }
787    else {
788        $parms = sprintf( "%d", 10 + $code );
789    }
790    my $query = sprintf( "%s%s;?%s", $OSC, $parms, $ST );
791    my $reply = &get_reply( $query, $ST );
792    if ( $reply =~ /^${OSC}${parms};rgb:/ ) {
793        $reply =~ s/^${OSC}${parms};rgb://;
794        $reply =~ s/[^[:print:]].*$//;
795        if ( $reply =~ /^[[:xdigit:]]+(\/[[:xdigit:]]+)+$/ ) {
796            $reply =~ s/([[:xdigit:]]+)/0x$1/g;
797            @result = split /\//, $reply;
798
799            # RGB should have 3 values
800            for my $n ( 0 .. $#result ) {
801                $result[$n] = hex $result[$n];
802            }
803
804            # add the limit based on the number of bits needed to print.
805            push @result, 2**( 4 * ( length($reply) - 2 ) / 3 );
806        }
807    }
808
809    # this would occur in case of error
810    push @result, $reply unless ( $#result >= 3 );
811    return @result;
812}
813
814sub get_color_string($$) {
815    my $ansi  = shift;
816    my $color = shift;
817    my $result;
818    my @check = &query_color( $ansi, $color );
819    if ( $#check == 3 ) {
820        while ( $check[3] > 0x10000 ) {
821            $check[0] /= ( 16 * 16 );
822            $check[1] /= ( 16 * 16 );
823            $check[2] /= ( 16 * 16 );
824            $check[3] /= ( 16 * 16 * 16 );
825        }
826        $result = sprintf "( %3d %3d %3d )", $check[0], $check[1], $check[2];
827    }
828    else {
829        $result = sprintf( "{%s}", $check[0] );
830    }
831    return $result;
832}
833
834sub guess_dark() {
835    my $result = 0;    # assume black-on-white
836    if (&isatty) {
837        my @check = &query_color( 0, 1 );
838        if ( $#check == 3 ) {
839            my $value = ( ( $check[0] ) + ( $check[1] ) + ( $check[2] ) ) / 3;
840            printf "%#x / %#x\n", $value, $check[3];
841            $result = 1 if ( $value < ( $check[3] / 2 ) );
842            printf "%s\n", $result ? "dark" : "light" if ($opt_v);
843        }
844    }
845    return $result;
846}
847
848sub for_tput($) {
849    my $value = shift;
850    $value *= 1000;
851    $value /= 255;
852    $value *= 256 / 255;
853    return sprintf( "%.0f", $value );
854}
855
856sub reset_Acolor($) {
857    my $number = shift;
858    printf STDERR "%s104;%d%s", $OSC, $number, $ST;
859    printf "\t%2d ->reset Acolor\n", $number if ($opt_v);
860}
861
862sub set_Acolor($) {
863    my $number = shift;
864    my $result = 0;
865    if ( defined $Acolors[$number] ) {
866        my $value = $Acolors[$number];
867        my $r     = ( ( $value / ( 256 * 256 ) ) % 256 );
868        my $g     = ( ( $value / (256) ) % 256 );
869        my $b     = ( ( $value / (1) ) % 256 );
870        if ($opt_x) {
871            system(
872                sprintf(
873                    "$opt_x $opt_T initc %d %d %d %d",
874                    $number, &for_tput($r), &for_tput($g), &for_tput($b)
875                )
876            );
877        }
878        else {
879            printf STDERR "%s4;%d;rgb:%02X/%02X/%02X%s", $OSC, $number, $r, $g,
880              $b,
881              $ST;
882        }
883        printf "\t%2d ->%06X ( %3d %3d %3d )\n", $number, $value, $r, $g, $b
884          if ($opt_v);
885        $result = 1;
886    }
887    return $result;
888}
889
890sub reset_Tcolor($) {
891    my $number = shift;
892    my $actual = $Tcolor_names{$number};
893    printf STDERR "%s%d%s", $OSC, 110 + $number, $ST;
894    printf "\t%2d ->reset Tcolor{%s}\n", $number, $actual
895      if ($opt_v);
896}
897
898sub set_Tcolor($) {
899    my $number = shift;
900    my $actual = $Tcolor_names{$number};
901    my $result = 0;
902    if (%Tcolors) {
903        if ( defined $Tcolors{$actual} ) {
904            my $value = $Tcolors{$actual};
905            my $r     = ( ( $value / ( 256 * 256 ) ) % 256 );
906            my $g     = ( ( $value / (256) ) % 256 );
907            my $b     = ( ( $value / (1) ) % 256 );
908            printf STDERR "%s%d;rgb:%02X/%02X/%02X%s", $OSC, 10 + $number, $r,
909              $g, $b, $ST;
910            printf "\t%2d ->set Tcolor{%s}\n", $number, $actual
911              if ($opt_v);
912            $result = 1;
913        }
914    }
915    return $result;
916}
917
918sub set_colors() {
919    for my $n ( 0 .. 2 ) {
920        &reset_Tcolor($n) unless &set_Tcolor($n);
921    }
922    for my $n ( 0 .. 15 ) {
923        &reset_Acolor($n) unless &set_Acolor($n);
924    }
925    printf STDERR "\007" if (&isatty);
926    STDERR->flush;
927}
928
929sub reset_colors() {
930    for my $n ( 0 .. 2 ) {
931        &reset_Tcolor($n);
932    }
933    printf STDERR "%s104%s", $OSC, $ST;
934    printf "\tall ->reset Acolor\n" if ($opt_v);
935}
936
937sub dump_colors($) {
938    my $theme = shift;
939    if ( open( DUMP, ">>", $opt_d ) ) {
940        my $state = &get_reply( sprintf( "%s#R", $CSI ), "Q" );
941        $state = substr( $state, length($CSI) )
942          if ( index( $state, $CSI ) == 0 );
943        printf DUMP "State \"%s\"\n",         $state;
944        printf DUMP "Palette after \"%s\"\n", $theme;
945        if (&isatty) {
946            printf DUMP "Tcolors:\n";
947            for my $n ( 0 .. 2 ) {
948                printf DUMP "\t%s = %s\n", $Tcolor_names{$n},
949                  &get_color_string( 0, $n );
950            }
951            printf DUMP "Acolors:\n";
952            for my $n ( 0 .. 15 ) {
953                printf DUMP "\t%2d -> %s\n", $n, &get_color_string( 1, $n );
954            }
955        }
956        close DUMP;
957    }
958}
959
960sub show_colors($) {
961    my $theme = shift;
962    if ( substr( $theme, 0, 1 ) eq "+" ) {
963
964        # push (or set slot, if number follows)
965        if ( $theme =~ /^\+[0-9]$/ ) {
966            my $slot = substr( $theme, 1 );
967            printf STDERR "%s#%dP", $CSI, $slot + 1;
968            printf "\tpush %s\n", $slot if ($opt_v);
969        }
970        else {
971            printf STDERR "%s#P", $CSI;
972            printf "\tpush\n" if ($opt_v);
973        }
974    }
975    elsif ( substr( $theme, 0, 1 ) eq "-" ) {
976
977        # pop (or restore from slot, if number follows)
978        if ( $theme =~ /^-[0-9]$/ ) {
979            my $slot = substr( $theme, 1 );
980            printf STDERR "%s#%dQ", $CSI, $slot + 1;
981            printf "\tpop %s\n", $slot if ($opt_v);
982        }
983        else {
984            printf STDERR "%s#Q", $CSI;
985            printf "\tpop\n" if ($opt_v);
986        }
987    }
988    elsif ( $theme eq "?" ) {
989
990        # query TODO
991        printf STDERR "%s#R", $CSI;
992        printf "\tquery\n" if ($opt_v);
993    }
994    else {
995        &init_theme($theme);
996        &set_colors if ( $#Acolors >= 0 );
997        &reset_colors unless ( $#Acolors >= 0 );
998    }
999    &dump_colors($theme) if ($opt_d);
1000}
1001
1002sub show_themes($) {
1003    my @themes = @{ $_[0] };
1004    for my $n ( 0 .. $#themes ) {
1005        &show_colors( $themes[$n] );
1006        sleep $opt_s if ( ( $n != $#themes ) and &isatty );
1007    }
1008}
1009
1010sub main::HELP_MESSAGE() {
1011    printf STDERR <<EOF
1012Usage: $0 [options] [themes]
1013
1014Options:
1015  -8      use 8-bit controls
1016  -a      show all themes
1017  -b      use BEL rather than ST for terminating strings
1018  -d FILE dump palette to file after setting colors
1019  -g      ask terminal for its default background color
1020  -i      assume terminal colors are reversed, i.e., white-on-black
1021  -s SECS sleep this long between changes
1022  -T TERM override "xterm-256color" for TPUT
1023  -x TPUT use TPUT program rather than hardcoded escapes
1024  -v      verbose
1025
1026Themes:
1027  solarized default
1028  rezza   named
1029  1-25    numbered
1030  0       reset
1031EOF
1032      ;
1033    exit 1;
1034}
1035
1036$Getopt::Std::STANDARD_HELP_VERSION = 1;
1037&getopts('abd:gis:T:x:v8') || &main::HELP_MESSAGE;
1038
1039&main::HELP_MESSAGE if ( $opt_a and ( $#ARGV >= 0 ) );
1040
1041if ($opt_8) {
1042    $CSI = "\x9b";
1043    $OSC = "\x9d";
1044    $ST  = "\x9c";
1045}
1046else {
1047    $CSI = "\x1b[";
1048    $OSC = "\x1b]";
1049    $ST  = "\x1b\\";
1050}
1051
1052$ST = "\007" if ($opt_b);
1053
1054$opt_s = 1 unless ($opt_s);
1055$opt_T = "-T $opt_T" if ($opt_T);
1056$opt_T = "-T xterm-256color" unless ($opt_T);
1057
1058$DARK = 0;
1059$DARK = 1 if ($opt_i);
1060$DARK = &guess_dark if ($opt_g);
1061
1062if ($opt_a) {
1063    &show_themes(&all_themes);
1064}
1065elsif ( $#ARGV >= 0 ) {
1066    &show_themes( \@ARGV );
1067}
1068else {
1069    &show_colors("solarized");
1070}
1071
10721;
1073