Browse Source

Merge branch 'unicode' into bfgminer

Luke Dashjr 12 years ago
parent
commit
224930f028
6 changed files with 208 additions and 30 deletions
  1. 1 1
      api.c
  2. 2 2
      driver-bitforce.c
  3. 1 1
      fpgautils.c
  4. 186 21
      miner.c
  5. 5 5
      util.c
  6. 13 0
      util.h

+ 1 - 1
api.c

@@ -3468,7 +3468,7 @@ static void setup_ipaccess()
 
 		group = NOPRIVGROUP;
 
-		if (isalpha(*ptr) && *(ptr+1) == ':') {
+		if (VALIDGROUP(*ptr) && *(ptr+1) == ':') {
 			if (DEFINEDGROUP(*ptr))
 				group = GROUP(*ptr);
 

+ 2 - 2
driver-bitforce.c

@@ -588,10 +588,10 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce)
 			goto skipvolts;
 		for (v = strtok_r(voltbuf, ",", &saveptr); v; v = strtok_r(NULL, ",", &saveptr))
 		{
-			while (isspace(v[0]))
+			while (isCspace(v[0]))
 				++v;
 			sz = strlen(v);
-			while (isspace(v[sz - 1]))
+			while (isCspace(v[sz - 1]))
 				--sz;
 			if (sz < 4)
 			{

+ 1 - 1
fpgautils.c

@@ -258,7 +258,7 @@ char *_sysfs_do_read(char *buf, size_t bufsz, const char *devpath, char *devfile
 		if (fgets(buf, bufsz, F))
 		{
 			size_t L = strlen(buf);
-			while (isspace(buf[--L]))
+			while (isCspace(buf[--L]))
 				buf[L] = '\0';
 		}
 		else

+ 186 - 21
miner.c

@@ -13,11 +13,17 @@
 #include "config.h"
 
 #ifdef HAVE_CURSES
+#define PDC_WIDE
 #include <curses.h>
+
+#ifdef WACS_HLINE
+#define USE_UNICODE
+#endif
 #endif
 
 #include <ctype.h>
 #include <limits.h>
+#include <locale.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -30,6 +36,7 @@
 #include <stdarg.h>
 #include <assert.h>
 #include <signal.h>
+#include <wctype.h>
 
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -280,6 +287,15 @@ const
 bool curses_active;
 
 #ifdef HAVE_CURSES
+static
+#ifdef USE_UNICODE
+bool use_unicode = true;
+bool have_unicode_degrees;
+#else
+const bool use_unicode;
+const bool have_unicode_degrees;
+#endif
+
 bool selecting_device;
 unsigned selected_device;
 #endif
@@ -1557,6 +1573,14 @@ static struct opt_table opt_config_table[] = {
 	                opt_set_invbool, &opt_opencl_binaries,
 	                "Don't attempt to use or save OpenCL kernel binaries"),
 #endif
+	OPT_WITHOUT_ARG("--no-unicode",
+	                opt_set_invbool, &use_unicode,
+#ifdef USE_UNICODE
+	                "Don't use Unicode characters in TUI"
+#else
+	                opt_hidden
+#endif
+	),
 	OPT_WITH_ARG("--pass|-p",
 		     set_pass, NULL, NULL,
 		     "Password for bitcoin JSON-RPC server"),
@@ -2586,6 +2610,26 @@ void format_statline(char *buf, const char *cHr, const char *aHr, const char *uH
 }
 #endif
 
+static inline
+void temperature_column_tail(char *buf, bool maybe_unicode, const float * const temp)
+{
+	if (!(use_unicode && have_unicode_degrees))
+		maybe_unicode = false;
+	if (temp && *temp > 0.)
+		if (maybe_unicode)
+			sprintf(buf, "%4.1f\xb0""C", *temp);
+		else
+			sprintf(buf, "%4.1fC", *temp);
+	else
+	{
+		if (temp)
+			strcpy(buf, "     ");
+		if (maybe_unicode)
+			strcat(buf, " ");
+	}
+	strcat(buf, " | ");
+}
+
 void get_statline3(char *buf, struct cgpu_info *cgpu, bool for_curses, bool opt_show_procs)
 {
 #ifndef HAVE_CURSES
@@ -2664,7 +2708,7 @@ void get_statline3(char *buf, struct cgpu_info *cgpu, bool for_curses, bool opt_
 	}
 	
 	if (likely(cgpu->status != LIFE_DEAD2) && drv->override_statline_temp && drv->override_statline_temp(buf, cgpu, opt_show_procs))
-		strcat(buf, " | ");
+		temperature_column_tail(&buf[strlen(buf)], for_curses, NULL);
 	else
 	{
 		float temp = cgpu->temp;
@@ -2675,16 +2719,13 @@ void get_statline3(char *buf, struct cgpu_info *cgpu, bool for_curses, bool opt_
 				if (proc->temp > temp)
 					temp = proc->temp;
 		}
-		if (temp > 0.)
-			tailsprintf(buf, "%4.1fC | ", temp);
-		else
-			strcat(buf, "      | ");
+		temperature_column_tail(&buf[strlen(buf)], for_curses, &temp);
 	}
 	
 #ifdef HAVE_CURSES
 	if (for_curses)
 	{
-		const char *cHrStatsOpt[] = {"DEAD ", "SICK ", "OFF  ", "REST ", " ERR ", "WAIT ", cHr};
+		const char *cHrStatsOpt[] = {"\2DEAD \1", "\2SICK \1", "OFF  ", "\2REST \1", " \2ERR \1", "\2WAIT \1", cHr};
 		int cHrStatsI = (sizeof(cHrStatsOpt) / sizeof(*cHrStatsOpt)) - 1;
 		bool all_dead = true, all_off = true;
 		for (struct cgpu_info *proc = cgpu; proc; proc = proc->next_proc)
@@ -2762,6 +2803,89 @@ static void text_print_status(int thr_id)
 }
 
 #ifdef HAVE_CURSES
+static int attr_bad = A_BOLD;
+
+static
+void bfg_waddstr(WINDOW *win, const char *s)
+{
+	const char *p = s;
+#ifdef USE_UNICODE
+	wchar_t buf[2] = {0, 0};
+#else
+	char buf[1];
+#endif
+	
+#define PREP_ADDCH  do {  \
+	if (p != s)  \
+		waddnstr(win, s, p - s);  \
+	s = ++p;  \
+}while(0)
+	while (true)
+	{
+next:
+		switch(p[0])
+		{
+			case '\0':
+				goto done;
+			default:
+def:
+				++p;
+				goto next;
+			case '\1':
+				PREP_ADDCH;
+				wattroff(win, attr_bad);
+				goto next;
+			case '\2':
+				PREP_ADDCH;
+				wattron(win, attr_bad);
+				goto next;
+#ifdef USE_UNICODE
+			case '|':
+				if (!use_unicode)
+					goto def;
+				PREP_ADDCH;
+				wadd_wch(win, WACS_VLINE);
+				goto next;
+#endif
+			case '\xc1':
+			case '\xc4':
+				if (!use_unicode)
+				{
+					buf[0] = '-';
+					break;
+				}
+#ifdef USE_UNICODE
+				PREP_ADDCH;
+				wadd_wch(win, (p[-1] == '\xc4') ? WACS_HLINE : WACS_BTEE);
+				goto next;
+			case '\xb0':  // Degrees symbol
+				buf[0] = ((unsigned char *)p)[0];
+#endif
+		}
+		PREP_ADDCH;
+#ifdef USE_UNICODE
+		waddwstr(win, buf);
+#else
+		waddch(win, buf[0]);
+#endif
+	}
+done:
+	PREP_ADDCH;
+	return;
+#undef PREP_ADDCH
+}
+
+static inline
+void bfg_hline(WINDOW *win, int y)
+{
+#ifdef USE_UNICODE
+	if (use_unicode)
+		mvwhline_set(win, y, 0, WACS_HLINE, 80);
+	else
+#endif
+		mvwhline(win, y, 0, '-', 80);
+}
+
 static int menu_attr = A_REVERSE;
 
 /* Must be called with curses mutex lock held and curses_active */
@@ -2771,6 +2895,7 @@ static void curses_print_status(void)
 	struct timeval now, tv;
 	float efficiency;
 	double utility;
+	int logdiv;
 
 	efficiency = total_bytes_xfer ? total_diff_accepted * 2048. / total_bytes_xfer : 0.0;
 
@@ -2796,7 +2921,8 @@ static void curses_print_status(void)
 		);
 	}
 	wattroff(statuswin, A_BOLD);
-	mvwprintw(statuswin, 5, 0, " %s", statusline);
+	wmove(statuswin, 5, 1);
+	bfg_waddstr(statuswin, statusline);
 	wclrtoeol(statuswin);
 
 	utility = total_accepted / total_secs * 60;
@@ -2827,8 +2953,25 @@ static void curses_print_status(void)
 	wclrtoeol(statuswin);
 	mvwprintw(statuswin, 3, 0, " Block: %s  Diff:%s (%s)  Started: %s",
 		  current_hash, block_diff, net_hashrate, blocktime);
-	mvwhline(statuswin, 6, 0, '-', 80);
-	mvwhline(statuswin, statusy - 1, 0, '-', 80);
+	
+	logdiv = statusy - 1;
+	bfg_hline(statuswin, 6);
+	bfg_hline(statuswin, logdiv);
+#ifdef USE_UNICODE
+	if (use_unicode)
+	{
+		int offset = 8 /* device */ + 5 /* temperature */ + 1 /* padding space */;
+		if (opt_show_procs && !opt_compact)
+			++offset;  // proc letter
+		if (have_unicode_degrees)
+			++offset;  // degrees symbol
+		mvwadd_wch(statuswin, 6, offset, WACS_PLUS);
+		mvwadd_wch(statuswin, logdiv, offset, WACS_BTEE);
+		offset += 24;  // hashrates etc
+		mvwadd_wch(statuswin, 6, offset, WACS_PLUS);
+		mvwadd_wch(statuswin, logdiv, offset, WACS_BTEE);
+	}
+#endif
 	
 	wattron(statuswin, menu_attr);
 	mvwprintw(statuswin, 1, 0, " [M]anage devices [P]ool management [S]ettings [D]isplay options  [H]elp [Q]uit ");
@@ -2873,7 +3016,7 @@ static void curses_print_devstatus(struct cgpu_info *cgpu)
 	get_statline2(logline, cgpu, true);
 	if (selecting_device && (opt_show_procs ? (selected_device == cgpu->cgminer_id) : (devices[selected_device]->device == cgpu)))
 		wattron(statuswin, A_REVERSE);
-	waddstr(statuswin, logline);
+	bfg_waddstr(statuswin, logline);
 	wattroff(statuswin, A_REVERSE);
 
 	wclrtoeol(statuswin);
@@ -2974,7 +3117,7 @@ void _wlog(const char *str)
 	size_t end = strlen(str) - 1;
 	
 	if (newline)
-		wprintw(logwin, "\n");
+		bfg_waddstr(logwin, "\n");
 	
 	if (str[end] == '\n')
 	{
@@ -2989,7 +3132,7 @@ void _wlog(const char *str)
 	else
 		newline = false;
 	
-	wprintw(logwin, "%s", str);
+	bfg_waddstr(logwin, str);
 }
 
 /* Mandatory printing */
@@ -6317,7 +6460,7 @@ void show_help(void)
 		"ST: work in queue              | F: network fails  | NB: new blocks detected\n"
 		"AS: shares being submitted     | BW: bandwidth (up/down)\n"
 		"E: # shares * diff per 2kB bw  | U: shares/minute  | BS: best share ever found\n"
-		"--------------------------------------------------------------------------------\n"
+		"\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc1\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc1\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\n"
 		"devices/processors hashing (only for totals line), hottest temperature\n"
 	);
 	wlogprint(
@@ -6523,6 +6666,7 @@ static void hashmeter(int thr_id, struct timeval *diff,
 		struct cgpu_info *proc;
 		int i, working_devs = 0, working_procs = 0;
 		int divx;
+		bool bad = false;
 		
 		// Find the highest temperature of all processors
 		for (i = 0; i < total_devices; ++i)
@@ -6532,29 +6676,38 @@ static void hashmeter(int thr_id, struct timeval *diff,
 			if (proc->temp > temp)
 				temp = proc->temp;
 			
-			if (likely(proc->status == LIFE_WELL && proc->deven == DEV_ENABLED && proc->rolling > .1))
+			if (unlikely(proc->deven == DEV_DISABLED || proc->rolling < .1))
+				;  // Just need to block it off from both conditions
+			else
+			if (likely(proc->status == LIFE_WELL && proc->deven == DEV_ENABLED))
 			{
 				++working_procs;
 				if (proc->device == proc)
 					++working_devs;
 			}
+			else
+				bad = true;
 		}
 		
 		if (working_devs == working_procs)
-			sprintf(statusline, "%d        ", working_devs);
+			sprintf(statusline, "%s%d        ", bad ? "\2" : "", working_devs);
 		else
-			sprintf(statusline, "%d/%d     ", working_devs, working_procs);
+			sprintf(statusline, "%s%d/%d     ", bad ? "\2" : "", working_devs, working_procs);
 		
 		divx = 7;
 		if (opt_show_procs && !opt_compact)
 			++divx;
 		
-		if (temp > 0.)
-			sprintf(&statusline[divx], "%4.1fC | ", temp);
-		else
-			strcpy(&statusline[divx], "      | ");
+		if (bad)
+		{
+			++divx;
+			statusline[divx] = '\1';
+			++divx;
+		}
+		
+		temperature_column_tail(&statusline[divx], true, &temp);
 		
-		format_statline(&statusline[15],
+		format_statline(statusline,
 		                cHr, aHr,
 		                uHr,
 		                total_accepted,
@@ -8945,10 +9098,22 @@ void enable_curses(void) {
 		return;
 	}
 
+#ifdef USE_UNICODE
+	if (use_unicode)
+	{
+		setlocale(LC_CTYPE, "");
+		if (iswprint(0xb0))
+			have_unicode_degrees = true;
+	}
+#endif
 	mainwin = initscr();
 	start_color();
 	if (has_colors() && ERR != init_pair(1, COLOR_WHITE, COLOR_BLUE))
+	{
 		menu_attr = COLOR_PAIR(1);
+		if (ERR != init_pair(2, COLOR_RED, COLOR_BLACK))
+			attr_bad |= COLOR_PAIR(2);
+	}
 	keypad(mainwin, true);
 	getmaxyx(mainwin, y, x);
 	statuswin = newwin(logstart, x, 0, 0);

+ 5 - 5
util.c

@@ -117,7 +117,7 @@ static size_t all_data_cb(const void *ptr, size_t size, size_t nmemb,
 	if (db->idlemarker) {
 		const unsigned char *cptr = ptr;
 		for (size_t i = 0; i < len; ++i)
-			if (!(isspace(cptr[i]) || cptr[i] == '{')) {
+			if (!(isCspace(cptr[i]) || cptr[i] == '{')) {
 				*db->idlemarker = CURL_SOCKET_BAD;
 				db->idlemarker = NULL;
 				break;
@@ -182,14 +182,14 @@ static size_t resp_hdr_cb(void *ptr, size_t size, size_t nmemb, void *user_data)
 
 	rem = ptr + slen + 1;		/* trim value's leading whitespace */
 	remlen = ptrlen - slen - 1;
-	while ((remlen > 0) && (isspace(*rem))) {
+	while ((remlen > 0) && (isCspace(*rem))) {
 		remlen--;
 		rem++;
 	}
 
 	memcpy(val, rem, remlen);	/* store value, trim trailing ws */
 	val[remlen] = 0;
-	while ((*val) && (isspace(val[strlen(val) - 1])))
+	while ((*val) && (isCspace(val[strlen(val) - 1])))
 		val[strlen(val) - 1] = 0;
 
 	if (!*val)			/* skip blank value */
@@ -356,7 +356,7 @@ static int curl_debug_cb(__maybe_unused CURL *handle, curl_infotype type,
 			// data is not null-terminated, so we need to copy and terminate it for applog
 			char datacp[size + 1];
 			memcpy(datacp, data, size);
-			while (likely(size) && unlikely(isspace(datacp[size-1])))
+			while (likely(size) && unlikely(isCspace(datacp[size-1])))
 				--size;
 			if (unlikely(!size))
 				break;
@@ -1578,7 +1578,7 @@ char *json_dumps_ANY(json_t *json, size_t flags)
 	if (!s)
 		return NULL;
 	for (i = 0; s[i] != '['; ++i)
-		if (unlikely(!(s[i] && isspace(s[i]))))
+		if (unlikely(!(s[i] && isCspace(s[i]))))
 			quit(1, "json_dumps_ANY failed to find opening bracket in array dump");
 	len = strlen(&s[++i]) - 1;
 	if (unlikely(s[i+len] != ']'))

+ 13 - 0
util.h

@@ -13,6 +13,7 @@
 #ifndef __UTIL_H__
 #define __UTIL_H__
 
+#include <stdbool.h>
 #include <sys/time.h>
 
 #include <curl/curl.h>
@@ -73,6 +74,18 @@
 #endif
 extern char *json_dumps_ANY(json_t *, size_t flags);
 
+static inline
+bool isCspace(int c)
+{
+	switch (c)
+	{
+		case ' ': case '\f': case '\n': case '\r': case '\t': case '\v':
+			return true;
+		default:
+			return false;
+	}
+}
+
 struct thr_info;
 struct pool;
 enum dev_reason;