2023-03-10 17:49:03 +08:00
|
|
|
#include "logo/logo.h"
|
2023-01-28 12:40:12 +01:00
|
|
|
#include "common/io/io.h"
|
2022-07-25 13:15:01 +02:00
|
|
|
#include "common/printing.h"
|
2022-09-04 13:33:18 +02:00
|
|
|
#include "detection/os/os.h"
|
2022-10-08 16:04:55 +08:00
|
|
|
#include "detection/terminalshell/terminalshell.h"
|
2022-12-06 17:03:31 +08:00
|
|
|
#include "util/textModifier.h"
|
2022-04-02 14:35:43 +02:00
|
|
|
|
|
|
|
|
#include <ctype.h>
|
2022-06-08 10:59:33 +02:00
|
|
|
#include <string.h>
|
2022-04-02 14:35:43 +02:00
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
static void ffLogoPrintCharsRaw(const char* data, size_t length)
|
2023-01-01 12:37:39 +08:00
|
|
|
{
|
2023-06-24 10:59:53 +08:00
|
|
|
FFLogoOptions* options = &instance.config.logo;
|
2023-01-01 12:37:39 +08:00
|
|
|
fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout);
|
2023-03-10 17:49:03 +08:00
|
|
|
ffPrintCharTimes('\n', options->paddingTop);
|
|
|
|
|
ffPrintCharTimes(' ', options->paddingLeft);
|
2023-01-01 12:37:39 +08:00
|
|
|
fwrite(data, length, 1, stdout);
|
2023-06-24 10:59:53 +08:00
|
|
|
instance.state.logoHeight = options->paddingTop + options->height;
|
|
|
|
|
instance.state.logoWidth = options->paddingLeft + options->width + options->paddingRight;
|
|
|
|
|
printf("\033[9999999D\n\033[%uA", instance.state.logoHeight);
|
2023-01-01 12:37:39 +08:00
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
void ffLogoPrintChars(const char* data, bool doColorReplacement)
|
2022-04-02 14:35:43 +02:00
|
|
|
{
|
2023-06-24 10:59:53 +08:00
|
|
|
FFLogoOptions* options = &instance.config.logo;
|
2023-03-10 17:49:03 +08:00
|
|
|
|
2022-04-02 14:35:43 +02:00
|
|
|
uint32_t currentlineLength = 0;
|
|
|
|
|
|
|
|
|
|
fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout);
|
2023-03-10 17:49:03 +08:00
|
|
|
ffPrintCharTimes('\n', options->paddingTop);
|
|
|
|
|
ffPrintCharTimes(' ', options->paddingLeft);
|
2022-04-02 14:35:43 +02:00
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
instance.state.logoHeight = options->paddingTop;
|
2023-01-01 17:24:37 +08:00
|
|
|
|
2022-04-02 14:35:43 +02:00
|
|
|
//Use logoColor[0] as the default color
|
|
|
|
|
if(doColorReplacement)
|
2023-03-10 17:49:03 +08:00
|
|
|
ffPrintColor(&options->colors[0]);
|
2022-04-02 14:35:43 +02:00
|
|
|
|
|
|
|
|
while(*data != '\0')
|
|
|
|
|
{
|
|
|
|
|
//We are at the end of a line. Print paddings and update max line length
|
|
|
|
|
if(*data == '\n' || (*data == '\r' && *(data + 1) == '\n'))
|
|
|
|
|
{
|
2023-03-10 17:49:03 +08:00
|
|
|
ffPrintCharTimes(' ', options->paddingRight);
|
2022-04-02 14:35:43 +02:00
|
|
|
|
|
|
|
|
//We have \r\n, skip the \r
|
|
|
|
|
if(*data == '\r')
|
|
|
|
|
++data;
|
|
|
|
|
|
|
|
|
|
putchar('\n');
|
|
|
|
|
++data;
|
|
|
|
|
|
2023-03-10 17:49:03 +08:00
|
|
|
ffPrintCharTimes(' ', options->paddingLeft);
|
2022-04-02 14:35:43 +02:00
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
if(currentlineLength > instance.state.logoWidth)
|
|
|
|
|
instance.state.logoWidth = currentlineLength;
|
2022-04-02 14:35:43 +02:00
|
|
|
|
|
|
|
|
currentlineLength = 0;
|
2023-06-24 10:59:53 +08:00
|
|
|
++instance.state.logoHeight;
|
2022-04-02 14:35:43 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Always print tabs as 4 spaces, to have consistent spacing
|
|
|
|
|
if(*data == '\t')
|
|
|
|
|
{
|
2022-04-08 15:50:49 +02:00
|
|
|
ffPrintCharTimes(' ', 4);
|
2022-04-02 14:35:43 +02:00
|
|
|
++data;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//We have an escape sequence direclty as bytes. We print it, but don't increase the line length
|
|
|
|
|
if(*data == '\033' && *(data + 1) == '[')
|
|
|
|
|
{
|
|
|
|
|
const char* start = data;
|
|
|
|
|
|
|
|
|
|
fputs("\033[", stdout);
|
|
|
|
|
data += 2;
|
|
|
|
|
|
|
|
|
|
while(isdigit(*data) || *data == ';')
|
|
|
|
|
putchar(*data++); // number
|
|
|
|
|
|
|
|
|
|
//We have a valid control sequence, print it and continue with next char
|
|
|
|
|
if(isascii(*data))
|
|
|
|
|
{
|
|
|
|
|
putchar(*data++); // single letter, end of control sequence
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Invalid control sequence, try to get most accurate length
|
|
|
|
|
currentlineLength += (uint32_t) (data - start - 1); //-1 for \033 which for sure doesn't take any space
|
|
|
|
|
|
|
|
|
|
//Don't continue here, print the char after the letters with the unicode printing
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//We have a fastfetch color placeholder. Replace it with the esacape sequence, don't increase the line length
|
|
|
|
|
if(doColorReplacement && *data == '$')
|
|
|
|
|
{
|
|
|
|
|
++data;
|
|
|
|
|
|
|
|
|
|
//If we have $$, or $\0, print it as single $
|
|
|
|
|
if(*data == '$' || *data == '\0')
|
|
|
|
|
{
|
|
|
|
|
putchar('$');
|
|
|
|
|
++currentlineLength;
|
|
|
|
|
++data;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Map the number to an array index, so that '1' -> 0, '2' -> 1, etc.
|
|
|
|
|
int index = ((int) *data) - 49;
|
|
|
|
|
|
|
|
|
|
//If the index is valid, print the color. Otherwise continue as normal
|
|
|
|
|
if(index < 0 || index >= FASTFETCH_LOGO_MAX_COLORS)
|
|
|
|
|
{
|
|
|
|
|
putchar('$');
|
|
|
|
|
++currentlineLength;
|
|
|
|
|
//Don't continue here, we want to print the current char as unicode
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2023-03-10 17:49:03 +08:00
|
|
|
ffPrintColor(&options->colors[index]);
|
2022-04-02 14:35:43 +02:00
|
|
|
++data;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Do the printing, respecting unicode
|
|
|
|
|
|
|
|
|
|
++currentlineLength;
|
|
|
|
|
|
|
|
|
|
int codepoint = (unsigned char) *data;
|
|
|
|
|
uint8_t bytes;
|
|
|
|
|
|
|
|
|
|
if(codepoint <= 127)
|
|
|
|
|
bytes = 1;
|
|
|
|
|
else if((codepoint & 0xE0) == 0xC0)
|
|
|
|
|
bytes = 2;
|
|
|
|
|
else if((codepoint & 0xF0) == 0xE0)
|
|
|
|
|
bytes = 3;
|
|
|
|
|
else if((codepoint & 0xF8) == 0xF0)
|
|
|
|
|
bytes = 4;
|
|
|
|
|
else
|
|
|
|
|
bytes = 1; //Invalid utf8, print it as is, byte by byte
|
|
|
|
|
|
|
|
|
|
for(uint8_t i = 0; i < bytes; ++i)
|
|
|
|
|
{
|
|
|
|
|
if(*data == '\0')
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
putchar(*data++);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-10 17:49:03 +08:00
|
|
|
ffPrintCharTimes(' ', options->paddingRight);
|
2022-04-02 14:35:43 +02:00
|
|
|
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
|
|
|
|
|
|
|
|
|
//Happens if the last line is the longest
|
2023-06-24 10:59:53 +08:00
|
|
|
if(currentlineLength > instance.state.logoWidth)
|
|
|
|
|
instance.state.logoWidth = currentlineLength;
|
2022-04-02 14:35:43 +02:00
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
instance.state.logoWidth += options->paddingLeft + options->paddingRight;
|
2022-04-02 14:35:43 +02:00
|
|
|
|
2022-04-06 14:02:05 +02:00
|
|
|
//Go to the leftmost position
|
|
|
|
|
fputs("\033[9999999D", stdout);
|
2022-04-02 14:35:43 +02:00
|
|
|
|
|
|
|
|
//If the logo height is > 1, go up the height
|
2023-06-24 10:59:53 +08:00
|
|
|
if(instance.state.logoHeight > 0)
|
|
|
|
|
printf("\033[%uA", instance.state.logoHeight);
|
2022-04-02 14:35:43 +02:00
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
static void logoApplyColors(const FFlogo* logo)
|
2022-04-02 14:35:43 +02:00
|
|
|
{
|
2023-06-24 10:59:53 +08:00
|
|
|
if(instance.config.colorKeys.length == 0)
|
|
|
|
|
ffStrbufAppendS(&instance.config.colorKeys, logo->colorKeys);
|
2022-09-07 19:50:10 +02:00
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
if(instance.config.colorTitle.length == 0)
|
|
|
|
|
ffStrbufAppendS(&instance.config.colorTitle, logo->colorTitle);
|
2022-06-08 10:59:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool logoHasName(const FFlogo* logo, const char* name)
|
|
|
|
|
{
|
|
|
|
|
const char** logoName = logo->names;
|
|
|
|
|
|
|
|
|
|
while(*logoName != NULL)
|
|
|
|
|
{
|
|
|
|
|
if(strcasecmp(*logoName, name) == 0)
|
|
|
|
|
return true;
|
|
|
|
|
++logoName;
|
|
|
|
|
}
|
2022-04-02 14:35:43 +02:00
|
|
|
|
2022-06-08 10:59:33 +02:00
|
|
|
return false;
|
2022-04-02 14:35:43 +02:00
|
|
|
}
|
|
|
|
|
|
2022-06-08 10:59:33 +02:00
|
|
|
static const FFlogo* logoGetBuiltin(const char* name)
|
2022-04-02 14:35:43 +02:00
|
|
|
{
|
2022-06-08 10:59:33 +02:00
|
|
|
GetLogoMethod* methods = ffLogoBuiltinGetAll();
|
|
|
|
|
|
|
|
|
|
while(*methods != NULL)
|
2022-04-29 21:52:42 +02:00
|
|
|
{
|
2022-06-08 10:59:33 +02:00
|
|
|
const FFlogo* logo = (*methods)();
|
|
|
|
|
|
|
|
|
|
if(logoHasName(logo, name))
|
|
|
|
|
return logo;
|
|
|
|
|
|
|
|
|
|
++methods;
|
2022-04-29 21:52:42 +02:00
|
|
|
}
|
2022-04-29 21:44:32 +02:00
|
|
|
|
2022-06-08 10:59:33 +02:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2022-04-29 21:44:32 +02:00
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
static const FFlogo* logoGetBuiltinDetected(void)
|
2022-06-08 10:59:33 +02:00
|
|
|
{
|
2023-06-24 10:59:53 +08:00
|
|
|
const FFOSResult* os = ffDetectOS();
|
2022-04-29 21:44:32 +02:00
|
|
|
|
2022-06-08 10:59:33 +02:00
|
|
|
const FFlogo* logo = logoGetBuiltin(os->id.chars);
|
|
|
|
|
if(logo != NULL)
|
|
|
|
|
return logo;
|
2022-04-29 21:44:32 +02:00
|
|
|
|
2022-06-08 10:59:33 +02:00
|
|
|
logo = logoGetBuiltin(os->name.chars);
|
|
|
|
|
if(logo != NULL)
|
|
|
|
|
return logo;
|
|
|
|
|
|
|
|
|
|
logo = logoGetBuiltin(os->prettyName.chars);
|
|
|
|
|
if(logo != NULL)
|
|
|
|
|
return logo;
|
|
|
|
|
|
|
|
|
|
logo = logoGetBuiltin(os->idLike.chars);
|
|
|
|
|
if(logo != NULL)
|
|
|
|
|
return logo;
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
logo = logoGetBuiltin(instance.state.platform.systemName.chars);
|
2022-06-08 10:59:33 +02:00
|
|
|
if(logo != NULL)
|
|
|
|
|
return logo;
|
|
|
|
|
|
|
|
|
|
return ffLogoBuiltinGetUnknown();
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
static inline void logoApplyColorsDetected(void)
|
2022-06-08 10:59:33 +02:00
|
|
|
{
|
2023-06-24 10:59:53 +08:00
|
|
|
logoApplyColors(logoGetBuiltinDetected());
|
2022-06-08 10:59:33 +02:00
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
static void logoPrintStruct(const FFlogo* logo)
|
2022-06-08 10:59:33 +02:00
|
|
|
{
|
2023-06-24 10:59:53 +08:00
|
|
|
logoApplyColors(logo);
|
2022-06-08 10:59:33 +02:00
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
FFLogoOptions* options = &instance.config.logo;
|
2023-03-10 17:49:03 +08:00
|
|
|
|
2022-06-08 10:59:33 +02:00
|
|
|
const char** colors = logo->builtinColors;
|
|
|
|
|
for(int i = 0; *colors != NULL && i < FASTFETCH_LOGO_MAX_COLORS; i++, colors++)
|
|
|
|
|
{
|
2023-03-10 17:49:03 +08:00
|
|
|
if(options->colors[i].length == 0)
|
|
|
|
|
ffStrbufAppendS(&options->colors[i], *colors);
|
2022-06-08 10:59:33 +02:00
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
ffLogoPrintChars(logo->data, true);
|
2022-06-08 10:59:33 +02:00
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
static void logoPrintNone(void)
|
2022-09-27 15:02:35 +02:00
|
|
|
{
|
2023-06-24 10:59:53 +08:00
|
|
|
logoApplyColorsDetected();
|
|
|
|
|
instance.state.logoHeight = 0;
|
|
|
|
|
instance.state.logoWidth = 0;
|
2022-09-27 15:02:35 +02:00
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
static bool logoPrintBuiltinIfExists(const char* name)
|
2022-06-08 10:59:33 +02:00
|
|
|
{
|
2022-09-27 15:02:35 +02:00
|
|
|
if(strcasecmp(name, "none") == 0)
|
|
|
|
|
{
|
2023-06-24 10:59:53 +08:00
|
|
|
logoPrintNone();
|
2022-09-27 15:02:35 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-08 10:59:33 +02:00
|
|
|
const FFlogo* logo = logoGetBuiltin(name);
|
|
|
|
|
if(logo == NULL)
|
|
|
|
|
return false;
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
logoPrintStruct(logo);
|
2022-09-27 15:02:35 +02:00
|
|
|
|
2022-06-08 10:59:33 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
static inline void logoPrintDetected(void)
|
2022-06-08 10:59:33 +02:00
|
|
|
{
|
2023-06-24 10:59:53 +08:00
|
|
|
logoPrintStruct(logoGetBuiltinDetected());
|
2022-06-08 10:59:33 +02:00
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
static bool logoPrintData(bool doColorReplacement) {
|
|
|
|
|
FFLogoOptions* options = &instance.config.logo;
|
2023-03-10 17:49:03 +08:00
|
|
|
if(options->source.length == 0)
|
2023-01-28 11:14:16 +01:00
|
|
|
return false;
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
ffLogoPrintChars(options->source.chars, doColorReplacement);
|
|
|
|
|
logoApplyColorsDetected();
|
2023-01-28 11:14:16 +01:00
|
|
|
return true;
|
2022-12-12 13:43:10 +01:00
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
static void updateLogoPath(void)
|
2023-01-08 12:30:36 +01:00
|
|
|
{
|
2023-06-24 10:59:53 +08:00
|
|
|
FFLogoOptions* options = &instance.config.logo;
|
2023-03-10 17:49:03 +08:00
|
|
|
|
|
|
|
|
if(ffPathExists(options->source.chars, FF_PATHTYPE_FILE))
|
2023-01-28 11:14:16 +01:00
|
|
|
return;
|
2023-01-08 12:30:36 +01:00
|
|
|
|
2023-04-15 15:29:54 +08:00
|
|
|
FF_STRBUF_AUTO_DESTROY fullPath = ffStrbufCreate();
|
2023-01-08 12:30:36 +01:00
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
FF_LIST_FOR_EACH(FFstrbuf, dataDir, instance.state.platform.dataDirs)
|
2023-01-08 12:30:36 +01:00
|
|
|
{
|
|
|
|
|
//We need to copy it, because multiple threads might be using dataDirs at the same time
|
|
|
|
|
ffStrbufSet(&fullPath, dataDir);
|
|
|
|
|
ffStrbufAppendS(&fullPath, "fastfetch/logos/");
|
2023-03-10 17:49:03 +08:00
|
|
|
ffStrbufAppend(&fullPath, &options->source);
|
2023-01-08 12:30:36 +01:00
|
|
|
|
2023-01-28 11:52:23 +01:00
|
|
|
if(ffPathExists(fullPath.chars, FF_PATHTYPE_FILE))
|
2023-01-08 12:30:36 +01:00
|
|
|
{
|
2023-03-10 17:49:03 +08:00
|
|
|
ffStrbufSet(&options->source, &fullPath);
|
2023-01-28 11:14:16 +01:00
|
|
|
break;
|
2023-01-08 12:30:36 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
static bool logoPrintFileIfExists(bool doColorReplacement, bool raw)
|
2022-06-08 10:59:33 +02:00
|
|
|
{
|
2023-06-24 10:59:53 +08:00
|
|
|
FFLogoOptions* options = &instance.config.logo;
|
2023-03-10 17:49:03 +08:00
|
|
|
|
2023-04-15 15:29:54 +08:00
|
|
|
FF_STRBUF_AUTO_DESTROY content = ffStrbufCreate();
|
2022-06-08 10:59:33 +02:00
|
|
|
|
2023-03-10 17:49:03 +08:00
|
|
|
if(!ffAppendFileBuffer(options->source.chars, &content))
|
2022-06-08 10:59:33 +02:00
|
|
|
{
|
2023-01-01 12:37:39 +08:00
|
|
|
fputs("Logo: Failed to load file content from logo source\n", stderr);
|
2022-06-08 10:59:33 +02:00
|
|
|
return false;
|
2022-04-02 14:35:43 +02:00
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
logoApplyColorsDetected();
|
2023-01-01 12:37:39 +08:00
|
|
|
if(raw)
|
2023-06-24 10:59:53 +08:00
|
|
|
ffLogoPrintCharsRaw(content.chars, content.length);
|
2023-01-01 12:37:39 +08:00
|
|
|
else
|
2023-06-24 10:59:53 +08:00
|
|
|
ffLogoPrintChars(content.chars, doColorReplacement);
|
2023-04-15 15:29:54 +08:00
|
|
|
|
2022-06-08 10:59:33 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
static bool logoPrintImageIfExists(FFLogoType logo, bool printError)
|
2022-06-08 10:59:33 +02:00
|
|
|
{
|
2023-06-24 10:59:53 +08:00
|
|
|
if(!ffLogoPrintImageIfExists(logo, printError))
|
2022-06-08 10:59:33 +02:00
|
|
|
return false;
|
2022-04-29 21:44:32 +02:00
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
logoApplyColorsDetected();
|
2022-06-08 10:59:33 +02:00
|
|
|
return true;
|
2022-04-02 14:35:43 +02:00
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
static bool logoTryKnownType(void)
|
2022-04-02 14:35:43 +02:00
|
|
|
{
|
2023-06-24 10:59:53 +08:00
|
|
|
FFLogoOptions* options = &instance.config.logo;
|
2023-03-10 17:49:03 +08:00
|
|
|
|
|
|
|
|
if(options->type == FF_LOGO_TYPE_NONE)
|
2023-01-28 11:14:16 +01:00
|
|
|
{
|
2023-06-24 10:59:53 +08:00
|
|
|
logoApplyColorsDetected();
|
2023-01-28 11:14:16 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
2022-06-08 10:59:33 +02:00
|
|
|
|
2023-03-10 17:49:03 +08:00
|
|
|
if(options->type == FF_LOGO_TYPE_BUILTIN)
|
2023-06-24 10:59:53 +08:00
|
|
|
return logoPrintBuiltinIfExists(options->source.chars);
|
2023-01-28 11:14:16 +01:00
|
|
|
|
2023-03-10 17:49:03 +08:00
|
|
|
if(options->type == FF_LOGO_TYPE_DATA)
|
2023-06-24 10:59:53 +08:00
|
|
|
return logoPrintData(true);
|
2023-01-28 11:14:16 +01:00
|
|
|
|
2023-03-10 17:49:03 +08:00
|
|
|
if(options->type == FF_LOGO_TYPE_DATA_RAW)
|
2023-06-24 10:59:53 +08:00
|
|
|
return logoPrintData(false);
|
2023-01-28 11:14:16 +01:00
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
updateLogoPath(); //We sure have a file, resolve relative paths
|
2023-01-28 11:14:16 +01:00
|
|
|
|
2023-03-10 17:49:03 +08:00
|
|
|
if(options->type == FF_LOGO_TYPE_FILE)
|
2023-06-24 10:59:53 +08:00
|
|
|
return logoPrintFileIfExists(true, false);
|
2023-01-28 11:14:16 +01:00
|
|
|
|
2023-03-10 17:49:03 +08:00
|
|
|
if(options->type == FF_LOGO_TYPE_FILE_RAW)
|
2023-06-24 10:59:53 +08:00
|
|
|
return logoPrintFileIfExists(false, false);
|
2023-01-28 11:14:16 +01:00
|
|
|
|
2023-03-10 17:49:03 +08:00
|
|
|
if(options->type == FF_LOGO_TYPE_IMAGE_RAW)
|
2023-01-01 12:37:39 +08:00
|
|
|
{
|
2023-03-10 17:49:03 +08:00
|
|
|
if(options->width == 0 || options->height == 0)
|
2023-01-01 12:37:39 +08:00
|
|
|
{
|
|
|
|
|
fputs("both `--logo-width` and `--logo-height` must be specified\n", stderr);
|
2023-01-28 11:14:16 +01:00
|
|
|
return false;
|
2023-01-01 12:37:39 +08:00
|
|
|
}
|
2023-01-28 11:14:16 +01:00
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
return logoPrintFileIfExists(false, true);
|
2023-01-01 12:37:39 +08:00
|
|
|
}
|
2022-06-08 10:59:33 +02:00
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
return logoPrintImageIfExists(options->type, true);
|
2023-01-28 11:14:16 +01:00
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
static void logoPrintKnownType(void)
|
2023-01-28 11:14:16 +01:00
|
|
|
{
|
2023-06-24 10:59:53 +08:00
|
|
|
if(!logoTryKnownType())
|
|
|
|
|
logoPrintDetected();
|
2022-06-08 10:59:33 +02:00
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
void ffLogoPrint(void)
|
2022-06-08 10:59:33 +02:00
|
|
|
{
|
|
|
|
|
//In pipe mode, we don't have a logo or padding.
|
|
|
|
|
//We also don't need to set main color, because it won't be printed anyway.
|
|
|
|
|
//So we can return quickly here.
|
2023-06-24 10:59:53 +08:00
|
|
|
if(instance.config.pipe)
|
2022-06-06 14:02:21 +02:00
|
|
|
{
|
2023-06-24 10:59:53 +08:00
|
|
|
instance.state.logoHeight = 0;
|
|
|
|
|
instance.state.logoWidth = 0;
|
2022-06-06 14:02:21 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
const FFLogoOptions* options = &instance.config.logo;
|
2023-03-10 17:49:03 +08:00
|
|
|
|
2023-06-25 21:22:44 +08:00
|
|
|
if (options->type == FF_LOGO_TYPE_NONE)
|
|
|
|
|
{
|
|
|
|
|
logoPrintNone();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-08 10:59:33 +02:00
|
|
|
//If the source is not set, we can directly print the detected logo.
|
2023-03-10 17:49:03 +08:00
|
|
|
if(options->source.length == 0)
|
2022-04-22 15:49:50 +02:00
|
|
|
{
|
2023-06-24 10:59:53 +08:00
|
|
|
logoPrintDetected();
|
2022-06-08 10:59:33 +02:00
|
|
|
return;
|
2022-04-22 15:49:50 +02:00
|
|
|
}
|
2022-06-08 10:59:33 +02:00
|
|
|
|
|
|
|
|
//If the source and source type is set to something else than auto, always print with the set type.
|
2023-03-10 17:49:03 +08:00
|
|
|
if(options->source.length > 0 && options->type != FF_LOGO_TYPE_AUTO)
|
2022-04-11 16:19:02 +02:00
|
|
|
{
|
2023-06-24 10:59:53 +08:00
|
|
|
logoPrintKnownType();
|
2022-06-08 10:59:33 +02:00
|
|
|
return;
|
2022-04-11 16:19:02 +02:00
|
|
|
}
|
2022-04-02 14:35:43 +02:00
|
|
|
|
2022-06-08 10:59:33 +02:00
|
|
|
//If source matches the name of a builtin logo, print it and return.
|
2023-06-24 10:59:53 +08:00
|
|
|
if(logoPrintBuiltinIfExists(options->source.chars))
|
2022-06-08 10:59:33 +02:00
|
|
|
return;
|
|
|
|
|
|
2023-01-28 11:14:16 +01:00
|
|
|
//Make sure the logo path is set correctly.
|
2023-06-24 10:59:53 +08:00
|
|
|
updateLogoPath();
|
2023-01-28 11:14:16 +01:00
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
const FFTerminalShellResult* terminalShell = ffDetectTerminalShell();
|
2022-06-08 10:59:33 +02:00
|
|
|
|
|
|
|
|
//Terminal emulators that support kitty graphics protocol.
|
|
|
|
|
bool supportsKitty =
|
|
|
|
|
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "kitty") == 0 ||
|
|
|
|
|
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "konsole") == 0 ||
|
|
|
|
|
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "wezterm") == 0 ||
|
|
|
|
|
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "wayst") == 0;
|
2022-06-06 14:02:21 +02:00
|
|
|
|
2022-06-08 10:59:33 +02:00
|
|
|
//Try to load the logo as an image. If it succeeds, print it and return.
|
2023-06-24 10:59:53 +08:00
|
|
|
if(logoPrintImageIfExists(supportsKitty ? FF_LOGO_TYPE_IMAGE_KITTY : FF_LOGO_TYPE_IMAGE_CHAFA, false))
|
2022-06-08 10:59:33 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
//Try to load the logo as a file. If it succeeds, print it and return.
|
2023-06-24 10:59:53 +08:00
|
|
|
if(logoPrintFileIfExists(true, false))
|
2022-06-08 10:59:33 +02:00
|
|
|
return;
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
logoPrintDetected();
|
2022-06-08 10:59:33 +02:00
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
void ffLogoPrintLine(void)
|
2022-04-06 14:02:05 +02:00
|
|
|
{
|
2023-06-24 10:59:53 +08:00
|
|
|
if(instance.state.logoWidth > 0)
|
|
|
|
|
printf("\033[%uC", instance.state.logoWidth);
|
2022-06-06 14:02:21 +02:00
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
++instance.state.keysHeight;
|
2022-04-06 14:02:05 +02:00
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
void ffLogoPrintRemaining(void)
|
2022-04-02 14:35:43 +02:00
|
|
|
{
|
2023-06-24 10:59:53 +08:00
|
|
|
while(instance.state.keysHeight <= instance.state.logoHeight)
|
2022-04-06 14:02:05 +02:00
|
|
|
{
|
2023-06-24 10:59:53 +08:00
|
|
|
ffLogoPrintLine();
|
2022-04-06 14:02:05 +02:00
|
|
|
putchar('\n');
|
|
|
|
|
}
|
2022-04-02 14:35:43 +02:00
|
|
|
}
|
2022-06-08 10:59:33 +02:00
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
void ffLogoBuiltinPrint(void)
|
2022-06-08 10:59:33 +02:00
|
|
|
{
|
|
|
|
|
GetLogoMethod* methods = ffLogoBuiltinGetAll();
|
2023-06-24 10:59:53 +08:00
|
|
|
FFLogoOptions* options = &instance.config.logo;
|
2022-06-08 10:59:33 +02:00
|
|
|
|
|
|
|
|
while(*methods != NULL)
|
|
|
|
|
{
|
|
|
|
|
const FFlogo* logo = (*methods)();
|
|
|
|
|
printf("\033[%sm%s:\033[0m\n", logo->builtinColors[0], logo->names[0]);
|
2023-06-24 10:59:53 +08:00
|
|
|
logoPrintStruct(logo);
|
|
|
|
|
ffLogoPrintRemaining();
|
2022-06-08 10:59:33 +02:00
|
|
|
|
2022-06-08 11:28:26 +02:00
|
|
|
//reset everything
|
2023-06-24 10:59:53 +08:00
|
|
|
instance.state.logoHeight = 0;
|
|
|
|
|
instance.state.keysHeight = 0;
|
2022-06-08 10:59:33 +02:00
|
|
|
for(uint8_t i = 0; i < FASTFETCH_LOGO_MAX_COLORS; i++)
|
2023-03-10 17:49:03 +08:00
|
|
|
ffStrbufClear(&options->colors[i]);
|
2022-06-08 10:59:33 +02:00
|
|
|
|
|
|
|
|
puts("\n");
|
|
|
|
|
++methods;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
void ffLogoBuiltinList(void)
|
2022-06-08 10:59:33 +02:00
|
|
|
{
|
|
|
|
|
GetLogoMethod* methods = ffLogoBuiltinGetAll();
|
|
|
|
|
|
|
|
|
|
uint32_t counter = 0;
|
|
|
|
|
|
|
|
|
|
while(*methods != NULL)
|
|
|
|
|
{
|
|
|
|
|
const FFlogo* logo = (*methods)();
|
|
|
|
|
const char** names = logo->names;
|
|
|
|
|
|
|
|
|
|
printf("%u)%s ", counter, counter < 10 ? " " : "");
|
|
|
|
|
++counter;
|
|
|
|
|
|
|
|
|
|
while(*names != NULL)
|
|
|
|
|
{
|
|
|
|
|
printf("\"%s\" ", *names);
|
|
|
|
|
++names;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
putchar('\n');
|
|
|
|
|
++methods;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
void ffLogoBuiltinListAutocompletion(void)
|
2022-06-08 10:59:33 +02:00
|
|
|
{
|
|
|
|
|
GetLogoMethod* methods = ffLogoBuiltinGetAll();
|
|
|
|
|
|
|
|
|
|
while(*methods != NULL)
|
|
|
|
|
{
|
|
|
|
|
printf("%s\n", (*methods)()->names[0]);
|
|
|
|
|
++methods;
|
|
|
|
|
}
|
|
|
|
|
}
|