aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--uxd.111
-rw-r--r--uxd.c123
-rw-r--r--uxd.rst9
3 files changed, 100 insertions, 43 deletions
diff --git a/uxd.1 b/uxd.1
index bd812d8..306b5a2 100644
--- a/uxd.1
+++ b/uxd.1
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
-.TH "UXD" 1 "2024-12-15" "0.1.0" "Urchlay's Utilities"
+.TH "UXD" 1 "2024-12-16" "0.1.0" "Urchlay's Utilities"
.SH NAME
uxd \- UTF-8 hex dumper
.SH SYNOPSIS
@@ -89,8 +89,8 @@ will be dumped.
.B \-m
Monochrome mode. Uses underline, bold, reverse video instead of color.
Use this if you have trouble distinguishing the colors, or if they
-look too much like angry fruit salad.
-NOT IMPLEMENTED YET.
+look too much like angry fruit salad. Disables prior \fB\-b\fP, \fB\-c\fP
+options.
.TP
.B \-n
Ignore \fBUXD_OPTS\fP environment variable. This option should not be
@@ -118,7 +118,7 @@ position after seeking. \fB\-S 100\fP is the same as \fB\-s 100 \-o \-100\fP\&.
Works with negative \fIpos\fP, too.
.TP
.B \-u
-Use uppercase hex digits A\-F. Default is lowercase.
+Use uppercase hex digits \fIA\-F\fP\&. Default is lowercase.
.TP
.B \-v\fP,\fB \-\-version
Print version number and exit.
@@ -266,7 +266,8 @@ any files other than standard output. There\(aqs no config file.
.TP
.B \fBUXD_OPTS\fP
If this is set, its value is treated as a set of options, which
-get applied before any command\-line options.
+get applied before any command\-line options (unless the command\-line
+options inclue \fB\-n\fP).
.TP
.B \fBNO_COLOR\fP
If this is set (to any value), \fBuxd\fP runs in monochrome mode, just
diff --git a/uxd.c b/uxd.c
index 93368a1..22a25f3 100644
--- a/uxd.c
+++ b/uxd.c
@@ -65,9 +65,13 @@ extern int optind;
#define BAD_FG BLACK
#define BAD_BG bad_color
+#define HL_NORMAL 0
+#define HL_NORM_INV 1
+#define HL_SPECIAL 2
+#define HL_BAD 3
+
int normal_colors[] = { GREEN, YELLOW };
-int cur_normal_color = 0;
-int dump_color;
+int cur_normal_hilite = 1;
int bad_color = RED;
int special_color = SPECIAL;
@@ -305,13 +309,33 @@ void print_line(void) {
dump_column = 0;
}
-void next_normal_color() {
- cur_normal_color++;
- cur_normal_color %= (sizeof(normal_colors) / sizeof(int));
+void next_normal_hilite() {
+ cur_normal_hilite = !cur_normal_hilite;
}
-void append_color(char *buf, int fgcolor, int bgcolor) {
+void append_color(char *buf, int hl_type) {
char tmpbuf[100];
+ int fgcolor, bgcolor;
+
+ switch(hl_type) {
+ case HL_NORMAL:
+ fgcolor = normal_colors[cur_normal_hilite];
+ bgcolor = 0;
+ break;
+ case HL_NORM_INV:
+ fgcolor = 0;
+ bgcolor = normal_colors[cur_normal_hilite];
+ break;
+ case HL_SPECIAL:
+ fgcolor = special_color;
+ bgcolor = 0;
+ break;
+ default:
+ case HL_BAD:
+ fgcolor = BAD_FG;
+ bgcolor = bad_color;
+ break;
+ }
sprintf(tmpbuf, "\x1b[%d;3%d", bold, fgcolor);
strcat(buf, tmpbuf);
@@ -323,7 +347,36 @@ void append_color(char *buf, int fgcolor, int bgcolor) {
strcat(buf, tmpbuf);
}
-void append_color_off(char *buf) {
+void append_mono(char *buf, int hl_type) {
+ char tmpbuf[100];
+ int code;
+
+ switch(hl_type) {
+ case HL_NORMAL:
+ case HL_NORM_INV:
+ code = cur_normal_hilite ? 4 : 0; /* underline : normal */
+ break;
+ case HL_SPECIAL:
+ code = 1; /* bold */
+ break;
+ default:
+ case HL_BAD:
+ code = 7; /* reverse video */
+ break;
+ }
+
+ sprintf(tmpbuf, "\x1b[%dm", code);
+ strcat(buf, tmpbuf);
+}
+
+void append_hilite(char *buf, int hl_type) {
+ if(mono)
+ append_mono(buf, hl_type);
+ else
+ append_color(buf, hl_type);
+}
+
+void append_hilite_off(char *buf) {
strcat(buf, "\x1b[0m");
}
@@ -331,13 +384,13 @@ void append_right(char *str) {
strcat(right_buf, str);
}
-void append_left(unsigned char byte, int dash, int fgcolor, int bgcolor) {
+void append_left(unsigned char byte, int dash, int hl_type) {
char tmpbuf[100];
if(!dump_column)
sprintf(left_buf, hex_word_fmt, filepos + display_offset);
- append_color(left_buf, fgcolor, bgcolor);
+ append_hilite(left_buf, hl_type);
sprintf(tmpbuf, hex_byte_fmt, byte);
strcat(left_buf, tmpbuf);
@@ -347,9 +400,9 @@ void append_left(unsigned char byte, int dash, int fgcolor, int bgcolor) {
strcat(left_buf, "-");
if(dump_column == (MAX_DUMP_COLS / 2))
strcat(left_buf, "-");
- append_color_off(left_buf);
+ append_hilite_off(left_buf);
} else {
- append_color_off(left_buf);
+ append_hilite_off(left_buf);
strcat(left_buf, " ");
if(dump_column == (MAX_DUMP_COLS / 2))
strcat(left_buf, " ");
@@ -397,8 +450,8 @@ int dump_utf8_char(void) {
unsigned char bytes[] = { 0, 0, 0, 0, 0 };
unsigned char *cont_bytes = bytes + 1;
char *printable;
- int bad = 0, special = 0;
- int c, cont_count, i, fg, bg;
+ int bad = 0, special = 0, hl_type;
+ int c, cont_count, i;
static int byte0;
c = fgetc(input);
@@ -415,28 +468,33 @@ int dump_utf8_char(void) {
check_utf16(byte0, c);
}
+ /* look at 1st byte to find out how long the sequence is */
if(c < 0x7f) {
ascii_count++;
cont_count = 0;
if(c <= ' ' || c == 0x7f)
special = 1;
- } else if((c & 0xe0) == 0xc0) /* 110xxxxx */
+ } else if((c & 0xe0) == 0xc0) { /* 110xxxxx */
cont_count = 1;
- else if((c & 0xf0) == 0xe0) /* 1110xxxx */
+ } else if((c & 0xf0) == 0xe0) { /* 1110xxxx */
cont_count = 2;
- else if((c & 0xf8) == 0xf0) /* 11110xxx */
+ } else if((c & 0xf8) == 0xf0) { /* 11110xxx */
cont_count = 3;
- else {
+ } else {
+ /* high bit set, but not a valid sequence-starter */
cont_count = 0;
bad = 1;
}
+ /* read and validate the continuation bytes, if any */
for(i = 0; i < cont_count; i++) {
int cb;
c = fgetc(input);
if(c == EOF) {
- /* EOF in mid-sequence */
+ /* EOF in mid-sequence. Don't return 0 here, since we still
+ have to dump the partial sequence. The next call will
+ give us EOF again. */
cont_count = i;
bad = 1;
break;
@@ -465,36 +523,33 @@ int dump_utf8_char(void) {
multi_count++;
}
+ /* decide how to highlight the current character */
if(bad) {
- fg = BAD_FG;
- bg = BAD_BG;
+ hl_type = HL_BAD;
/* replacement character � is U+FFFD */
printable = "�";
} else if(special) {
- fg = special_color;
- bg = 0;
+ hl_type = HL_SPECIAL;
printable = get_special(bytes[0]);
} else if(cont_count == 2 && is_bom(bytes)) {
- fg = special_color;
- bg = 0;
+ hl_type = HL_SPECIAL;
printable = "B";
} else {
- fg = normal_colors[cur_normal_color];
- bg = 0;
+ hl_type = HL_NORMAL;
printable = (char *)bytes;
- next_normal_color();
+ next_normal_hilite();
}
- append_color(right_buf, fg, bg);
+ /* human-readable (right) column: */
+ append_hilite(right_buf, hl_type);
append_right(printable);
- append_color_off(right_buf);
-
- if(hilite_multi && cont_count) {
- c = bg; bg = fg; fg = c;
- }
+ append_hilite_off(right_buf);
+ /* hex columns: */
+ if(hilite_multi && cont_count)
+ hl_type = HL_NORM_INV;
for(i = 0; i <= cont_count; i++) {
- append_left(bytes[i], (i != cont_count), fg, bg);
+ append_left(bytes[i], (i != cont_count), hl_type);
}
return 1;
diff --git a/uxd.rst b/uxd.rst
index de5cc86..ed487ae 100644
--- a/uxd.rst
+++ b/uxd.rst
@@ -78,8 +78,8 @@ by itself.
-m
Monochrome mode. Uses underline, bold, reverse video instead of color.
Use this if you have trouble distinguishing the colors, or if they
- look too much like angry fruit salad.
- NOT IMPLEMENTED YET.
+ look too much like angry fruit salad. Disables prior **-b**, **-c**
+ options.
-n
Ignore **UXD_OPTS** environment variable. This option should not be
@@ -107,7 +107,7 @@ by itself.
Works with negative *pos*, too.
-u
- Use uppercase hex digits A-F. Default is lowercase.
+ Use uppercase hex digits *A-F*. Default is lowercase.
-v, --version
Print version number and exit.
@@ -251,7 +251,8 @@ ENVIRONMENT
**UXD_OPTS**
If this is set, its value is treated as a set of options, which
- get applied before any command-line options.
+ get applied before any command-line options (unless the command-line
+ options inclue **-n**).
**NO_COLOR**
If this is set (to any value), **uxd** runs in monochrome mode, just