aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Fadel <samuelfadel@gmail.com>2015-04-01 22:43:44 -0300
committerSamuel Fadel <samuelfadel@gmail.com>2015-04-01 22:43:44 -0300
commita605c88ba3a0180d5783722c2c877f2ab8b01659 (patch)
tree3ec8f1712b2549cf596ff4bf595a5b5bc767e29a
parent52913a6131fdc950065d33ec18f75a1bcd329896 (diff)
Rewritten as a client-server application, similar to urxvt{d,c}.
-rw-r--r--Makefile45
-rw-r--r--T.c (renamed from src/T.c)144
-rw-r--r--T.h43
-rw-r--r--Tc.c100
-rw-r--r--Td.c142
-rw-r--r--config.h (renamed from src/config.h)41
6 files changed, 399 insertions, 116 deletions
diff --git a/Makefile b/Makefile
index 3b0eb6a..debd6de 100644
--- a/Makefile
+++ b/Makefile
@@ -1,33 +1,38 @@
DESTDIR = /
PREFIX = usr
-INCS = `pkg-config --cflags gtk+-2.0 vte`
-LIBS = `pkg-config --libs gtk+-2.0 vte`
-CFLAGS = -ansi -pedantic -Wall -O2 ${INCS}
+INCS = `pkg-config --cflags gtk+-2.0 gdk-2.0 vte`
+LIBS = `pkg-config --libs gtk+-2.0 gdk-2.0 vte`
+CFLAGS = -std=c99 -pedantic -Wall -O2 ${INCS}
LDFLAGS = -s ${LIBS}
-VER = 0.7
+VER = 0.9
CC = cc
-SRC = src/T.c
+SRC = T.c Tc.c Td.c
OBJ = ${SRC:.c=.o}
-all: T
+all: Tc Td
-.c.o:
+%.o: %.c
@echo CC $<
@${CC} -c ${CFLAGS} -o $@ $<
-${OBJ}: src/config.h
+${OBJ}: config.h T.h
-T: ${OBJ}
+Tc: T.o Tc.o
@echo CC -o $@
- @${CC} -o $@ ${OBJ} ${LDFLAGS}
+ @${CC} -o $@ $^ ${LDFLAGS}
+
+Td: T.o Td.o
+ @echo CC -o $@
+ @${CC} -o $@ $^ ${LDFLAGS}
clean:
@echo cleaning
- @rm -f T ${OBJ} T-${VER}.tar.bz2
+ @rm -f Tc Td ${OBJ} T-${VER}.tar.bz2
dist: clean
+ #TODO: remove .desktop file?
@echo creating distributable tarball
@mkdir T-${VER}
@cp -R src/ T.desktop Makefile T-${VER}
@@ -35,9 +40,15 @@ dist: clean
@rm -rf T-${VER}
install: all
- @echo installing executable file in ${DESTDIR}${PREFIX}/bin
- @install -D -m755 T ${DESTDIR}${PREFIX}/bin/T
- @echo installing desktop file in ${DESTDIR}${PREFIX}/share/applications
- @install -D -m644 T.desktop ${DESTDIR}${PREFIX}/share/applications/T.desktop
-
-.PHONY: all clean dist install
+ @echo installing executable files in ${DESTDIR}${PREFIX}/bin
+ @install -D -m755 Tc ${DESTDIR}${PREFIX}/bin/Tc
+ @install -D -m755 Td ${DESTDIR}${PREFIX}/bin/Td
+ #@echo installing desktop file in ${DESTDIR}${PREFIX}/share/applications
+ #@install -D -m644 T.desktop ${DESTDIR}${PREFIX}/share/applications/T.desktop
+
+uninstall:
+ @echo removing executables files from ${DESTDIR}${PREFIX}/bin
+ @rm -f ${DESTDIR}${PREFIX}/bin/Tc
+ @rm -f ${DESTDIR}${PREFIX}/bin/Td
+
+.PHONY: all clean dist install uninstall
diff --git a/src/T.c b/T.c
index c776983..dc62c3d 100644
--- a/src/T.c
+++ b/T.c
@@ -1,6 +1,5 @@
/*
* T.c
- *
* T is a lean Terminal emulator.
*
* This file is part of T.
@@ -23,42 +22,28 @@
#include <gtk/gtk.h>
#include <unistd.h>
#include <vte/vte.h>
+#include <stdlib.h>
-#include "config.h"
+#include "T.h"
-static int window_count;
+static int window_count = 0;
/* Event callbacks */
-static gboolean window_delete_event_callback(GtkWidget *widget, GdkEvent *event, gpointer data);
static void window_destroy_callback(GtkWidget *widget, gpointer data);
-
static gboolean key_press_callback(GtkWidget *widget, GdkEvent *event, gpointer data);
-
static void terminal_child_exited_callback(VteTerminal *terminal, gpointer data);
static void terminal_window_title_changed_callback(VteTerminal *terminal, gpointer data);
/* Helper functions */
-static void set_font_size(VteTerminal *terminal, int diff);
-static void setup_pty(VteTerminal *terminal, GPid *child_pid);
+static void change_font_size(VteTerminal *terminal, int delta);
static void set_preferences(VteTerminal *terminal);
static void setup_terminal(GtkWindow *window, VteTerminal *terminal);
-static void setup_window(GtkWindow *window);
-static void spawn_window(void);
-
-static gboolean
-window_delete_event_callback(GtkWidget *widget, GdkEvent *event, gpointer data)
-{
- /* TODO: always false? */
- return FALSE;
-}
static void
window_destroy_callback(GtkWidget *widget, gpointer data)
{
+ /* Keeping track of the open windows */
window_count--;
-
- if (window_count == 0)
- gtk_main_quit();
}
static gboolean
@@ -75,10 +60,10 @@ key_press_callback(GtkWidget *widget, GdkEvent *event, gpointer data)
switch (key_event->keyval) {
case GDK_KEY_minus:
- set_font_size(terminal, -1);
+ change_font_size(terminal, -1);
return TRUE;
case GDK_KEY_plus:
- set_font_size(terminal, 1);
+ change_font_size(terminal, 1);
return TRUE;
}
@@ -101,7 +86,7 @@ key_press_callback(GtkWidget *widget, GdkEvent *event, gpointer data)
break;
case GDK_KEY_N:
case GDK_KEY_n:
- spawn_window();
+ new_window();
return TRUE;
}
@@ -111,48 +96,31 @@ key_press_callback(GtkWidget *widget, GdkEvent *event, gpointer data)
static void
terminal_child_exited_callback(VteTerminal *terminal, gpointer data)
{
- GtkWindow *window;
-
- window = GTK_WINDOW(data);
- gtk_widget_destroy(GTK_WIDGET(window));
+ /* The forked process exited; issue destruction of the terminal window */
+ gtk_widget_destroy(GTK_WIDGET(GTK_WINDOW(data)));
}
static void
terminal_window_title_changed_callback(VteTerminal *terminal, gpointer data)
{
- GtkWindow *window;
-
- window = (GtkWindow *) data;
+ GtkWindow *window = GTK_WINDOW(data);
gtk_window_set_title(window, vte_terminal_get_window_title(terminal));
}
static void
-set_font_size(VteTerminal *terminal, int diff)
+change_font_size(VteTerminal *terminal, int delta)
{
PangoFontDescription *desc = (PangoFontDescription *) vte_terminal_get_font(terminal);
- gint font_size = pango_font_description_get_size(desc) + diff * PANGO_SCALE;
+ gint font_size = pango_font_description_get_size(desc) + delta * PANGO_SCALE;
pango_font_description_set_size(desc, font_size);
vte_terminal_set_font(terminal, desc);
}
static void
-setup_pty(VteTerminal *terminal, GPid *child_pid)
-{
- VtePty* pty;
- char *argv[] = { NULL, NULL };
-
- /* TODO: error handling */
- argv[0] = vte_get_user_shell();
- pty = vte_terminal_pty_new(terminal, VTE_PTY_DEFAULT, NULL);
- vte_terminal_set_pty_object(terminal, pty);
- vte_terminal_fork_command_full(terminal, VTE_PTY_DEFAULT, ".", argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, child_pid, NULL);
-}
-
-static void
set_preferences(VteTerminal *terminal)
{
/*
- * Options set here can (and should) be configured through config.h
+ * Options set here can (and should) be configured in config.h
*/
/*
@@ -161,6 +129,24 @@ set_preferences(VteTerminal *terminal)
*/
static gboolean colors_parsed = FALSE;
static GdkColor palette[CONFIG_PALETTE_SIZE], bg_color, fg_color;
+ static const char *CONFIG_COLOR_PALETTE[CONFIG_PALETTE_SIZE] = {
+ CONFIG_PALLETE_0,
+ CONFIG_PALLETE_1,
+ CONFIG_PALLETE_2,
+ CONFIG_PALLETE_3,
+ CONFIG_PALLETE_4,
+ CONFIG_PALLETE_5,
+ CONFIG_PALLETE_6,
+ CONFIG_PALLETE_7,
+ CONFIG_PALLETE_8,
+ CONFIG_PALLETE_9,
+ CONFIG_PALLETE_10,
+ CONFIG_PALLETE_11,
+ CONFIG_PALLETE_12,
+ CONFIG_PALLETE_13,
+ CONFIG_PALLETE_14,
+ CONFIG_PALLETE_15,
+ };
if (!colors_parsed) {
int i;
@@ -186,10 +172,19 @@ set_preferences(VteTerminal *terminal)
static void
setup_terminal(GtkWindow *window, VteTerminal *terminal)
{
+ char *argv[] = { vte_get_user_shell(), NULL };
GPid child_pid;
- setup_pty(terminal, &child_pid);
- vte_terminal_watch_child(terminal, child_pid);
+ vte_terminal_fork_command_full(terminal,
+ VTE_PTY_DEFAULT,
+ NULL, /* wd; NULL for cwd */
+ argv, /* the program to fork into and its args */
+ NULL, /* env vars */
+ G_SPAWN_DO_NOT_REAP_CHILD,
+ NULL, /* setup func */
+ NULL, /* custom data to setup func */
+ &child_pid,
+ NULL); /* TODO: error handling */
g_signal_connect(terminal, "child-exited", G_CALLBACK(terminal_child_exited_callback), window);
g_signal_connect(terminal, "key-press-event", G_CALLBACK(key_press_callback), window);
@@ -198,15 +193,20 @@ setup_terminal(GtkWindow *window, VteTerminal *terminal)
set_preferences(terminal);
}
-static void
-setup_window(GtkWindow *window)
+int
+num_open_windows()
{
- GdkGeometry hints;
- VteTerminal *terminal;
+ return window_count;
+}
- terminal = (VteTerminal *) vte_terminal_new();
+void
+new_window()
+{
+ GtkWindow *window = (GtkWindow *) gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ VteTerminal *terminal = (VteTerminal *) vte_terminal_new();
setup_terminal(window, terminal);
+ GdkGeometry hints;
hints.base_width = vte_terminal_get_char_width(terminal);
hints.base_height = vte_terminal_get_char_height(terminal);
hints.min_width = hints.base_width * CONFIG_MIN_WIDTH;
@@ -214,44 +214,28 @@ setup_window(GtkWindow *window)
hints.width_inc = hints.base_width;
hints.height_inc = hints.base_height;
gtk_window_set_geometry_hints(window, GTK_WIDGET(terminal), &hints, GDK_HINT_RESIZE_INC | GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE);
+ gtk_window_set_icon_name(window, "utilities-terminal");
- g_signal_connect(window, "delete-event", G_CALLBACK(window_delete_event_callback), NULL);
+ g_signal_connect(window, "delete-event", G_CALLBACK(gtk_false), NULL);
g_signal_connect(window, "destroy", G_CALLBACK(window_destroy_callback), NULL);
- gtk_window_set_icon_name(window, "utilities-terminal");
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(terminal));
gtk_widget_show(GTK_WIDGET(terminal));
gtk_widget_show(GTK_WIDGET(window));
-}
-
-static void
-spawn_window(void)
-{
- GtkWindow *window;
-
- window = (GtkWindow *) gtk_window_new(GTK_WINDOW_TOPLEVEL);
- setup_window(window);
window_count++;
}
-int
-main(int argc, char *argv[])
+void
+wrn(const char *message)
{
- gtk_init(&argc, &argv);
-
- /* Initial state: single window */
- window_count = 0;
- spawn_window();
-
- /*
- * TODO:
- * Find out a nice and clean way of opening more windows when the user
- * does not have focus on a T window.
- */
-
- gtk_main();
+ fprintf(stderr, "%s: %s\n", PROGRAM_NAME, message);
+}
- return 0;
+void
+err(const char *message, int ecode)
+{
+ wrn(message);
+ exit(ecode);
}
diff --git a/T.h b/T.h
new file mode 100644
index 0000000..a891982
--- /dev/null
+++ b/T.h
@@ -0,0 +1,43 @@
+/*
+ * T.h
+ * Common definitions and utilities.
+ *
+ * This file is part of T.
+ *
+ * T 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 3 of the License, or (at your option) any later
+ * version.
+ *
+ * T 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
+ * T. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef T_H
+#define T_H
+
+#include "config.h"
+
+#define PROGRAM_NAME "T"
+
+#define SOCKPATH CONFIG_SOCKDIR "/" CONFIG_SOCKNAME
+#define SOCKPATH_MAXLEN sizeof((SOCKPATH))
+
+typedef enum {
+ MSG_NEWWIN,
+ MSG_EXIT,
+ MSG_OK,
+ MSG_ERROR
+} TMessage;
+
+int num_open_windows();
+void new_window();
+
+void wrn(const char *message);
+void err(const char *message, int ecode);
+
+#endif /* T_H */
diff --git a/Tc.c b/Tc.c
new file mode 100644
index 0000000..f54a2a2
--- /dev/null
+++ b/Tc.c
@@ -0,0 +1,100 @@
+/*
+ * Tc.c
+ * T client. Merely issues commands to the T daemon.
+ *
+ * T is a lean Terminal emulator.
+ *
+ * This file is part of T.
+ *
+ * T 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 3 of the License, or (at your option) any later
+ * version.
+ *
+ * T 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
+ * T. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "T.h"
+
+#define ARG_NEWWIN "-n"
+#define ARG_EXIT "-x"
+
+static int open_conn();
+static TMessage parse_args(int argc, char *argv[]);
+static void usage();
+
+static int
+open_conn()
+{
+ struct sockaddr_un sock_addr;
+
+ int sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sock_fd < 0)
+ err("Failed to create socket", EXIT_FAILURE);
+
+ memset(&sock_addr, 0, sizeof(sock_addr));
+ sock_addr.sun_family = AF_UNIX;
+ strncpy(sock_addr.sun_path, SOCKPATH, sizeof(sock_addr.sun_path) - 1);
+
+ if (connect(sock_fd, (struct sockaddr *) &sock_addr, sizeof(sock_addr)) < 0)
+ err("Failed to connect to daemon", EXIT_FAILURE);
+
+ return sock_fd;
+}
+
+static TMessage
+parse_args(int argc, char *argv[])
+{
+ if (argc == 1) /* No args means new window */
+ return MSG_NEWWIN;
+ if (argc > 2) /* More than 1 arg means derp */
+ return MSG_ERROR;
+ if (strcmp(argv[1], ARG_NEWWIN) == 0)
+ return MSG_NEWWIN;
+ if (strcmp(argv[1], ARG_EXIT) == 0)
+ return MSG_EXIT;
+
+ return MSG_ERROR;
+}
+
+static void
+usage()
+{
+ puts("usage:");
+ puts("\tTc [ARG]");
+ puts("\nwhere ARG is one of:");
+ puts("\t" ARG_NEWWIN "\tRequests a new window; default if ommited");
+ puts("\t" ARG_EXIT "\tRequests daemon termination; only successful if there are no open windows");
+}
+
+int
+main(int argc, char *argv[])
+{
+ TMessage msg = parse_args(argc, argv);
+ if (msg == MSG_ERROR) {
+ usage();
+ return EXIT_FAILURE;
+ }
+
+ int sock_fd = open_conn();
+ if (write(sock_fd, &msg, sizeof(msg)) < 0)
+ err("Failed to send data", EXIT_FAILURE);
+ if (recv(sock_fd, &msg, sizeof(msg), 0) < 0)
+ err("Failed to recv data", EXIT_FAILURE);
+ close(sock_fd);
+
+ return msg == MSG_OK ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/Td.c b/Td.c
new file mode 100644
index 0000000..22a847b
--- /dev/null
+++ b/Td.c
@@ -0,0 +1,142 @@
+/*
+ * Td.c
+ * T daemon. Saves resources by uniting all T windows under the same process.
+ *
+ * This file is part of T.
+ *
+ * T 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 3 of the License, or (at your option) any later
+ * version.
+ *
+ * T 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
+ * T. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+#include <vte/vte.h>
+
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "T.h"
+
+#define MSGBUF_MAXLEN 64
+
+static int bind_socket();
+static TMessage handle_message(TMessage msg);
+static gboolean socket_g_io_watch(GIOChannel *source, GIOCondition condition, gpointer data);
+
+static int
+bind_socket()
+{
+ struct sockaddr_un sock_addr;
+
+ memset(&sock_addr, 0, sizeof(sock_addr));
+ sock_addr.sun_family = AF_UNIX;
+ strncpy(sock_addr.sun_path, SOCKPATH, sizeof(sock_addr.sun_path) - 1);
+
+ /* Remove old socket */
+ if (!access(sock_addr.sun_path, F_OK) && unlink(sock_addr.sun_path) < 0)
+ err("Failed to remove socket file at " SOCKPATH, EXIT_FAILURE);
+ if (!access(CONFIG_SOCKDIR, F_OK) && rmdir(CONFIG_SOCKDIR) < 0)
+ err("Failed to remove socket directory at " CONFIG_SOCKDIR, EXIT_FAILURE);
+
+ /* Create a new directory */
+ if (mkdir(CONFIG_SOCKDIR, S_IRWXU) < 0)
+ err("Failed to create socket directory at " CONFIG_SOCKDIR, EXIT_FAILURE);
+
+ int sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sock_fd < 0)
+ err("Failed to create socket", EXIT_FAILURE);
+
+ if (bind(sock_fd, (struct sockaddr *) &sock_addr, sizeof(sock_addr)) < 0)
+ err("Failed to bind the socket to the file at " SOCKPATH, EXIT_FAILURE);
+
+ return sock_fd;
+}
+
+static TMessage
+handle_message(TMessage msg)
+{
+ switch (msg) {
+ case MSG_NEWWIN:
+ new_window();
+ return MSG_OK;
+
+ case MSG_EXIT:
+ if (num_open_windows() == 0) {
+ gtk_main_quit();
+ return MSG_OK;
+ }
+ return MSG_ERROR;
+
+ default:
+ return MSG_ERROR;
+ }
+}
+
+static gboolean
+socket_g_io_watch(GIOChannel *source, GIOCondition condition, gpointer data)
+{
+ int sock_fd = g_io_channel_unix_get_fd(source);
+ int client_fd = accept(sock_fd, NULL, NULL);
+ if (client_fd < 0) {
+ wrn("accept() failed");
+ return TRUE;
+ }
+
+ TMessage msg;
+ int len = recv(client_fd, &msg, sizeof(msg), 0);
+ if (len < 0) {
+ wrn("recv() failed");
+ goto socket_g_io_watch_cleanup;
+ }
+
+ msg = handle_message(msg);
+ write(client_fd, &msg, sizeof(msg));
+
+socket_g_io_watch_cleanup:
+ close(client_fd);
+ return TRUE;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int sock_fd;
+
+ gtk_init(&argc, &argv);
+
+ sock_fd = bind_socket();
+ if (listen(sock_fd, SOMAXCONN) < 0)
+ err("Failed to listen to socket", EXIT_SUCCESS);
+
+ /* poll the socket in the main loop */
+ GIOChannel *sock_chan = g_io_channel_unix_new(sock_fd);
+ g_io_add_watch(sock_chan, G_IO_IN, socket_g_io_watch, NULL);
+
+ gtk_main();
+
+ /* clean up */
+ close(sock_fd);
+ unlink(SOCKPATH);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/config.h b/config.h
index ee466ee..2afffe4 100644
--- a/src/config.h
+++ b/config.h
@@ -1,6 +1,5 @@
/*
* config.h
- *
* Configuration file. Modify these to customize T.
*
* This file is part of T.
@@ -18,6 +17,12 @@
* T. If not, see <http://www.gnu.org/licenses/>.
*/
+/* The directory of the connection socket used by the T daemon. */
+#define CONFIG_SOCKDIR "/tmp/Td"
+
+/* The name of the connection socket used by the T daemon. */
+#define CONFIG_SOCKNAME "Td.sock"
+
/* Minimum width/height, in characters */
#define CONFIG_MIN_WIDTH 20
#define CONFIG_MIN_HEIGHT 5
@@ -29,24 +34,22 @@
/* PALETTE_SIZE must be 8, 16, 24 or between 25 and 255, inclusive */
#define CONFIG_PALETTE_SIZE 16
-static const char *CONFIG_COLOR_PALETTE[CONFIG_PALETTE_SIZE] = {
- "#000000", /* 0 Black */
- "#95513a", /* 1 Red */
- "#3a9551", /* 2 Green */
- "#7e953a", /* 3 Yellow */
- "#3d558d", /* 4 Blue */
- "#953a7e", /* 5 Magenta */
- "#3a7e95", /* 6 Cyan */
- "#d9d9d9", /* 7 White */
- "#262626", /* 8 Black */
- "#c17860", /* 9 Red */
- "#60c178", /* 10 Green */
- "#a9c160", /* 11 Yellow */
- "#5f7aba", /* 12 Blue */
- "#c160a9", /* 13 Magenta */
- "#60a9c1", /* 14 Cyan */
- "#ffffff", /* 15 White */
-};
+#define CONFIG_PALLETE_0 "#000000" /* Black */
+#define CONFIG_PALLETE_1 "#95513a" /* Red */
+#define CONFIG_PALLETE_2 "#3a9551" /* Green */
+#define CONFIG_PALLETE_3 "#7e953a" /* Yellow */
+#define CONFIG_PALLETE_4 "#3d558d" /* Blue */
+#define CONFIG_PALLETE_5 "#953a7e" /* Magenta */
+#define CONFIG_PALLETE_6 "#3a7e95" /* Cyan */
+#define CONFIG_PALLETE_7 "#d9d9d9" /* White */
+#define CONFIG_PALLETE_8 "#262626" /* Black */
+#define CONFIG_PALLETE_9 "#c17860" /* Red */
+#define CONFIG_PALLETE_10 "#60c178" /* Green */
+#define CONFIG_PALLETE_11 "#a9c160" /* Yellow */
+#define CONFIG_PALLETE_12 "#5f7aba" /* Blue */
+#define CONFIG_PALLETE_13 "#c160a9" /* Magenta */
+#define CONFIG_PALLETE_14 "#60a9c1" /* Cyan */
+#define CONFIG_PALLETE_15 "#ffffff" /* White */
/* Foreground and background. */
#define CONFIG_FOREGROUND_COLOR "#d9e6f2" /* COLOR_PALETTE[7] */