2015-09-07 23:56:20 +00:00
|
|
|
|
2015-07-27 00:35:07 +00:00
|
|
|
//
|
|
|
|
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
|
|
|
//
|
2019-06-30 01:28:51 +00:00
|
|
|
// Copyright (C) 2011, 2012, 2013, 2014, 2019 John Langner, WB2OSZ
|
2015-07-27 00:35:07 +00:00
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 2 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* Name: textcolor.c
|
|
|
|
*
|
|
|
|
* Purpose: Originally this would only set color of text
|
|
|
|
* and we used printf everywhere.
|
|
|
|
* Now we also have a printf replacement that can
|
|
|
|
* be used to redirect all output to the desired place.
|
|
|
|
* This opens the door to using ncurses, a GUI, or
|
|
|
|
* running as a daemon.
|
|
|
|
*
|
|
|
|
* Description: For Linux and Cygwin use the ANSI escape sequences.
|
|
|
|
* In earlier versions of Windows, the cmd window and ANSI.SYS
|
|
|
|
* could interpret this but it doesn't seem to be available
|
|
|
|
* anymore so we use a different interface.
|
|
|
|
*
|
2019-10-01 02:00:14 +00:00
|
|
|
* Reference:
|
2015-07-27 00:35:07 +00:00
|
|
|
* http://en.wikipedia.org/wiki/ANSI_escape_code
|
|
|
|
*
|
2015-09-07 23:56:20 +00:00
|
|
|
*
|
|
|
|
|
|
|
|
>>>> READ THIS PART!!! <<<<
|
|
|
|
|
|
|
|
*
|
|
|
|
*
|
2019-10-01 02:00:14 +00:00
|
|
|
* Problem: Years ago, when I started on this...
|
|
|
|
*
|
|
|
|
* The ANSI escape sequences, used for text colors, allowed 8 basic colors.
|
2015-07-27 00:35:07 +00:00
|
|
|
* Unfortunately, white is not one of them. We only have dark
|
|
|
|
* white, also known as light gray. To get brighter colors,
|
|
|
|
* we need to apply an attribute. On some systems, the bold
|
|
|
|
* attribute produces a brighter color rather than a bold font.
|
|
|
|
* On other systems, we need to use the blink attribute to get
|
|
|
|
* bright colors, including white. However on others, blink
|
|
|
|
* does actually produce blinking characters.
|
|
|
|
*
|
2019-06-30 01:28:51 +00:00
|
|
|
* Previously, the only option was to put "-t 0" on the command
|
2015-07-27 00:35:07 +00:00
|
|
|
* line to disable all text color. This is more readable but
|
|
|
|
* makes it harder to distinguish different types of
|
|
|
|
* information, e.g. received packets vs. error messages.
|
|
|
|
*
|
2019-06-30 01:28:51 +00:00
|
|
|
* A few people have suggested ncurses.
|
|
|
|
* I looked at ncurses, and it doesn't seem to be the solution.
|
|
|
|
* It always sends the same color control codes rather than
|
|
|
|
* detecting the terminal type and adjusting its behavior.
|
|
|
|
*
|
2019-10-01 02:00:14 +00:00
|
|
|
* Version 1.6:
|
|
|
|
*
|
2019-06-30 01:28:51 +00:00
|
|
|
* For a long time, there was a compile time distinction between
|
|
|
|
* ARM (e.g. Raspberry Pi) and other platforms. With the arrival
|
|
|
|
* of Raspbian Buster, we get flashing and the general Linux settings
|
|
|
|
* work better.
|
|
|
|
*
|
|
|
|
* Since there doesn't seem to be a single universal solution,
|
|
|
|
* the text color option will now be allowed to have multiple values.
|
2019-10-01 02:00:14 +00:00
|
|
|
* Several people have also complained that bright green is
|
|
|
|
* very hard to read against a light background so only dark green will be used.
|
2015-07-27 00:35:07 +00:00
|
|
|
*
|
|
|
|
*--------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
2016-07-03 22:09:34 +00:00
|
|
|
#include "direwolf.h" // Should be first. includes windows.h
|
|
|
|
|
2015-07-27 00:35:07 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
|
|
|
|
#if __WIN32__
|
|
|
|
|
|
|
|
#define BACKGROUND_WHITE (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY)
|
|
|
|
|
2019-06-30 01:28:51 +00:00
|
|
|
#else /* Linux, BSD, Mac OSX */
|
2015-07-27 00:35:07 +00:00
|
|
|
|
2019-06-30 01:28:51 +00:00
|
|
|
// Alternative 1:
|
2015-07-27 01:05:48 +00:00
|
|
|
|
2019-10-01 02:00:14 +00:00
|
|
|
// Using RGB colors - New in version 1.6.
|
|
|
|
// Since version 1.2, we've been using RGB to set the background to white.
|
|
|
|
// From this we can deduce that pretty much everyone recognizes RGB colors by now.
|
|
|
|
// The only known exception was PuTTY 0.70 and this has been rectified in 0.71.
|
|
|
|
// Instead of picking 1 of 8 colors, and using some attribute to get bright, just specify it directly.
|
|
|
|
// This should eliminate the need to reset the background after messing with the bright/bold/blink
|
|
|
|
// attributes to get more than 8 colors.
|
|
|
|
|
|
|
|
|
|
|
|
// Alternative 2:
|
|
|
|
|
2019-06-30 01:28:51 +00:00
|
|
|
// Was new in version 1.2, as suggested by IW2DHW.
|
|
|
|
// Tested with gnome-terminal and xterm.
|
|
|
|
// Raspbian Buster LXTerminal also likes this.
|
2019-10-01 02:00:14 +00:00
|
|
|
// There was probably an issue with an earlier release because I intentionally made ARM different at one time.
|
2015-07-27 01:05:48 +00:00
|
|
|
|
2019-06-30 01:28:51 +00:00
|
|
|
// Here we are using the RGB color format to set the background.
|
2019-10-01 02:00:14 +00:00
|
|
|
// PuTTY 0.70 doesn't recognize the RGB format so the background is not set.
|
|
|
|
// Instead of complaining about it, just upgrade to PuTTY 0.71.
|
2015-07-27 00:35:07 +00:00
|
|
|
|
2015-07-27 01:17:23 +00:00
|
|
|
|
2019-10-01 02:00:14 +00:00
|
|
|
// Alternative 3:
|
2015-07-27 01:17:23 +00:00
|
|
|
|
2019-10-01 02:00:14 +00:00
|
|
|
// For some terminals we needed "blink" (5) rather than the expected bright/bold (1)
|
|
|
|
// attribute to get bright white background.
|
2019-06-30 01:28:51 +00:00
|
|
|
// Makes no sense but I stumbled across that somewhere.
|
2015-07-27 01:17:23 +00:00
|
|
|
|
2019-10-01 02:00:14 +00:00
|
|
|
// In some cases, you might find background (around text but not rest of line) is set to white.
|
2019-06-30 01:28:51 +00:00
|
|
|
// On GNOME Terminal and LXTerminal, this produces blinking text with a gray background.
|
2015-07-27 01:17:23 +00:00
|
|
|
|
|
|
|
|
2019-10-01 02:00:14 +00:00
|
|
|
// Alternative 4:
|
2015-07-27 01:17:23 +00:00
|
|
|
|
2019-06-30 01:28:51 +00:00
|
|
|
// This is using the bright/bold attribute, as you would expect from the documentation.
|
|
|
|
// Whenever a dark color is used, the background is reset and needs to be set again.
|
|
|
|
// In recent tests, background is always gray, not white like it should be.
|
2015-07-27 01:17:23 +00:00
|
|
|
|
|
|
|
|
2019-10-01 02:00:14 +00:00
|
|
|
#define MAX_T 4
|
2015-07-27 00:35:07 +00:00
|
|
|
|
2019-10-01 02:00:14 +00:00
|
|
|
static const char *t_background_white[MAX_T+1] = { "", "\e[48;2;255;255;255m", "\e[48;2;255;255;255m", "\e[5;47m", "\e[1;47m" };
|
2015-07-27 00:35:07 +00:00
|
|
|
|
2019-10-01 02:00:14 +00:00
|
|
|
static const char *t_black[MAX_T+1] = { "", "\e[38;2;0;0;0m", "\e[0;30m" "\e[48;2;255;255;255m", "\e[0;30m" "\e[5;47m", "\e[0;30m" "\e[1;47m" };
|
|
|
|
static const char *t_red[MAX_T+1] = { "", "\e[38;2;255;0;0m", "\e[1;31m" "\e[48;2;255;255;255m", "\e[1;31m" "\e[5;47m", "\e[1;31m" "\e[1;47m" };
|
|
|
|
static const char *t_green[MAX_T+1] = { "", "\e[38;2;0;255;0m", "\e[1;32m" "\e[48;2;255;255;255m", "\e[1;32m" "\e[5;47m", "\e[1;32m" "\e[1;47m" };
|
|
|
|
static const char *t_dark_green[MAX_T+1]= { "", "\e[38;2;0;192;0m", "\e[0;32m" "\e[48;2;255;255;255m", "\e[0;32m" "\e[5;47m", "\e[0;32m" "\e[1;47m" };
|
|
|
|
static const char *t_yellow[MAX_T+1] = { "", "\e[38;2;255;255;0m", "\e[1;33m" "\e[48;2;255;255;255m", "\e[1;33m" "\e[5;47m", "\e[1;33m" "\e[1;47m" };
|
|
|
|
static const char *t_blue[MAX_T+1] = { "", "\e[38;2;0;0;255m", "\e[1;34m" "\e[48;2;255;255;255m", "\e[1;34m" "\e[5;47m", "\e[1;34m" "\e[1;47m" };
|
|
|
|
static const char *t_magenta[MAX_T+1] = { "", "\e[38;2;255;0;255m", "\e[1;35m" "\e[48;2;255;255;255m", "\e[1;35m" "\e[5;47m", "\e[1;35m" "\e[1;47m" };
|
|
|
|
static const char *t_cyan[MAX_T+1] = { "", "\e[38;2;0;255;255m", "\e[0;36m" "\e[48;2;255;255;255m", "\e[0;36m" "\e[5;47m", "\e[0;36m" "\e[1;47m" };
|
2015-07-27 01:17:23 +00:00
|
|
|
|
|
|
|
|
2015-07-27 00:35:07 +00:00
|
|
|
/* Clear from cursor to end of screen. */
|
|
|
|
|
|
|
|
static const char clear_eos[] = "\e[0J";
|
|
|
|
|
|
|
|
#endif /* end Linux */
|
|
|
|
|
|
|
|
|
|
|
|
#include "textcolor.h"
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* g_enable_color:
|
|
|
|
* 0 = disable text colors.
|
2019-10-01 02:00:14 +00:00
|
|
|
* 1 = default, should be good for LXTerminal >= 0.3.2, GNOME Terminal, xterm, PuTTY >= 0.71.
|
|
|
|
* 2 = what we had for a few earlier versions. Should be good for LXTerminal, GNOME Terminal, xterm.
|
|
|
|
* 3 = use 8 basic colors, blinking attribute to get brighter color. Best for older PuTTY.
|
|
|
|
* 4 = use 8 basic colors, bold attribute to get brighter color.
|
|
|
|
*
|
|
|
|
* others... future possibility - tell me if none of these work properly for your terminal type.
|
|
|
|
*
|
|
|
|
* 9 (more accurately any invalid value) = try all of them and exit.
|
2015-07-27 00:35:07 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
static int g_enable_color = 1;
|
|
|
|
|
|
|
|
|
|
|
|
void text_color_init (int enable_color)
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
#if __WIN32__
|
|
|
|
|
|
|
|
|
2019-06-30 01:28:51 +00:00
|
|
|
if (g_enable_color != 0) {
|
2015-07-27 00:35:07 +00:00
|
|
|
|
|
|
|
HANDLE h;
|
|
|
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
|
|
|
WORD attr = BACKGROUND_WHITE;
|
|
|
|
DWORD length;
|
|
|
|
COORD coord;
|
|
|
|
DWORD nwritten;
|
|
|
|
|
|
|
|
h = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
|
|
if (h != NULL && h != INVALID_HANDLE_VALUE) {
|
|
|
|
|
|
|
|
GetConsoleScreenBufferInfo (h, &csbi);
|
|
|
|
|
|
|
|
length = csbi.dwSize.X * csbi.dwSize.Y;
|
|
|
|
coord.X = 0;
|
|
|
|
coord.Y = 0;
|
|
|
|
FillConsoleOutputAttribute (h, attr, length, coord, &nwritten);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
2019-06-30 01:28:51 +00:00
|
|
|
|
|
|
|
// Run a test if outside of acceptable range.
|
|
|
|
|
|
|
|
if (enable_color < 0 || enable_color > MAX_T) {
|
|
|
|
int t;
|
|
|
|
for (t = 0; t <= MAX_T; t++) {
|
|
|
|
text_color_init (t);
|
|
|
|
printf ("-t %d", t);
|
|
|
|
if (t) printf (" [white background] ");
|
|
|
|
printf ("\n");
|
|
|
|
printf ("%sBlack ", t_black[t]);
|
|
|
|
printf ("%sRed ", t_red[t]);
|
|
|
|
printf ("%sGreen ", t_green[t]);
|
|
|
|
printf ("%sDark-Green ", t_dark_green[t]);
|
|
|
|
printf ("%sYellow ", t_yellow[t]);
|
|
|
|
printf ("%sBlue ", t_blue[t]);
|
|
|
|
printf ("%sMagenta ", t_magenta[t]);
|
|
|
|
printf ("%sCyan \n", t_cyan[t]);
|
|
|
|
}
|
|
|
|
exit (EXIT_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_enable_color = enable_color;
|
|
|
|
|
|
|
|
if (g_enable_color != 0) {
|
|
|
|
int t = g_enable_color;
|
|
|
|
|
|
|
|
if (t < 0) t = 0;
|
|
|
|
if (t > MAX_T) t = MAX_T;
|
|
|
|
|
|
|
|
printf ("%s", t_background_white[t]);
|
2015-07-27 01:17:23 +00:00
|
|
|
printf ("%s", clear_eos);
|
2019-06-30 01:28:51 +00:00
|
|
|
printf ("%s", t_black[t]);
|
2015-07-27 00:35:07 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if __WIN32__
|
|
|
|
|
|
|
|
/* Seems that ANSI.SYS is no longer available. */
|
|
|
|
|
|
|
|
|
|
|
|
void text_color_set ( enum dw_color_e c )
|
|
|
|
{
|
|
|
|
WORD attr;
|
|
|
|
HANDLE h;
|
|
|
|
|
|
|
|
if (g_enable_color == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (c) {
|
|
|
|
|
|
|
|
default:
|
|
|
|
case DW_COLOR_INFO:
|
|
|
|
attr = BACKGROUND_WHITE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DW_COLOR_ERROR:
|
|
|
|
attr = FOREGROUND_RED | FOREGROUND_INTENSITY | BACKGROUND_WHITE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DW_COLOR_REC:
|
2019-06-30 01:28:51 +00:00
|
|
|
// Release 1.6. Dark green, same as for debug.
|
|
|
|
// Bright green is too hard to see with white background,
|
|
|
|
// attr = FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_WHITE;
|
|
|
|
attr = FOREGROUND_GREEN | BACKGROUND_WHITE;
|
2015-07-27 00:35:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DW_COLOR_DECODED:
|
|
|
|
attr = FOREGROUND_BLUE | FOREGROUND_INTENSITY | BACKGROUND_WHITE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DW_COLOR_XMIT:
|
|
|
|
attr = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY | BACKGROUND_WHITE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DW_COLOR_DEBUG:
|
|
|
|
attr = FOREGROUND_GREEN | BACKGROUND_WHITE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
h = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
|
|
|
|
|
|
if (h != NULL && h != INVALID_HANDLE_VALUE) {
|
|
|
|
SetConsoleTextAttribute (h, attr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
void text_color_set ( enum dw_color_e c )
|
|
|
|
{
|
|
|
|
|
|
|
|
if (g_enable_color == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-06-30 01:28:51 +00:00
|
|
|
int t = g_enable_color;
|
|
|
|
|
|
|
|
if (t < 0) t = 0;
|
|
|
|
if (t > MAX_T) t = MAX_T;
|
|
|
|
|
2015-07-27 00:35:07 +00:00
|
|
|
switch (c) {
|
|
|
|
|
|
|
|
default:
|
|
|
|
case DW_COLOR_INFO:
|
2019-06-30 01:28:51 +00:00
|
|
|
printf ("%s", t_black[t]);
|
2015-07-27 00:35:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DW_COLOR_ERROR:
|
2019-06-30 01:28:51 +00:00
|
|
|
printf ("%s", t_red[t]);
|
2015-07-27 00:35:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DW_COLOR_REC:
|
2019-06-30 01:28:51 +00:00
|
|
|
// Bright green is very difficult to read against a while background.
|
|
|
|
// Let's use dark green instead. release 1.6.
|
|
|
|
//printf ("%s", t_green[t]);
|
|
|
|
printf ("%s", t_dark_green[t]);
|
2015-07-27 00:35:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DW_COLOR_DECODED:
|
2019-06-30 01:28:51 +00:00
|
|
|
printf ("%s", t_blue[t]);
|
2015-07-27 00:35:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DW_COLOR_XMIT:
|
2019-06-30 01:28:51 +00:00
|
|
|
printf ("%s", t_magenta[t]);
|
2015-07-27 00:35:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DW_COLOR_DEBUG:
|
2019-06-30 01:28:51 +00:00
|
|
|
printf ("%s", t_dark_green[t]);
|
2015-07-27 00:35:07 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* Name: dw_printf
|
|
|
|
*
|
|
|
|
* Purpose: printf replacement that allows us to send all text
|
|
|
|
* output to stdout or other desired destination.
|
|
|
|
*
|
|
|
|
* Inputs: fmt - C language format.
|
2021-09-19 18:51:18 +00:00
|
|
|
* ... - Additional arguments, just like printf.
|
2015-07-27 00:35:07 +00:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* Returns: Number of characters in result.
|
|
|
|
*
|
|
|
|
* Bug: Fixed size buffer.
|
|
|
|
* I'd rather not do a malloc for each print.
|
|
|
|
*
|
|
|
|
*--------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: replace all printf, look for stderr, perror
|
|
|
|
// TODO: $ grep printf *.c | grep -v dw_printf | grep -v fprintf | gawk '{ print $1 }' | sort -u
|
|
|
|
|
|
|
|
|
|
|
|
int dw_printf (const char *fmt, ...)
|
|
|
|
{
|
|
|
|
#define BSIZE 1000
|
|
|
|
va_list args;
|
|
|
|
char buffer[BSIZE];
|
|
|
|
int len;
|
|
|
|
|
|
|
|
va_start (args, fmt);
|
|
|
|
len = vsnprintf (buffer, BSIZE, fmt, args);
|
|
|
|
va_end (args);
|
|
|
|
|
|
|
|
// TODO: other possible destinations...
|
|
|
|
|
|
|
|
fputs (buffer, stdout);
|
|
|
|
return (len);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if TESTC
|
|
|
|
main ()
|
|
|
|
{
|
|
|
|
printf ("Initial condition\n");
|
|
|
|
text_color_init (1);
|
|
|
|
printf ("After text_color_init\n");
|
|
|
|
text_color_set(DW_COLOR_INFO); printf ("Info\n");
|
|
|
|
text_color_set(DW_COLOR_ERROR); printf ("Error\n");
|
|
|
|
text_color_set(DW_COLOR_REC); printf ("Rec\n");
|
|
|
|
text_color_set(DW_COLOR_DECODED); printf ("Decoded\n");
|
|
|
|
text_color_set(DW_COLOR_XMIT); printf ("Xmit\n");
|
|
|
|
text_color_set(DW_COLOR_DEBUG); printf ("Debug\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* end textcolor.c */
|