1316958Sdchagin/* $Header: /p/tcsh/cvsroot/tcsh/tw.color.c,v 1.33 2015/05/28 11:53:49 christos Exp $ */ 259243Sobrien/* 359243Sobrien * tw.color.c: builtin color ls-F 459243Sobrien */ 559243Sobrien/*- 659243Sobrien * Copyright (c) 1998 The Regents of the University of California. 759243Sobrien * All rights reserved. 859243Sobrien * 959243Sobrien * Redistribution and use in source and binary forms, with or without 1059243Sobrien * modification, are permitted provided that the following conditions 1159243Sobrien * are met: 1259243Sobrien * 1. Redistributions of source code must retain the above copyright 1359243Sobrien * notice, this list of conditions and the following disclaimer. 1459243Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1559243Sobrien * notice, this list of conditions and the following disclaimer in the 1659243Sobrien * documentation and/or other materials provided with the distribution. 17100616Smp * 3. Neither the name of the University nor the names of its contributors 1859243Sobrien * may be used to endorse or promote products derived from this software 1959243Sobrien * without specific prior written permission. 2059243Sobrien * 2159243Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2259243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2359243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2459243Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2559243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2659243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2759243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2859243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2959243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3059243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3159243Sobrien * SUCH DAMAGE. 3259243Sobrien */ 3359243Sobrien#include "sh.h" 3459243Sobrien 35316958SdchaginRCSID("$tcsh: tw.color.c,v 1.33 2015/05/28 11:53:49 christos Exp $") 3659243Sobrien 3759243Sobrien#include "tw.h" 3859243Sobrien#include "ed.h" 3959243Sobrien#include "tc.h" 4059243Sobrien 4159243Sobrien#ifdef COLOR_LS_F 4259243Sobrien 4359243Sobrientypedef struct { 44167465Smp const char *s; 45167465Smp size_t len; 4659243Sobrien} Str; 4759243Sobrien 4859243Sobrien 4959243Sobrien#define VAR(suffix,variable,defaultcolor) \ 5059243Sobrien{ \ 5159243Sobrien suffix, variable, { defaultcolor, sizeof(defaultcolor) - 1 }, \ 5259243Sobrien { defaultcolor, sizeof(defaultcolor) - 1 } \ 5359243Sobrien} 5459243Sobrien#define NOS '\0' /* no suffix */ 5559243Sobrien 5659243Sobrientypedef struct { 5759243Sobrien const char suffix; 5859243Sobrien const char *variable; 59167465Smp Str color; 60167465Smp Str defaultcolor; 6159243Sobrien} Variable; 6259243Sobrien 6359243Sobrienstatic Variable variables[] = { 6459243Sobrien VAR('/', "di", "01;34"), /* Directory */ 6559243Sobrien VAR('@', "ln", "01;36"), /* Symbolic link */ 6659243Sobrien VAR('&', "or", ""), /* Orphanned symbolic link (defaults to ln) */ 6759243Sobrien VAR('|', "pi", "33"), /* Named pipe (FIFO) */ 6859243Sobrien VAR('=', "so", "01;35"), /* Socket */ 6983098Smp VAR('>', "do", "01;35"), /* Door (solaris fast ipc mechanism) */ 7059243Sobrien VAR('#', "bd", "01;33"), /* Block device */ 7159243Sobrien VAR('%', "cd", "01;33"), /* Character device */ 7259243Sobrien VAR('*', "ex", "01;32"), /* Executable file */ 7359243Sobrien VAR(NOS, "fi", "0"), /* Regular file */ 7459243Sobrien VAR(NOS, "no", "0"), /* Normal (non-filename) text */ 7559243Sobrien VAR(NOS, "mi", ""), /* Missing file (defaults to fi) */ 7669408Sache#ifdef IS_ASCII 7769408Sache VAR(NOS, "lc", "\033["), /* Left code (ASCII) */ 7869408Sache#else 7959243Sobrien VAR(NOS, "lc", "\x27["), /* Left code (EBCDIC)*/ 8069408Sache#endif 8159243Sobrien VAR(NOS, "rc", "m"), /* Right code */ 8259243Sobrien VAR(NOS, "ec", ""), /* End code (replaces lc+no+rc) */ 83167465Smp VAR(NOS, "su", ""), /* Setuid file (u+s) */ 84167465Smp VAR(NOS, "sg", ""), /* Setgid file (g+s) */ 85167465Smp VAR(NOS, "tw", ""), /* Sticky and other writable dir (+t,o+w) */ 86167465Smp VAR(NOS, "ow", ""), /* Other writable dir (o+w) but not sticky */ 87167465Smp VAR(NOS, "st", ""), /* Sticky dir (+t) but not other writable */ 88195609Smp VAR(NOS, "rs", "0"), /* Reset to normal color */ 89231990Smp VAR(NOS, "hl", "44;37"), /* Reg file extra hard links, obsolete? */ 90231990Smp VAR(NOS, "mh", "44;37"), /* Reg file extra hard links */ 91231990Smp VAR(NOS, "ca", "30;41"), /* File with capability */ 9259243Sobrien}; 9359243Sobrien 94316958Sdchagin#define nvariables (sizeof(variables)/sizeof(variables[0])) 95316958Sdchagin 9659243Sobrienenum FileType { 9783098Smp VDir, VSym, VOrph, VPipe, VSock, VDoor, VBlock, VChr, VExe, 98316958Sdchagin VFile, VNormal, VMiss, VLeft, VRight, VEnd, VSuid, VSgid, VSticky, 99316958Sdchagin VOther, Vstird, VReset, Vhard, Vhard2, VCap 10059243Sobrien}; 10159243Sobrien 102316958Sdchagin/* 103316958Sdchagin * Map from LSCOLORS entry index to Variable array index 104316958Sdchagin */ 105316958Sdchaginstatic const uint8_t map[] = { 106316958Sdchagin VDir, /* Directory */ 107316958Sdchagin VSym, /* Symbolic Link */ 108316958Sdchagin VSock, /* Socket */ 109316958Sdchagin VPipe, /* Named Pipe */ 110316958Sdchagin VExe, /* Executable */ 111316958Sdchagin VBlock, /* Block Special */ 112316958Sdchagin VChr, /* Character Special */ 113316958Sdchagin VSuid, /* Setuid Executable */ 114316958Sdchagin VSgid, /* Setgid Executable */ 115316958Sdchagin VSticky, /* Directory writable to others and sticky */ 116316958Sdchagin VOther, /* Directory writable to others but not sticky */ 117316958Sdchagin}; 11859243Sobrien 119316958Sdchagin 120316958Sdchagin 121316958Sdchaginenum ansi { 122316958Sdchagin ANSI_RESET_ON = 0, /* reset colors/styles (white on black) */ 123316958Sdchagin ANSI_BOLD_ON = 1, /* bold on */ 124316958Sdchagin ANSI_ITALICS_ON = 3, /* italics on */ 125316958Sdchagin ANSI_UNDERLINE_ON = 4, /* underline on */ 126316958Sdchagin ANSI_INVERSE_ON = 7, /* inverse on */ 127316958Sdchagin ANSI_STRIKETHROUGH_ON = 9, /* strikethrough on */ 128316958Sdchagin ANSI_BOLD_OFF = 21, /* bold off */ 129316958Sdchagin ANSI_ITALICS_OFF = 23, /* italics off */ 130316958Sdchagin ANSI_UNDERLINE_OFF = 24, /* underline off */ 131316958Sdchagin ANSI_INVERSE_OFF = 27, /* inverse off */ 132316958Sdchagin ANSI_STRIKETHROUGH_OFF = 29,/* strikethrough off */ 133316958Sdchagin ANSI_FG_BLACK = 30, /* fg black */ 134316958Sdchagin ANSI_FG_RED = 31, /* fg red */ 135316958Sdchagin ANSI_FG_GREEN = 32, /* fg green */ 136316958Sdchagin ANSI_FG_YELLOW = 33, /* fg yellow */ 137316958Sdchagin ANSI_FG_BLUE = 34, /* fg blue */ 138316958Sdchagin ANSI_FG_MAGENTA = 35, /* fg magenta */ 139316958Sdchagin ANSI_FG_CYAN = 36, /* fg cyan */ 140316958Sdchagin ANSI_FG_WHITE = 37, /* fg white */ 141316958Sdchagin ANSI_FG_DEFAULT = 39, /* fg default (white) */ 142316958Sdchagin ANSI_BG_BLACK = 40, /* bg black */ 143316958Sdchagin ANSI_BG_RED = 41, /* bg red */ 144316958Sdchagin ANSI_BG_GREEN = 42, /* bg green */ 145316958Sdchagin ANSI_BG_YELLOW = 43, /* bg yellow */ 146316958Sdchagin ANSI_BG_BLUE = 44, /* bg blue */ 147316958Sdchagin ANSI_BG_MAGENTA = 45, /* bg magenta */ 148316958Sdchagin ANSI_BG_CYAN = 46, /* bg cyan */ 149316958Sdchagin ANSI_BG_WHITE = 47, /* bg white */ 150316958Sdchagin ANSI_BG_DEFAULT = 49, /* bg default (black) */ 151316958Sdchagin}; 152316958Sdchagin#define TCSH_BOLD 0x80 153316958Sdchagin 15459243Sobrientypedef struct { 155167465Smp Str extension; /* file extension */ 156167465Smp Str color; /* color string */ 15759243Sobrien} Extension; 15859243Sobrien 15959243Sobrienstatic Extension *extensions = NULL; 160145479Smpstatic size_t nextensions = 0; 16159243Sobrien 16259243Sobrienstatic char *colors = NULL; 163145479Smpint color_context_ls = FALSE; /* do colored ls */ 164167465Smpstatic int color_context_lsmF = FALSE; /* do colored ls-F */ 16559243Sobrien 166167465Smpstatic int getstring (char **, const Char **, Str *, int); 167167465Smpstatic void put_color (const Str *); 168167465Smpstatic void print_color (const Char *, size_t, Char); 16959243Sobrien 17059243Sobrien/* set_color_context(): 17159243Sobrien */ 17259243Sobrienvoid 173167465Smpset_color_context(void) 17459243Sobrien{ 17559243Sobrien struct varent *vp = adrof(STRcolor); 17659243Sobrien 177100616Smp if (vp == NULL || vp->vec == NULL) { 17859243Sobrien color_context_ls = FALSE; 17959243Sobrien color_context_lsmF = FALSE; 180100616Smp } else if (!vp->vec[0] || vp->vec[0][0] == '\0') { 18159243Sobrien color_context_ls = TRUE; 18259243Sobrien color_context_lsmF = TRUE; 183100616Smp } else { 18459243Sobrien size_t i; 18559243Sobrien 18659243Sobrien color_context_ls = FALSE; 18759243Sobrien color_context_lsmF = FALSE; 18859243Sobrien for (i = 0; vp->vec[i]; i++) 18959243Sobrien if (Strcmp(vp->vec[i], STRls) == 0) 19059243Sobrien color_context_ls = TRUE; 19159243Sobrien else if (Strcmp(vp->vec[i], STRlsmF) == 0) 19259243Sobrien color_context_lsmF = TRUE; 19359243Sobrien } 19459243Sobrien} 19559243Sobrien 19659243Sobrien 19759243Sobrien/* getstring(): 19859243Sobrien */ 199167465Smpstatic int 200167465Smpgetstring(char **dp, const Char **sp, Str *pd, int f) 20159243Sobrien{ 20259243Sobrien const Char *s = *sp; 20359243Sobrien char *d = *dp; 204145479Smp eChar sc; 20559243Sobrien 206145479Smp while (*s && (*s & CHAR) != (Char)f && (*s & CHAR) != ':') { 20759243Sobrien if ((*s & CHAR) == '\\' || (*s & CHAR) == '^') { 208145479Smp if ((sc = parseescape(&s)) == CHAR_ERR) 20959243Sobrien return 0; 21059243Sobrien } 21159243Sobrien else 212145479Smp sc = *s++ & CHAR; 213145479Smp d += one_wctomb(d, sc); 21459243Sobrien } 21559243Sobrien 21659243Sobrien pd->s = *dp; 217167465Smp pd->len = d - *dp; 21859243Sobrien *sp = s; 21959243Sobrien *dp = d; 220145479Smp return *s == (Char)f; 22159243Sobrien} 22259243Sobrien 223316958Sdchaginstatic void 224316958Sdchagininit(size_t colorlen, size_t extnum) 225316958Sdchagin{ 226316958Sdchagin size_t i; 22759243Sobrien 228316958Sdchagin xfree(extensions); 229316958Sdchagin for (i = 0; i < nvariables; i++) 230316958Sdchagin variables[i].color = variables[i].defaultcolor; 231316958Sdchagin if (colorlen == 0 && extnum == 0) { 232316958Sdchagin extensions = NULL; 233316958Sdchagin colors = NULL; 234316958Sdchagin } else { 235316958Sdchagin extensions = xmalloc(colorlen + extnum * sizeof(*extensions)); 236316958Sdchagin colors = extnum * sizeof(*extensions) + (char *)extensions; 237316958Sdchagin } 238316958Sdchagin nextensions = 0; 239316958Sdchagin} 240316958Sdchagin 241316958Sdchaginstatic int 242316958Sdchagincolor(Char x) 243316958Sdchagin{ 244316958Sdchagin static const char ccolors[] = "abcdefghx"; 245316958Sdchagin char *p; 246316958Sdchagin if (Isupper(x)) { 247316958Sdchagin x = Tolower(x); 248316958Sdchagin } 249316958Sdchagin 250316958Sdchagin if (x == '\0' || (p = strchr(ccolors, x)) == NULL) 251316958Sdchagin return -1; 252316958Sdchagin return 30 + (p - ccolors); 253316958Sdchagin} 254316958Sdchagin 255316958Sdchaginstatic void 256316958Sdchaginmakecolor(char **c, int fg, int bg, Str *v) 257316958Sdchagin{ 258316958Sdchagin int l; 259316958Sdchagin if (fg & 0x80) 260316958Sdchagin l = xsnprintf(*c, 12, "%.2d;%.2d;%.2d;%.2d", ANSI_BOLD_ON, 261316958Sdchagin fg & ~TCSH_BOLD, (10 + bg) & ~TCSH_BOLD, ANSI_BOLD_OFF); 262316958Sdchagin l = xsnprintf(*c, 6, "%.2d;%.2d", 263316958Sdchagin fg & ~TCSH_BOLD, (10 + bg) & ~TCSH_BOLD); 264316958Sdchagin 265316958Sdchagin v->s = *c; 266316958Sdchagin v->len = l; 267316958Sdchagin *c += l + 1; 268316958Sdchagin} 269316958Sdchagin 270316958Sdchagin/* parseLSCOLORS(): 271316958Sdchagin * Parse the LSCOLORS environment variable 272316958Sdchagin */ 273316958Sdchaginstatic const Char *xv; /* setjmp clobbering */ 274316958Sdchaginvoid 275316958SdchaginparseLSCOLORS(const Char *value) 276316958Sdchagin{ 277316958Sdchagin size_t i, len, clen; 278316958Sdchagin jmp_buf_t osetexit; 279316958Sdchagin size_t omark; 280316958Sdchagin xv = value; 281316958Sdchagin 282316958Sdchagin if (xv == NULL) { 283316958Sdchagin init(0, 0); 284316958Sdchagin return; 285316958Sdchagin } 286316958Sdchagin 287316958Sdchagin len = Strlen(xv); 288316958Sdchagin len >>= 1; 289316958Sdchagin clen = len * 12; /* "??;??;??;??\0" */ 290316958Sdchagin init(clen, 0); 291316958Sdchagin 292316958Sdchagin /* Prevent from crashing if unknown parameters are given. */ 293316958Sdchagin omark = cleanup_push_mark(); 294316958Sdchagin getexit(osetexit); 295316958Sdchagin 296316958Sdchagin /* init pointers */ 297316958Sdchagin 298316958Sdchagin if (setexit() == 0) { 299316958Sdchagin const Char *v = xv; 300316958Sdchagin char *c = colors; 301316958Sdchagin 302316958Sdchagin int fg, bg; 303316958Sdchagin for (i = 0; i < len; i++) { 304316958Sdchagin fg = color(*v++); 305316958Sdchagin if (fg == -1) 306316958Sdchagin stderror(ERR_BADCOLORVAR, v[-1], '?'); 307316958Sdchagin 308316958Sdchagin bg = color(*v++); 309316958Sdchagin if (bg == -1) 310316958Sdchagin stderror(ERR_BADCOLORVAR, '?', v[-1]); 311316958Sdchagin makecolor(&c, fg, bg, &variables[map[i]].color); 312316958Sdchagin } 313316958Sdchagin 314316958Sdchagin } 315316958Sdchagin cleanup_pop_mark(omark); 316316958Sdchagin resexit(osetexit); 317316958Sdchagin} 318316958Sdchagin 31959243Sobrien/* parseLS_COLORS(): 32059243Sobrien * Parse the LS_COLORS environment variable 32159243Sobrien */ 32259243Sobrienvoid 323167465SmpparseLS_COLORS(const Char *value) 32459243Sobrien{ 325145479Smp size_t i, len; 326167465Smp const Char *v; /* pointer in value */ 32759243Sobrien char *c; /* pointer in colors */ 328145479Smp Extension *volatile e; /* pointer in extensions */ 32959415Sobrien jmp_buf_t osetexit; 330167465Smp size_t omark; 33159243Sobrien 332100616Smp (void) &e; 333100616Smp 33459243Sobrien 335316958Sdchagin if (value == NULL) { 336316958Sdchagin init(0, 0); 33759243Sobrien return; 338316958Sdchagin } 33959243Sobrien 34059243Sobrien len = Strlen(value); 34159243Sobrien /* allocate memory */ 34259243Sobrien i = 1; 34359243Sobrien for (v = value; *v; v++) 34459243Sobrien if ((*v & CHAR) == ':') 34559243Sobrien i++; 34659243Sobrien 347316958Sdchagin init(len, i); 348316958Sdchagin 34959243Sobrien /* init pointers */ 35059243Sobrien v = value; 35159243Sobrien c = colors; 352316958Sdchagin e = extensions; 35359243Sobrien 35459415Sobrien /* Prevent from crashing if unknown parameters are given. */ 35559415Sobrien 356167465Smp omark = cleanup_push_mark(); 35759415Sobrien getexit(osetexit); 35859415Sobrien 35959415Sobrien if (setexit() == 0) { 360167465Smp 361316958Sdchagin /* parse */ 362316958Sdchagin while (*v) { 363316958Sdchagin switch (*v & CHAR) { 364316958Sdchagin case ':': 36559243Sobrien v++; 36659243Sobrien continue; 36759243Sobrien 368316958Sdchagin case '*': /* :*ext=color: */ 369316958Sdchagin v++; 370316958Sdchagin if (getstring(&c, &v, &e->extension, '=') && 371316958Sdchagin 0 < e->extension.len) { 372316958Sdchagin v++; 373316958Sdchagin getstring(&c, &v, &e->color, ':'); 374316958Sdchagin e++; 37559243Sobrien continue; 37659243Sobrien } 377316958Sdchagin break; 378316958Sdchagin 379316958Sdchagin default: /* :vl=color: */ 380316958Sdchagin if (v[0] && v[1] && (v[2] & CHAR) == '=') { 381316958Sdchagin for (i = 0; i < nvariables; i++) 382316958Sdchagin if ((Char)variables[i].variable[0] == (v[0] & CHAR) && 383316958Sdchagin (Char)variables[i].variable[1] == (v[1] & CHAR)) 384316958Sdchagin break; 385316958Sdchagin if (i < nvariables) { 386316958Sdchagin v += 3; 387316958Sdchagin getstring(&c, &v, &variables[i].color, ':'); 388316958Sdchagin continue; 389316958Sdchagin } 390316958Sdchagin else 391316958Sdchagin stderror(ERR_BADCOLORVAR, v[0], v[1]); 392316958Sdchagin } 393316958Sdchagin break; 39459243Sobrien } 395316958Sdchagin while (*v && (*v & CHAR) != ':') 396316958Sdchagin v++; 39759243Sobrien } 39859243Sobrien } 39959243Sobrien 400167465Smp cleanup_pop_mark(omark); 40159415Sobrien resexit(osetexit); 40259415Sobrien 403167465Smp nextensions = e - extensions; 40459243Sobrien} 40559243Sobrien 40659243Sobrien/* put_color(): 40759243Sobrien */ 40859243Sobrienstatic void 409316958Sdchaginput_color(const Str *colorp) 41059243Sobrien{ 41159243Sobrien size_t i; 412316958Sdchagin const char *c = colorp->s; 413167465Smp int original_output_raw = output_raw; 41459243Sobrien 41559243Sobrien output_raw = TRUE; 416167465Smp cleanup_push(&original_output_raw, output_raw_restore); 417316958Sdchagin for (i = colorp->len; 0 < i; i--) 41859243Sobrien xputchar(*c++); 419167465Smp cleanup_until(&original_output_raw); 42059243Sobrien} 42159243Sobrien 42259243Sobrien 42359243Sobrien/* print_color(): 42459243Sobrien */ 42559243Sobrienstatic void 426167465Smpprint_color(const Char *fname, size_t len, Char suffix) 42759243Sobrien{ 428145479Smp size_t i; 42959243Sobrien char *filename = short2str(fname); 43059243Sobrien char *last = filename + len; 431316958Sdchagin Str *colorp = &variables[VFile].color; 43259243Sobrien 43359243Sobrien switch (suffix) { 43459243Sobrien case '>': /* File is a symbolic link pointing to 43559243Sobrien * a directory */ 436316958Sdchagin colorp = &variables[VDir].color; 437167465Smp break; 43859243Sobrien case '+': /* File is a hidden directory [aix] or 43959243Sobrien * context dependent [hpux] */ 44059243Sobrien case ':': /* File is network special [hpux] */ 441167465Smp break; 44259243Sobrien default: 44359243Sobrien for (i = 0; i < nvariables; i++) 44459243Sobrien if (variables[i].suffix != NOS && 445145479Smp (Char)variables[i].suffix == suffix) { 446316958Sdchagin colorp = &variables[i].color; 44759243Sobrien break; 44859243Sobrien } 44959243Sobrien if (i == nvariables) { 45059243Sobrien for (i = 0; i < nextensions; i++) 451167465Smp if (len >= extensions[i].extension.len 452167465Smp && strncmp(last - extensions[i].extension.len, 453167465Smp extensions[i].extension.s, 454167465Smp extensions[i].extension.len) == 0) { 455316958Sdchagin colorp = &extensions[i].color; 45659243Sobrien break; 45759243Sobrien } 45859243Sobrien } 45959243Sobrien break; 46059243Sobrien } 46159243Sobrien 46259243Sobrien put_color(&variables[VLeft].color); 463316958Sdchagin put_color(colorp); 46459243Sobrien put_color(&variables[VRight].color); 46559243Sobrien} 46659243Sobrien 46759243Sobrien 46859243Sobrien/* print_with_color(): 46959243Sobrien */ 47059243Sobrienvoid 471167465Smpprint_with_color(const Char *filename, size_t len, Char suffix) 47259243Sobrien{ 47359243Sobrien if (color_context_lsmF && 47459243Sobrien (haderr ? (didfds ? is2atty : isdiagatty) : 47559243Sobrien (didfds ? is1atty : isoutatty))) { 47659243Sobrien print_color(filename, len, suffix); 47759243Sobrien xprintf("%S", filename); 47859243Sobrien if (0 < variables[VEnd].color.len) 47959243Sobrien put_color(&variables[VEnd].color); 48059243Sobrien else { 48159243Sobrien put_color(&variables[VLeft].color); 48259243Sobrien put_color(&variables[VNormal].color); 48359243Sobrien put_color(&variables[VRight].color); 48459243Sobrien } 48559243Sobrien } 48659243Sobrien else 487145479Smp xprintf("%S", filename); 488145479Smp xputwchar(suffix); 48959243Sobrien} 49059243Sobrien 49159243Sobrien 49259243Sobrien#endif /* COLOR_LS_F */ 493