diff options
Diffstat (limited to 'src/ui/color.c')
-rw-r--r-- | src/ui/color.c | 86 |
1 files changed, 81 insertions, 5 deletions
diff --git a/src/ui/color.c b/src/ui/color.c index a6ba18e4..05ec1f6f 100644 --- a/src/ui/color.c +++ b/src/ui/color.c | |||
@@ -24,11 +24,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
24 | #include "root.h" | 24 | #include "root.h" |
25 | #include "app.h" | 25 | #include "app.h" |
26 | 26 | ||
27 | #include <the_Foundation/file.h> | ||
28 | #include <the_Foundation/path.h> | ||
27 | #include <the_Foundation/string.h> | 29 | #include <the_Foundation/string.h> |
28 | 30 | ||
29 | static const iColor transparent_; | 31 | static const iColor transparent_; |
30 | 32 | ||
31 | static const iColor darkPalette_[] = { | 33 | static iColor darkPalette_[] = { |
32 | { 0, 0, 0, 255 }, | 34 | { 0, 0, 0, 255 }, |
33 | { 40, 40, 40, 255 }, | 35 | { 40, 40, 40, 255 }, |
34 | { 80, 80, 80, 255 }, | 36 | { 80, 80, 80, 255 }, |
@@ -47,7 +49,7 @@ static const iColor darkPalette_[] = { | |||
47 | { 0, 200, 0, 255 }, | 49 | { 0, 200, 0, 255 }, |
48 | }; | 50 | }; |
49 | 51 | ||
50 | static const iColor lightPalette_[] = { | 52 | static iColor lightPalette_[] = { |
51 | { 0, 0, 0, 255 }, | 53 | { 0, 0, 0, 255 }, |
52 | { 75, 75, 75, 255 }, | 54 | { 75, 75, 75, 255 }, |
53 | { 150, 150, 150, 255 }, | 55 | { 150, 150, 150, 255 }, |
@@ -468,12 +470,12 @@ const char *escape_Color(int color) { | |||
468 | return esc[color]; | 470 | return esc[color]; |
469 | } | 471 | } |
470 | /* TODO: Conflict with format strings! "%" (37) may be used as the color value. */ | 472 | /* TODO: Conflict with format strings! "%" (37) may be used as the color value. */ |
471 | /* Double-\r is used for range extension. */ | 473 | /* Double-\v is used for range extension. */ |
472 | if (color + asciiBase_ColorEscape > 127) { | 474 | if (color + asciiBase_ColorEscape > 127) { |
473 | iAssert(color - asciiExtended_ColorEscape + asciiBase_ColorEscape <= 127); | 475 | iAssert(color - asciiExtended_ColorEscape + asciiBase_ColorEscape <= 127); |
474 | return format_CStr("\r\r%c", color - asciiExtended_ColorEscape + asciiBase_ColorEscape); | 476 | return format_CStr("\v\v%c", color - asciiExtended_ColorEscape + asciiBase_ColorEscape); |
475 | } | 477 | } |
476 | return format_CStr("\r%c", color + asciiBase_ColorEscape); | 478 | return format_CStr("\v%c", color + asciiBase_ColorEscape); |
477 | } | 479 | } |
478 | 480 | ||
479 | iHSLColor setSat_HSLColor(iHSLColor d, float sat) { | 481 | iHSLColor setSat_HSLColor(iHSLColor d, float sat) { |
@@ -804,3 +806,77 @@ iColor ansiForeground_Color(iRangecc escapeSequence, int fallback) { | |||
804 | } | 806 | } |
805 | return clr; | 807 | return clr; |
806 | } | 808 | } |
809 | |||
810 | iBool loadPalette_Color(const char *path) { | ||
811 | iBool wasLoaded = iFalse; | ||
812 | iFile *f = newCStr_File(concatPath_CStr(path, "palette.txt")); | ||
813 | if (open_File(f, text_FileMode | readOnly_FileMode)) { | ||
814 | iColor *dstPal = darkPalette_; | ||
815 | iRangecc srcLine = iNullRange; | ||
816 | const iBlock *src = collect_Block(readAll_File(f)); | ||
817 | while (nextSplit_Rangecc(range_Block(src), "\n", &srcLine)) { | ||
818 | iRangecc line = srcLine; | ||
819 | trim_Rangecc(&line); | ||
820 | if (isEmpty_Range(&line)) { | ||
821 | continue; | ||
822 | } | ||
823 | if (*line.start == '#') { | ||
824 | /* Control directive. */ | ||
825 | line.start++; | ||
826 | trim_Rangecc(&line); | ||
827 | if (equalCase_Rangecc(line, "dark")) { | ||
828 | dstPal = darkPalette_; | ||
829 | } | ||
830 | else if (equalCase_Rangecc(line, "light")) { | ||
831 | dstPal = lightPalette_; | ||
832 | } | ||
833 | continue; | ||
834 | } | ||
835 | static const struct { | ||
836 | const char *label; | ||
837 | int paletteIndex; | ||
838 | } colors_[] = { | ||
839 | { "black:", 0 }, { "gray25:", 1 }, { "gray50:", 2 }, { "gray75:", 3 }, | ||
840 | { "white:", 4 }, { "brown:", 5 }, { "orange:", 6 }, { "teal:", 7 }, | ||
841 | { "cyan:", 8 }, { "yellow:", 9 }, { "red:", 10 }, { "magenta:", 11 }, | ||
842 | { "blue:", 12 }, { "green:", 13 }, | ||
843 | }; | ||
844 | iForIndices(i, colors_) { | ||
845 | if (startsWithCase_Rangecc(line, colors_[i].label)) { | ||
846 | iColor *dst = &dstPal[colors_[i].paletteIndex]; | ||
847 | line.start += strlen(colors_[i].label); | ||
848 | trim_Rangecc(&line); | ||
849 | if (!isEmpty_Range(&line)) { | ||
850 | if (*line.start == '#') { | ||
851 | /* Hexadecimal color. */ | ||
852 | line.start++; | ||
853 | if (size_Range(&line) == 6) { | ||
854 | iBlock *vals = hexDecode_Rangecc(line); | ||
855 | iAssert(size_Block(vals) == 3); | ||
856 | const uint8_t *rgb = constData_Block(vals); | ||
857 | *dst = (iColor){ rgb[0], rgb[1], rgb[2], 255 }; | ||
858 | delete_Block(vals); | ||
859 | } | ||
860 | else { | ||
861 | fprintf(stderr, "[Color] invalid custom color: %s\n", | ||
862 | cstr_Rangecc(line)); | ||
863 | } | ||
864 | } | ||
865 | else { | ||
866 | unsigned int red = 0, green = 0, blue = 0; | ||
867 | sscanf(line.start, "%u %u %u", &red, &green, &blue); | ||
868 | if (red > 255 || green > 255 || blue > 255) { | ||
869 | fprintf(stderr, "[Color] RGB value(s) out of range: %s\n", | ||
870 | cstr_Rangecc(line)); | ||
871 | } | ||
872 | *dst = (iColor){ red, green, blue, 255 }; | ||
873 | } | ||
874 | } | ||
875 | } | ||
876 | } | ||
877 | } | ||
878 | wasLoaded = iTrue; | ||
879 | } | ||
880 | iRelease(f); | ||
881 | return wasLoaded; | ||
882 | } | ||