diff options
author | Burt P <pburt0@gmail.com> | 2019-12-27 17:13:10 -0600 |
---|---|---|
committer | Leandro A. F. Pereira <leandro@hardinfo.org> | 2019-12-27 22:16:36 -0800 |
commit | 74fe3984106ac559a2bea67a6f6fcdd5d2ca5464 (patch) | |
tree | 0cdf7ecd0e12f8a6f8959ab14581eb4a92b42632 | |
parent | 4c386e89eb9bf28e43164b958374bee113b4cee7 (diff) |
shell: add key flag for strings expected to contian vendors
Signed-off-by: Burt P <pburt0@gmail.com>
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | deps/sysobj_early/include/format_early.h | 43 | ||||
-rw-r--r-- | deps/sysobj_early/src/format_early.c | 130 | ||||
-rw-r--r-- | hardinfo/info.c | 7 | ||||
-rw-r--r-- | includes/info.h | 1 | ||||
-rw-r--r-- | includes/shell.h | 6 | ||||
-rw-r--r-- | modules/devices/dmi_memory.c | 27 | ||||
-rw-r--r-- | shell/shell.c | 98 |
8 files changed, 280 insertions, 33 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 674d1d2c..078ae9ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -236,6 +236,7 @@ add_library(sysobj_early STATIC deps/sysobj_early/src/nice_name.c deps/sysobj_early/gui/uri_handler.c deps/sysobj_early/src/util_edid.c + deps/sysobj_early/src/format_early.c ) set_target_properties(sysobj_early PROPERTIES COMPILE_FLAGS "-std=c99 -Wall -Wextra -Wno-parentheses -Wno-unused-function") target_link_libraries(sysobj_early m) diff --git a/deps/sysobj_early/include/format_early.h b/deps/sysobj_early/include/format_early.h new file mode 100644 index 00000000..81a5fa37 --- /dev/null +++ b/deps/sysobj_early/include/format_early.h @@ -0,0 +1,43 @@ +/* + * sysobj - https://github.com/bp0/verbose-spork + * Copyright (C) 2018 Burt P. <pburt0@gmail.com> + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _FORMAT_EARLY_H_ +#define _FORMAT_EARLY_H_ + +#include <glib.h> +#include <strings.h> +#include "appf.h" +#include "util_sysobj.h" + +enum { + FMT_OPT_ATERM = 1<<16, /* ANSI color terminal */ + FMT_OPT_PANGO = 1<<17, /* pango markup for gtk */ + FMT_OPT_HTML = 1<<18, /* html */ +}; + +gchar *safe_ansi_color(gchar *ansi_color, gboolean free_in); /* verify the ansi color */ +const gchar *color_lookup(int ansi_color); /* ansi_color to html color */ +/* wrap the input str with color based on fmt_opts (none,term,html,pango) */ +gchar *format_with_ansi_color(const gchar *str, const gchar *ansi_color, int fmt_opts); + +void tag_vendor(gchar **str, guint offset, const gchar *vendor_str, const char *ansi_color, int fmt_opts); +gchar *vendor_match_tag(const gchar *vendor_str, int fmt_opts); + +#endif diff --git a/deps/sysobj_early/src/format_early.c b/deps/sysobj_early/src/format_early.c new file mode 100644 index 00000000..bc5883cc --- /dev/null +++ b/deps/sysobj_early/src/format_early.c @@ -0,0 +1,130 @@ +/* + * sysobj - https://github.com/bp0/verbose-spork + * Copyright (C) 2018 Burt P. <pburt0@gmail.com> + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "format_early.h" +#include "vendor.h" + +#define ANSI_COLOR_RESET "\x1b[0m" + +const gchar *color_lookup(int ansi_color) { + static struct { int ansi; const gchar *html; } tab[] = { + { 30, "#010101" }, { 31, "#de382b" }, { 32, "#39b54a" }, { 33, "#ffc706" }, + { 34, "#006fb8" }, { 35, "#762671" }, { 36, "#2cb5e9" }, { 37, "#cccccc" }, + { 90, "#808080" }, { 91, "#ff0000" }, { 92, "#00ff00" }, { 93, "#ffff00" }, + { 94, "#0000ff" }, { 95, "#ff00ff" }, { 96, "#00ffff" }, { 97, "#ffffff" }, + { 40, "#010101" }, { 41, "#de382b" }, { 42, "#39b54a" }, { 43, "#ffc706" }, + { 44, "#006fb8" }, { 45, "#762671" }, { 46, "#2cb5e9" }, { 47, "#cccccc" }, + { 100, "#808080" }, { 101, "#ff0000" }, { 102, "#00ff00" }, { 103, "#ffff00" }, + { 104, "#0000ff" }, { 105, "#ff00ff" }, { 106, "#00ffff" }, { 107, "#ffffff" }, + }; + for (int i = 0; i<(int)G_N_ELEMENTS(tab); i++) + if (tab[i].ansi == ansi_color) + return tab[i].html; + return NULL; +} + +gchar *safe_ansi_color(gchar *ansi_color, gboolean free_in) { + if (!ansi_color) return NULL; + gchar *ret = NULL; + gchar **codes = g_strsplit(ansi_color, ";", -1); + if (free_in) + g_free(ansi_color); + int len = g_strv_length(codes); + for(int i = 0; i < len; i++) { + int c = atoi(codes[i]); + if (c == 0 || c == 1 + || ( c >= 30 && c <= 37) + || ( c >= 40 && c <= 47) + || ( c >= 90 && c <= 97) + || ( c >= 100 && c <= 107) ) { + ret = appf(ret, ";", "%s", codes[i]); + } + } + g_strfreev(codes); + return ret; +} + +gchar *format_with_ansi_color(const gchar *str, const gchar *ansi_color, int fmt_opts) { + gchar *ret = NULL; + + gchar *safe_color = g_strdup(ansi_color); + util_strstrip_double_quotes_dumb(safe_color); + + if (fmt_opts & FMT_OPT_ATERM) { + safe_color = safe_ansi_color(safe_color, TRUE); + ret = g_strdup_printf("\x1b[%sm%s" ANSI_COLOR_RESET, safe_color, str); + goto format_with_ansi_color_end; + } + + if (fmt_opts & FMT_OPT_PANGO || fmt_opts & FMT_OPT_HTML) { + int fgc = 37, bgc = 40; + gchar **codes = g_strsplit(safe_color, ";", -1); + int len = g_strv_length(codes); + for(int i = 0; i < len; i++) { + int c = atoi(codes[i]); + if ( (c >= 30 && c <= 37) + || ( c >= 90 && c <= 97 ) ) { + fgc = c; + } + if ( (c >= 40 && c <= 47) + || ( c >= 100 && c <= 107) ) { + bgc = c; + } + } + g_strfreev(codes); + const gchar *html_color_fg = color_lookup(fgc); + const gchar *html_color_bg = color_lookup(bgc); + if (fmt_opts & FMT_OPT_PANGO) + ret = g_strdup_printf("<span background=\"%s\" color=\"%s\"><b> %s </b></span>", html_color_bg, html_color_fg, str); + else if (fmt_opts & FMT_OPT_HTML) + ret = g_strdup_printf("<span style=\"background-color: %s; color: %s;\"><b> %s </b></span>", html_color_bg, html_color_fg, str); + } + +format_with_ansi_color_end: + g_free(safe_color); + if (!ret) + ret = g_strdup(str); + return ret; +} + +void tag_vendor(gchar **str, guint offset, const gchar *vendor_str, const char *ansi_color, int fmt_opts) { + if (!str || !*str) return; + if (!vendor_str || !ansi_color) return; + gchar *work = *str, *new = NULL; + if (g_str_has_prefix(work + offset, vendor_str) + || strncasecmp(work + offset, vendor_str, strlen(vendor_str)) == 0) { + gchar *cvs = format_with_ansi_color(vendor_str, ansi_color, fmt_opts); + *(work+offset) = 0; + new = g_strdup_printf("%s%s%s", work, cvs, work + offset + strlen(vendor_str) ); + g_free(work); + *str = new; + g_free(cvs); + } +} + +gchar *vendor_match_tag(const gchar *vendor_str, int fmt_opts) { + const Vendor *v = vendor_match(vendor_str, NULL); + if (v) { + gchar *ven_tag = v->name_short ? g_strdup(v->name_short) : g_strdup(v->name); + tag_vendor(&ven_tag, 0, ven_tag, v->ansi_color, fmt_opts); + return ven_tag; + } + return NULL; +} diff --git a/hardinfo/info.c b/hardinfo/info.c index 7f682dfe..49c44e2e 100644 --- a/hardinfo/info.c +++ b/hardinfo/info.c @@ -276,16 +276,17 @@ static void flatten_group(GString *output, const struct InfoGroup *group, guint const gchar *tp = field->tag; gboolean tagged = !!tp; - gboolean flagged = field->highlight || field->report_details; + gboolean flagged = field->highlight || field->report_details || field->value_has_vendor; if (!tp) { snprintf(tmp_tag, 255, "ITEM%d-%d", group_count, i); tp = tmp_tag; } if (tagged || flagged || field->icon) { - g_string_append_printf(output, "$%s%s%s$", + g_string_append_printf(output, "$%s%s%s%s$", field->highlight ? "*" : "", field->report_details ? "!" : "", + field->value_has_vendor ? "^" : "", tp); } @@ -462,6 +463,8 @@ struct Info *info_unflatten(const gchar *str) field.report_details = TRUE; if (key_is_highlighted(flags)) field.highlight = TRUE; + if (key_value_has_vendor_string(flags)) + field.value_has_vendor = TRUE; g_free(flags); g_array_append_val(group.fields, field); diff --git a/includes/info.h b/includes/info.h index 8166b1d1..6aa510dc 100644 --- a/includes/info.h +++ b/includes/info.h @@ -64,6 +64,7 @@ struct InfoField { int update_interval; gboolean highlight; /* select in GUI, highlight in report (flag:*) */ gboolean report_details; /* show moreinfo() in report (flag:!) */ + gboolean value_has_vendor; /* (flag:^) */ gboolean free_name_on_flatten; gboolean free_value_on_flatten; diff --git a/includes/shell.h b/includes/shell.h index e73dae49..b70b963e 100644 --- a/includes/shell.h +++ b/includes/shell.h @@ -223,18 +223,20 @@ void shell_set_remote_label(Shell *shell, gchar *label); * key syntax: * [$[<flags>][<tag>]$]<name>[#[<dis>]] * flags: - * [[!][*]] + * [[!][*][^]] * ! = show details (moreinfo) in reports * * = highlight/select this row + * ^ = value is/has a vendor string */ gboolean key_is_flagged(const gchar *key); /* has $[<flags>][<tag>]$ at the start of the key */ gboolean key_is_highlighted(const gchar *key); /* flag '*' = select/highlight */ gboolean key_wants_details(const gchar *key); /* flag '!' = report should include the "moreinfo" */ +gboolean key_value_has_vendor_string(const gchar *key); /* flag '^' = try and match the value to a vendor */ gchar *key_mi_tag(const gchar *key); /* moreinfo lookup tag */ const gchar *key_get_name(const gchar *key); /* get the key's name, flagged or not */ /* * example for key = "$*!Foo$Bar#7": - * flags = "$*!Foo$" // key_is/wants_*() still works on flags + * flags = "$*!^Foo$" // key_is/wants_*() still works on flags * tag = "Foo" // the moreinfo/icon tag * name = "Bar#7" // the full unique name * label = "Bar" // the label displayed diff --git a/modules/devices/dmi_memory.c b/modules/devices/dmi_memory.c index 270c44eb..19fafa80 100644 --- a/modules/devices/dmi_memory.c +++ b/modules/devices/dmi_memory.c @@ -604,14 +604,6 @@ gchar *make_spd_section(spd_data *spd) { default: DEBUG("blug for type: %d %s\n", spd->type, ram_types[spd->type]); } - gchar *vendor_str = NULL; - if (spd->vendor) { - vendor_str = vendor_get_link_from_vendor(spd->vendor); - } - gchar *dram_vendor_str = NULL; - if (spd->dram_vendor) { - dram_vendor_str = vendor_get_link_from_vendor(spd->dram_vendor); - } gchar *size_str = NULL; if (!spd->size_MiB) size_str = g_strdup(_("(Unknown)")); @@ -627,8 +619,8 @@ gchar *make_spd_section(spd_data *spd) { "%s=%d.%d\n" "%s=%s\n" "%s=%s\n" - "%s=[%02x%02x] %s%s\n" /* module vendor */ - "%s=[%02x%02x] %s%s\n" /* dram vendor */ + "$^$%s=[%02x%02x] %s\n" /* module vendor */ + "$^$%s=[%02x%02x] %s\n" /* dram vendor */ "%s=%s\n" /* part */ "%s=%s\n" /* size */ "%s=%s\n" /* mfg date */ @@ -640,16 +632,15 @@ gchar *make_spd_section(spd_data *spd) { _("Form Factor"), UNKIFNULL2(spd->form_factor), _("Type"), UNKIFEMPTY2(spd->type_detail), _("Module Vendor"), spd->vendor_bank, spd->vendor_index, - UNKIFNULL2(spd->vendor_str), vendor_str ? vendor_str : "", + UNKIFNULL2(spd->vendor_str), _("DRAM Vendor"), spd->dram_vendor_bank, spd->dram_vendor_index, - UNKIFNULL2(spd->dram_vendor_str), dram_vendor_str ? dram_vendor_str : "", + UNKIFNULL2(spd->dram_vendor_str), _("Part Number"), UNKIFEMPTY2(spd->partno), _("Size"), size_str, _("Manufacturing Date (Week / Year)"), UNKIFNULL2(mfg_date_str), full_spd ? full_spd : "" ); g_free(full_spd); - g_free(vendor_str); g_free(size_str); g_free(mfg_date_str); } @@ -748,10 +739,6 @@ gchar *memory_devices_get_info() { tag_make_safe_inplace(tag); if (s->populated) { - gchar *vendor_str = NULL; - if (s->vendor) { - vendor_str = vendor_get_link_from_vendor(s->vendor); - } gchar *size_str = NULL; if (!s->size_str) size_str = g_strdup(_("(Unknown)")); @@ -768,7 +755,7 @@ gchar *memory_devices_get_info() { "%s=%s\n" "%s=%s\n" "%s=%s / %s\n" - "%s=[%02x%02x] %s%s\n" + "$^$%s=[%02x%02x] %s\n" "%s=%s\n" "%s=%s\n" "%s=%s\n" @@ -786,8 +773,7 @@ gchar *memory_devices_get_info() { _("Form Factor"), UNKIFNULL2(s->form_factor), _("Type"), UNKIFNULL2(s->type), UNKIFNULL2(s->type_detail), _("Vendor"), - s->mfgr_bank, s->mfgr_index, - UNKIFNULL2(s->mfgr), vendor_str ? vendor_str : "", + s->mfgr_bank, s->mfgr_index, UNKIFNULL2(s->mfgr), _("Part Number"), UNKIFNULL2(s->partno), _("Size"), size_str, _("Rated Speed"), UNKIFNULL2(s->speed_str), @@ -809,7 +795,6 @@ gchar *memory_devices_get_info() { UNKIFNULL2(s->partno), size_str, UNKIFNULL2(mfgr) ); icons = h_strdup_cprintf("Icon$%s$=%s\n", icons, tag, mem_icon); - g_free(vendor_str); g_free(size_str); } else { gchar *details = g_strdup_printf("[%s]\n" diff --git a/shell/shell.c b/shell/shell.c index 2f3a68fc..3ece6a84 100644 --- a/shell/shell.c +++ b/shell/shell.c @@ -1524,6 +1524,46 @@ static gboolean detail_activate_link (GtkLabel *label, gchar *uri, gpointer user return uri_open(uri); } +#include "format_early.h" + +static gchar *vendor_info_markup(const Vendor *v) { + if (!v) return NULL; + gchar *ven_mt = NULL; + gchar *full_link = NULL, *p = NULL; + gchar *ven_tag = v->name_short ? g_strdup(v->name_short) : g_strdup(v->name); + tag_vendor(&ven_tag, 0, ven_tag, v->ansi_color, FMT_OPT_PANGO); + //if (v->name_short) + // ven_mt = appf(ven_mt, "\n", "%s", v->name); + ven_mt = appf(ven_mt, "\n", "%s", ven_tag); + if (v->url) { + if (!g_str_has_prefix(v->url, "http") ) + full_link = g_strdup_printf("http://%s", v->url); + ven_mt = appf(ven_mt, "\n", "<b>%s:</b> <a href=\"%s\">%s</a>", _("URL"), full_link ? full_link : v->url, v->url); + g_free(full_link); + full_link = NULL; + } + if (v->url_support) { + if (!g_str_has_prefix(v->url_support, "http") ) + full_link = g_strdup_printf("http://%s", v->url_support); + ven_mt = appf(ven_mt, "\n", "<b>%s:</b> <a href=\"%s\">%s</a>", _("Support URL"), full_link ? full_link : v->url_support, v->url_support); + g_free(full_link); + full_link = NULL; + } + if (v->wikipedia) { + /* sending the title to wikipedia.com/wiki will autmatically handle the language and section parts, + * but perhaps that shouldn't be relied on so much? */ + full_link = g_strdup_printf("http://wikipedia.com/wiki/%s", v->wikipedia); + for(p = full_link; *p; p++) { + if (*p == ' ') *p = '_'; + } + ven_mt = appf(ven_mt, "\n", "<b>%s:</b> <a href=\"%s\">%s</a>", _("Wikipedia"), full_link ? full_link : v->wikipedia, v->wikipedia); + g_free(full_link); + full_link = NULL; + } + g_free(ven_tag); + return ven_mt; +} + static void module_selected_show_info_detail(GKeyFile *key_file, ShellModuleEntry *entry, gchar **groups) @@ -1557,12 +1597,12 @@ static void module_selected_show_info_detail(GKeyFile *key_file, gtk_container_set_border_width(GTK_CONTAINER(table), 4); gtk_container_add(GTK_CONTAINER(frame), table); - gint j; + gint j, a = 0; for (j = 0; keys[j]; j++) { gchar *key_markup; gchar *value; - gchar *name, *label, *tag; - key_get_components(keys[j], NULL, &tag, &name, &label, NULL, TRUE); + gchar *name, *label, *tag, *flags; + key_get_components(keys[j], &flags, &tag, &name, &label, NULL, TRUE); value = g_key_file_get_string(key_file, groups[i], keys[j], NULL); @@ -1571,6 +1611,20 @@ static void module_selected_show_info_detail(GKeyFile *key_file, value = entry->fieldfunc(keys[j]); } + gboolean has_ven = key_value_has_vendor_string(flags); + const Vendor *v = has_ven ? vendor_match(value, NULL) : NULL; + gchar *value_markup = NULL; + +/* + if (v) { + gchar *vendor_markup = vendor_info_markup(v); + value_markup = g_strdup_printf("%s\n%s", value, vendor_markup); + g_free(vendor_markup); + } else { */ + value_markup = g_strdup(value); + g_free(value); + //} + key_markup = g_strdup_printf("<span color=\"#666\">%s</span>", label); @@ -1578,7 +1632,7 @@ static void module_selected_show_info_detail(GKeyFile *key_file, gtk_label_set_use_markup(GTK_LABEL(key_label), TRUE); gtk_misc_set_alignment(GTK_MISC(key_label), 1.0f, 0.5f); - GtkWidget *value_label = gtk_label_new(value); + GtkWidget *value_label = gtk_label_new(value_markup); gtk_label_set_use_markup(GTK_LABEL(value_label), TRUE); gtk_label_set_selectable(GTK_LABEL(value_label), TRUE); #if !GTK_CHECK_VERSION(3, 0, 0) @@ -1599,11 +1653,28 @@ static void module_selected_show_info_detail(GKeyFile *key_file, gtk_widget_show(value_box); gtk_widget_show(value_label); - gtk_table_attach(GTK_TABLE(table), key_label, 0, 1, j, j + 1, + gtk_table_attach(GTK_TABLE(table), key_label, 0, 1, j + a, j + a + 1, GTK_FILL, GTK_FILL, 6, 4); - gtk_table_attach(GTK_TABLE(table), value_box, 1, 2, j, j + 1, + gtk_table_attach(GTK_TABLE(table), value_box, 1, 2, j + a, j + a + 1, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 4); + if (v) { + a++; /* insert a row */ + gchar *vendor_markup = vendor_info_markup(v); + GtkWidget *vendor_label = gtk_label_new(vendor_markup); + gtk_label_set_use_markup(GTK_LABEL(vendor_label), TRUE); + gtk_label_set_selectable(GTK_LABEL(vendor_label), TRUE); + gtk_misc_set_alignment(GTK_MISC(vendor_label), 0.0f, 0.5f); + g_signal_connect(vendor_label, "activate-link", G_CALLBACK(detail_activate_link), NULL); + GtkWidget *vendor_box = gtk_hbox_new(FALSE, 4); + gtk_box_pack_start(GTK_BOX(vendor_box), vendor_label, TRUE, TRUE, 0); + gtk_table_attach(GTK_TABLE(table), vendor_box, 1, 2, j + a, j + a + 1, + GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 4); + gtk_widget_show(vendor_box); + gtk_widget_show(vendor_label); + g_free(vendor_markup); + } + struct UpdateTableItem *item = g_new0(struct UpdateTableItem, 1); item->is_iter = FALSE; item->widget = g_object_ref(value_box); @@ -1616,7 +1687,8 @@ static void module_selected_show_info_detail(GKeyFile *key_file, g_free(tag); } - g_free(value); + g_free(flags); + g_free(value_markup); g_free(key_markup); g_free(label); } @@ -2185,6 +2257,16 @@ gboolean key_wants_details(const gchar *key) { return FALSE; } +gboolean key_value_has_vendor_string(const gchar *key) { + gchar *flags; + key_get_components(key, &flags, NULL, NULL, NULL, NULL, TRUE); + if (flags && strchr(flags, '^')) { + g_free(flags); + return TRUE; + } + return FALSE; +} + gchar *key_mi_tag(const gchar *key) { gchar *p = (gchar*)key, *l, *t; @@ -2212,7 +2294,7 @@ const gchar *key_get_name(const gchar *key) { * [$[<flags>][<tag>]$]<name>[#[<dis>]] * * example for key = "$*!Foo$Bar#7": - * flags = "$*!Foo$" // key_is/wants_*() still works on flags + * flags = "$*!^Foo$" // key_is/wants_*() still works on flags * tag = "Foo" // the moreinfo/icon tag * name = "Bar#7" // the full unique name * label = "Bar" // the label displayed |