From af2b5dc45c3925d8a3c98557bf164248b2ceda00 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Thu, 6 Mar 2014 16:21:40 +0000 Subject: [PATCH 01/51] T.83.5: Fix 'M'erge giving bogus time when a marked entry is running. --- configure | 18 +++++++++--------- configure.ac | 2 +- tts.c | 6 ++---- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/configure b/configure index 735cc19..e969348 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for RT/TTS T.83.4. +# Generated by GNU Autoconf 2.69 for RT/TTS T.83.5. # # Report bugs to . # @@ -580,8 +580,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='RT/TTS' PACKAGE_TARNAME='rt-tts' -PACKAGE_VERSION='T.83.4' -PACKAGE_STRING='RT/TTS T.83.4' +PACKAGE_VERSION='T.83.5' +PACKAGE_STRING='RT/TTS T.83.5' PACKAGE_BUGREPORT='felicity@loreley.flyingparchment.org.uk' PACKAGE_URL='' @@ -1232,7 +1232,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures RT/TTS T.83.4 to adapt to many kinds of systems. +\`configure' configures RT/TTS T.83.5 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1293,7 +1293,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of RT/TTS T.83.4:";; + short | recursive ) echo "Configuration of RT/TTS T.83.5:";; esac cat <<\_ACEOF @@ -1380,7 +1380,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -RT/TTS configure T.83.4 +RT/TTS configure T.83.5 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1749,7 +1749,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by RT/TTS $as_me T.83.4, which was +It was created by RT/TTS $as_me T.83.5, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -4766,7 +4766,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by RT/TTS $as_me T.83.4, which was +This file was extended by RT/TTS $as_me T.83.5, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -4828,7 +4828,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -RT/TTS config.status T.83.4 +RT/TTS config.status T.83.5 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index d08577f..3101cda 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ([2.69]) -AC_INIT([RT/TTS], [T.83.4], [felicity@loreley.flyingparchment.org.uk]) +AC_INIT([RT/TTS], [T.83.5], [felicity@loreley.flyingparchment.org.uk]) AC_CONFIG_SRCDIR([tts.c]) AC_CONFIG_HEADERS([config.h]) diff --git a/tts.c b/tts.c index 53eb15b..f904518 100644 --- a/tts.c +++ b/tts.c @@ -1317,11 +1317,9 @@ int h, m, s = 0; TAILQ_FOREACH_SAFE(en, &entries, en_entries, ten) { if (!en->en_flags.efl_marked || en == curent) continue; - curent->en_secs += en->en_secs; - if (en->en_started) { + if (en->en_started) entry_stop(en); - curent->en_secs += time(NULL) - en->en_started; - } + curent->en_secs += en->en_secs; TAILQ_REMOVE(&entries, en, en_entries); entry_free(en); } From b174130c91a93b08e7465c8f0a4e66dd9cfd46be Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Fri, 7 Mar 2014 16:11:23 +0000 Subject: [PATCH 02/51] T.83.6: Incorrect memory allocation in configuration parser. --- configure | 18 +++++++++--------- configure.ac | 2 +- tts.c | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/configure b/configure index e969348..a3798e9 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for RT/TTS T.83.5. +# Generated by GNU Autoconf 2.69 for RT/TTS T.83.6. # # Report bugs to . # @@ -580,8 +580,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='RT/TTS' PACKAGE_TARNAME='rt-tts' -PACKAGE_VERSION='T.83.5' -PACKAGE_STRING='RT/TTS T.83.5' +PACKAGE_VERSION='T.83.6' +PACKAGE_STRING='RT/TTS T.83.6' PACKAGE_BUGREPORT='felicity@loreley.flyingparchment.org.uk' PACKAGE_URL='' @@ -1232,7 +1232,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures RT/TTS T.83.5 to adapt to many kinds of systems. +\`configure' configures RT/TTS T.83.6 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1293,7 +1293,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of RT/TTS T.83.5:";; + short | recursive ) echo "Configuration of RT/TTS T.83.6:";; esac cat <<\_ACEOF @@ -1380,7 +1380,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -RT/TTS configure T.83.5 +RT/TTS configure T.83.6 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1749,7 +1749,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by RT/TTS $as_me T.83.5, which was +It was created by RT/TTS $as_me T.83.6, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -4766,7 +4766,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by RT/TTS $as_me T.83.5, which was +This file was extended by RT/TTS $as_me T.83.6, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -4828,7 +4828,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -RT/TTS config.status T.83.5 +RT/TTS config.status T.83.6 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 3101cda..05984dd 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ([2.69]) -AC_INIT([RT/TTS], [T.83.5], [felicity@loreley.flyingparchment.org.uk]) +AC_INIT([RT/TTS], [T.83.6], [felicity@loreley.flyingparchment.org.uk]) AC_CONFIG_SRCDIR([tts.c]) AC_CONFIG_HEADERS([config.h]) diff --git a/tts.c b/tts.c index f904518..495e385 100644 --- a/tts.c +++ b/tts.c @@ -2484,7 +2484,7 @@ const WCHAR *p, *q; /* Copy the argument (which is sz bytes long) into the result array */ sz = (q - p); *res = realloc(*res, sizeof(WCHAR *) * (ntoks + 1)); - (*res)[ntoks] = malloc(sizeof(WCHAR) * sz + 1); + (*res)[ntoks] = malloc(sizeof(WCHAR) * (sz + 1)); MEMCPY((*res)[ntoks], p, sz); (*res)[ntoks][sz] = 0; ntoks++; From 332fdba0bddd7ec7e89f8dae867e26c054e344fe Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Fri, 7 Mar 2014 17:43:41 +0000 Subject: [PATCH 03/51] Source refactoring; no functional changes. --- Makefile.in | 6 +- bindings.c | 13 + bindings.h | 36 ++ commands.c | 133 +++++ commands.h | 32 ++ entry.c | 124 +++++ entry.h | 59 ++ functions.c | 800 +++++++++++++++++++++++++++ functions.h | 51 ++ str.c | 107 ++++ str.h | 21 + style.h | 50 ++ tts.c | 1482 ++------------------------------------------------ tts.h | 65 +++ tts_curses.h | 30 + ui.c | 65 +++ ui.h | 37 ++ variable.h | 28 + wide.c | 26 + wide.h | 81 +++ 20 files changed, 1806 insertions(+), 1440 deletions(-) create mode 100644 bindings.c create mode 100644 bindings.h create mode 100644 commands.c create mode 100644 commands.h create mode 100644 entry.c create mode 100644 entry.h create mode 100644 functions.c create mode 100644 functions.h create mode 100644 str.c create mode 100644 str.h create mode 100644 style.h create mode 100644 tts.h create mode 100644 tts_curses.h create mode 100644 ui.c create mode 100644 ui.h create mode 100644 variable.h create mode 100644 wide.c create mode 100644 wide.h diff --git a/Makefile.in b/Makefile.in index 8ee1584..dd1b3a1 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,13 +1,15 @@ VPATH = @top_srcdir@ CC = @CC@ -CPPFLAGS = @CPPFLAGS@ +# _GNU_SOURCE is required for wcsdup() on older version of glibc that don't +# implement XPG7. +CPPFLAGS = @CPPFLAGS@ -D_XOPEN_SOURCE=700 -D_XOPEN_SOURCE_EXTENDED -D__EXTENSIONS__ CFLAGS = @CFLAGS@ -I@top_srcdir@ -I@top_builddir@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ INSTALL = @INSTALL@ -OBJS = tts.o +OBJS = tts.o wide.o entry.o ui.o functions.o commands.o bindings.o str.o prefix = @prefix@ exec_prefix = @exec_prefix@ diff --git a/bindings.c b/bindings.c new file mode 100644 index 0000000..0132f65 --- /dev/null +++ b/bindings.c @@ -0,0 +1,13 @@ +/* + * TTS - track your time. + * Copyright (c) 2012-2014 Felicity Tarnell. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely. This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "bindings.h" + +binding_list_t bindings = TAILQ_HEAD_INITIALIZER(bindings); diff --git a/bindings.h b/bindings.h new file mode 100644 index 0000000..8b7df24 --- /dev/null +++ b/bindings.h @@ -0,0 +1,36 @@ +/* + * TTS - track your time. + * Copyright (c) 2012-2014 Felicity Tarnell. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely. This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef TTS_BINDINGS_H +#define TTS_BINDINGS_H + +#include "wide.h" +#include "functions.h" +#include "queue.h" + +typedef struct tkey { + INT ky_code; + const WCHAR *ky_name; +} tkey_t; + +typedef struct binding { + INT bi_code; + tkey_t *bi_key; + function_t *bi_func; + TAILQ_ENTRY(binding) bi_entries; +} binding_t; + +typedef TAILQ_HEAD(bindlist, binding) binding_list_t; +extern binding_list_t bindings; + +tkey_t *find_key(const WCHAR *name); +void bind_key(const WCHAR *key, const WCHAR *func); + +#endif /* !TTS_BINDINGS_H */ diff --git a/commands.c b/commands.c new file mode 100644 index 0000000..906cabc --- /dev/null +++ b/commands.c @@ -0,0 +1,133 @@ +/* + * TTS - track your time. + * Copyright (c) 2012-2014 Felicity Tarnell. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely. This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "commands.h" +#include "style.h" +#include "bindings.h" +#include "variable.h" + +static command_t commands[] = { + { WIDE("bind"), c_bind }, + { WIDE("style"), c_style }, + { WIDE("set"), c_set }, + { } +}; + +command_t * +find_command(name) + const WCHAR *name; +{ +size_t i; + for (i = 0; i < sizeof(commands) / sizeof(*commands); i++) + if (STRCMP(name, commands[i].cm_name) == 0) + return &commands[i]; + return NULL; +} + +void +c_style(argc, argv) + size_t argc; + WCHAR **argv; +{ +style_t *sy; +WCHAR *last, *tok; + + if (argc < 3 || argc > 4) { + cmderr(WIDE("Usage: style [background]")); + return; + } + + if (STRCMP(argv[1], WIDE("header")) == 0) + sy = &sy_header; + else if (STRCMP(argv[1], WIDE("status")) == 0) + sy = &sy_status; + else if (STRCMP(argv[1], WIDE("entry")) == 0) + sy = &sy_entry; + else if (STRCMP(argv[1], WIDE("selected")) == 0) + sy = &sy_selected; + else if (STRCMP(argv[1], WIDE("running")) == 0) + sy = &sy_running; + else if (STRCMP(argv[1], WIDE("date")) == 0) + sy = &sy_date; + else { + cmderr(WIDE("Unknown style item.")); + return; + } + + style_clear(sy); + for (tok = STRTOK(argv[2], WIDE(","), &last); tok != NULL; + tok = STRTOK(NULL, WIDE(","), &last)) { + style_add(sy, tok, argv[3]); + } + + apply_styles(); +} + +void +c_bind(argc, argv) + size_t argc; + WCHAR **argv; +{ + if (argc != 3) { + cmderr(WIDE("Usage: bind ")); + return; + } + + bind_key(argv[1], argv[2]); +} + +void +c_set(argc, argv) + size_t argc; + WCHAR **argv; +{ +variable_t *var; +int val; + + if (argc != 3) { + cmderr(WIDE("Usage: set ")); + return; + } + + if ((var = find_variable(argv[1])) == NULL) { + cmderr(WIDE("Unknown variable \"%"FMT_L"s\"."), argv[1]); + return; + } + + switch (var->va_type) { + case VTYPE_BOOL: + if (STRCMP(argv[2], WIDE("true")) == 0 || + STRCMP(argv[2], WIDE("yes")) == 0 || + STRCMP(argv[2], WIDE("on")) == 0 || + STRCMP(argv[2], WIDE("1")) == 0) { + val = 1; + } else if (STRCMP(argv[2], WIDE("false")) == 0 || + STRCMP(argv[2], WIDE("no")) == 0 || + STRCMP(argv[2], WIDE("off")) == 0 || + STRCMP(argv[2], WIDE("0")) == 0) { + val = 0; + } else { + cmderr(WIDE("Invalid value for boolean: \"%"FMT_L"s\"."), argv[2]); + return; + } + + *(int *)var->va_addr = val; + break; + + case VTYPE_STRING: + *(WCHAR **)var->va_addr = STRDUP(argv[2]); + break; + + case VTYPE_INT: + *(int *)var->va_addr = STRTOL(argv[2], NULL, 0); + break; + } +} + diff --git a/commands.h b/commands.h new file mode 100644 index 0000000..cad450b --- /dev/null +++ b/commands.h @@ -0,0 +1,32 @@ +/* + * TTS - track your time. + * Copyright (c) 2012-2014 Felicity Tarnell. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely. This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef TTS_COMMANDS_H +#define TTS_COMMANDS_H + +#include + +#include "wide.h" + +typedef struct command { + const WCHAR *cm_name; + void (*cm_hdl) (size_t, WCHAR **); +} command_t; + +command_t *find_command(const WCHAR *); + +void c_bind (size_t, WCHAR **); +void c_style (size_t, WCHAR **); +void c_set (size_t, WCHAR **); + +void cmderr (const WCHAR *, ...); +void vcmderr (const WCHAR *, va_list); + +#endif /* !TTS_COMMANDS_H */ diff --git a/entry.c b/entry.c new file mode 100644 index 0000000..b6e4ce6 --- /dev/null +++ b/entry.c @@ -0,0 +1,124 @@ +/* + * TTS - track your time. + * Copyright (c) 2012-2014 Felicity Tarnell. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely. This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include +#include +#include +#include + +#include "entry.h" +#include "wide.h" +#include "tts.h" + +entry_list entries = TAILQ_HEAD_INITIALIZER(entries); + +entry_t *running; + +entry_t * +entry_new(desc) + const WCHAR *desc; +{ +entry_t *en; + if ((en = calloc(1, sizeof(*en))) == NULL) + return NULL; + + if (auto_nonbillable && STRSTR(desc, auto_nonbillable)) + en->en_flags.efl_nonbillable = 1; + + TAILQ_INSERT_HEAD(&entries, en, en_entries); + + en->en_desc = STRDUP(desc); + time(&en->en_created); + + return en; +} + +void +entry_start(en) + entry_t *en; +{ + if (running) + entry_stop(running); + time(&en->en_started); + running = en; +} + +void +entry_stop(en) + entry_t *en; +{ + if (running == en) + running = NULL; + en->en_secs += time(NULL) - en->en_started; + en->en_started = 0; +} + +void +entry_free(en) + entry_t *en; +{ + if (en == running) + entry_stop(en); + free(en->en_desc); +} + +void +entry_account(en) + entry_t *en; +{ + if (!en->en_started) + return; + en->en_secs += time(NULL) - en->en_started; + time(&en->en_started); +} + +/* + * Return the amount of time for the day on which the timestamp .when falls. + * If .inv is 0, sum non-invoiced entries; if 1, sum invoiced entries; if + * 2, sum billable entries; if -1, sum all entries. If .incr is non-zero, + * individual entry time will be rounded up to intervals of that many minutes. + */ +time_t +entry_time_for_day(when, inv, incr) + time_t when; +{ +time_t day = time_day(when); +time_t sum = 0; +entry_t *en; +int rnd = incr * 60; + TAILQ_FOREACH(en, &entries, en_entries) { + time_t n; + + if (entry_day(en) > day) + continue; + if (entry_day(en) < day) + break; + + if (inv == 0 && en->en_flags.efl_invoiced) + continue; + if (inv == 1 && !en->en_flags.efl_invoiced) + continue; + if (inv == 2 && en->en_flags.efl_nonbillable) + continue; + + n = en->en_secs; + if (en->en_started) + n += time(NULL) - en->en_started; + + if (!n) + continue; + + if (rnd) + n = (1 + round((n - 1) / rnd)) * rnd; + sum += n; + } + return sum; +} + diff --git a/entry.h b/entry.h new file mode 100644 index 0000000..68b45a1 --- /dev/null +++ b/entry.h @@ -0,0 +1,59 @@ +/* + * TTS - track your time. + * Copyright (c) 2012-2014 Felicity Tarnell. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely. This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef TTS_ENTRY_H +#define TTS_ENTRY_H + +#include + +#include "queue.h" +#include "wide.h" + +typedef struct entry { + WCHAR *en_desc; + int en_secs; + time_t en_started; + time_t en_created; + + struct { + int efl_visible:1; + int efl_invoiced:1; + int efl_marked:1; + int efl_deleted:1; + int efl_nonbillable:1; + } en_flags; + TAILQ_ENTRY(entry) en_entries; +} entry_t; + +typedef TAILQ_HEAD(entrylist, entry) entry_list; +extern entry_list entries; + +extern entry_t *running; + +entry_t *entry_new (const WCHAR *); +void entry_start (entry_t *); +void entry_stop (entry_t *); +void entry_free (entry_t *); +void entry_account (entry_t *); +time_t entry_time_for_day (time_t, int, int); + +#define time_day(t) (((t) / (60 * 60 * 24)) * (60 * 60 * 24)) +#define entry_day(e) (time_day((e)->en_created)) + +#define time_to_hms(t, h, m, s) do { \ + time_t n = t; \ + h = n / (60 * 60); \ + n %= (60 * 60); \ + m = n / 60; \ + n %= 60; \ + s = n; \ + } while (0) + +#endif /* !TTS_ENTRY_H */ diff --git a/functions.c b/functions.c new file mode 100644 index 0000000..3b8631a --- /dev/null +++ b/functions.c @@ -0,0 +1,800 @@ +/* + * TTS - track your time. + * Copyright (c) 2012-2014 Felicity Tarnell. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely. This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include + +#include "functions.h" +#include "tts.h" +#include "entry.h" +#include "ui.h" +#include "commands.h" +#include "tts_curses.h" +#include "bindings.h" +#include "str.h" + +function_t funcs[] = { + { WIDE("help"), khelp, WIDE("display help screen") }, + { WIDE("add"), kadd, WIDE("add a new entry and start the timer") }, + { WIDE("add-old"), kaddold, WIDE("add a new entry and specify its duration") }, + { WIDE("delete"), kmarkdel, WIDE("delete the current entry") }, + { WIDE("undelete"), kundel, WIDE("undelete the current entry") }, + { WIDE("quit"), kquit, WIDE("exit TTS") }, + { WIDE("invoice"), kinvoiced, WIDE("toggle current entry as invoiced") }, + { WIDE("billable"), kbillable, WIDE("toggle current entry as billable") }, + { WIDE("mark"), kmark, WIDE("mark the current entry") }, + { WIDE("unmarkall"), kunmarkall, WIDE("unmark all entries") }, + { WIDE("startstop"), ktoggle, WIDE("start or stop the timer") }, + { WIDE("edit-desc"), keddesc, WIDE("edit the current entry's description") }, + { WIDE("edit-time"), kedtime, WIDE("edit the current entry's duration") }, + { WIDE("showhide-inv"), ktoggleinv, WIDE("show or hide invoiced entries") }, + { WIDE("copy"), kcopy, WIDE("copy the current entry's description to a new entry") }, + { WIDE("add-time"), kaddtime, WIDE("add time to the current entry") }, + { WIDE("sub-time"), kdeltime, WIDE("subtract time from the current entry") }, + { WIDE("search"), ksearch, WIDE("search for an entry by name") }, + { WIDE("sync"), ksync, WIDE("purge all deleted entries") }, + { WIDE("prev"), kup, WIDE("move to the previous entry") }, + { WIDE("next"), kdown, WIDE("move to the next entry") }, + { WIDE("execute"), kexec, WIDE("execute a configuration command") }, + { WIDE("merge"), kmerge, WIDE("merge marked entries into current entry") }, + { WIDE("interrupt"), kint, WIDE("split current entry into new entry")}, + { } +}; + +void +kquit() +{ +entry_t *en; +int ndel = 0; + + TAILQ_FOREACH(en, &entries, en_entries) { + if (en->en_flags.efl_deleted) + ndel++; + } + + if (ndel) { + WCHAR s[128]; + SNPRINTF(s, WSIZEOF(s), WIDE("Purge %d deleted entries?"), ndel); + if (yesno(s)) { + ksync(); + } + } + + doexit = 1; +} + +void +kadd() +{ +WCHAR *name; +entry_t *en; + name = prompt(WIDE("Description:"), NULL, NULL); + if (!name || !*name) { + free(name); + return; + } + en = entry_new(name); + entry_start(en); + curent = en; + save(); +} + +void +kaddold() +{ +WCHAR *name; +entry_t *en; + name = prompt(WIDE("Description:"), NULL, NULL); + + if (!name || !*name) { + free(name); + return; + } + + en = entry_new(name); + curent = en; + kedtime(); + save(); +} + +void +ktoggle() +{ + itime = 0; + + if (!curent) + return; + + if (curent == running) { + entry_stop(curent); + save(); + return; + } + + if (running) + entry_stop(running); + entry_start(curent); + save(); +} + +void +kundel() +{ + if (!curent) + return; + + curent->en_flags.efl_deleted = 0; + if (delete_advance) + cursadvance(); +} + +void +kmarkdel() +{ +entry_t *en; +int nmarked = 0; + + TAILQ_FOREACH(en, &entries, en_entries) { + if (en->en_flags.efl_marked) { + nmarked++; + en->en_flags.efl_deleted = 1; + } + } + + if (nmarked) + return; + + if (!curent) { + drawstatus(WIDE("No entries to delete.")); + return; + } + + curent->en_flags.efl_deleted = 1; + + if (delete_advance) + cursadvance(); +} + +void +ksync() +{ +entry_t *en, *ten; + + TAILQ_FOREACH_SAFE(en, &entries, en_entries, ten) { + if (!en->en_flags.efl_deleted) + continue; + if (en == curent) + curent = NULL; + TAILQ_REMOVE(&entries, en, en_entries); + entry_free(en); + } + + if (curent == NULL) + curent = TAILQ_FIRST(&entries); + save(); +} + +void +kup() +{ +entry_t *prev = curent; + if (!curent) + return; + + do { + if ((prev = TAILQ_PREV(prev, entrylist, en_entries)) == NULL) + break; + } while (!showinv && prev->en_flags.efl_invoiced); + + if (prev == NULL) { + drawstatus(WIDE("Already at first entry.")); + return; + } + + curent = prev; + if (!curent->en_flags.efl_visible) + pagestart--; +} + +void +kdown() +{ +entry_t *next = curent; + if (!curent) + return; + + do { + if ((next = TAILQ_NEXT(next, en_entries)) == NULL) + break; + } while (!showinv && next->en_flags.efl_invoiced); + + if (next == NULL) { + drawstatus(WIDE("Already at last entry.")); + return; + } + + curent = next; + if (!curent->en_flags.efl_visible) + pagestart++; +} + +void +kinvoiced() +{ +entry_t *en; +int anymarked = 0; + + TAILQ_FOREACH(en, &entries, en_entries) { + if (!en->en_flags.efl_marked) + continue; + anymarked = 1; + en->en_flags.efl_invoiced = !en->en_flags.efl_invoiced; + en->en_flags.efl_marked = 0; + } + + if (anymarked) { + save(); + return; + } + + if (!curent) { + drawstatus(WIDE("No entry selected.")); + return; + } + + curent->en_flags.efl_invoiced = !curent->en_flags.efl_invoiced; + save(); + + en = curent; + + if (showinv) { + if (TAILQ_NEXT(curent, en_entries) != NULL) + curent = TAILQ_NEXT(curent, en_entries); + return; + } + + /* + * Try to find the next uninvoiced request to move the cursor to. + */ + for (;;) { + if ((curent = TAILQ_NEXT(curent, en_entries)) == NULL) + break; /* end of list */ + if (!curent->en_flags.efl_invoiced) + return; + } + + /* + * We didn't find any, so try searching backwards instead. + */ + for (curent = en;;) { + if ((curent = TAILQ_PREV(curent, entrylist, en_entries)) == NULL) + break; /* end of list */ + if (!curent->en_flags.efl_invoiced) + return; + } +} + +void +kbillable() +{ +entry_t *en; +int anymarked = 0; + + TAILQ_FOREACH(en, &entries, en_entries) { + if (!en->en_flags.efl_marked) + continue; + anymarked = 1; + en->en_flags.efl_nonbillable = !en->en_flags.efl_nonbillable; + en->en_flags.efl_marked = 0; + } + + if (anymarked) { + save(); + return; + } + + if (!curent) { + drawstatus(WIDE("No entry selected.")); + return; + } + + curent->en_flags.efl_nonbillable = !curent->en_flags.efl_nonbillable; + save(); + + if (bill_advance) + cursadvance(); +} + +void +keddesc() +{ +WCHAR *new; + + if (!curent) { + drawstatus(WIDE("No entry selected.")); + return; + } + + if ((new = prompt(WIDE("Description:"), curent->en_desc, NULL)) == NULL) + return; + + free(curent->en_desc); + curent->en_desc = new; + save(); +} + +void +kedtime() +{ +WCHAR *new, old[64]; +time_t n; +int h, m, s; + + if (!curent) { + drawstatus(WIDE("No entry selected.")); + return; + } + + n = curent->en_secs; + if (curent->en_started) + n += time(NULL) - curent->en_started; + h = n / (60 * 60); + n %= (60 * 60); + m = n / 60; + n %= 60; + s = n; + + SNPRINTF(old, WSIZEOF(old), WIDE("%02d:%02d:%02d"), h, m, s); + if ((new = prompt(WIDE("Duration [HH:MM:SS]:"), old, NULL)) == NULL) + return; + + if (!SSCANF(new, WIDE("%d:%d:%d"), &h, &m, &s)) { + free(new); + drawstatus(WIDE("Invalid duration.")); + } + + curent->en_secs = (h * 60 * 60) + (m * 60) + s; + if (curent->en_started) + time(&curent->en_started); + + save(); +} + +void +ktoggleinv() +{ +entry_t *en = curent; + showinv = !showinv; + drawstatus(WIDE("%"FMT_L"s invoiced entries."), + showinv ? L"Showing" : L"Hiding"); + + if (curent && !curent->en_flags.efl_invoiced) + return; + + if (!curent) { + curent = TAILQ_FIRST(&entries); + return; + } + + /* + * Try to find the next uninvoiced request to move the cursor to. + */ + for (;;) { + if ((curent = TAILQ_NEXT(curent, en_entries)) == NULL) + break; /* end of list */ + if (!curent->en_flags.efl_invoiced) + return; + } + + /* + * We didn't find any, so try searching backwards instead. + */ + for (curent = en;;) { + if ((curent = TAILQ_PREV(curent, entrylist, en_entries)) == NULL) + break; /* end of list */ + if (!curent->en_flags.efl_invoiced) + return; + } +} + +void +kcopy() +{ +entry_t *en; + + if (!curent) { + drawstatus(WIDE("No entry selected.")); + return; + } + + en = entry_new(curent->en_desc); + curent = en; + entry_start(en); + save(); +} + +void +kaddtime() +{ +WCHAR *tstr; +int h = 0, m = 0, s = 0, secs; + if (!curent) { + drawstatus(WIDE("No entry selected.")); + return; + } + + if ((tstr = prompt(WIDE("Time to add ([[HH:]MM:]SS):"), NULL, NULL)) == NULL) + return; + + if (!*tstr) { + drawstatus(WIDE("")); + free(tstr); + return; + } + + if (SSCANF(tstr, WIDE("%d:%d:%d"), &h, &m, &s) != 3) { + h = 0; + if (SSCANF(tstr, WIDE("%d:%d"), &m, &s) != 2) { + m = 0; + if (SSCANF(tstr, WIDE("%d"), &s) != 1) { + free(tstr); + drawstatus(WIDE("Invalid time format.")); + return; + } + } + } + + free(tstr); + + if (m >= 60) { + drawstatus(WIDE("Minutes cannot be more than 59.")); + return; + } + + if (s >= 60) { + drawstatus(WIDE("Seconds cannot be more than 59.")); + return; + } + + secs = s + m*60 + h*60*60; + curent->en_secs += secs; + save(); +} + +void +kdeltime() +{ +WCHAR *tstr; +int h = 0, m = 0, s = 0, secs; + if (!curent) { + drawstatus(WIDE("No entry selected.")); + return; + } + + if ((tstr = prompt(WIDE("Time to subtract, ([[HH:]MM:]SS):"), NULL, NULL)) == NULL) + return; + + if (!*tstr) { + drawstatus(WIDE("")); + free(tstr); + return; + } + + if (SSCANF(tstr, WIDE("%d:%d:%d"), &h, &m, &s) != 3) { + h = 0; + if (SSCANF(tstr, WIDE("%d:%d"), &m, &s) != 2) { + m = 0; + if (SSCANF(tstr, WIDE("%d"), &s) != 1) { + free(tstr); + drawstatus(WIDE("Invalid time format.")); + return; + } + } + } + + free(tstr); + if (m >= 60) { + drawstatus(WIDE("Minutes cannot be more than 59.")); + return; + } + + if (s >= 60) { + drawstatus(WIDE("Seconds cannot be more than 59.")); + return; + } + + entry_account(curent); + + secs = s + m*60 + h*60*60; + if (curent->en_secs - secs < 0) { + drawstatus(WIDE("Remaining time cannot be less than zero.")); + return; + } + + curent->en_secs -= secs; + save(); +} + +void +kmerge() +{ +entry_t *en, *ten; +int nmarked = 0; +WCHAR pr[128]; +int h, m, s = 0; + + if (!curent) { + drawstatus(WIDE("No entry selected.")); + return; + } + + /* + * Count number of marked entries and the summed time. + */ + TAILQ_FOREACH(en, &entries, en_entries) { + if (!en->en_flags.efl_marked || en == curent) + continue; + nmarked++; + s += en->en_secs; + if (en->en_started) + s += time(NULL) - en->en_started; + } + + if (nmarked == 0) { + drawstatus(WIDE("No marked entries.")); + return; + } + + h = s / (60 * 60); + s %= (60 * 60); + m = s / 60; + s %= 60; + + SNPRINTF(pr, WSIZEOF(pr), WIDE("Merge %d marked entries [%02d:%02d:%02d] into current entry?"), + nmarked, h, m, s); + if (!yesno(pr)) + return; + + TAILQ_FOREACH_SAFE(en, &entries, en_entries, ten) { + if (!en->en_flags.efl_marked || en == curent) + continue; + if (en->en_started) + entry_stop(en); + curent->en_secs += en->en_secs; + TAILQ_REMOVE(&entries, en, en_entries); + entry_free(en); + } + save(); +} + +void +khelp() +{ +WINDOW *hwin; +size_t nhelp = 0; +WCHAR **help; +#define HTITLE WIDE(" TTS keys ") +size_t width = 0; +size_t i; +INT c; +binding_t *bi; + + /* Count the number of bindings */ + TAILQ_FOREACH(bi, &bindings, bi_entries) + nhelp++; + help = calloc(nhelp, sizeof(const WCHAR *)); + + i = 0; + TAILQ_FOREACH(bi, &bindings, bi_entries) { + WCHAR s[128]; + if (bi->bi_key) + SNPRINTF(s, WSIZEOF(s), WIDE("%-10"FMT_L"s %"FMT_L"s (%"FMT_L"s)"), + bi->bi_key->ky_name, bi->bi_func->fn_desc, + bi->bi_func->fn_name); + else + SNPRINTF(s, WSIZEOF(s), WIDE("%"FMT_L"c %"FMT_L"s (%"FMT_L"s)"), + bi->bi_code, bi->bi_func->fn_desc, bi->bi_func->fn_name); + help[i] = STRDUP(s); + i++; + } + + if (nhelp > (LINES - 6)) + nhelp = LINES - 6; + + for (i = 0; i < nhelp; i++) + if (STRLEN(help[i]) > width) + width = STRLEN(help[i]); + + hwin = newwin(nhelp + 4, width + 4, + (LINES / 2) - ((nhelp + 2) / 2), + (COLS / 2) - ((width + 2) / 2)); + wborder(hwin, 0, 0, 0, 0, 0, 0, 0, 0); + + wattron(hwin, A_REVERSE | A_BOLD); + wmove(hwin, 0, (width / 2) - (WSIZEOF(HTITLE) - 1)/2); + WADDSTR(hwin, HTITLE); + wattroff(hwin, A_REVERSE | A_BOLD); + + for (i = 0; i < nhelp; i++) { + wmove(hwin, i + 2, 2); + WADDSTR(hwin, help[i]); + } + + wrefresh(hwin); + + while (WGETCH(hwin, &c) == ERR +#ifdef KEY_RESIZE + || (c == KEY_RESIZE) +#endif + ) + ; + + delwin(hwin); + + for (i = 0; i < nhelp; i++) + free(help[i]); + free(help); +} + +void +kmark() +{ + if (!curent) { + drawstatus(WIDE("No entry selected.")); + return; + } + + curent->en_flags.efl_marked = !curent->en_flags.efl_marked; + + if (mark_advance) + cursadvance(); +} + +void +kunmarkall() +{ +entry_t *en; + TAILQ_FOREACH(en, &entries, en_entries) + en->en_flags.efl_marked = 0; +} + +void +kint() +{ +time_t duration; +entry_t *en; +WCHAR *name; + + if (!itime) { + if (!running) { + drawstatus(WIDE("No running entry.")); + return; + } + + itime = time(NULL); + return; + } + + if (!running) { + drawstatus(WIDE("No running entry.")); + return; + } + + name = prompt(WIDE("Description:"), NULL, NULL); + + if (!name || !*name) { + itime = 0; + free(name); + return; + } + + if (itime) { + duration = time(NULL) - itime; + } else { + int h, m, s; + if (prduration(WIDE("Duration [HH:MM:SS]:"), &h, &m, &s) == -1) + return; + + duration = (h * 60 * 60) + (m * 60) + s; + } + + itime = 0; + running->en_secs += (time(NULL) - running->en_started); + running->en_started = time(NULL); + running->en_secs -= duration; + + en = entry_new(name); + en->en_created = time(NULL) - duration; + en->en_secs = duration; + save(); + + free(name); +} + +void +ksearch() +{ +static WCHAR *lastsearch; +WCHAR *term; +entry_t *start, *cur; + + if (!curent) { + drawstatus(WIDE("No entries.")); + return; + } + + if ((term = prompt(WIDE("Search:"), NULL, NULL)) == NULL) + return; + + if (!*term) { + free(term); + if (!lastsearch) + return; + + term = lastsearch; + } else { + free(lastsearch); + lastsearch = term; + } + + cur = start = curent; + + for (;;) { + cur = TAILQ_NEXT(cur, en_entries); + if (cur == NULL) { + drawstatus(WIDE("Search reached last entry, continuing from top.")); + cur = TAILQ_FIRST(&entries); + } + + if (cur == start) { + drawstatus(WIDE("No matches.")); + break; + } + + if (STRSTR(cur->en_desc, term)) { + curent = cur; + if (!showinv && cur->en_flags.efl_invoiced) + showinv = 1; + return; + } + + } +} + +void +kexec() +{ +WCHAR *cmd; +WCHAR **args; +command_t *cmds; +size_t nargs; + + if ((cmd = prompt(WIDE(":"), NULL, NULL)) == NULL || !*cmd) { + free(cmd); + return; + } + + nargs = tokenise(cmd, &args); + free(cmd); + + if (nargs == 0) { + tokfree(&args); + return; + } + + if ((cmds = find_command(args[0])) == NULL) { + drawstatus(WIDE("Unknown command.")); + tokfree(&args); + return; + } + + cmds->cm_hdl(nargs, args); + tokfree(&args); +} + diff --git a/functions.h b/functions.h new file mode 100644 index 0000000..1ef87b2 --- /dev/null +++ b/functions.h @@ -0,0 +1,51 @@ +/* + * TTS - track your time. + * Copyright (c) 2012-2014 Felicity Tarnell. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely. This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef TTS_FUNCTIONS_H +#define TTS_FUNCTIONS_H + +#include "wide.h" + +void kadd(void); +void kaddold(void); +void kquit(void); +void kup(void); +void kdown(void); +void ktoggle(void); +void kinvoiced(void); +void kbillable(void); +void keddesc(void); +void kedtime(void); +void ktoggleinv(void); +void kcopy(void); +void kaddtime(void); +void kdeltime(void); +void khelp(void); +void kmark(void); +void kunmarkall(void); +void ksearch(void); +void kmarkdel(void); +void kundel(void); +void ksync(void); +void kexec(void); +void kmerge(void); +void kint(void); + +typedef struct function { + const WCHAR *fn_name; + void (*fn_hdl) (void); + const WCHAR *fn_desc; +} function_t; + +extern function_t funcs[]; + +function_t *find_func(const WCHAR *name); + +#endif /* !TTS_FUNCTIONS_H */ diff --git a/str.c b/str.c new file mode 100644 index 0000000..4b89814 --- /dev/null +++ b/str.c @@ -0,0 +1,107 @@ +/* + * TTS - track your time. + * Copyright (c) 2012-2014 Felicity Tarnell. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely. This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "str.h" + +size_t +tokenise(str, res) + const WCHAR *str; + WCHAR ***res; +{ +int ntoks = 0; +const WCHAR *p, *q; + + *res = NULL; + p = str; + + for (;;) { + ptrdiff_t sz; + int qskip = 0; + + /* Skip leading whitespace */ + while (ISSPACE(*p)) + p++; + + /* End of string - no more arguments */ + if (!*p) + break; + + q = p; + + if (*q == '"') { + /* Quoted string - scan for end of string */ + int isbsl = 0; + p++; + + while (*++q) { + /* Handle escaping with backslash; currently works but the \ isn't + * removed from the string. + */ + if (*q == '\\') { + isbsl = 1; + continue; + } + + if (!isbsl && (*q == '"')) + break; + + isbsl = 0; + } + /* At this point, *q == '"'. If it's NUL instead, then the + * string was not terminated with a closing '"' before the end + * of the line. We could give an error here, but it seems + * more useful to just accept it. + */ + if (*q == '"') + qskip = 1; + } else { + /* Not quoted - just find the next whitespace */ + while (!ISSPACE(*q) && *q) + q++; + } + + /* Copy the argument (which is sz bytes long) into the result array */ + sz = (q - p); + *res = realloc(*res, sizeof(WCHAR *) * (ntoks + 1)); + (*res)[ntoks] = malloc(sizeof(WCHAR) * (sz + 1)); + MEMCPY((*res)[ntoks], p, sz); + (*res)[ntoks][sz] = 0; + ntoks++; + + if (qskip) + q += qskip; + + while (ISSPACE(*q)) + q++; + + /* + * q is the start of the next token (with leading whitespace); reset + * p to process the next argument. + */ + if (!*q) + break; + p = q; + } + + *res = realloc(*res, sizeof(WCHAR *) * (ntoks + 1)); + (*res)[ntoks] = NULL; + return ntoks; +} + +void +tokfree(vec) + WCHAR ***vec; +{ +WCHAR **p; + for (p = (*vec); *p; p++) + free(*p); + free(*vec); +} + diff --git a/str.h b/str.h new file mode 100644 index 0000000..c7b88e6 --- /dev/null +++ b/str.h @@ -0,0 +1,21 @@ +/* + * TTS - track your time. + * Copyright (c) 2012-2014 Felicity Tarnell. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely. This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef TTS_STR_H +#define TTS_STR_H + +#include + +#include "wide.h" + +size_t tokenise(const WCHAR *, WCHAR ***result); +void tokfree(WCHAR ***); + +#endif /* !TTS_STR_H */ diff --git a/style.h b/style.h new file mode 100644 index 0000000..9afac1b --- /dev/null +++ b/style.h @@ -0,0 +1,50 @@ +/* + * TTS - track your time. + * Copyright (c) 2012-2014 Felicity Tarnell. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely. This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef TTS_STYLE_H +#define TTS_STYLE_H + +#include "tts_curses.h" + +typedef struct style { + short sy_pair; + attr_t sy_attrs; +} style_t; + +#define style_fg(s) (COLOR_PAIR((s).sy_pair) | (s).sy_attrs) +#define style_bg(s) ((INT) ' ' | COLOR_PAIR((s).sy_pair) | ((s).sy_attrs & ~WA_UNDERLINE)) + +typedef struct attrname { + const WCHAR *an_name; + attr_t an_value; +} attrname_t; + +typedef struct colour { + const WCHAR *co_name; + short co_value; +} colour_t; + +extern style_t sy_header, + sy_status, + sy_entry, + sy_running, + sy_selected, + sy_date; + +int attr_find(const WCHAR *name, attr_t *result); +int colour_find(const WCHAR *name, short *result); + +void style_clear(style_t *); +int style_set(style_t *, const WCHAR *fg, const WCHAR *bg); +int style_add(style_t *, const WCHAR *fg, const WCHAR *bg); + +void apply_styles(void); + +#endif /* !TTS_STYLE_H */ diff --git a/tts.c b/tts.c index 495e385..b6da855 100644 --- a/tts.c +++ b/tts.c @@ -8,15 +8,6 @@ * warranty. */ -#define __EXTENSIONS__ -/* - * Older versions of glibc don't supporte _XOPEN_SOURCE==700 and require - * this for wcsdup() prototype. - */ -#define _GNU_SOURCE -#define _XOPEN_SOURCE 700 -#define _XOPEN_SOURCE_EXTENDED - #include #include @@ -52,244 +43,38 @@ # include #endif -#if defined HAVE_NCURSESW_CURSES_H -# include -#elif defined HAVE_NCURSESW_H -# include -#elif defined HAVE_NCURSES_CURSES_H -# include -#elif defined HAVE_NCURSES_H -# include -#elif defined HAVE_CURSES_H -# include -#else -# error "SVR4 or XSI compatible curses header file required" -#endif - #include "queue.h" - -#ifdef HAVE_CURSES_ENHANCED -# define WPFX(x) wcs##x -# define WIDE(x) L##x -# define ISX(x) isw##x -# define WCHAR wchar_t -# define FMT_L "l" -# define SNPRINTF swprintf -# define VSNPRINTF vswprintf -# define SSCANF swscanf -# define MEMCPY wmemcpy -# define MEMMOVE wmemmove -# define MBSTOWCS mbstowcs -# define WCSTOMBS wcstombs -# define FPRINTF fwprintf -# define STRTOK wcstok - -# define GETCH get_wch -# define WGETCH wget_wch -# define ADDSTR addwstr -# define WADDSTR waddwstr -# define INT wint_t -#else -# define WPFX(x) str##x -# define WIDE(x) x -# define ISX(x) is##x -# define WCHAR char -# define FMT_L -# define SNPRINTF snprintf -# define VSNPRINTF vsnprintf -# define SSCANF sscanf -# define MEMCPY memcpy -# define MEMMOVE memmove -# define MBSTOWCS strncpy -# define WCSTOMBS strncpy -# define FPRINTF fprintf -# define STRTOK strtok_r - -# define ADDSTR addstr -# define WADDSTR waddstr -# define INT int - -static int -tss_wgetch(win, d) - WINDOW *win; - int *d; -{ -int c; - if ((c = wgetch(win)) == ERR) - return ERR; - *d = c; - return OK; -} -# define WGETCH tss_wgetch -# define GETCH(c) tss_wgetch(stdscr,c) -#endif - -#define STRLEN WPFX(len) -#define STRCMP WPFX(cmp) -#define STRNCMP WPFX(ncmp) -#define STRCPY WPFX(cpy) -#define STRNCPY WPFX(ncpy) -#define STRSTR WPFX(str) -#define STRFTIME WPFX(ftime) -#define STRDUP WPFX(dup) -#define STRTOL WPFX(tol) - -#define ISSPACE ISX(space) - -#define WSIZEOF(s) (sizeof(s) / sizeof(WCHAR)) +#include "tts.h" +#include "entry.h" +#include "wide.h" +#include "tts_curses.h" +#include "ui.h" +#include "functions.h" +#include "commands.h" +#include "bindings.h" +#include "str.h" +#include "style.h" +#include "variable.h" extern char const *tts_version; -static volatile sig_atomic_t doexit; - -static WINDOW *titwin, *statwin, *listwin; - -static int in_curses; - -static void drawstatus(const WCHAR *msg, ...); -static void vdrawstatus(const WCHAR *msg, va_list); -static void drawheader(void); -static void drawentries(void); +volatile sig_atomic_t doexit; static time_t laststatus; -typedef struct entry { - WCHAR *en_desc; - int en_secs; - time_t en_started; - time_t en_created; - - struct { - int efl_visible:1; - int efl_invoiced:1; - int efl_marked:1; - int efl_deleted:1; - int efl_nonbillable:1; - } en_flags; - TAILQ_ENTRY(entry) en_entries; -} entry_t; - -static TAILQ_HEAD(entrylist, entry) entries = TAILQ_HEAD_INITIALIZER(entries); - -static entry_t *running; - -static entry_t *entry_new(const WCHAR *); -static void entry_start(entry_t *); -static void entry_stop(entry_t *); -static void entry_free(entry_t *); -static void entry_account(entry_t *); -static time_t entry_time_for_day(time_t, int, int); - -#define time_day(t) (((t) / (60 * 60 * 24)) * (60 * 60 * 24)) -#define entry_day(e) (time_day((e)->en_created)) - -#define time_to_hms(t, h, m, s) do { \ - time_t n = t; \ - h = n / (60 * 60); \ - n %= (60 * 60); \ - m = n / 60; \ - n %= 60; \ - s = n; \ - } while (0) - -#define NHIST 50 -typedef struct histent { - WCHAR *he_text; - TAILQ_ENTRY(histent) he_entries; -} histent_t; -typedef TAILQ_HEAD(hentlist, histent) hentlist_t; - -typedef struct history { - int hi_nents; - hentlist_t hi_ents; -} history_t; - -static history_t *hist_new(void); -static void hist_add(history_t *, WCHAR const *); - -static history_t *searchhist, *prompthist; - -static WCHAR *prompt(WCHAR const *, WCHAR const *, history_t *); -static int prduration(WCHAR *prompt, int *h, int *m, int *s); -static int yesno(WCHAR const *); -static void errbox(WCHAR const *, ...); -static void verrbox(WCHAR const *, va_list); +history_t *searchhist; +history_t *prompthist; #define STATFILE ".rttts" #define RCFILE ".ttsrc" -static int load(void); -static int save(void); +int load(void); +int save(void); static time_t lastsave; static char statfile[PATH_MAX + 1]; static int load_file(const char *); -static void cursadvance(void); - -static void kadd(void); -static void kaddold(void); -static void kquit(void); -static void kup(void); -static void kdown(void); -static void ktoggle(void); -static void kinvoiced(void); -static void kbillable(void); -static void keddesc(void); -static void kedtime(void); -static void ktoggleinv(void); -static void kcopy(void); -static void kaddtime(void); -static void kdeltime(void); -static void khelp(void); -static void kmark(void); -static void kunmarkall(void); -static void ksearch(void); -static void kmarkdel(void); -static void kundel(void); -static void ksync(void); -static void kexec(void); -static void kmerge(void); -static void kint(void); - -typedef struct function { - const WCHAR *fn_name; - void (*fn_hdl) (void); - const WCHAR *fn_desc; -} function_t; - -static function_t funcs[] = { - { WIDE("help"), khelp, WIDE("display help screen") }, - { WIDE("add"), kadd, WIDE("add a new entry and start the timer") }, - { WIDE("add-old"), kaddold, WIDE("add a new entry and specify its duration") }, - { WIDE("delete"), kmarkdel, WIDE("delete the current entry") }, - { WIDE("undelete"), kundel, WIDE("undelete the current entry") }, - { WIDE("quit"), kquit, WIDE("exit TTS") }, - { WIDE("invoice"), kinvoiced, WIDE("toggle current entry as invoiced") }, - { WIDE("billable"), kbillable, WIDE("toggle current entry as billable") }, - { WIDE("mark"), kmark, WIDE("mark the current entry") }, - { WIDE("unmarkall"), kunmarkall, WIDE("unmark all entries") }, - { WIDE("startstop"), ktoggle, WIDE("start or stop the timer") }, - { WIDE("edit-desc"), keddesc, WIDE("edit the current entry's description") }, - { WIDE("edit-time"), kedtime, WIDE("edit the current entry's duration") }, - { WIDE("showhide-inv"), ktoggleinv, WIDE("show or hide invoiced entries") }, - { WIDE("copy"), kcopy, WIDE("copy the current entry's description to a new entry") }, - { WIDE("add-time"), kaddtime, WIDE("add time to the current entry") }, - { WIDE("sub-time"), kdeltime, WIDE("subtract time from the current entry") }, - { WIDE("search"), ksearch, WIDE("search for an entry by name") }, - { WIDE("sync"), ksync, WIDE("purge all deleted entries") }, - { WIDE("prev"), kup, WIDE("move to the previous entry") }, - { WIDE("next"), kdown, WIDE("move to the next entry") }, - { WIDE("execute"), kexec, WIDE("execute a configuration command") }, - { WIDE("merge"), kmerge, WIDE("merge marked entries into current entry") }, - { WIDE("interrupt"), kint, WIDE("split current entry into new entry")}, -}; - -typedef struct tkey { - INT ky_code; - const WCHAR *ky_name; -} tkey_t; - static tkey_t keys[] = { { KEY_BREAK, WIDE("") }, { KEY_DOWN, WIDE("") }, @@ -358,58 +143,10 @@ static tkey_t keys[] = { { KEY_DC, WIDE("") } }; -typedef struct binding { - INT bi_code; - tkey_t *bi_key; - function_t *bi_func; - TAILQ_ENTRY(binding) bi_entries; -} binding_t; +int pagestart; +entry_t *curent; -typedef struct command { - const WCHAR *cm_name; - void (*cm_hdl) (size_t, WCHAR **); -} command_t; - -static command_t *find_command(const WCHAR *); -static void c_bind(size_t, WCHAR **); -static void c_style(size_t, WCHAR **); -static void c_set(size_t, WCHAR **); - -static command_t commands[] = { - { WIDE("bind"), c_bind }, - { WIDE("style"), c_style }, - { WIDE("set"), c_set }, -}; - -static void cmderr(const WCHAR *, ...); -static void vcmderr(const WCHAR *, va_list); - -static size_t tokenise(const WCHAR *, WCHAR ***result); -static void tokfree(WCHAR ***); - -static TAILQ_HEAD(bindlist, binding) bindings = TAILQ_HEAD_INITIALIZER(bindings); - -static tkey_t *find_key(const WCHAR *name); -static function_t *find_func(const WCHAR *name); -static void bind_key(const WCHAR *key, const WCHAR *func); - -static int pagestart; -static entry_t *curent; - -static int showinv = 0; - -typedef struct style { - short sy_pair; - attr_t sy_attrs; -} style_t; - -#define style_fg(s) (COLOR_PAIR((s).sy_pair) | (s).sy_attrs) -#define style_bg(s) ((INT) ' ' | COLOR_PAIR((s).sy_pair) | ((s).sy_attrs & ~WA_UNDERLINE)) - -typedef struct attrname { - const WCHAR *an_name; - attr_t an_value; -} attrname_t; +int showinv = 0; static attrname_t attrnames[] = { { WIDE("normal"), WA_NORMAL }, @@ -421,11 +158,6 @@ static attrname_t attrnames[] = { { WIDE("standout"), WA_STANDOUT } }; -typedef struct colour { - const WCHAR *co_name; - short co_value; -} colour_t; - static colour_t colours[] = { { WIDE("black"), COLOR_BLACK }, { WIDE("red"), COLOR_RED }, @@ -437,55 +169,34 @@ static colour_t colours[] = { { WIDE("white"), COLOR_WHITE } }; -static int attr_find(const WCHAR *name, attr_t *result); -static int colour_find(const WCHAR *name, short *result); - -static void style_clear(style_t *); -static int style_set(style_t *, const WCHAR *fg, const WCHAR *bg); -static int style_add(style_t *, const WCHAR *fg, const WCHAR *bg); - static short default_fg, default_bg; -static void apply_styles(void); +style_t sy_header = { 1, 0 }, + sy_status = { 2, 0 }, + sy_entry = { 3, 0 }, + sy_running = { 4, 0 }, + sy_selected = { 5, 0 }, + sy_date = { 6, 0 }; -static style_t - sy_header = { 1, 0 }, - sy_status = { 2, 0 }, - sy_entry = { 3, 0 }, - sy_running = { 4, 0 }, - sy_selected = { 5, 0 }, - sy_date = { 6, 0 }; +time_t itime = 0; -static time_t itime = 0; +int show_billable = 0; +int delete_advance = 1; +int mark_advance = 1; +int bill_advance = 0; +int bill_increment = 0; +WCHAR *auto_nonbillable; -static int show_billable = 0; -static int delete_advance = 1; -static int mark_advance = 1; -static int bill_advance = 0; -static int bill_increment = 0; -static WCHAR *auto_nonbillable; - -#define VTYPE_INT 1 -#define VTYPE_BOOL 2 -#define VTYPE_STRING 3 - -typedef struct variable { - WCHAR const *va_name; - int va_type; - void *va_addr; -} variable_t; - -static variable_t variables[] = { +variable_t variables[] = { { WIDE("delete_advance"), VTYPE_BOOL, &delete_advance }, { WIDE("mark_advance"), VTYPE_BOOL, &mark_advance }, { WIDE("billable_advance"), VTYPE_BOOL, &bill_advance }, { WIDE("show_billable"), VTYPE_BOOL, &show_billable }, { WIDE("auto_non_billable"), VTYPE_STRING, &auto_nonbillable }, - { WIDE("bill_increment"), VTYPE_INT, &bill_increment } + { WIDE("bill_increment"), VTYPE_INT, &bill_increment }, + { } }; -static variable_t *find_variable(const WCHAR *name); - #ifdef USE_DARWIN_POWER static pthread_t power_thread; static io_connect_t root_port; @@ -751,805 +462,6 @@ char rcfile[PATH_MAX + 1]; return 0; } -void -kquit() -{ -entry_t *en; -int ndel = 0; - - TAILQ_FOREACH(en, &entries, en_entries) { - if (en->en_flags.efl_deleted) - ndel++; - } - - if (ndel) { - WCHAR s[128]; - SNPRINTF(s, WSIZEOF(s), WIDE("Purge %d deleted entries?"), ndel); - if (yesno(s)) { - ksync(); - } - } - - doexit = 1; -} - -void -kadd() -{ -WCHAR *name; -entry_t *en; - name = prompt(WIDE("Description:"), NULL, NULL); - if (!name || !*name) { - free(name); - return; - } - en = entry_new(name); - entry_start(en); - curent = en; - save(); -} - -void -kaddold() -{ -WCHAR *name; -entry_t *en; - name = prompt(WIDE("Description:"), NULL, NULL); - - if (!name || !*name) { - free(name); - return; - } - - en = entry_new(name); - curent = en; - kedtime(); - save(); -} - -void -ktoggle() -{ - itime = 0; - - if (!curent) - return; - - if (curent == running) { - entry_stop(curent); - save(); - return; - } - - if (running) - entry_stop(running); - entry_start(curent); - save(); -} - -void -kundel() -{ - if (!curent) - return; - - curent->en_flags.efl_deleted = 0; - if (delete_advance) - cursadvance(); -} - -void -kmarkdel() -{ -entry_t *en; -int nmarked = 0; - - TAILQ_FOREACH(en, &entries, en_entries) { - if (en->en_flags.efl_marked) { - nmarked++; - en->en_flags.efl_deleted = 1; - } - } - - if (nmarked) - return; - - if (!curent) { - drawstatus(WIDE("No entries to delete.")); - return; - } - - curent->en_flags.efl_deleted = 1; - - if (delete_advance) - cursadvance(); -} - -/* - * Move the cursor to the next entry after an operation like mark or deleted. - * If there are no suitable entries after this one, move it backwards instead. - */ -void -cursadvance() -{ -entry_t *en; - - if (!curent) { - curent = TAILQ_FIRST(&entries); - return; - } - - /* - * Try to find the next suitable entry to move the cursor to. - */ - for (en = TAILQ_NEXT(curent, en_entries); en; en = TAILQ_NEXT(en, en_entries)) { - if (!showinv && en->en_flags.efl_invoiced) - continue; - curent = en; - if (!curent->en_flags.efl_visible) - pagestart++; - return; - } - - /* - * No entries; if the current entry is visible, stay here, otherwise - * try moving backwards instead. - */ - if (showinv || !curent->en_flags.efl_invoiced) - return; - - for (en = TAILQ_PREV(curent, entrylist, en_entries); en; - en = TAILQ_PREV(en, entrylist, en_entries)) { - if (!showinv && en->en_flags.efl_invoiced) - continue; - curent = en; - if (!curent->en_flags.efl_visible) - pagestart--; - return; - } - - /* - * Couldn't find any entries at all? - */ - curent = NULL; -} - -void -ksync() -{ -entry_t *en, *ten; - - TAILQ_FOREACH_SAFE(en, &entries, en_entries, ten) { - if (!en->en_flags.efl_deleted) - continue; - if (en == curent) - curent = NULL; - TAILQ_REMOVE(&entries, en, en_entries); - entry_free(en); - } - - if (curent == NULL) - curent = TAILQ_FIRST(&entries); - save(); -} - -void -kup() -{ -entry_t *prev = curent; - if (!curent) - return; - - do { - if ((prev = TAILQ_PREV(prev, entrylist, en_entries)) == NULL) - break; - } while (!showinv && prev->en_flags.efl_invoiced); - - if (prev == NULL) { - drawstatus(WIDE("Already at first entry.")); - return; - } - - curent = prev; - if (!curent->en_flags.efl_visible) - pagestart--; -} - -void -kdown() -{ -entry_t *next = curent; - if (!curent) - return; - - do { - if ((next = TAILQ_NEXT(next, en_entries)) == NULL) - break; - } while (!showinv && next->en_flags.efl_invoiced); - - if (next == NULL) { - drawstatus(WIDE("Already at last entry.")); - return; - } - - curent = next; - if (!curent->en_flags.efl_visible) - pagestart++; -} - -void -kinvoiced() -{ -entry_t *en; -int anymarked = 0; - - TAILQ_FOREACH(en, &entries, en_entries) { - if (!en->en_flags.efl_marked) - continue; - anymarked = 1; - en->en_flags.efl_invoiced = !en->en_flags.efl_invoiced; - en->en_flags.efl_marked = 0; - } - - if (anymarked) { - save(); - return; - } - - if (!curent) { - drawstatus(WIDE("No entry selected.")); - return; - } - - curent->en_flags.efl_invoiced = !curent->en_flags.efl_invoiced; - save(); - - en = curent; - - if (showinv) { - if (TAILQ_NEXT(curent, en_entries) != NULL) - curent = TAILQ_NEXT(curent, en_entries); - return; - } - - /* - * Try to find the next uninvoiced request to move the cursor to. - */ - for (;;) { - if ((curent = TAILQ_NEXT(curent, en_entries)) == NULL) - break; /* end of list */ - if (!curent->en_flags.efl_invoiced) - return; - } - - /* - * We didn't find any, so try searching backwards instead. - */ - for (curent = en;;) { - if ((curent = TAILQ_PREV(curent, entrylist, en_entries)) == NULL) - break; /* end of list */ - if (!curent->en_flags.efl_invoiced) - return; - } -} - -void -kbillable() -{ -entry_t *en; -int anymarked = 0; - - TAILQ_FOREACH(en, &entries, en_entries) { - if (!en->en_flags.efl_marked) - continue; - anymarked = 1; - en->en_flags.efl_nonbillable = !en->en_flags.efl_nonbillable; - en->en_flags.efl_marked = 0; - } - - if (anymarked) { - save(); - return; - } - - if (!curent) { - drawstatus(WIDE("No entry selected.")); - return; - } - - curent->en_flags.efl_nonbillable = !curent->en_flags.efl_nonbillable; - save(); - - if (bill_advance) - cursadvance(); -} - -void -keddesc() -{ -WCHAR *new; - - if (!curent) { - drawstatus(WIDE("No entry selected.")); - return; - } - - if ((new = prompt(WIDE("Description:"), curent->en_desc, NULL)) == NULL) - return; - - free(curent->en_desc); - curent->en_desc = new; - save(); -} - -void -kedtime() -{ -WCHAR *new, old[64]; -time_t n; -int h, m, s; - - if (!curent) { - drawstatus(WIDE("No entry selected.")); - return; - } - - n = curent->en_secs; - if (curent->en_started) - n += time(NULL) - curent->en_started; - h = n / (60 * 60); - n %= (60 * 60); - m = n / 60; - n %= 60; - s = n; - - SNPRINTF(old, WSIZEOF(old), WIDE("%02d:%02d:%02d"), h, m, s); - if ((new = prompt(WIDE("Duration [HH:MM:SS]:"), old, NULL)) == NULL) - return; - - if (!SSCANF(new, WIDE("%d:%d:%d"), &h, &m, &s)) { - free(new); - drawstatus(WIDE("Invalid duration.")); - } - - curent->en_secs = (h * 60 * 60) + (m * 60) + s; - if (curent->en_started) - time(&curent->en_started); - - save(); -} - -void -ktoggleinv() -{ -entry_t *en = curent; - showinv = !showinv; - drawstatus(WIDE("%"FMT_L"s invoiced entries."), - showinv ? L"Showing" : L"Hiding"); - - if (curent && !curent->en_flags.efl_invoiced) - return; - - if (!curent) { - curent = TAILQ_FIRST(&entries); - return; - } - - /* - * Try to find the next uninvoiced request to move the cursor to. - */ - for (;;) { - if ((curent = TAILQ_NEXT(curent, en_entries)) == NULL) - break; /* end of list */ - if (!curent->en_flags.efl_invoiced) - return; - } - - /* - * We didn't find any, so try searching backwards instead. - */ - for (curent = en;;) { - if ((curent = TAILQ_PREV(curent, entrylist, en_entries)) == NULL) - break; /* end of list */ - if (!curent->en_flags.efl_invoiced) - return; - } -} - -void -kcopy() -{ -entry_t *en; - - if (!curent) { - drawstatus(WIDE("No entry selected.")); - return; - } - - en = entry_new(curent->en_desc); - curent = en; - entry_start(en); - save(); -} - -void -kaddtime() -{ -WCHAR *tstr; -int h = 0, m = 0, s = 0, secs; - if (!curent) { - drawstatus(WIDE("No entry selected.")); - return; - } - - if ((tstr = prompt(WIDE("Time to add ([[HH:]MM:]SS):"), NULL, NULL)) == NULL) - return; - - if (!*tstr) { - drawstatus(WIDE("")); - free(tstr); - return; - } - - if (SSCANF(tstr, WIDE("%d:%d:%d"), &h, &m, &s) != 3) { - h = 0; - if (SSCANF(tstr, WIDE("%d:%d"), &m, &s) != 2) { - m = 0; - if (SSCANF(tstr, WIDE("%d"), &s) != 1) { - free(tstr); - drawstatus(WIDE("Invalid time format.")); - return; - } - } - } - - free(tstr); - - if (m >= 60) { - drawstatus(WIDE("Minutes cannot be more than 59.")); - return; - } - - if (s >= 60) { - drawstatus(WIDE("Seconds cannot be more than 59.")); - return; - } - - secs = s + m*60 + h*60*60; - curent->en_secs += secs; - save(); -} - -void -kdeltime() -{ -WCHAR *tstr; -int h = 0, m = 0, s = 0, secs; - if (!curent) { - drawstatus(WIDE("No entry selected.")); - return; - } - - if ((tstr = prompt(WIDE("Time to subtract, ([[HH:]MM:]SS):"), NULL, NULL)) == NULL) - return; - - if (!*tstr) { - drawstatus(WIDE("")); - free(tstr); - return; - } - - if (SSCANF(tstr, WIDE("%d:%d:%d"), &h, &m, &s) != 3) { - h = 0; - if (SSCANF(tstr, WIDE("%d:%d"), &m, &s) != 2) { - m = 0; - if (SSCANF(tstr, WIDE("%d"), &s) != 1) { - free(tstr); - drawstatus(WIDE("Invalid time format.")); - return; - } - } - } - - free(tstr); - if (m >= 60) { - drawstatus(WIDE("Minutes cannot be more than 59.")); - return; - } - - if (s >= 60) { - drawstatus(WIDE("Seconds cannot be more than 59.")); - return; - } - - entry_account(curent); - - secs = s + m*60 + h*60*60; - if (curent->en_secs - secs < 0) { - drawstatus(WIDE("Remaining time cannot be less than zero.")); - return; - } - - curent->en_secs -= secs; - save(); -} - -void -kmerge() -{ -entry_t *en, *ten; -int nmarked = 0; -WCHAR pr[128]; -int h, m, s = 0; - - if (!curent) { - drawstatus(WIDE("No entry selected.")); - return; - } - - /* - * Count number of marked entries and the summed time. - */ - TAILQ_FOREACH(en, &entries, en_entries) { - if (!en->en_flags.efl_marked || en == curent) - continue; - nmarked++; - s += en->en_secs; - if (en->en_started) - s += time(NULL) - en->en_started; - } - - if (nmarked == 0) { - drawstatus(WIDE("No marked entries.")); - return; - } - - h = s / (60 * 60); - s %= (60 * 60); - m = s / 60; - s %= 60; - - SNPRINTF(pr, WSIZEOF(pr), WIDE("Merge %d marked entries [%02d:%02d:%02d] into current entry?"), - nmarked, h, m, s); - if (!yesno(pr)) - return; - - TAILQ_FOREACH_SAFE(en, &entries, en_entries, ten) { - if (!en->en_flags.efl_marked || en == curent) - continue; - if (en->en_started) - entry_stop(en); - curent->en_secs += en->en_secs; - TAILQ_REMOVE(&entries, en, en_entries); - entry_free(en); - } - save(); -} - -void -khelp() -{ -WINDOW *hwin; -size_t nhelp = 0; -WCHAR **help; -#define HTITLE WIDE(" TTS keys ") -size_t width = 0; -size_t i; -INT c; -binding_t *bi; - /* Count the number of bindings */ - TAILQ_FOREACH(bi, &bindings, bi_entries) - nhelp++; - help = calloc(nhelp, sizeof(const WCHAR *)); - - i = 0; - TAILQ_FOREACH(bi, &bindings, bi_entries) { - WCHAR s[128]; - if (bi->bi_key) - SNPRINTF(s, WSIZEOF(s), WIDE("%-10"FMT_L"s %"FMT_L"s (%"FMT_L"s)"), - bi->bi_key->ky_name, bi->bi_func->fn_desc, - bi->bi_func->fn_name); - else - SNPRINTF(s, WSIZEOF(s), WIDE("%"FMT_L"c %"FMT_L"s (%"FMT_L"s)"), - bi->bi_code, bi->bi_func->fn_desc, bi->bi_func->fn_name); - help[i] = STRDUP(s); - i++; - } - - if (nhelp > (LINES - 6)) - nhelp = LINES - 6; - - for (i = 0; i < nhelp; i++) - if (STRLEN(help[i]) > width) - width = STRLEN(help[i]); - - hwin = newwin(nhelp + 4, width + 4, - (LINES / 2) - ((nhelp + 2) / 2), - (COLS / 2) - ((width + 2) / 2)); - wborder(hwin, 0, 0, 0, 0, 0, 0, 0, 0); - - wattron(hwin, A_REVERSE | A_BOLD); - wmove(hwin, 0, (width / 2) - (WSIZEOF(HTITLE) - 1)/2); - WADDSTR(hwin, HTITLE); - wattroff(hwin, A_REVERSE | A_BOLD); - - for (i = 0; i < nhelp; i++) { - wmove(hwin, i + 2, 2); - WADDSTR(hwin, help[i]); - } - - wrefresh(hwin); - - while (WGETCH(hwin, &c) == ERR -#ifdef KEY_RESIZE - || (c == KEY_RESIZE) -#endif - ) - ; - - delwin(hwin); - - for (i = 0; i < nhelp; i++) - free(help[i]); - free(help); -} - -void -kmark() -{ - if (!curent) { - drawstatus(WIDE("No entry selected.")); - return; - } - - curent->en_flags.efl_marked = !curent->en_flags.efl_marked; - - if (mark_advance) - cursadvance(); -} - -void -kunmarkall() -{ -entry_t *en; - TAILQ_FOREACH(en, &entries, en_entries) - en->en_flags.efl_marked = 0; -} - -void -kint() -{ -time_t duration; -entry_t *en; -WCHAR *name; - - if (!itime) { - if (!running) { - drawstatus(WIDE("No running entry.")); - return; - } - - itime = time(NULL); - return; - } - - if (!running) { - drawstatus(WIDE("No running entry.")); - return; - } - - name = prompt(WIDE("Description:"), NULL, NULL); - - if (!name || !*name) { - itime = 0; - free(name); - return; - } - - if (itime) { - duration = time(NULL) - itime; - } else { - int h, m, s; - if (prduration(WIDE("Duration [HH:MM:SS]:"), &h, &m, &s) == -1) - return; - - duration = (h * 60 * 60) + (m * 60) + s; - } - - itime = 0; - running->en_secs += (time(NULL) - running->en_started); - running->en_started = time(NULL); - running->en_secs -= duration; - - en = entry_new(name); - en->en_created = time(NULL) - duration; - en->en_secs = duration; - save(); - - free(name); -} - -void -ksearch() -{ -static WCHAR *lastsearch; -WCHAR *term; -entry_t *start, *cur; - - if (!curent) { - drawstatus(WIDE("No entries.")); - return; - } - - if ((term = prompt(WIDE("Search:"), NULL, NULL)) == NULL) - return; - - if (!*term) { - free(term); - if (!lastsearch) - return; - - term = lastsearch; - } else { - free(lastsearch); - lastsearch = term; - } - - cur = start = curent; - - for (;;) { - cur = TAILQ_NEXT(cur, en_entries); - if (cur == NULL) { - drawstatus(WIDE("Search reached last entry, continuing from top.")); - cur = TAILQ_FIRST(&entries); - } - - if (cur == start) { - drawstatus(WIDE("No matches.")); - break; - } - - if (STRSTR(cur->en_desc, term)) { - curent = cur; - if (!showinv && cur->en_flags.efl_invoiced) - showinv = 1; - return; - } - - } -} - -void -kexec() -{ -WCHAR *cmd; -WCHAR **args; -command_t *cmds; -size_t nargs; - - if ((cmd = prompt(WIDE(":"), NULL, NULL)) == NULL || !*cmd) { - free(cmd); - return; - } - - nargs = tokenise(cmd, &args); - free(cmd); - - if (nargs == 0) { - tokfree(&args); - return; - } - - if ((cmds = find_command(args[0])) == NULL) { - drawstatus(WIDE("Unknown command.")); - tokfree(&args); - return; - } - - cmds->cm_hdl(nargs, args); - tokfree(&args); -} - void drawheader() { @@ -1982,107 +894,6 @@ chtype oldbg; wbkgdset(listwin, oldbg); } -entry_t * -entry_new(desc) - const WCHAR *desc; -{ -entry_t *en; - if ((en = calloc(1, sizeof(*en))) == NULL) - return NULL; - - if (auto_nonbillable && STRSTR(desc, auto_nonbillable)) - en->en_flags.efl_nonbillable = 1; - - TAILQ_INSERT_HEAD(&entries, en, en_entries); - - en->en_desc = STRDUP(desc); - time(&en->en_created); - - return en; -} - -void -entry_start(en) - entry_t *en; -{ - if (running) - entry_stop(running); - time(&en->en_started); - running = en; -} - -void -entry_stop(en) - entry_t *en; -{ - if (running == en) - running = NULL; - en->en_secs += time(NULL) - en->en_started; - en->en_started = 0; -} - -void -entry_free(en) - entry_t *en; -{ - if (en == running) - entry_stop(en); - free(en->en_desc); -} - -void -entry_account(en) - entry_t *en; -{ - if (!en->en_started) - return; - en->en_secs += time(NULL) - en->en_started; - time(&en->en_started); -} - -/* - * Return the amount of time for the day on which the timestamp .when falls. - * If .inv is 0, sum non-invoiced entries; if 1, sum invoiced entries; if - * 2, sum billable entries; if -1, sum all entries. If .incr is non-zero, - * individual entry time will be rounded up to intervals of that many minutes. - */ -time_t -entry_time_for_day(when, inv, incr) - time_t when; -{ -time_t day = time_day(when); -time_t sum = 0; -entry_t *en; -int rnd = incr * 60; - TAILQ_FOREACH(en, &entries, en_entries) { - time_t n; - - if (entry_day(en) > day) - continue; - if (entry_day(en) < day) - break; - - if (inv == 0 && en->en_flags.efl_invoiced) - continue; - if (inv == 1 && !en->en_flags.efl_invoiced) - continue; - if (inv == 2 && en->en_flags.efl_nonbillable) - continue; - - n = en->en_secs; - if (en->en_started) - n += time(NULL) - en->en_started; - - if (!n) - continue; - - if (rnd) - n = (1 + round((n - 1) / rnd)) * rnd; - sum += n; - } - return sum; -} - int load() { @@ -2368,10 +1179,10 @@ function_t * find_func(name) const WCHAR *name; { -size_t i; - for (i = 0; i < sizeof(funcs) / sizeof(*funcs); i++) - if (STRCMP(name, funcs[i].fn_name) == 0) - return &funcs[i]; +function_t *f; + for (f = funcs; f->fn_name; f++) + if (STRCMP(name, f->fn_name) == 0) + return f; return NULL; } @@ -2424,223 +1235,17 @@ INT code; TAILQ_INSERT_TAIL(&bindings, binding, bi_entries); } -size_t -tokenise(str, res) - const WCHAR *str; - WCHAR ***res; -{ -int ntoks = 0; -const WCHAR *p, *q; - - *res = NULL; - p = str; - - for (;;) { - ptrdiff_t sz; - int qskip = 0; - - /* Skip leading whitespace */ - while (ISSPACE(*p)) - p++; - - /* End of string - no more arguments */ - if (!*p) - break; - - q = p; - - if (*q == '"') { - /* Quoted string - scan for end of string */ - int isbsl = 0; - p++; - - while (*++q) { - /* Handle escaping with backslash; currently works but the \ isn't - * removed from the string. - */ - if (*q == '\\') { - isbsl = 1; - continue; - } - - if (!isbsl && (*q == '"')) - break; - - isbsl = 0; - } - /* At this point, *q == '"'. If it's NUL instead, then the - * string was not terminated with a closing '"' before the end - * of the line. We could give an error here, but it seems - * more useful to just accept it. - */ - if (*q == '"') - qskip = 1; - } else { - /* Not quoted - just find the next whitespace */ - while (!ISSPACE(*q) && *q) - q++; - } - - /* Copy the argument (which is sz bytes long) into the result array */ - sz = (q - p); - *res = realloc(*res, sizeof(WCHAR *) * (ntoks + 1)); - (*res)[ntoks] = malloc(sizeof(WCHAR) * (sz + 1)); - MEMCPY((*res)[ntoks], p, sz); - (*res)[ntoks][sz] = 0; - ntoks++; - - if (qskip) - q += qskip; - - while (ISSPACE(*q)) - q++; - - /* - * q is the start of the next token (with leading whitespace); reset - * p to process the next argument. - */ - if (!*q) - break; - p = q; - } - - *res = realloc(*res, sizeof(WCHAR *) * (ntoks + 1)); - (*res)[ntoks] = NULL; - return ntoks; -} - -void -tokfree(vec) - WCHAR ***vec; -{ -WCHAR **p; - for (p = (*vec); *p; p++) - free(*p); - free(*vec); -} - -command_t * -find_command(name) - const WCHAR *name; -{ -size_t i; - for (i = 0; i < sizeof(commands) / sizeof(*commands); i++) - if (STRCMP(name, commands[i].cm_name) == 0) - return &commands[i]; - return NULL; -} - -void -c_style(argc, argv) - size_t argc; - WCHAR **argv; -{ -style_t *sy; -WCHAR *last, *tok; - - if (argc < 3 || argc > 4) { - cmderr(WIDE("Usage: style [background]")); - return; - } - - if (STRCMP(argv[1], WIDE("header")) == 0) - sy = &sy_header; - else if (STRCMP(argv[1], WIDE("status")) == 0) - sy = &sy_status; - else if (STRCMP(argv[1], WIDE("entry")) == 0) - sy = &sy_entry; - else if (STRCMP(argv[1], WIDE("selected")) == 0) - sy = &sy_selected; - else if (STRCMP(argv[1], WIDE("running")) == 0) - sy = &sy_running; - else if (STRCMP(argv[1], WIDE("date")) == 0) - sy = &sy_date; - else { - cmderr(WIDE("Unknown style item.")); - return; - } - - style_clear(sy); - for (tok = STRTOK(argv[2], WIDE(","), &last); tok != NULL; - tok = STRTOK(NULL, WIDE(","), &last)) { - style_add(sy, tok, argv[3]); - } - - apply_styles(); -} - -void -c_bind(argc, argv) - size_t argc; - WCHAR **argv; -{ - if (argc != 3) { - cmderr(WIDE("Usage: bind ")); - return; - } - - bind_key(argv[1], argv[2]); -} - variable_t * find_variable(name) WCHAR const *name; { -size_t i; - for (i = 0; i < sizeof(variables) / sizeof(*variables); i++) - if (STRCMP(name, variables[i].va_name) == 0) - return &variables[i]; +variable_t *v; + for (v = variables; v->va_name; v++) + if (STRCMP(name, v->va_name) == 0) + return v; return NULL; } -void -c_set(argc, argv) - size_t argc; - WCHAR **argv; -{ -variable_t *var; -int val; - - if (argc != 3) { - cmderr(WIDE("Usage: set ")); - return; - } - - if ((var = find_variable(argv[1])) == NULL) { - cmderr(WIDE("Unknown variable \"%"FMT_L"s\"."), argv[1]); - return; - } - - switch (var->va_type) { - case VTYPE_BOOL: - if (STRCMP(argv[2], WIDE("true")) == 0 || - STRCMP(argv[2], WIDE("yes")) == 0 || - STRCMP(argv[2], WIDE("on")) == 0 || - STRCMP(argv[2], WIDE("1")) == 0) { - val = 1; - } else if (STRCMP(argv[2], WIDE("false")) == 0 || - STRCMP(argv[2], WIDE("no")) == 0 || - STRCMP(argv[2], WIDE("off")) == 0 || - STRCMP(argv[2], WIDE("0")) == 0) { - val = 0; - } else { - cmderr(WIDE("Invalid value for boolean: \"%"FMT_L"s\"."), argv[2]); - return; - } - - *(int *)var->va_addr = val; - break; - - case VTYPE_STRING: - *(WCHAR **)var->va_addr = STRDUP(argv[2]); - break; - - case VTYPE_INT: - *(int *)var->va_addr = STRTOL(argv[2], NULL, 0); - break; - } -} - int attr_find(name, result) const WCHAR *name; @@ -2672,6 +1277,7 @@ size_t i; return -1; } + void style_clear(sy) style_t *sy; diff --git a/tts.h b/tts.h new file mode 100644 index 0000000..318f8ba --- /dev/null +++ b/tts.h @@ -0,0 +1,65 @@ +/* + * TTS - track your time. + * Copyright (c) 2012-2014 Felicity Tarnell. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely. This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef TTS_H +#define TTS_H + +#include + +#include "wide.h" +#include "queue.h" +#include "entry.h" + +/* + * Configuration options. + */ + +extern int show_billable; +extern int delete_advance; +extern int mark_advance; +extern int bill_advance; +extern int bill_increment; +extern WCHAR *auto_nonbillable; + +/* + * Global state. + */ + +extern entry_t *curent; +extern volatile sig_atomic_t doexit; +extern int pagestart; +extern time_t itime; + +int load(void); +int save(void); + +/* + * Command history. + */ + +#define NHIST 50 +typedef struct histent { + WCHAR *he_text; + TAILQ_ENTRY(histent) he_entries; +} histent_t; +typedef TAILQ_HEAD(hentlist, histent) hentlist_t; + +typedef struct history { + int hi_nents; + hentlist_t hi_ents; +} history_t; + +history_t *hist_new(void); +void hist_add(history_t *, WCHAR const *); + +extern history_t *searchhist; +extern history_t *prompthist; + +#endif /* !TTS_H */ diff --git a/tts_curses.h b/tts_curses.h new file mode 100644 index 0000000..79f4e20 --- /dev/null +++ b/tts_curses.h @@ -0,0 +1,30 @@ +/* + * TTS - track your time. + * Copyright (c) 2012-2014 Felicity Tarnell. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely. This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef TTS_CURSES_H +#define TTS_CURSES_H + +#include "config.h" + +#if defined HAVE_NCURSESW_CURSES_H +# include +#elif defined HAVE_NCURSESW_H +# include +#elif defined HAVE_NCURSES_CURSES_H +# include +#elif defined HAVE_NCURSES_H +# include +#elif defined HAVE_CURSES_H +# include +#else +# error "SVR4 or XSI compatible curses header file required" +#endif + +#endif /* !TTS_CURSES_H */ diff --git a/ui.c b/ui.c new file mode 100644 index 0000000..1ac4965 --- /dev/null +++ b/ui.c @@ -0,0 +1,65 @@ +/* + * TTS - track your time. + * Copyright (c) 2012-2014 Felicity Tarnell. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely. This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "ui.h" +#include "tts.h" + +WINDOW *titwin, *statwin, *listwin; +int in_curses; + +/* + * Move the cursor to the next entry after an operation like mark or deleted. + * If there are no suitable entries after this one, move it backwards instead. + */ +void +cursadvance() +{ +entry_t *en; + + if (!curent) { + curent = TAILQ_FIRST(&entries); + return; + } + + /* + * Try to find the next suitable entry to move the cursor to. + */ + for (en = TAILQ_NEXT(curent, en_entries); en; en = TAILQ_NEXT(en, en_entries)) { + if (!showinv && en->en_flags.efl_invoiced) + continue; + curent = en; + if (!curent->en_flags.efl_visible) + pagestart++; + return; + } + + /* + * No entries; if the current entry is visible, stay here, otherwise + * try moving backwards instead. + */ + if (showinv || !curent->en_flags.efl_invoiced) + return; + + for (en = TAILQ_PREV(curent, entrylist, en_entries); en; + en = TAILQ_PREV(en, entrylist, en_entries)) { + if (!showinv && en->en_flags.efl_invoiced) + continue; + curent = en; + if (!curent->en_flags.efl_visible) + pagestart--; + return; + } + + /* + * Couldn't find any entries at all? + */ + curent = NULL; +} + diff --git a/ui.h b/ui.h new file mode 100644 index 0000000..005ac7e --- /dev/null +++ b/ui.h @@ -0,0 +1,37 @@ +/* + * TTS - track your time. + * Copyright (c) 2012-2014 Felicity Tarnell. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely. This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef TTS_UI_H +#define TTS_UI_H + +#include + +#include "tts.h" +#include "tts_curses.h" +#include "wide.h" + +extern WINDOW *titwin, *statwin, *listwin; +extern int in_curses; +extern int showinv; + +void cursadvance(void); + +void drawstatus (const WCHAR *msg, ...); +void vdrawstatus (const WCHAR *msg, va_list); +void drawheader (void); +void drawentries (void); + +WCHAR *prompt (WCHAR const *, WCHAR const *, history_t *); +int prduration (WCHAR *prompt, int *h, int *m, int *s); +int yesno (WCHAR const *); +void errbox (WCHAR const *, ...); +void verrbox (WCHAR const *, va_list); + +#endif /* !TTS_UI_H */ diff --git a/variable.h b/variable.h new file mode 100644 index 0000000..8cb8447 --- /dev/null +++ b/variable.h @@ -0,0 +1,28 @@ +/* + * TTS - track your time. + * Copyright (c) 2012-2014 Felicity Tarnell. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely. This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef TTS_VARIABLE_H +#define TTS_VARIABLE_H + +#include "wide.h" + +typedef struct variable { + WCHAR const *va_name; + int va_type; + void *va_addr; +} variable_t; + +#define VTYPE_INT 1 +#define VTYPE_BOOL 2 +#define VTYPE_STRING 3 + +variable_t *find_variable(const WCHAR *name); + +#endif /* !TTS_VARIABLE_H */ diff --git a/wide.c b/wide.c new file mode 100644 index 0000000..7e339c5 --- /dev/null +++ b/wide.c @@ -0,0 +1,26 @@ +/* + * TTS - track your time. + * Copyright (c) 2012-2014 Felicity Tarnell. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely. This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "wide.h" +#include "tts_curses.h" + +#ifdef NEED_TTS_WGETCH +static int +tts_wgetch(win, d) + WINDOW *win; + int *d; +{ +int c; + if ((c = wgetch(win)) == ERR) + return ERR; + *d = c; + return OK; +} +#endif /* !NEED_TTS_WGETCH */ diff --git a/wide.h b/wide.h new file mode 100644 index 0000000..85df84d --- /dev/null +++ b/wide.h @@ -0,0 +1,81 @@ +/* + * TTS - track your time. + * Copyright (c) 2012-2014 Felicity Tarnell. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely. This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef TTS_WIDE_H +#define TTS_WIDE_H + +#include "config.h" +#include "tts_curses.h" + +#ifdef HAVE_CURSES_ENHANCED +# include + +# define WPFX(x) wcs##x +# define WIDE(x) L##x +# define ISX(x) isw##x +# define WCHAR wchar_t +# define FMT_L "l" +# define SNPRINTF swprintf +# define VSNPRINTF vswprintf +# define SSCANF swscanf +# define MEMCPY wmemcpy +# define MEMMOVE wmemmove +# define MBSTOWCS mbstowcs +# define WCSTOMBS wcstombs +# define FPRINTF fwprintf +# define STRTOK wcstok + +# define GETCH get_wch +# define WGETCH wget_wch +# define ADDSTR addwstr +# define WADDSTR waddwstr +# define INT wint_t +#else +# define WPFX(x) str##x +# define WIDE(x) x +# define ISX(x) is##x +# define WCHAR char +# define FMT_L +# define SNPRINTF snprintf +# define VSNPRINTF vsnprintf +# define SSCANF sscanf +# define MEMCPY memcpy +# define MEMMOVE memmove +# define MBSTOWCS strncpy +# define WCSTOMBS strncpy +# define FPRINTF fprintf +# define STRTOK strtok_r + +# define ADDSTR addstr +# define WADDSTR waddstr +# define INT int + +# define NEED_TTS_WGETCH +extern int tts_wgetch(WINDOW *, int *); + +# define WGETCH tts_wgetch +# define GETCH(c) tts_wgetch(stdscr,c) +#endif + +#define STRLEN WPFX(len) +#define STRCMP WPFX(cmp) +#define STRNCMP WPFX(ncmp) +#define STRCPY WPFX(cpy) +#define STRNCPY WPFX(ncpy) +#define STRSTR WPFX(str) +#define STRFTIME WPFX(ftime) +#define STRDUP WPFX(dup) +#define STRTOL WPFX(tol) + +#define ISSPACE ISX(space) + +#define WSIZEOF(s) (sizeof(s) / sizeof(WCHAR)) + +#endif /* !TTS_WIDE_H */ From 50d9efdac9b067e835b880731f83ee4acd66a45f Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Fri, 7 Mar 2014 19:18:20 +0000 Subject: [PATCH 04/51] Cleanups; add 'make depend'. --- Makefile.in | 19 +++- tts.c | 244 +--------------------------------------------------- tts.h | 3 + ui.c | 243 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 265 insertions(+), 244 deletions(-) diff --git a/Makefile.in b/Makefile.in index dd1b3a1..ab67424 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,6 +1,9 @@ +.SUFFIXES: .c .o .d .h + VPATH = @top_srcdir@ CC = @CC@ +MAKEDEPEND = @CC@ -M # _GNU_SOURCE is required for wcsdup() on older version of glibc that don't # implement XPG7. CPPFLAGS = @CPPFLAGS@ -D_XOPEN_SOURCE=700 -D_XOPEN_SOURCE_EXTENDED -D__EXTENSIONS__ @@ -25,8 +28,22 @@ install: .c.o: ${CC} ${CPPFLAGS} ${CFLAGS} -c $< +.c.d: + $(MAKEDEPEND) $(CPPFLAGS) $(CFLAGS) $< -o $@ + vers.c: vers.c.sh configure.ac sh @top_srcdir@/vers.c.sh @top_srcdir@/configure.ac clean: - rm -f tts *.o + rm -f tts ${OBJS} $(OBJS:.o=.d) + +depend: $(OBJS:.o=.d) + sed '/^# Do not remove this line -- make depend needs it/,$$ d' \ + Makefile.new + echo '# Do not remove this line -- make depend needs it' >>Makefile.new + cat *.d >> Makefile.new + mv Makefile.new Makefile + +.PHONY: depend clean install libuv + +# Do not remove this line -- make depend needs it diff --git a/tts.c b/tts.c index b6da855..38fe8f9 100644 --- a/tts.c +++ b/tts.c @@ -56,11 +56,9 @@ #include "style.h" #include "variable.h" -extern char const *tts_version; - volatile sig_atomic_t doexit; -static time_t laststatus; +time_t laststatus; history_t *searchhist; history_t *prompthist; @@ -462,246 +460,6 @@ char rcfile[PATH_MAX + 1]; return 0; } -void -drawheader() -{ -WCHAR title[64]; - - SNPRINTF(title, WSIZEOF(title), WIDE("TTS %s - Type '?' for help"), - tts_version); - wmove(titwin, 0, 0); - WADDSTR(titwin, title); - - if (itime > 0) { - WCHAR str[128]; - int h, m, s; - time_t passed = time(NULL) - itime; - - time_to_hms(passed, h, m, s); - SNPRINTF(str, WSIZEOF(str), WIDE(" *** MARK INTERRUPT: %02d:%02d:%02d ***"), - h, m, s); - - wattron(titwin, A_BOLD); - WADDSTR(titwin, str); - wattroff(titwin, A_BOLD); - } - wclrtoeol(titwin); - wrefresh(titwin); -} - -void -vdrawstatus(msg, ap) - const WCHAR *msg; - va_list ap; -{ -WCHAR s[1024]; - VSNPRINTF(s, WSIZEOF(s), msg, ap); - - wmove(statwin, 0, 0); - WADDSTR(statwin, s); - wclrtoeol(statwin); - wrefresh(statwin); - time(&laststatus); -} - -void -drawstatus(const WCHAR *msg, ...) -{ -va_list ap; - va_start(ap, msg); - vdrawstatus(msg, ap); - va_end(ap); -} - -int -yesno(msg) - const WCHAR *msg; -{ -WINDOW *pwin; -INT c; - - pwin = newwin(1, COLS, LINES - 2, 0); - keypad(pwin, TRUE); - wattron(pwin, A_BOLD); - wmove(pwin, 0, 0); - WADDSTR(pwin, msg); - WADDSTR(pwin, WIDE(" [y/N]? ")); - wattroff(pwin, A_BOLD); - - while (WGETCH(pwin, &c) == ERR -#ifdef KEY_RESIZE - || (c == KEY_RESIZE) -#endif - ) - ; - - return (c == 'Y' || c == 'y') ? 1 : 0; -} - -WCHAR * -prompt(msg, def, hist) - const WCHAR *msg, *def; - history_t *hist; -{ -WINDOW *pwin; -WCHAR input[256]; -size_t pos = 0; -histent_t *histpos = NULL; - - if (hist == NULL) - hist = prompthist; - - memset(input, 0, sizeof(input)); - if (def) { - STRNCPY(input, def, WSIZEOF(input) - 1); - pos = STRLEN(input); - } - - pwin = newwin(1, COLS, LINES - 2, 0); - keypad(pwin, TRUE); - - wattr_on(pwin, style_fg(sy_status), NULL); - wbkgd(pwin, style_bg(sy_status)); - - wattron(pwin, A_BOLD); - wmove(pwin, 0, 0); - WADDSTR(pwin, msg); - wattroff(pwin, A_BOLD); - - curs_set(1); - - for (;;) { - INT c; - wmove(pwin, 0, STRLEN(msg) + 1); - WADDSTR(pwin, input); - wclrtoeol(pwin); - wmove(pwin, 0, STRLEN(msg) + 1 + pos); - wrefresh(pwin); - - if (WGETCH(pwin, &c) == ERR) - continue; - - switch (c) { - case '\n': - case '\r': - goto end; - - case KEY_BACKSPACE: - case 0x7F: - case 0x08: - if (pos) { - if (pos == STRLEN(input)) - input[--pos] = 0; - else { - int i = STRLEN(input); - pos--; - MEMCPY(input + pos, input + pos + 1, STRLEN(input) - pos); - input[i] = 0; - } - } - break; - - case KEY_DC: - if (pos < STRLEN(input)) { - int i = STRLEN(input); - MEMCPY(input + pos, input + pos + 1, STRLEN(input) - pos); - input[i] = 0; - } - break; - - case KEY_LEFT: - if (pos) - pos--; - break; - - case KEY_RIGHT: - if (pos < STRLEN(input)) - pos++; - break; - - case KEY_HOME: - case 0x01: /* ^A */ - pos = 0; - break; - - case KEY_END: - case 0x05: /* ^E */ - pos = STRLEN(input); - break; - - case 0x07: /* ^G */ - case 0x1B: /* ESC */ - curs_set(0); - delwin(pwin); - return NULL; - - case 0x15: /* ^U */ - input[0] = 0; - pos = 0; - break; - -#ifdef KEY_RESIZE - case KEY_RESIZE: - break; -#endif - - case KEY_UP: - if (histpos == NULL) { - if ((histpos = TAILQ_LAST(&hist->hi_ents, hentlist)) == NULL) { - beep(); - break; - } - } else { - if (TAILQ_PREV(histpos, hentlist, he_entries) == NULL) { - beep(); - break; - } else - histpos = TAILQ_PREV(histpos, hentlist, he_entries); - } - - - STRNCPY(input, histpos->he_text, WSIZEOF(input) - 1); - pos = STRLEN(input); - break; - - case KEY_DOWN: - if (histpos == NULL) { - beep(); - break; - } - - if (TAILQ_NEXT(histpos, he_entries) == NULL) { - beep(); - break; - } else - histpos = TAILQ_NEXT(histpos, he_entries); - - - STRNCPY(input, histpos->he_text, WSIZEOF(input) - 1); - pos = STRLEN(input); - break; - - default: - if (pos != STRLEN(input)) { - MEMMOVE(input + pos + 1, input + pos, STRLEN(input) - pos); - input[pos++] = c; - } else { - input[pos++] = c; - input[pos] = 0; - } - - break; - } - } -end: ; - - curs_set(0); - delwin(pwin); - wtouchln(statwin, 1, 1, 1); - hist_add(hist, input); - return STRDUP(input); -} - void drawentries() { diff --git a/tts.h b/tts.h index 318f8ba..d9e70e4 100644 --- a/tts.h +++ b/tts.h @@ -17,6 +17,9 @@ #include "queue.h" #include "entry.h" +extern char const *tts_version; +extern time_t laststatus; + /* * Configuration options. */ diff --git a/ui.c b/ui.c index 1ac4965..325b745 100644 --- a/ui.c +++ b/ui.c @@ -8,8 +8,11 @@ * warranty. */ +#include + #include "ui.h" #include "tts.h" +#include "style.h" WINDOW *titwin, *statwin, *listwin; int in_curses; @@ -63,3 +66,243 @@ entry_t *en; curent = NULL; } +void +drawheader() +{ +WCHAR title[64]; + + SNPRINTF(title, WSIZEOF(title), WIDE("TTS %s - Type '?' for help"), + tts_version); + wmove(titwin, 0, 0); + WADDSTR(titwin, title); + + if (itime > 0) { + WCHAR str[128]; + int h, m, s; + time_t passed = time(NULL) - itime; + + time_to_hms(passed, h, m, s); + SNPRINTF(str, WSIZEOF(str), WIDE(" *** MARK INTERRUPT: %02d:%02d:%02d ***"), + h, m, s); + + wattron(titwin, A_BOLD); + WADDSTR(titwin, str); + wattroff(titwin, A_BOLD); + } + wclrtoeol(titwin); + wrefresh(titwin); +} + +void +vdrawstatus(msg, ap) + const WCHAR *msg; + va_list ap; +{ +WCHAR s[1024]; + VSNPRINTF(s, WSIZEOF(s), msg, ap); + + wmove(statwin, 0, 0); + WADDSTR(statwin, s); + wclrtoeol(statwin); + wrefresh(statwin); + time(&laststatus); +} + +void +drawstatus(const WCHAR *msg, ...) +{ +va_list ap; + va_start(ap, msg); + vdrawstatus(msg, ap); + va_end(ap); +} + +int +yesno(msg) + const WCHAR *msg; +{ +WINDOW *pwin; +INT c; + + pwin = newwin(1, COLS, LINES - 2, 0); + keypad(pwin, TRUE); + wattron(pwin, A_BOLD); + wmove(pwin, 0, 0); + WADDSTR(pwin, msg); + WADDSTR(pwin, WIDE(" [y/N]? ")); + wattroff(pwin, A_BOLD); + + while (WGETCH(pwin, &c) == ERR +#ifdef KEY_RESIZE + || (c == KEY_RESIZE) +#endif + ) + ; + + return (c == 'Y' || c == 'y') ? 1 : 0; +} + +WCHAR * +prompt(msg, def, hist) + const WCHAR *msg, *def; + history_t *hist; +{ +WINDOW *pwin; +WCHAR input[256]; +size_t pos = 0; +histent_t *histpos = NULL; + + if (hist == NULL) + hist = prompthist; + + memset(input, 0, sizeof(input)); + if (def) { + STRNCPY(input, def, WSIZEOF(input) - 1); + pos = STRLEN(input); + } + + pwin = newwin(1, COLS, LINES - 2, 0); + keypad(pwin, TRUE); + + wattr_on(pwin, style_fg(sy_status), NULL); + wbkgd(pwin, style_bg(sy_status)); + + wattron(pwin, A_BOLD); + wmove(pwin, 0, 0); + WADDSTR(pwin, msg); + wattroff(pwin, A_BOLD); + + curs_set(1); + + for (;;) { + INT c; + wmove(pwin, 0, STRLEN(msg) + 1); + WADDSTR(pwin, input); + wclrtoeol(pwin); + wmove(pwin, 0, STRLEN(msg) + 1 + pos); + wrefresh(pwin); + + if (WGETCH(pwin, &c) == ERR) + continue; + + switch (c) { + case '\n': + case '\r': + goto end; + + case KEY_BACKSPACE: + case 0x7F: + case 0x08: + if (pos) { + if (pos == STRLEN(input)) + input[--pos] = 0; + else { + int i = STRLEN(input); + pos--; + MEMCPY(input + pos, input + pos + 1, STRLEN(input) - pos); + input[i] = 0; + } + } + break; + + case KEY_DC: + if (pos < STRLEN(input)) { + int i = STRLEN(input); + MEMCPY(input + pos, input + pos + 1, STRLEN(input) - pos); + input[i] = 0; + } + break; + + case KEY_LEFT: + if (pos) + pos--; + break; + + case KEY_RIGHT: + if (pos < STRLEN(input)) + pos++; + break; + + case KEY_HOME: + case 0x01: /* ^A */ + pos = 0; + break; + + case KEY_END: + case 0x05: /* ^E */ + pos = STRLEN(input); + break; + + case 0x07: /* ^G */ + case 0x1B: /* ESC */ + curs_set(0); + delwin(pwin); + return NULL; + + case 0x15: /* ^U */ + input[0] = 0; + pos = 0; + break; + +#ifdef KEY_RESIZE + case KEY_RESIZE: + break; +#endif + + case KEY_UP: + if (histpos == NULL) { + if ((histpos = TAILQ_LAST(&hist->hi_ents, hentlist)) == NULL) { + beep(); + break; + } + } else { + if (TAILQ_PREV(histpos, hentlist, he_entries) == NULL) { + beep(); + break; + } else + histpos = TAILQ_PREV(histpos, hentlist, he_entries); + } + + + STRNCPY(input, histpos->he_text, WSIZEOF(input) - 1); + pos = STRLEN(input); + break; + + case KEY_DOWN: + if (histpos == NULL) { + beep(); + break; + } + + if (TAILQ_NEXT(histpos, he_entries) == NULL) { + beep(); + break; + } else + histpos = TAILQ_NEXT(histpos, he_entries); + + + STRNCPY(input, histpos->he_text, WSIZEOF(input) - 1); + pos = STRLEN(input); + break; + + default: + if (pos != STRLEN(input)) { + MEMMOVE(input + pos + 1, input + pos, STRLEN(input) - pos); + input[pos++] = c; + } else { + input[pos++] = c; + input[pos] = 0; + } + + break; + } + } +end: ; + + curs_set(0); + delwin(pwin); + wtouchln(statwin, 1, 1, 1); + hist_add(hist, input); + return STRDUP(input); +} + From a1a3b576a09a39fd4f6210a315ced1fdd306833d Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Fri, 7 Mar 2014 20:20:20 +0000 Subject: [PATCH 05/51] OS X: Remove CoreFoundation; use kqueue() directly. --- bindings.c | 2 +- bindings.h | 13 +- configure | 2 +- configure.ac | 2 +- entry.c | 6 +- entry.h | 6 +- functions.c | 48 ++-- queue.h | 611 --------------------------------------------------- tailq.h | 163 ++++++++++++++ tts.c | 84 +++++-- tts.h | 6 +- ui.c | 18 +- 12 files changed, 279 insertions(+), 682 deletions(-) delete mode 100644 queue.h create mode 100644 tailq.h diff --git a/bindings.c b/bindings.c index 0132f65..dfcb5d1 100644 --- a/bindings.c +++ b/bindings.c @@ -10,4 +10,4 @@ #include "bindings.h" -binding_list_t bindings = TAILQ_HEAD_INITIALIZER(bindings); +binding_list_t bindings = TTS_TAILQ_HEAD_INITIALIZER(bindings); diff --git a/bindings.h b/bindings.h index 8b7df24..1819a08 100644 --- a/bindings.h +++ b/bindings.h @@ -13,7 +13,7 @@ #include "wide.h" #include "functions.h" -#include "queue.h" +#include "tailq.h" typedef struct tkey { INT ky_code; @@ -21,13 +21,14 @@ typedef struct tkey { } tkey_t; typedef struct binding { - INT bi_code; - tkey_t *bi_key; - function_t *bi_func; - TAILQ_ENTRY(binding) bi_entries; + INT bi_code; + tkey_t *bi_key; + function_t *bi_func; + + TTS_TAILQ_ENTRY(binding) bi_entries; } binding_t; -typedef TAILQ_HEAD(bindlist, binding) binding_list_t; +typedef TTS_TAILQ_HEAD(bindlist, binding) binding_list_t; extern binding_list_t bindings; tkey_t *find_key(const WCHAR *name); diff --git a/configure b/configure index a3798e9..836b004 100755 --- a/configure +++ b/configure @@ -4243,7 +4243,7 @@ fi oLDFLAGS="$LDFLAGS" -LDFLAGS="$LDFLAGS -framework CoreFoundation -framework IOKit" +LDFLAGS="$LDFLAGS -framework IOKit" for ac_func in IORegisterForSystemPower do : ac_fn_c_check_func "$LINENO" "IORegisterForSystemPower" "ac_cv_func_IORegisterForSystemPower" diff --git a/configure.ac b/configure.ac index 05984dd..dce8aa5 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ AC_CHECK_HEADERS([IOKit/pwr_mgt/IOPMLib.h]) AC_CHECK_LIB(m, round) oLDFLAGS="$LDFLAGS" -LDFLAGS="$LDFLAGS -framework CoreFoundation -framework IOKit" +LDFLAGS="$LDFLAGS -framework IOKit" AC_CHECK_FUNCS([IORegisterForSystemPower], [], [LDFLAGS="$oLDFLAGS"]) AC_CONFIG_FILES([Makefile]) diff --git a/entry.c b/entry.c index b6e4ce6..6bcfefa 100644 --- a/entry.c +++ b/entry.c @@ -17,7 +17,7 @@ #include "wide.h" #include "tts.h" -entry_list entries = TAILQ_HEAD_INITIALIZER(entries); +entry_list entries = TTS_TAILQ_HEAD_INITIALIZER(entries); entry_t *running; @@ -32,7 +32,7 @@ entry_t *en; if (auto_nonbillable && STRSTR(desc, auto_nonbillable)) en->en_flags.efl_nonbillable = 1; - TAILQ_INSERT_HEAD(&entries, en, en_entries); + TTS_TAILQ_INSERT_HEAD(&entries, en, en_entries); en->en_desc = STRDUP(desc); time(&en->en_created); @@ -93,7 +93,7 @@ time_t day = time_day(when); time_t sum = 0; entry_t *en; int rnd = incr * 60; - TAILQ_FOREACH(en, &entries, en_entries) { + TTS_TAILQ_FOREACH(en, &entries, en_entries) { time_t n; if (entry_day(en) > day) diff --git a/entry.h b/entry.h index 68b45a1..54e33c0 100644 --- a/entry.h +++ b/entry.h @@ -13,7 +13,7 @@ #include -#include "queue.h" +#include "tailq.h" #include "wide.h" typedef struct entry { @@ -29,10 +29,10 @@ typedef struct entry { int efl_deleted:1; int efl_nonbillable:1; } en_flags; - TAILQ_ENTRY(entry) en_entries; + TTS_TAILQ_ENTRY(entry) en_entries; } entry_t; -typedef TAILQ_HEAD(entrylist, entry) entry_list; +typedef TTS_TAILQ_HEAD(entrylist, entry) entry_list; extern entry_list entries; extern entry_t *running; diff --git a/functions.c b/functions.c index 3b8631a..57c91a0 100644 --- a/functions.c +++ b/functions.c @@ -53,7 +53,7 @@ kquit() entry_t *en; int ndel = 0; - TAILQ_FOREACH(en, &entries, en_entries) { + TTS_TAILQ_FOREACH(en, &entries, en_entries) { if (en->en_flags.efl_deleted) ndel++; } @@ -140,7 +140,7 @@ kmarkdel() entry_t *en; int nmarked = 0; - TAILQ_FOREACH(en, &entries, en_entries) { + TTS_TAILQ_FOREACH(en, &entries, en_entries) { if (en->en_flags.efl_marked) { nmarked++; en->en_flags.efl_deleted = 1; @@ -166,17 +166,17 @@ ksync() { entry_t *en, *ten; - TAILQ_FOREACH_SAFE(en, &entries, en_entries, ten) { + TTS_TAILQ_FOREACH_SAFE(en, &entries, en_entries, ten) { if (!en->en_flags.efl_deleted) continue; if (en == curent) curent = NULL; - TAILQ_REMOVE(&entries, en, en_entries); + TTS_TAILQ_REMOVE(&entries, en, en_entries); entry_free(en); } if (curent == NULL) - curent = TAILQ_FIRST(&entries); + curent = TTS_TAILQ_FIRST(&entries); save(); } @@ -188,7 +188,7 @@ entry_t *prev = curent; return; do { - if ((prev = TAILQ_PREV(prev, entrylist, en_entries)) == NULL) + if ((prev = TTS_TAILQ_PREV(prev, entrylist, en_entries)) == NULL) break; } while (!showinv && prev->en_flags.efl_invoiced); @@ -210,7 +210,7 @@ entry_t *next = curent; return; do { - if ((next = TAILQ_NEXT(next, en_entries)) == NULL) + if ((next = TTS_TAILQ_NEXT(next, en_entries)) == NULL) break; } while (!showinv && next->en_flags.efl_invoiced); @@ -230,7 +230,7 @@ kinvoiced() entry_t *en; int anymarked = 0; - TAILQ_FOREACH(en, &entries, en_entries) { + TTS_TAILQ_FOREACH(en, &entries, en_entries) { if (!en->en_flags.efl_marked) continue; anymarked = 1; @@ -254,8 +254,8 @@ int anymarked = 0; en = curent; if (showinv) { - if (TAILQ_NEXT(curent, en_entries) != NULL) - curent = TAILQ_NEXT(curent, en_entries); + if (TTS_TAILQ_NEXT(curent, en_entries) != NULL) + curent = TTS_TAILQ_NEXT(curent, en_entries); return; } @@ -263,7 +263,7 @@ int anymarked = 0; * Try to find the next uninvoiced request to move the cursor to. */ for (;;) { - if ((curent = TAILQ_NEXT(curent, en_entries)) == NULL) + if ((curent = TTS_TAILQ_NEXT(curent, en_entries)) == NULL) break; /* end of list */ if (!curent->en_flags.efl_invoiced) return; @@ -273,7 +273,7 @@ int anymarked = 0; * We didn't find any, so try searching backwards instead. */ for (curent = en;;) { - if ((curent = TAILQ_PREV(curent, entrylist, en_entries)) == NULL) + if ((curent = TTS_TAILQ_PREV(curent, entrylist, en_entries)) == NULL) break; /* end of list */ if (!curent->en_flags.efl_invoiced) return; @@ -286,7 +286,7 @@ kbillable() entry_t *en; int anymarked = 0; - TAILQ_FOREACH(en, &entries, en_entries) { + TTS_TAILQ_FOREACH(en, &entries, en_entries) { if (!en->en_flags.efl_marked) continue; anymarked = 1; @@ -378,7 +378,7 @@ entry_t *en = curent; return; if (!curent) { - curent = TAILQ_FIRST(&entries); + curent = TTS_TAILQ_FIRST(&entries); return; } @@ -386,7 +386,7 @@ entry_t *en = curent; * Try to find the next uninvoiced request to move the cursor to. */ for (;;) { - if ((curent = TAILQ_NEXT(curent, en_entries)) == NULL) + if ((curent = TTS_TAILQ_NEXT(curent, en_entries)) == NULL) break; /* end of list */ if (!curent->en_flags.efl_invoiced) return; @@ -396,7 +396,7 @@ entry_t *en = curent; * We didn't find any, so try searching backwards instead. */ for (curent = en;;) { - if ((curent = TAILQ_PREV(curent, entrylist, en_entries)) == NULL) + if ((curent = TTS_TAILQ_PREV(curent, entrylist, en_entries)) == NULL) break; /* end of list */ if (!curent->en_flags.efl_invoiced) return; @@ -537,7 +537,7 @@ int h, m, s = 0; /* * Count number of marked entries and the summed time. */ - TAILQ_FOREACH(en, &entries, en_entries) { + TTS_TAILQ_FOREACH(en, &entries, en_entries) { if (!en->en_flags.efl_marked || en == curent) continue; nmarked++; @@ -561,13 +561,13 @@ int h, m, s = 0; if (!yesno(pr)) return; - TAILQ_FOREACH_SAFE(en, &entries, en_entries, ten) { + TTS_TAILQ_FOREACH_SAFE(en, &entries, en_entries, ten) { if (!en->en_flags.efl_marked || en == curent) continue; if (en->en_started) entry_stop(en); curent->en_secs += en->en_secs; - TAILQ_REMOVE(&entries, en, en_entries); + TTS_TAILQ_REMOVE(&entries, en, en_entries); entry_free(en); } save(); @@ -586,12 +586,12 @@ INT c; binding_t *bi; /* Count the number of bindings */ - TAILQ_FOREACH(bi, &bindings, bi_entries) + TTS_TAILQ_FOREACH(bi, &bindings, bi_entries) nhelp++; help = calloc(nhelp, sizeof(const WCHAR *)); i = 0; - TAILQ_FOREACH(bi, &bindings, bi_entries) { + TTS_TAILQ_FOREACH(bi, &bindings, bi_entries) { WCHAR s[128]; if (bi->bi_key) SNPRINTF(s, WSIZEOF(s), WIDE("%-10"FMT_L"s %"FMT_L"s (%"FMT_L"s)"), @@ -660,7 +660,7 @@ void kunmarkall() { entry_t *en; - TAILQ_FOREACH(en, &entries, en_entries) + TTS_TAILQ_FOREACH(en, &entries, en_entries) en->en_flags.efl_marked = 0; } @@ -746,10 +746,10 @@ entry_t *start, *cur; cur = start = curent; for (;;) { - cur = TAILQ_NEXT(cur, en_entries); + cur = TTS_TAILQ_NEXT(cur, en_entries); if (cur == NULL) { drawstatus(WIDE("Search reached last entry, continuing from top.")); - cur = TAILQ_FIRST(&entries); + cur = TTS_TAILQ_FIRST(&entries); } if (cur == start) { diff --git a/queue.h b/queue.h deleted file mode 100644 index fc3c633..0000000 --- a/queue.h +++ /dev/null @@ -1,611 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - * FreeBSD: release/9.0.0/sys/sys/queue.h 221843 2011-05-13 15:49:23Z mdf - */ - -#ifndef TTS_QUEUE_H -#define TTS_QUEUE_H - -/* - * This file defines four types of data structures: singly-linked lists, - * singly-linked tail queues, lists and tail queues. - * - * A singly-linked list is headed by a single forward pointer. The elements - * are singly linked for minimum space and pointer manipulation overhead at - * the expense of O(n) removal for arbitrary elements. New elements can be - * added to the list after an existing element or at the head of the list. - * Elements being removed from the head of the list should use the explicit - * macro for this purpose for optimum efficiency. A singly-linked list may - * only be traversed in the forward direction. Singly-linked lists are ideal - * for applications with large datasets and few or no removals or for - * implementing a LIFO queue. - * - * A singly-linked tail queue is headed by a pair of pointers, one to the - * head of the list and the other to the tail of the list. The elements are - * singly linked for minimum space and pointer manipulation overhead at the - * expense of O(n) removal for arbitrary elements. New elements can be added - * to the list after an existing element, at the head of the list, or at the - * end of the list. Elements being removed from the head of the tail queue - * should use the explicit macro for this purpose for optimum efficiency. - * A singly-linked tail queue may only be traversed in the forward direction. - * Singly-linked tail queues are ideal for applications with large datasets - * and few or no removals or for implementing a FIFO queue. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may only be traversed in the forward direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may be traversed in either direction. - * - * For details on the use of these macros, see the queue(3) manual page. - * - * - * SLIST LIST STAILQ TAILQ - * _HEAD + + + + - * _HEAD_INITIALIZER + + + + - * _ENTRY + + + + - * _INIT + + + + - * _EMPTY + + + + - * _FIRST + + + + - * _NEXT + + + + - * _PREV - - - + - * _LAST - - + + - * _FOREACH + + + + - * _FOREACH_SAFE + + + + - * _FOREACH_REVERSE - - - + - * _FOREACH_REVERSE_SAFE - - - + - * _INSERT_HEAD + + + + - * _INSERT_BEFORE - + - + - * _INSERT_AFTER + + + + - * _INSERT_TAIL - - + + - * _CONCAT - - + + - * _REMOVE_AFTER + - + - - * _REMOVE_HEAD + - + - - * _REMOVE + + + + - * _SWAP + + + + - * - */ -#ifdef QUEUE_MACRO_DEBUG -/* Store the last 2 places the queue element or head was altered */ -struct qm_trace { - char * lastfile; - int lastline; - char * prevfile; - int prevline; -}; - -#define TRACEBUF struct qm_trace trace; -#define TRASHIT(x) do {(x) = (void *)-1;} while (0) -#define QMD_SAVELINK(name, link) void **name = (void *)&(link) - -#define QMD_TRACE_HEAD(head) do { \ - (head)->trace.prevline = (head)->trace.lastline; \ - (head)->trace.prevfile = (head)->trace.lastfile; \ - (head)->trace.lastline = __LINE__; \ - (head)->trace.lastfile = __FILE__; \ -} while (0) - -#define QMD_TRACE_ELEM(elem) do { \ - (elem)->trace.prevline = (elem)->trace.lastline; \ - (elem)->trace.prevfile = (elem)->trace.lastfile; \ - (elem)->trace.lastline = __LINE__; \ - (elem)->trace.lastfile = __FILE__; \ -} while (0) - -#else -#define QMD_TRACE_ELEM(elem) -#define QMD_TRACE_HEAD(head) -#define QMD_SAVELINK(name, link) -#define TRACEBUF -#define TRASHIT(x) -#endif /* QUEUE_MACRO_DEBUG */ - -/* - * Singly-linked List declarations. - */ -#define SLIST_HEAD(name, type) \ -struct name { \ - struct type *slh_first; /* first element */ \ -} - -#define SLIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define SLIST_ENTRY(type) \ -struct { \ - struct type *sle_next; /* next element */ \ -} - -/* - * Singly-linked List functions. - */ -#define SLIST_EMPTY(head) ((head)->slh_first == NULL) - -#define SLIST_FIRST(head) ((head)->slh_first) - -#define SLIST_FOREACH(var, head, field) \ - for ((var) = SLIST_FIRST((head)); \ - (var); \ - (var) = SLIST_NEXT((var), field)) - -#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = SLIST_FIRST((head)); \ - (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ - for ((varp) = &SLIST_FIRST((head)); \ - ((var) = *(varp)) != NULL; \ - (varp) = &SLIST_NEXT((var), field)) - -#define SLIST_INIT(head) do { \ - SLIST_FIRST((head)) = NULL; \ -} while (0) - -#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ - SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ - SLIST_NEXT((slistelm), field) = (elm); \ -} while (0) - -#define SLIST_INSERT_HEAD(head, elm, field) do { \ - SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ - SLIST_FIRST((head)) = (elm); \ -} while (0) - -#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) - -#define SLIST_REMOVE(head, elm, type, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.sle_next); \ - if (SLIST_FIRST((head)) == (elm)) { \ - SLIST_REMOVE_HEAD((head), field); \ - } \ - else { \ - struct type *curelm = SLIST_FIRST((head)); \ - while (SLIST_NEXT(curelm, field) != (elm)) \ - curelm = SLIST_NEXT(curelm, field); \ - SLIST_REMOVE_AFTER(curelm, field); \ - } \ - TRASHIT(*oldnext); \ -} while (0) - -#define SLIST_REMOVE_AFTER(elm, field) do { \ - SLIST_NEXT(elm, field) = \ - SLIST_NEXT(SLIST_NEXT(elm, field), field); \ -} while (0) - -#define SLIST_REMOVE_HEAD(head, field) do { \ - SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ -} while (0) - -#define SLIST_SWAP(head1, head2, type) do { \ - struct type *swap_first = SLIST_FIRST(head1); \ - SLIST_FIRST(head1) = SLIST_FIRST(head2); \ - SLIST_FIRST(head2) = swap_first; \ -} while (0) - -/* - * Singly-linked Tail queue declarations. - */ -#define STAILQ_HEAD(name, type) \ -struct name { \ - struct type *stqh_first;/* first element */ \ - struct type **stqh_last;/* addr of last next element */ \ -} - -#define STAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).stqh_first } - -#define STAILQ_ENTRY(type) \ -struct { \ - struct type *stqe_next; /* next element */ \ -} - -/* - * Singly-linked Tail queue functions. - */ -#define STAILQ_CONCAT(head1, head2) do { \ - if (!STAILQ_EMPTY((head2))) { \ - *(head1)->stqh_last = (head2)->stqh_first; \ - (head1)->stqh_last = (head2)->stqh_last; \ - STAILQ_INIT((head2)); \ - } \ -} while (0) - -#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) - -#define STAILQ_FIRST(head) ((head)->stqh_first) - -#define STAILQ_FOREACH(var, head, field) \ - for((var) = STAILQ_FIRST((head)); \ - (var); \ - (var) = STAILQ_NEXT((var), field)) - - -#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = STAILQ_FIRST((head)); \ - (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define STAILQ_INIT(head) do { \ - STAILQ_FIRST((head)) = NULL; \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ -} while (0) - -#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ - if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ - STAILQ_NEXT((tqelm), field) = (elm); \ -} while (0) - -#define STAILQ_INSERT_HEAD(head, elm, field) do { \ - if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ - STAILQ_FIRST((head)) = (elm); \ -} while (0) - -#define STAILQ_INSERT_TAIL(head, elm, field) do { \ - STAILQ_NEXT((elm), field) = NULL; \ - *(head)->stqh_last = (elm); \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ -} while (0) - -#define STAILQ_LAST(head, type, field) \ - (STAILQ_EMPTY((head)) ? \ - NULL : \ - ((struct type *)(void *) \ - ((char *)((head)->stqh_last) - __offsetof(struct type, field)))) - -#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) - -#define STAILQ_REMOVE(head, elm, type, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \ - if (STAILQ_FIRST((head)) == (elm)) { \ - STAILQ_REMOVE_HEAD((head), field); \ - } \ - else { \ - struct type *curelm = STAILQ_FIRST((head)); \ - while (STAILQ_NEXT(curelm, field) != (elm)) \ - curelm = STAILQ_NEXT(curelm, field); \ - STAILQ_REMOVE_AFTER(head, curelm, field); \ - } \ - TRASHIT(*oldnext); \ -} while (0) - -#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ - if ((STAILQ_NEXT(elm, field) = \ - STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ -} while (0) - -#define STAILQ_REMOVE_HEAD(head, field) do { \ - if ((STAILQ_FIRST((head)) = \ - STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ -} while (0) - -#define STAILQ_SWAP(head1, head2, type) do { \ - struct type *swap_first = STAILQ_FIRST(head1); \ - struct type **swap_last = (head1)->stqh_last; \ - STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ - (head1)->stqh_last = (head2)->stqh_last; \ - STAILQ_FIRST(head2) = swap_first; \ - (head2)->stqh_last = swap_last; \ - if (STAILQ_EMPTY(head1)) \ - (head1)->stqh_last = &STAILQ_FIRST(head1); \ - if (STAILQ_EMPTY(head2)) \ - (head2)->stqh_last = &STAILQ_FIRST(head2); \ -} while (0) - - -/* - * List declarations. - */ -#define LIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define LIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define LIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} - -/* - * List functions. - */ - -#define LIST_EMPTY(head) ((head)->lh_first == NULL) - -#define LIST_FIRST(head) ((head)->lh_first) - -#define LIST_FOREACH(var, head, field) \ - for ((var) = LIST_FIRST((head)); \ - (var); \ - (var) = LIST_NEXT((var), field)) - -#define LIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = LIST_FIRST((head)); \ - (var) && ((tvar) = LIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define LIST_INIT(head) do { \ - LIST_FIRST((head)) = NULL; \ -} while (0) - -#define LIST_INSERT_AFTER(listelm, elm, field) do { \ - QMD_LIST_CHECK_NEXT(listelm, field); \ - if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ - LIST_NEXT((listelm), field)->field.le_prev = \ - &LIST_NEXT((elm), field); \ - LIST_NEXT((listelm), field) = (elm); \ - (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ -} while (0) - -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ - QMD_LIST_CHECK_PREV(listelm, field); \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - LIST_NEXT((elm), field) = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ -} while (0) - -#define LIST_INSERT_HEAD(head, elm, field) do { \ - QMD_LIST_CHECK_HEAD((head), field); \ - if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ - LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ - LIST_FIRST((head)) = (elm); \ - (elm)->field.le_prev = &LIST_FIRST((head)); \ -} while (0) - -#define LIST_PREV(elm, field) ((elm)->field.le_prev ? *(elm)->field.le_prev : NULL) -#define LIST_NEXT(elm, field) ((elm)->field.le_next) - -#define LIST_REMOVE(elm, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.le_next); \ - QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ - QMD_LIST_CHECK_NEXT(elm, field); \ - QMD_LIST_CHECK_PREV(elm, field); \ - if (LIST_NEXT((elm), field) != NULL) \ - LIST_NEXT((elm), field)->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = LIST_NEXT((elm), field); \ - TRASHIT(*oldnext); \ - TRASHIT(*oldprev); \ -} while (0) - -#define LIST_SWAP(head1, head2, type, field) do { \ - struct type *swap_tmp = LIST_FIRST((head1)); \ - LIST_FIRST((head1)) = LIST_FIRST((head2)); \ - LIST_FIRST((head2)) = swap_tmp; \ - if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ - swap_tmp->field.le_prev = &LIST_FIRST((head1)); \ - if ((swap_tmp = LIST_FIRST((head2))) != NULL) \ - swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ -} while (0) - -/* - * Tail queue declarations. - */ -#define TAILQ_HEAD(name, type) \ -struct name { \ - struct type *tqh_first; /* first element */ \ - struct type **tqh_last; /* addr of last next element */ \ - TRACEBUF \ -} - -#define TAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first } - -#define TAILQ_ENTRY(type) \ -struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ - TRACEBUF \ -} - -/* - * Tail queue functions. - */ -#if (defined(_KERNEL) && defined(INVARIANTS)) -#define QMD_TAILQ_CHECK_HEAD(head, field) do { \ - if (!TAILQ_EMPTY(head) && \ - TAILQ_FIRST((head))->field.tqe_prev != \ - &TAILQ_FIRST((head))) \ - panic("Bad tailq head %p first->prev != head", (head)); \ -} while (0) - -#define QMD_TAILQ_CHECK_TAIL(head, field) do { \ - if (*(head)->tqh_last != NULL) \ - panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ -} while (0) - -#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ - if (TAILQ_NEXT((elm), field) != NULL && \ - TAILQ_NEXT((elm), field)->field.tqe_prev != \ - &((elm)->field.tqe_next)) \ - panic("Bad link elm %p next->prev != elm", (elm)); \ -} while (0) - -#define QMD_TAILQ_CHECK_PREV(elm, field) do { \ - if (*(elm)->field.tqe_prev != (elm)) \ - panic("Bad link elm %p prev->next != elm", (elm)); \ -} while (0) -#else -#define QMD_TAILQ_CHECK_HEAD(head, field) -#define QMD_TAILQ_CHECK_TAIL(head, headname) -#define QMD_TAILQ_CHECK_NEXT(elm, field) -#define QMD_TAILQ_CHECK_PREV(elm, field) -#endif /* (_KERNEL && INVARIANTS) */ - -#define TAILQ_CONCAT(head1, head2, field) do { \ - if (!TAILQ_EMPTY(head2)) { \ - *(head1)->tqh_last = (head2)->tqh_first; \ - (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ - (head1)->tqh_last = (head2)->tqh_last; \ - TAILQ_INIT((head2)); \ - QMD_TRACE_HEAD(head1); \ - QMD_TRACE_HEAD(head2); \ - } \ -} while (0) - -#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) - -#define TAILQ_FIRST(head) ((head)->tqh_first) - -#define TAILQ_FOREACH(var, head, field) \ - for ((var) = TAILQ_FIRST((head)); \ - (var); \ - (var) = TAILQ_NEXT((var), field)) - -#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = TAILQ_FIRST((head)); \ - (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ - for ((var) = TAILQ_LAST((head), headname); \ - (var); \ - (var) = TAILQ_PREV((var), headname, field)) - -#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ - for ((var) = TAILQ_LAST((head), headname); \ - (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ - (var) = (tvar)) - -#define TAILQ_INIT(head) do { \ - TAILQ_FIRST((head)) = NULL; \ - (head)->tqh_last = &TAILQ_FIRST((head)); \ - QMD_TRACE_HEAD(head); \ -} while (0) - -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ - QMD_TAILQ_CHECK_NEXT(listelm, field); \ - if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ - TAILQ_NEXT((elm), field)->field.tqe_prev = \ - &TAILQ_NEXT((elm), field); \ - else { \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_HEAD(head); \ - } \ - TAILQ_NEXT((listelm), field) = (elm); \ - (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ - QMD_TRACE_ELEM(&(elm)->field); \ - QMD_TRACE_ELEM(&listelm->field); \ -} while (0) - -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - QMD_TAILQ_CHECK_PREV(listelm, field); \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - TAILQ_NEXT((elm), field) = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_ELEM(&(elm)->field); \ - QMD_TRACE_ELEM(&listelm->field); \ -} while (0) - -#define TAILQ_INSERT_HEAD(head, elm, field) do { \ - QMD_TAILQ_CHECK_HEAD(head, field); \ - if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ - TAILQ_FIRST((head))->field.tqe_prev = \ - &TAILQ_NEXT((elm), field); \ - else \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - TAILQ_FIRST((head)) = (elm); \ - (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ - QMD_TRACE_HEAD(head); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ - QMD_TAILQ_CHECK_TAIL(head, field); \ - TAILQ_NEXT((elm), field) = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_HEAD(head); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - -#define TAILQ_LAST(head, headname) \ - (*(((struct headname *)((head)->tqh_last))->tqh_last)) - -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) - -#define TAILQ_PREV(elm, headname, field) \ - (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) - -#define TAILQ_REMOVE(head, elm, field) do { \ - QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ - QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ - QMD_TAILQ_CHECK_NEXT(elm, field); \ - QMD_TAILQ_CHECK_PREV(elm, field); \ - if ((TAILQ_NEXT((elm), field)) != NULL) \ - TAILQ_NEXT((elm), field)->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else { \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - QMD_TRACE_HEAD(head); \ - } \ - *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ - TRASHIT(*oldnext); \ - TRASHIT(*oldprev); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - -#define TAILQ_SWAP(head1, head2, type, field) do { \ - struct type *swap_first = (head1)->tqh_first; \ - struct type **swap_last = (head1)->tqh_last; \ - (head1)->tqh_first = (head2)->tqh_first; \ - (head1)->tqh_last = (head2)->tqh_last; \ - (head2)->tqh_first = swap_first; \ - (head2)->tqh_last = swap_last; \ - if ((swap_first = (head1)->tqh_first) != NULL) \ - swap_first->field.tqe_prev = &(head1)->tqh_first; \ - else \ - (head1)->tqh_last = &(head1)->tqh_first; \ - if ((swap_first = (head2)->tqh_first) != NULL) \ - swap_first->field.tqe_prev = &(head2)->tqh_first; \ - else \ - (head2)->tqh_last = &(head2)->tqh_first; \ -} while (0) - -#endif /* !TTS_QUEUE_H */ diff --git a/tailq.h b/tailq.h new file mode 100644 index 0000000..940f155 --- /dev/null +++ b/tailq.h @@ -0,0 +1,163 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + * FreeBSD: release/9.0.0/sys/sys/queue.h 221843 2011-05-13 15:49:23Z mdf + */ + +#ifndef TTS_TAILQ_H +#define TTS_TAILQ_H + +/* + * Tail queue declarations. + */ +#define TTS_TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ +} + +#define TTS_TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TTS_TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} + +#define TTS_TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TTS_TAILQ_INIT((head2)); \ + } \ +} while (0) + +#define TTS_TAILQ_EMPTY(head) ((head)->tqh_first == NULL) + +#define TTS_TAILQ_FIRST(head) ((head)->tqh_first) + +#define TTS_TAILQ_FOREACH(var, head, field) \ + for ((var) = TTS_TAILQ_FIRST((head)); \ + (var); \ + (var) = TTS_TAILQ_NEXT((var), field)) + +#define TTS_TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TTS_TAILQ_FIRST((head)); \ + (var) && ((tvar) = TTS_TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TTS_TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = TTS_TAILQ_LAST((head), headname); \ + (var); \ + (var) = TTS_TAILQ_PREV((var), headname, field)) + +#define TTS_TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar)\ + for ((var) = TTS_TAILQ_LAST((head), headname); \ + (var) && ((tvar) = TTS_TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TTS_TAILQ_INIT(head) do { \ + TTS_TAILQ_FIRST((head)) = NULL; \ + (head)->tqh_last = &TTS_TAILQ_FIRST((head)); \ +} while (0) + +#define TTS_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if ((TTS_TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ + TTS_TAILQ_NEXT((elm), field)->field.tqe_prev = \ + &TTS_TAILQ_NEXT((elm), field); \ + else { \ + (head)->tqh_last = &TTS_TAILQ_NEXT((elm), field); \ + } \ + TTS_TAILQ_NEXT((listelm), field) = (elm); \ + (elm)->field.tqe_prev = &TTS_TAILQ_NEXT((listelm), field); \ +} while (0) + +#define TTS_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + TTS_TAILQ_NEXT((elm), field) = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &TTS_TAILQ_NEXT((elm), field); \ +} while (0) + +#define TTS_TAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((TTS_TAILQ_NEXT((elm), field) = TTS_TAILQ_FIRST((head))) != NULL) \ + TTS_TAILQ_FIRST((head))->field.tqe_prev = \ + &TTS_TAILQ_NEXT((elm), field); \ + else \ + (head)->tqh_last = &TTS_TAILQ_NEXT((elm), field); \ + TTS_TAILQ_FIRST((head)) = (elm); \ + (elm)->field.tqe_prev = &TTS_TAILQ_FIRST((head)); \ +} while (0) + +#define TTS_TAILQ_INSERT_TAIL(head, elm, field) do { \ + TTS_TAILQ_NEXT((elm), field) = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &TTS_TAILQ_NEXT((elm), field); \ +} while (0) + +#define TTS_TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) + +#define TTS_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TTS_TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +#define TTS_TAILQ_REMOVE(head, elm, field) do { \ + if ((TTS_TAILQ_NEXT((elm), field)) != NULL) \ + TTS_TAILQ_NEXT((elm), field)->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else { \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + } \ + *(elm)->field.tqe_prev = TTS_TAILQ_NEXT((elm), field); \ +} while (0) + +#define TTS_TAILQ_SWAP(head1, head2, type, field) do { \ + struct type *swap_first = (head1)->tqh_first; \ + struct type **swap_last = (head1)->tqh_last; \ + (head1)->tqh_first = (head2)->tqh_first; \ + (head1)->tqh_last = (head2)->tqh_last; \ + (head2)->tqh_first = swap_first; \ + (head2)->tqh_last = swap_last; \ + if ((swap_first = (head1)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head1)->tqh_first; \ + else \ + (head1)->tqh_last = &(head1)->tqh_first; \ + if ((swap_first = (head2)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head2)->tqh_first; \ + else \ + (head2)->tqh_last = &(head2)->tqh_first; \ +} while (0) + + +#endif /* !TTS_TAILQ_H */ diff --git a/tts.c b/tts.c index 38fe8f9..019f23b 100644 --- a/tts.c +++ b/tts.c @@ -36,6 +36,9 @@ # include # include # include +# include + +# include # include # include @@ -43,7 +46,7 @@ # include #endif -#include "queue.h" +#include "tailq.h" #include "tts.h" #include "entry.h" #include "wide.h" @@ -223,9 +226,12 @@ static void * power_thread_run(arg) void *arg; { +struct kevent ev, rev; +int kq; sigset_t ss; IONotificationPortRef port_ref; io_object_t notifier; +mach_port_t ioport; /* Block SIGUSR1 so it's always delivered to the main thread, not us */ sigemptyset(&ss); @@ -235,10 +241,48 @@ io_object_t notifier; /* Register a handler for sleep and wake events */ root_port = IORegisterForSystemPower(NULL, &port_ref, power_event, ¬ifier); - CFRunLoopAddSource(CFRunLoopGetCurrent(), - IONotificationPortGetRunLoopSource(port_ref), - kCFRunLoopCommonModes); - CFRunLoopRun(); + ioport = IONotificationPortGetMachPort(port_ref); + EV_SET(&ev, ioport, EVFILT_MACHPORT, EV_ADD, 0, 0, 0); + +/* Create our queue */ + if ((kq = kqueue()) == -1) { + perror("kqueue"); + exit(1); + } + + for (;;) { + int nev; + + struct { + mach_msg_header_t hdr; + char data[8192]; + mach_msg_trailer_t trailer; + } msg; + mach_msg_return_t ret; + + /* Wait for an event */ + if ((nev = kevent(kq, &ev, 1, &rev, 1, NULL)) == -1) { + perror("kevent"); + exit(1); + } + + if (nev == 0) + continue; + + /* Receive the message */ + memset(&msg, 0, sizeof(ret)); + ret = mach_msg(&msg.hdr, MACH_RCV_MSG, 0, sizeof(msg), ioport, + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + + if (ret != MACH_MSG_SUCCESS) { + fprintf(stderr, "mach_msg: %s [%x]\n", + mach_error_string(ret), ret); + exit(1); + } + + /* Give the message to IOKit to handle */ + IODispatchCalloutFromMessage(NULL, &msg.hdr, port_ref); + } /*NOTREACHED*/ return NULL; @@ -400,10 +444,10 @@ char rcfile[PATH_MAX + 1]; drawheader(); drawstatus(WIDE("")); - if (!TAILQ_EMPTY(&entries)) { - curent = TAILQ_FIRST(&entries); + if (!TTS_TAILQ_EMPTY(&entries)) { + curent = TTS_TAILQ_FIRST(&entries); while (!showinv && curent->en_flags.efl_invoiced) - if ((curent = TAILQ_NEXT(curent, en_entries)) == NULL) + if ((curent = TTS_TAILQ_NEXT(curent, en_entries)) == NULL) break; } @@ -444,7 +488,7 @@ char rcfile[PATH_MAX + 1]; drawstatus(WIDE("")); - TAILQ_FOREACH(bi, &bindings, bi_entries) { + TTS_TAILQ_FOREACH(bi, &bindings, bi_entries) { if (bi->bi_code != c) continue; bi->bi_func->fn_hdl(); @@ -471,15 +515,15 @@ chtype oldbg; getmaxyx(listwin, nlines, i); - TAILQ_FOREACH(en, &entries, en_entries) + TTS_TAILQ_FOREACH(en, &entries, en_entries) en->en_flags.efl_visible = 0; - en = TAILQ_FIRST(&entries); + en = TTS_TAILQ_FIRST(&entries); for (i = 0; i < pagestart; i++) - if ((en = TAILQ_NEXT(en, en_entries)) == NULL) + if ((en = TTS_TAILQ_NEXT(en, en_entries)) == NULL) return; - for (; en; en = TAILQ_NEXT(en, en_entries)) { + for (; en; en = TTS_TAILQ_NEXT(en, en_entries)) { time_t n; int h, s, m; WCHAR flags[10], stime[16], *p; @@ -660,7 +704,7 @@ char input[4096]; WCHAR line[4096]; entry_t *en; - TAILQ_FOREACH(en, &entries, en_entries) + TTS_TAILQ_FOREACH(en, &entries, en_entries) entry_free(en); if ((f = fopen(statfile, "r")) == NULL) { @@ -779,7 +823,7 @@ entry_t *en; exit(1); } - TAILQ_FOREACH_REVERSE(en, &entries, entrylist, en_entries) { + TTS_TAILQ_FOREACH_REVERSE(en, &entries, entrylist, en_entries) { char flags[10], *fp = flags, wdesc[4096] = {}; time_t n; @@ -884,7 +928,7 @@ hist_new() history_t *hi; if ((hi = calloc(1, sizeof(*hi))) == NULL) return NULL; - TAILQ_INIT(&hi->hi_ents); + TTS_TAILQ_INIT(&hi->hi_ents); return hi; } @@ -905,10 +949,10 @@ histent_t *hent; return; } - TAILQ_INSERT_TAIL(&hi->hi_ents, hent, he_entries); + TTS_TAILQ_INSERT_TAIL(&hi->hi_ents, hent, he_entries); if (hi->hi_nents == 50) - TAILQ_REMOVE(&hi->hi_ents, TAILQ_FIRST(&hi->hi_ents), he_entries); + TTS_TAILQ_REMOVE(&hi->hi_ents, TTS_TAILQ_FIRST(&hi->hi_ents), he_entries); else ++hi->hi_nents; } @@ -976,7 +1020,7 @@ INT code; } /* Do we already have a binding for this key? */ - TAILQ_FOREACH(binding, &bindings, bi_entries) { + TTS_TAILQ_FOREACH(binding, &bindings, bi_entries) { if (binding->bi_code == code) { binding->bi_func = func; return; @@ -990,7 +1034,7 @@ INT code; binding->bi_key = key; binding->bi_func = func; binding->bi_code = code; - TAILQ_INSERT_TAIL(&bindings, binding, bi_entries); + TTS_TAILQ_INSERT_TAIL(&bindings, binding, bi_entries); } variable_t * diff --git a/tts.h b/tts.h index d9e70e4..b1e779e 100644 --- a/tts.h +++ b/tts.h @@ -14,7 +14,7 @@ #include #include "wide.h" -#include "queue.h" +#include "tailq.h" #include "entry.h" extern char const *tts_version; @@ -50,9 +50,9 @@ int save(void); #define NHIST 50 typedef struct histent { WCHAR *he_text; - TAILQ_ENTRY(histent) he_entries; + TTS_TAILQ_ENTRY(histent) he_entries; } histent_t; -typedef TAILQ_HEAD(hentlist, histent) hentlist_t; +typedef TTS_TAILQ_HEAD(hentlist, histent) hentlist_t; typedef struct history { int hi_nents; diff --git a/ui.c b/ui.c index 325b745..c5aa9fd 100644 --- a/ui.c +++ b/ui.c @@ -27,14 +27,14 @@ cursadvance() entry_t *en; if (!curent) { - curent = TAILQ_FIRST(&entries); + curent = TTS_TAILQ_FIRST(&entries); return; } /* * Try to find the next suitable entry to move the cursor to. */ - for (en = TAILQ_NEXT(curent, en_entries); en; en = TAILQ_NEXT(en, en_entries)) { + for (en = TTS_TAILQ_NEXT(curent, en_entries); en; en = TTS_TAILQ_NEXT(en, en_entries)) { if (!showinv && en->en_flags.efl_invoiced) continue; curent = en; @@ -50,8 +50,8 @@ entry_t *en; if (showinv || !curent->en_flags.efl_invoiced) return; - for (en = TAILQ_PREV(curent, entrylist, en_entries); en; - en = TAILQ_PREV(en, entrylist, en_entries)) { + for (en = TTS_TAILQ_PREV(curent, entrylist, en_entries); en; + en = TTS_TAILQ_PREV(en, entrylist, en_entries)) { if (!showinv && en->en_flags.efl_invoiced) continue; curent = en; @@ -251,16 +251,16 @@ histent_t *histpos = NULL; case KEY_UP: if (histpos == NULL) { - if ((histpos = TAILQ_LAST(&hist->hi_ents, hentlist)) == NULL) { + if ((histpos = TTS_TAILQ_LAST(&hist->hi_ents, hentlist)) == NULL) { beep(); break; } } else { - if (TAILQ_PREV(histpos, hentlist, he_entries) == NULL) { + if (TTS_TAILQ_PREV(histpos, hentlist, he_entries) == NULL) { beep(); break; } else - histpos = TAILQ_PREV(histpos, hentlist, he_entries); + histpos = TTS_TAILQ_PREV(histpos, hentlist, he_entries); } @@ -274,11 +274,11 @@ histent_t *histpos = NULL; break; } - if (TAILQ_NEXT(histpos, he_entries) == NULL) { + if (TTS_TAILQ_NEXT(histpos, he_entries) == NULL) { beep(); break; } else - histpos = TAILQ_NEXT(histpos, he_entries); + histpos = TTS_TAILQ_NEXT(histpos, he_entries); STRNCPY(input, histpos->he_text, WSIZEOF(input) - 1); From 9676c8837860abdf85e56c824fc49968fae689e9 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Fri, 7 Mar 2014 20:21:09 +0000 Subject: [PATCH 06/51] Add .gitignore. --- .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b6b25c1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.swp +*~ +/build +/autom4te.cache +/doconf +/bling_import.pl.old +/queue.h From 38021971e30b84ab066d105aced098d8bce815f6 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Fri, 7 Mar 2014 21:54:26 +0000 Subject: [PATCH 07/51] Rework input handling; no functional changes. Instead of using halfdelay() and relying on GETCH() to return, poll for input ourselves using select() and only call GETCH() when input is ready. On Darwin, use kqueue instead of select. This allows us to receive IOKit notifications directly to the main thread, instead of having a separate thread dedicated to that. We also no longer link to CoreFoundation. --- tts.c | 211 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 120 insertions(+), 91 deletions(-) diff --git a/tts.c b/tts.c index 019f23b..70e45f0 100644 --- a/tts.c +++ b/tts.c @@ -9,6 +9,7 @@ */ #include +#include #include #include @@ -43,7 +44,7 @@ # include # include -# include +# include #endif #include "tailq.h" @@ -199,93 +200,68 @@ variable_t variables[] = { }; #ifdef USE_DARWIN_POWER -static pthread_t power_thread; -static io_connect_t root_port; -static volatile sig_atomic_t donesleep; -static time_t sleeptime; +static IONotificationPortRef port_ref; +static io_object_t notifier; +static mach_port_t ioport; +static io_connect_t root_port; -static void *power_thread_run(void *); +static volatile sig_atomic_t donesleep; +static time_t sleeptime; + +static void power_setup(struct kevent64_s *); +static void power_handle(struct kevent64_s *); static void power_event(void *, io_service_t, natural_t, void *); static void prompt_sleep(void); static void -sigsleep(sig) +power_setup(ev) + struct kevent64_s *ev; { -/* Delivered from the power thread as SIGUSR1 */ - donesleep = 1; -} +mach_port_t pset; +int ret; -/* - * Darwin power notifications are delivered from IOKit via Mach ports, which - * is incompatible with TTS's curses-based main loop. We therefore spawn a - * separate thread to listen for these events, and when we receive one, we - * translate it into a signal (SIGUSR1) which is delivered to the main thread - * to handle. The signal will interrupt getch(). - */ -static void * -power_thread_run(arg) - void *arg; -{ -struct kevent ev, rev; -int kq; -sigset_t ss; -IONotificationPortRef port_ref; -io_object_t notifier; -mach_port_t ioport; - -/* Block SIGUSR1 so it's always delivered to the main thread, not us */ - sigemptyset(&ss); - sigaddset(&ss, SIGUSR1); - pthread_sigmask(SIG_BLOCK, &ss, NULL); + if ((ret = mach_port_allocate(mach_task_self(), + MACH_PORT_RIGHT_PORT_SET, + &pset)) != KERN_SUCCESS) { + fprintf(stderr, "mach_port_allocate: %s [%x]\n", + mach_error_string(ret), ret); + exit(1); + } /* Register a handler for sleep and wake events */ root_port = IORegisterForSystemPower(NULL, &port_ref, power_event, ¬ifier); ioport = IONotificationPortGetMachPort(port_ref); - EV_SET(&ev, ioport, EVFILT_MACHPORT, EV_ADD, 0, 0, 0); + EV_SET64(ev, pset, EVFILT_MACHPORT, EV_ADD, 0, 0, 0, 0, 0); -/* Create our queue */ - if ((kq = kqueue()) == -1) { - perror("kqueue"); + if ((ret = mach_port_insert_member(mach_task_self(), ioport, + pset)) != KERN_SUCCESS) { + fprintf(stderr, "mach_port_insert_member: %s [%x]\n", + mach_error_string(ret), ret); + exit(1); + } +} + +static void +power_handle(ev) + struct kevent64_s *ev; +{ +mach_msg_return_t ret; +void *msg = alloca(ev->data); + +/* Receive the message */ + memset(msg, 0, ev->data); + ret = mach_msg(msg, MACH_RCV_MSG, 0, ev->data, ioport, + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + + if (ret != MACH_MSG_SUCCESS) { + fprintf(stderr, "mach_msg: %s [%x]\n", + mach_error_string(ret), ret); exit(1); } - for (;;) { - int nev; - - struct { - mach_msg_header_t hdr; - char data[8192]; - mach_msg_trailer_t trailer; - } msg; - mach_msg_return_t ret; - - /* Wait for an event */ - if ((nev = kevent(kq, &ev, 1, &rev, 1, NULL)) == -1) { - perror("kevent"); - exit(1); - } - - if (nev == 0) - continue; - - /* Receive the message */ - memset(&msg, 0, sizeof(ret)); - ret = mach_msg(&msg.hdr, MACH_RCV_MSG, 0, sizeof(msg), ioport, - MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - - if (ret != MACH_MSG_SUCCESS) { - fprintf(stderr, "mach_msg: %s [%x]\n", - mach_error_string(ret), ret); - exit(1); - } - - /* Give the message to IOKit to handle */ - IODispatchCalloutFromMessage(NULL, &msg.hdr, port_ref); - } - - /*NOTREACHED*/ - return NULL; +/* Give the message to IOKit to handle */ + IODispatchCalloutFromMessage(NULL, msg, port_ref); } static void @@ -306,12 +282,12 @@ time_t diff; case kIOMessageSystemHasPoweredOn: /* System has finished wake-up; calculate the sleep time and - * notify the main thread. + * prompt the user. */ time(&diff); diff -= sleep_started; sleeptime += diff; - raise(SIGUSR1); + prompt_sleep(); break; } } @@ -327,19 +303,37 @@ int main(argc, argv) char **argv; { -struct passwd *pw; -char rcfile[PATH_MAX + 1]; +struct passwd *pw; +char rcfile[PATH_MAX + 1]; +#ifdef USE_DARWIN_POWER +int kq; +struct kevent64_s evs[2], rev; +# define STDIN_EV 0 +# define IOKIT_EV 1 +#endif setlocale(LC_ALL, ""); +#ifdef USE_DARWIN_POWER + if ((kq = kqueue()) == -1) { + perror("kqueue"); + return 1; + } + + memset(evs, 0, sizeof(evs)); + + EV_SET64(&evs[STDIN_EV], STDIN_FILENO, EVFILT_READ, EV_ADD, 0, 0, 0, 0, 0); + power_setup(&evs[IOKIT_EV]); + + if (kevent64(kq, evs, 2, NULL, 0, 0, NULL) == -1) { + perror("kevent"); + return 1; + } +#endif + signal(SIGTERM, sigexit); signal(SIGINT, sigexit); -#ifdef USE_DARWIN_POWER - signal(SIGUSR1, sigsleep); - pthread_create(&power_thread, NULL, power_thread_run, NULL); -#endif - searchhist = hist_new(); prompthist = hist_new(); @@ -360,7 +354,7 @@ char rcfile[PATH_MAX + 1]; cbreak(); noecho(); nonl(); - halfdelay(5); + nodelay(stdscr, 1); pair_content(0, &default_fg, &default_bg); @@ -454,26 +448,61 @@ char rcfile[PATH_MAX + 1]; for (;;) { INT c; binding_t *bi; +#ifdef USE_DARWIN_POWER + struct timespec timeout; + int nev; +#else + fd_set in_set; + struct timeval timeout; +#endif + if (doexit) break; -#ifdef USE_DARWIN_POWER - if (donesleep) - prompt_sleep(); -#endif - drawheader(); drawentries(); wrefresh(listwin); +#ifdef USE_DARWIN_POWER + timeout.tv_sec = 0; + timeout.tv_nsec = 500000000; + + if ((nev = kevent64(kq, NULL, 0, &rev, 1, 0, + running ? &timeout : NULL)) == -1) { + perror("kevent"); + return 1; + } + + if (nev == 0) + continue; + + if (rev.filter == EVFILT_MACHPORT) { + power_handle(&rev); + continue; + } +#else + /* Wait for input to be ready. */ + FD_ZERO(&in_set); + FD_SET(STDIN_FILENO, &in_set); + + timeout.tv_sec = 0; + timeout.tv_usec = 500000; + + /* + * If there's a running entry, wake up in 0.5 seconds time to update + * the display. Otherwise, we can sleep forever. + */ + select(STDIN_FILENO + 1, &in_set, NULL, NULL, + running ? &timeout : NULL); + + if (!FD_ISSET(STDIN_FILENO, &in_set)) + continue; +#endif + if (GETCH(&c) == ERR) { if (doexit) break; -#ifdef USE_DARWIN_POWER - if (donesleep) - prompt_sleep(); -#endif if (time(NULL) - laststatus >= 2) drawstatus(WIDE("")); if (time(NULL) - lastsave > 60) From 9a3719817ef06d3cc753ed0606b10d72e61bd7f2 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Fri, 7 Mar 2014 21:58:10 +0000 Subject: [PATCH 08/51] Fix ^C handling. --- tts.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tts.c b/tts.c index 70e45f0..630e31a 100644 --- a/tts.c +++ b/tts.c @@ -470,6 +470,10 @@ struct kevent64_s evs[2], rev; if ((nev = kevent64(kq, NULL, 0, &rev, 1, 0, running ? &timeout : NULL)) == -1) { + if (doexit) + break; + if (errno == EINTR) + continue; perror("kevent"); return 1; } @@ -493,8 +497,13 @@ struct kevent64_s evs[2], rev; * If there's a running entry, wake up in 0.5 seconds time to update * the display. Otherwise, we can sleep forever. */ - select(STDIN_FILENO + 1, &in_set, NULL, NULL, - running ? &timeout : NULL); + if (select(STDIN_FILENO + 1, &in_set, NULL, NULL, + running ? &timeout : NULL) == -1) { + if (doexit) + break; + if (errno == EINTR) + continue; + } if (!FD_ISSET(STDIN_FILENO, &in_set)) continue; From 0c3b7443d5a0116ec027cf152655ec55ca446236 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Fri, 7 Mar 2014 22:00:47 +0000 Subject: [PATCH 09/51] Handle multiple input characters at once. --- tts.c | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/tts.c b/tts.c index 630e31a..4f35001 100644 --- a/tts.c +++ b/tts.c @@ -455,7 +455,6 @@ struct kevent64_s evs[2], rev; fd_set in_set; struct timeval timeout; #endif - if (doexit) break; @@ -509,32 +508,31 @@ struct kevent64_s evs[2], rev; continue; #endif - if (GETCH(&c) == ERR) { - if (doexit) - break; - if (time(NULL) - laststatus >= 2) - drawstatus(WIDE("")); - if (time(NULL) - lastsave > 60) - save(); - continue; - } - + while (GETCH(&c) != ERR) { #ifdef KEY_RESIZE - if (c == KEY_RESIZE) - continue; + if (c == KEY_RESIZE) + continue; #endif - drawstatus(WIDE("")); + drawstatus(WIDE("")); - TTS_TAILQ_FOREACH(bi, &bindings, bi_entries) { - if (bi->bi_code != c) - continue; - bi->bi_func->fn_hdl(); - goto next; + TTS_TAILQ_FOREACH(bi, &bindings, bi_entries) { + if (bi->bi_code != c) + continue; + bi->bi_func->fn_hdl(); + goto next;; + } + + drawstatus(WIDE("Unknown command.")); + next: ; } - drawstatus(WIDE("Unknown command.")); - next: ; + if (doexit) + break; + if (time(NULL) - laststatus >= 2) + drawstatus(WIDE("")); + if (time(NULL) - lastsave > 60) + save(); } save(); From e8396d70bad9860d59c2e59028b651fe08d5db30 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Fri, 7 Mar 2014 22:03:47 +0000 Subject: [PATCH 10/51] Always timeout the poll. Otherwise, events like the laststatus update and (more importantly) lastsave don't get run unless there's a running entry. --- tts.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/tts.c b/tts.c index 4f35001..66a4b41 100644 --- a/tts.c +++ b/tts.c @@ -467,8 +467,7 @@ struct kevent64_s evs[2], rev; timeout.tv_sec = 0; timeout.tv_nsec = 500000000; - if ((nev = kevent64(kq, NULL, 0, &rev, 1, 0, - running ? &timeout : NULL)) == -1) { + if ((nev = kevent64(kq, NULL, 0, &rev, 1, 0, &timeout)) == -1) { if (doexit) break; if (errno == EINTR) @@ -477,9 +476,6 @@ struct kevent64_s evs[2], rev; return 1; } - if (nev == 0) - continue; - if (rev.filter == EVFILT_MACHPORT) { power_handle(&rev); continue; @@ -492,20 +488,12 @@ struct kevent64_s evs[2], rev; timeout.tv_sec = 0; timeout.tv_usec = 500000; - /* - * If there's a running entry, wake up in 0.5 seconds time to update - * the display. Otherwise, we can sleep forever. - */ - if (select(STDIN_FILENO + 1, &in_set, NULL, NULL, - running ? &timeout : NULL) == -1) { + if (select(STDIN_FILENO + 1, &in_set, NULL, NULL, &timeout) == -1) { if (doexit) break; if (errno == EINTR) continue; } - - if (!FD_ISSET(STDIN_FILENO, &in_set)) - continue; #endif while (GETCH(&c) != ERR) { @@ -529,8 +517,10 @@ struct kevent64_s evs[2], rev; if (doexit) break; + if (time(NULL) - laststatus >= 2) drawstatus(WIDE("")); + if (time(NULL) - lastsave > 60) save(); } From ca908281b4386debfd053d574a90c6a4c3eb43a2 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Fri, 7 Mar 2014 22:19:07 +0000 Subject: [PATCH 11/51] No need to use kevent64(). --- tts.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tts.c b/tts.c index 66a4b41..8315bae 100644 --- a/tts.c +++ b/tts.c @@ -208,14 +208,14 @@ static io_connect_t root_port; static volatile sig_atomic_t donesleep; static time_t sleeptime; -static void power_setup(struct kevent64_s *); -static void power_handle(struct kevent64_s *); +static void power_setup(struct kevent *); +static void power_handle(struct kevent *); static void power_event(void *, io_service_t, natural_t, void *); static void prompt_sleep(void); static void power_setup(ev) - struct kevent64_s *ev; + struct kevent *ev; { mach_port_t pset; int ret; @@ -232,7 +232,7 @@ int ret; root_port = IORegisterForSystemPower(NULL, &port_ref, power_event, ¬ifier); ioport = IONotificationPortGetMachPort(port_ref); - EV_SET64(ev, pset, EVFILT_MACHPORT, EV_ADD, 0, 0, 0, 0, 0); + EV_SET(ev, pset, EVFILT_MACHPORT, EV_ADD, 0, 0, 0); if ((ret = mach_port_insert_member(mach_task_self(), ioport, pset)) != KERN_SUCCESS) { @@ -244,7 +244,7 @@ int ret; static void power_handle(ev) - struct kevent64_s *ev; + struct kevent *ev; { mach_msg_return_t ret; void *msg = alloca(ev->data); @@ -303,11 +303,11 @@ int main(argc, argv) char **argv; { -struct passwd *pw; -char rcfile[PATH_MAX + 1]; +struct passwd *pw; +char rcfile[PATH_MAX + 1]; #ifdef USE_DARWIN_POWER -int kq; -struct kevent64_s evs[2], rev; +int kq; +struct kevent evs[2], rev; # define STDIN_EV 0 # define IOKIT_EV 1 #endif @@ -322,10 +322,10 @@ struct kevent64_s evs[2], rev; memset(evs, 0, sizeof(evs)); - EV_SET64(&evs[STDIN_EV], STDIN_FILENO, EVFILT_READ, EV_ADD, 0, 0, 0, 0, 0); + EV_SET(&evs[STDIN_EV], STDIN_FILENO, EVFILT_READ, EV_ADD, 0, 0, 0); power_setup(&evs[IOKIT_EV]); - if (kevent64(kq, evs, 2, NULL, 0, 0, NULL) == -1) { + if (kevent(kq, evs, 2, NULL, 0, NULL) == -1) { perror("kevent"); return 1; } @@ -467,7 +467,7 @@ struct kevent64_s evs[2], rev; timeout.tv_sec = 0; timeout.tv_nsec = 500000000; - if ((nev = kevent64(kq, NULL, 0, &rev, 1, 0, &timeout)) == -1) { + if ((nev = kevent(kq, NULL, 0, &rev, 1, &timeout)) == -1) { if (doexit) break; if (errno == EINTR) @@ -476,7 +476,7 @@ struct kevent64_s evs[2], rev; return 1; } - if (rev.filter == EVFILT_MACHPORT) { + if (nev == 1 && (rev.filter == EVFILT_MACHPORT)) { power_handle(&rev); continue; } From 707812a0784a2ed81d37e35dde98a8c1f4170101 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Fri, 7 Mar 2014 22:24:33 +0000 Subject: [PATCH 12/51] Draw the input prompt in the right place. --- tts.c | 2 +- ui.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tts.c b/tts.c index 8315bae..25e9aff 100644 --- a/tts.c +++ b/tts.c @@ -354,7 +354,7 @@ struct kevent evs[2], rev; cbreak(); noecho(); nonl(); - nodelay(stdscr, 1); + nodelay(stdscr, TRUE); pair_content(0, &default_fg, &default_bg); diff --git a/ui.c b/ui.c index c5aa9fd..f7c9688 100644 --- a/ui.c +++ b/ui.c @@ -161,7 +161,7 @@ histent_t *histpos = NULL; pos = STRLEN(input); } - pwin = newwin(1, COLS, LINES - 2, 0); + pwin = newwin(1, COLS, LINES - 1, 0); keypad(pwin, TRUE); wattr_on(pwin, style_fg(sy_status), NULL); @@ -301,7 +301,8 @@ end: ; curs_set(0); delwin(pwin); - wtouchln(statwin, 1, 1, 1); + wtouchln(statwin, 0, 1, 1); + wrefresh(statwin); hist_add(hist, input); return STRDUP(input); } From fb9ffde20925ffd0bc2630eed72f041955cc267b Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Fri, 7 Mar 2014 22:37:43 +0000 Subject: [PATCH 13/51] Fix prompt styling & memory leak in yesno(). --- ui.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ui.c b/ui.c index f7c9688..88d0461 100644 --- a/ui.c +++ b/ui.c @@ -124,9 +124,13 @@ yesno(msg) WINDOW *pwin; INT c; - pwin = newwin(1, COLS, LINES - 2, 0); + pwin = newwin(1, COLS, LINES - 1, 0); keypad(pwin, TRUE); + wattron(pwin, A_BOLD); + wattr_on(pwin, style_fg(sy_status), NULL); + wbkgd(pwin, style_bg(sy_status)); + wmove(pwin, 0, 0); WADDSTR(pwin, msg); WADDSTR(pwin, WIDE(" [y/N]? ")); @@ -139,6 +143,10 @@ INT c; ) ; + delwin(pwin); + wtouchln(statwin, 0, 1, 1); + wrefresh(statwin); + return (c == 'Y' || c == 'y') ? 1 : 0; } From 0b072f4d3a5c90554acfc4a70e3076d376964e39 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Fri, 7 Mar 2014 22:39:02 +0000 Subject: [PATCH 14/51] Fix up the sample style a bit. --- ttsrc.sample | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ttsrc.sample b/ttsrc.sample index 43791fd..9e3f599 100644 --- a/ttsrc.sample +++ b/ttsrc.sample @@ -101,8 +101,8 @@ bind k prev # style header yellow,bold blue style status yellow,bold blue +style date white,underline black style entry white black style selected yellow,bold red # Use bold *and* underline, because we already bolded 'selected' above. -style running bold,underline -style date underline,bold +style running white,bold,underline black From ba30bffef25857acec61341ccdff119e3623b4bc Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Fri, 7 Mar 2014 22:40:18 +0000 Subject: [PATCH 15/51] Lots of changes, so make this version D.84.0. --- configure | 18 +++++++++--------- configure.ac | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/configure b/configure index 836b004..ffcc0f5 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for RT/TTS T.83.6. +# Generated by GNU Autoconf 2.69 for RT/TTS D.84.0. # # Report bugs to . # @@ -580,8 +580,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='RT/TTS' PACKAGE_TARNAME='rt-tts' -PACKAGE_VERSION='T.83.6' -PACKAGE_STRING='RT/TTS T.83.6' +PACKAGE_VERSION='D.84.0' +PACKAGE_STRING='RT/TTS D.84.0' PACKAGE_BUGREPORT='felicity@loreley.flyingparchment.org.uk' PACKAGE_URL='' @@ -1232,7 +1232,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures RT/TTS T.83.6 to adapt to many kinds of systems. +\`configure' configures RT/TTS D.84.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1293,7 +1293,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of RT/TTS T.83.6:";; + short | recursive ) echo "Configuration of RT/TTS D.84.0:";; esac cat <<\_ACEOF @@ -1380,7 +1380,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -RT/TTS configure T.83.6 +RT/TTS configure D.84.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1749,7 +1749,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by RT/TTS $as_me T.83.6, which was +It was created by RT/TTS $as_me D.84.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -4766,7 +4766,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by RT/TTS $as_me T.83.6, which was +This file was extended by RT/TTS $as_me D.84.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -4828,7 +4828,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -RT/TTS config.status T.83.6 +RT/TTS config.status D.84.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index dce8aa5..6d691a2 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ([2.69]) -AC_INIT([RT/TTS], [T.83.6], [felicity@loreley.flyingparchment.org.uk]) +AC_INIT([RT/TTS], [D.84.0], [felicity@loreley.flyingparchment.org.uk]) AC_CONFIG_SRCDIR([tts.c]) AC_CONFIG_HEADERS([config.h]) From 44b2e4371e50bb7a2c60781ee836a0d83622f914 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Fri, 7 Mar 2014 22:44:57 +0000 Subject: [PATCH 16/51] Copyright notice for Makefile. --- Makefile.in | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Makefile.in b/Makefile.in index ab67424..77c9e0e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,3 +1,11 @@ +# TTS - track your time. +# Copyright (c) 2012-2014 Felicity Tarnell. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely. This software is provided 'as-is', without any express or implied +# warranty. + .SUFFIXES: .c .o .d .h VPATH = @top_srcdir@ From 3440a87ea36d4af217316ba94583e0daf79d0383 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Fri, 7 Mar 2014 23:34:06 +0000 Subject: [PATCH 17/51] Add macro support. Replace WGETCH() with input_char(), which works the same except it supports an input buffer. Calling input_macro(s) sets the input buffer to 's'. The input buffer is returned by input_char() as if it had been typed by the user. If an error occurs (cmderr()), the input buffer is cleared. --- bindings.h | 3 +- commands.c | 16 ++++++- commands.h | 1 + functions.c | 18 +++++--- str.c | 32 +++++++++++++- tts.c | 123 ++++++++++++++++++++++++++++++++++++--------------- ttsrc.sample | 8 +++- ui.c | 4 +- wide.h | 3 ++ 9 files changed, 159 insertions(+), 49 deletions(-) diff --git a/bindings.h b/bindings.h index 1819a08..ce07811 100644 --- a/bindings.h +++ b/bindings.h @@ -24,6 +24,7 @@ typedef struct binding { INT bi_code; tkey_t *bi_key; function_t *bi_func; + WCHAR *bi_macro; TTS_TAILQ_ENTRY(binding) bi_entries; } binding_t; @@ -32,6 +33,6 @@ typedef TTS_TAILQ_HEAD(bindlist, binding) binding_list_t; extern binding_list_t bindings; tkey_t *find_key(const WCHAR *name); -void bind_key(const WCHAR *key, const WCHAR *func); +void bind_key(const WCHAR *key, const WCHAR *func, int is_macro); #endif /* !TTS_BINDINGS_H */ diff --git a/commands.c b/commands.c index 906cabc..4696625 100644 --- a/commands.c +++ b/commands.c @@ -15,6 +15,7 @@ static command_t commands[] = { { WIDE("bind"), c_bind }, + { WIDE("macro"), c_macro }, { WIDE("style"), c_style }, { WIDE("set"), c_set }, { } @@ -80,7 +81,20 @@ c_bind(argc, argv) return; } - bind_key(argv[1], argv[2]); + bind_key(argv[1], argv[2], 0); +} + +void +c_macro(argc, argv) + size_t argc; + WCHAR **argv; +{ + if (argc != 3) { + cmderr(WIDE("Usage: macro ")); + return; + } + + bind_key(argv[1], argv[2], 1); } void diff --git a/commands.h b/commands.h index cad450b..22b1085 100644 --- a/commands.h +++ b/commands.h @@ -25,6 +25,7 @@ command_t *find_command(const WCHAR *); void c_bind (size_t, WCHAR **); void c_style (size_t, WCHAR **); void c_set (size_t, WCHAR **); +void c_macro (size_t, WCHAR **); void cmderr (const WCHAR *, ...); void vcmderr (const WCHAR *, va_list); diff --git a/functions.c b/functions.c index 57c91a0..c1ed4c6 100644 --- a/functions.c +++ b/functions.c @@ -592,14 +592,20 @@ binding_t *bi; i = 0; TTS_TAILQ_FOREACH(bi, &bindings, bi_entries) { - WCHAR s[128]; + WCHAR s[128], t[16]; + if (bi->bi_key) - SNPRINTF(s, WSIZEOF(s), WIDE("%-10"FMT_L"s %"FMT_L"s (%"FMT_L"s)"), - bi->bi_key->ky_name, bi->bi_func->fn_desc, - bi->bi_func->fn_name); + SNPRINTF(t, WSIZEOF(t), WIDE("%"FMT_L"s"), bi->bi_key->ky_name); else - SNPRINTF(s, WSIZEOF(s), WIDE("%"FMT_L"c %"FMT_L"s (%"FMT_L"s)"), - bi->bi_code, bi->bi_func->fn_desc, bi->bi_func->fn_name); + SNPRINTF(t, WSIZEOF(t), WIDE("%"FMT_L"c"), bi->bi_code); + + if (bi->bi_macro) + SNPRINTF(s, WSIZEOF(s), WIDE("%-10"FMT_L"s execute macro: %"FMT_L"s"), + t, bi->bi_macro); + else + SNPRINTF(s, WSIZEOF(s), WIDE("%-10"FMT_L"s %"FMT_L"s (%"FMT_L"s)"), + t, bi->bi_func->fn_desc, bi->bi_func->fn_name); + help[i] = STRDUP(s); i++; } diff --git a/str.c b/str.c index 4b89814..a489a91 100644 --- a/str.c +++ b/str.c @@ -17,6 +17,7 @@ tokenise(str, res) { int ntoks = 0; const WCHAR *p, *q; +WCHAR *r; *res = NULL; p = str; @@ -24,6 +25,7 @@ const WCHAR *p, *q; for (;;) { ptrdiff_t sz; int qskip = 0; + int isbsl = 0; /* Skip leading whitespace */ while (ISSPACE(*p)) @@ -37,14 +39,13 @@ const WCHAR *p, *q; if (*q == '"') { /* Quoted string - scan for end of string */ - int isbsl = 0; p++; while (*++q) { /* Handle escaping with backslash; currently works but the \ isn't * removed from the string. */ - if (*q == '\\') { + if (!isbsl && (*q == '\\')) { isbsl = 1; continue; } @@ -72,6 +73,33 @@ const WCHAR *p, *q; *res = realloc(*res, sizeof(WCHAR *) * (ntoks + 1)); (*res)[ntoks] = malloc(sizeof(WCHAR) * (sz + 1)); MEMCPY((*res)[ntoks], p, sz); + + /* Handle \ escapes */ + for (r = (*res)[ntoks]; r < ((*res)[ntoks] + sz);) { + if (!isbsl) { + if (*r == '\\') { + MEMMOVE(r, r + 1, sz - (r - (*res)[ntoks])); + sz--; + isbsl = 1; + continue; + } + + r++; + continue; + } + + switch (*r) { + case 't': *r = '\t'; break; + case 'n': *r = '\n'; break; + case 'r': *r = '\r'; break; + case 'v': *r = '\v'; break; + case '\\': *r = '\\'; break; + } + + isbsl = 0; + r++; + } + (*res)[ntoks][sz] = 0; ntoks++; diff --git a/tts.c b/tts.c index 25e9aff..dc74e9d 100644 --- a/tts.c +++ b/tts.c @@ -150,6 +150,8 @@ entry_t *curent; int showinv = 0; +static WCHAR *macro_text, *macro_pos; + static attrname_t attrnames[] = { { WIDE("normal"), WA_NORMAL }, { WIDE("bold"), WA_BOLD }, @@ -401,32 +403,32 @@ struct kevent evs[2], rev; curs_set(0); - bind_key(WIDE("?"), WIDE("help")); - bind_key(WIDE("a"), WIDE("add")); - bind_key(WIDE("A"), WIDE("add-old")); - bind_key(WIDE("d"), WIDE("delete")); - bind_key(WIDE("u"), WIDE("undelete")); - bind_key(WIDE("q"), WIDE("quit")); - bind_key(WIDE(""), WIDE("quit")); - bind_key(WIDE("i"), WIDE("invoice")); - bind_key(WIDE("b"), WIDE("billable")); - bind_key(WIDE("m"), WIDE("mark")); - bind_key(WIDE("U"), WIDE("unmarkall")); - bind_key(WIDE(""), WIDE("startstop")); - bind_key(WIDE("e"), WIDE("edit-desc")); - bind_key(WIDE("\\"), WIDE("edit-time")); - bind_key(WIDE(""), WIDE("showhide-inv")); - bind_key(WIDE("c"), WIDE("copy")); - bind_key(WIDE("+"), WIDE("add-time")); - bind_key(WIDE("-"), WIDE("sub-time")); - bind_key(WIDE("/"), WIDE("search")); - bind_key(WIDE("$"), WIDE("sync")); - bind_key(WIDE(""), WIDE("prev")); - bind_key(WIDE(""), WIDE("next")); - bind_key(WIDE(":"), WIDE("execute")); - bind_key(WIDE("M"), WIDE("merge")); - bind_key(WIDE("r"), WIDE("interrupt")); - bind_key(WIDE("R"), WIDE("interrupt")); + bind_key(WIDE("?"), WIDE("help"), 0); + bind_key(WIDE("a"), WIDE("add"), 0); + bind_key(WIDE("A"), WIDE("add-old"), 0); + bind_key(WIDE("d"), WIDE("delete"), 0); + bind_key(WIDE("u"), WIDE("undelete"), 0); + bind_key(WIDE("q"), WIDE("quit"), 0); + bind_key(WIDE(""), WIDE("quit"), 0); + bind_key(WIDE("i"), WIDE("invoice"), 0); + bind_key(WIDE("b"), WIDE("billable"), 0); + bind_key(WIDE("m"), WIDE("mark"), 0); + bind_key(WIDE("U"), WIDE("unmarkall"), 0); + bind_key(WIDE(""), WIDE("startstop"), 0); + bind_key(WIDE("e"), WIDE("edit-desc"), 0); + bind_key(WIDE("\\"), WIDE("edit-time"), 0); + bind_key(WIDE(""), WIDE("showhide-inv"), 0); + bind_key(WIDE("c"), WIDE("copy"), 0); + bind_key(WIDE("+"), WIDE("add-time"), 0); + bind_key(WIDE("-"), WIDE("sub-time"), 0); + bind_key(WIDE("/"), WIDE("search"), 0); + bind_key(WIDE("$"), WIDE("sync"), 0); + bind_key(WIDE(""), WIDE("prev"), 0); + bind_key(WIDE(""), WIDE("next"), 0); + bind_key(WIDE(":"), WIDE("execute"), 0); + bind_key(WIDE("M"), WIDE("merge"), 0); + bind_key(WIDE("r"), WIDE("interrupt"), 0); + bind_key(WIDE("R"), WIDE("interrupt"), 0); /* * Make sure we can save (even if it's an empty file or nothing has @@ -496,7 +498,7 @@ struct kevent evs[2], rev; } #endif - while (GETCH(&c) != ERR) { + while (input_char(&c) != ERR) { #ifdef KEY_RESIZE if (c == KEY_RESIZE) continue; @@ -507,8 +509,13 @@ struct kevent evs[2], rev; TTS_TAILQ_FOREACH(bi, &bindings, bi_entries) { if (bi->bi_code != c) continue; - bi->bi_func->fn_hdl(); - goto next;; + + if (!macro_text && bi->bi_macro) + input_macro(bi->bi_macro); + else if (bi->bi_func) + bi->bi_func->fn_hdl(); + + goto next; } drawstatus(WIDE("Unknown command.")); @@ -1022,7 +1029,7 @@ function_t *f; * directly, rather than being looked up in the key table. */ void -bind_key(keyname, funcname) +bind_key(keyname, funcname, is_macro) const WCHAR *keyname, *funcname; { tkey_t *key = NULL; @@ -1040,15 +1047,23 @@ INT code; } else code = *keyname; - if ((func = find_func(funcname)) == NULL) { - errbox(WIDE("Unknown function \"%"FMT_L"s\""), funcname); - return; + if (!is_macro) { + if ((func = find_func(funcname)) == NULL) { + errbox(WIDE("Unknown function \"%"FMT_L"s\""), funcname); + return; + } } /* Do we already have a binding for this key? */ TTS_TAILQ_FOREACH(binding, &bindings, bi_entries) { if (binding->bi_code == code) { - binding->bi_func = func; + if (is_macro) { + binding->bi_func = NULL; + binding->bi_macro = STRDUP(funcname); + } else { + free(binding->bi_macro); + binding->bi_func = func; + } return; } } @@ -1058,8 +1073,13 @@ INT code; return; binding->bi_key = key; - binding->bi_func = func; binding->bi_code = code; + + if (is_macro) + binding->bi_macro = STRDUP(funcname); + else + binding->bi_func = func; + TTS_TAILQ_INSERT_TAIL(&bindings, binding, bi_entries); } @@ -1191,8 +1211,10 @@ vcmderr(msg, ap) fprintf(stderr, "\"%s\", line %d: %s\n", curfile, lineno, t); - } else + } else { + input_macro(NULL); vdrawstatus(msg, ap); + } } /* @@ -1349,3 +1371,32 @@ int h, m, s = 0; sleeptime = 0; } #endif /* USE_DARWIN_POWER */ + +void +input_macro(s) + WCHAR *s; +{ + free(macro_text); + macro_text = macro_pos = NULL; + + if (!s) + return; + + macro_text = macro_pos = STRDUP(s); +} + +int +input_char(c) + WCHAR *c; +{ + if (macro_pos) { + if (*macro_pos) { + *c = *macro_pos++; + return 0; + } + free(macro_text); + macro_text = macro_pos = NULL; + } + + return GETCH(c); +} diff --git a/ttsrc.sample b/ttsrc.sample index 9e3f599..51a8f1d 100644 --- a/ttsrc.sample +++ b/ttsrc.sample @@ -33,7 +33,7 @@ #set bill_advance 0 -#### Bindings +#### Bindings and macros # # Use the 'bind' command to (re)define keybindings. Type '?' while TTS is # running for a full list of key bindings. @@ -45,6 +45,12 @@ bind j next bind k prev +# Macros work in a similar way to bindings, except the second argument is a +# string which will be executed as if it was typed. For example, the +# following macro would add a new entry called "test", and set its timer to +# 30 minutes. +#macro t "atest\n+30:00\n" + #### Styling # # You can style UI elements with the 'style' command. Its syntax is: diff --git a/ui.c b/ui.c index 88d0461..c9e44ec 100644 --- a/ui.c +++ b/ui.c @@ -136,7 +136,7 @@ INT c; WADDSTR(pwin, WIDE(" [y/N]? ")); wattroff(pwin, A_BOLD); - while (WGETCH(pwin, &c) == ERR + while (input_char(&c) == ERR #ifdef KEY_RESIZE || (c == KEY_RESIZE) #endif @@ -190,7 +190,7 @@ histent_t *histpos = NULL; wmove(pwin, 0, STRLEN(msg) + 1 + pos); wrefresh(pwin); - if (WGETCH(pwin, &c) == ERR) + if (input_char(&c) == ERR) continue; switch (c) { diff --git a/wide.h b/wide.h index 85df84d..61ab2c8 100644 --- a/wide.h +++ b/wide.h @@ -78,4 +78,7 @@ extern int tts_wgetch(WINDOW *, int *); #define WSIZEOF(s) (sizeof(s) / sizeof(WCHAR)) +int input_char(WCHAR *); +void input_macro(WCHAR *); + #endif /* !TTS_WIDE_H */ From 524b09511d3647444ac2efe4572a8755068a69a9 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Fri, 7 Mar 2014 23:47:31 +0000 Subject: [PATCH 18/51] Code cleanups; no functional changes. --- Makefile.in | 3 +- bindings.c | 151 ++++++++++++++ functions.c | 15 ++ style.c | 128 ++++++++++++ style.h | 3 + tts.c | 569 +--------------------------------------------------- ui.c | 292 +++++++++++++++++++++++++++ 7 files changed, 593 insertions(+), 568 deletions(-) create mode 100644 style.c diff --git a/Makefile.in b/Makefile.in index 77c9e0e..d582022 100644 --- a/Makefile.in +++ b/Makefile.in @@ -20,7 +20,8 @@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ INSTALL = @INSTALL@ -OBJS = tts.o wide.o entry.o ui.o functions.o commands.o bindings.o str.o +OBJS = tts.o wide.o entry.o ui.o functions.o commands.o bindings.o \ + str.o style.o prefix = @prefix@ exec_prefix = @exec_prefix@ diff --git a/bindings.c b/bindings.c index dfcb5d1..9115989 100644 --- a/bindings.c +++ b/bindings.c @@ -8,6 +8,157 @@ * warranty. */ +#include + #include "bindings.h" +#include "wide.h" +#include "ui.h" binding_list_t bindings = TTS_TAILQ_HEAD_INITIALIZER(bindings); + +static tkey_t keys[] = { + { KEY_BREAK, WIDE("") }, + { KEY_DOWN, WIDE("") }, + { KEY_UP, WIDE("") }, + { KEY_LEFT, WIDE("") }, + { KEY_RIGHT, WIDE("") }, + { KEY_HOME, WIDE("") }, + { KEY_BACKSPACE, WIDE("") }, + { 0x7F, WIDE("") }, /* DEL */ + { KEY_F(0), WIDE("") }, + { KEY_F(1), WIDE("") }, + { KEY_F(2), WIDE("") }, + { KEY_F(3), WIDE("") }, + { KEY_F(4), WIDE("") }, + { KEY_F(5), WIDE("") }, + { KEY_F(6), WIDE("") }, + { KEY_F(7), WIDE("") }, + { KEY_F(8), WIDE("") }, + { KEY_F(9), WIDE("") }, + { KEY_F(10), WIDE("") }, + { KEY_F(11), WIDE("") }, + { KEY_F(12), WIDE("") }, + { KEY_F(13), WIDE("") }, + { KEY_F(14), WIDE("") }, + { KEY_F(15), WIDE("") }, + { KEY_F(16), WIDE("") }, + { KEY_F(17), WIDE("") }, + { KEY_F(18), WIDE("") }, + { KEY_F(19), WIDE("") }, + { KEY_F(20), WIDE("") }, + { KEY_F(21), WIDE("") }, + { KEY_F(22), WIDE("") }, + { KEY_F(23), WIDE("") }, + { KEY_F(24), WIDE("") }, + { KEY_NPAGE, WIDE("") }, + { KEY_PPAGE, WIDE("") }, + { '\001', WIDE("") }, + { '\002', WIDE("") }, + { '\003', WIDE("") }, + { '\004', WIDE("") }, + { '\005', WIDE("") }, + { '\006', WIDE("") }, + { '\007', WIDE("") }, + { '\010', WIDE("") }, + { '\011', WIDE("") }, + { '\011', WIDE("") }, + { '\012', WIDE("") }, + { '\013', WIDE("") }, + { '\014', WIDE("") }, + { '\015', WIDE("") }, + { '\016', WIDE("") }, + { '\017', WIDE("") }, + { '\020', WIDE("") }, + { '\021', WIDE("") }, + { '\022', WIDE("") }, + { '\023', WIDE("") }, + { '\024', WIDE("") }, + { '\025', WIDE("") }, + { '\026', WIDE("") }, + { '\027', WIDE("") }, + { '\030', WIDE("") }, + { '\031', WIDE("") }, + { ' ', WIDE("") }, + { KEY_ENTER, WIDE("") }, + { KEY_BACKSPACE, WIDE("") }, + { KEY_DC, WIDE("") } +}; + +/* + * Bind .keyname to run the function .funcname. If a binding for .keyname + * already exists, overwrite it. + * + * If .keyname is a single character, e.g. 'a', it is used as a key name + * directly, rather than being looked up in the key table. + */ +void +bind_key(keyname, funcname, is_macro) + const WCHAR *keyname, *funcname; +{ +tkey_t *key = NULL; +function_t *func; +binding_t *binding; +INT code; + + /* Find the key and the function */ + if (STRLEN(keyname) > 1) { + if ((key = find_key(keyname)) == NULL) { + errbox(WIDE("Unknown key \"%"FMT_L"s\""), keyname); + return; + } + code = key->ky_code; + } else + code = *keyname; + + if (!is_macro) { + if ((func = find_func(funcname)) == NULL) { + errbox(WIDE("Unknown function \"%"FMT_L"s\""), funcname); + return; + } + } + + /* Do we already have a binding for this key? */ + TTS_TAILQ_FOREACH(binding, &bindings, bi_entries) { + if (binding->bi_code == code) { + if (is_macro) { + binding->bi_func = NULL; + binding->bi_macro = STRDUP(funcname); + } else { + free(binding->bi_macro); + binding->bi_func = func; + } + return; + } + } + + /* No, add a new one */ + if ((binding = calloc(1, sizeof(*binding))) == NULL) + return; + + binding->bi_key = key; + binding->bi_code = code; + + if (is_macro) + binding->bi_macro = STRDUP(funcname); + else + binding->bi_func = func; + + TTS_TAILQ_INSERT_TAIL(&bindings, binding, bi_entries); +} + +/* + * Return the tkey_t for the key called .name, or NULL if such a key doesn't + * exist. + */ +tkey_t * +find_key(name) + const WCHAR *name; +{ +size_t i; + + for (i = 0; i < sizeof(keys) / sizeof(*keys); i++) + if (STRCMP(name, keys[i].ky_name) == 0) + return &keys[i]; + return NULL; +} + diff --git a/functions.c b/functions.c index c1ed4c6..62acfd0 100644 --- a/functions.c +++ b/functions.c @@ -804,3 +804,18 @@ size_t nargs; tokfree(&args); } +/* + * Return the function_t for the function called .name, or NULL if such a + * function doesn't exist. + */ +function_t * +find_func(name) + const WCHAR *name; +{ +function_t *f; + for (f = funcs; f->fn_name; f++) + if (STRCMP(name, f->fn_name) == 0) + return f; + return NULL; +} + diff --git a/style.c b/style.c new file mode 100644 index 0000000..bca75a7 --- /dev/null +++ b/style.c @@ -0,0 +1,128 @@ +/* + * TTS - track your time. + * Copyright (c) 2012-2014 Felicity Tarnell. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely. This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "style.h" +#include "ui.h" +#include "wide.h" + +short default_fg, default_bg; + +style_t sy_header = { 1, 0 }, + sy_status = { 2, 0 }, + sy_entry = { 3, 0 }, + sy_running = { 4, 0 }, + sy_selected = { 5, 0 }, + sy_date = { 6, 0 }; + +static attrname_t attrnames[] = { + { WIDE("normal"), WA_NORMAL }, + { WIDE("bold"), WA_BOLD }, + { WIDE("reverse"), WA_REVERSE }, + { WIDE("blink"), WA_BLINK }, + { WIDE("dim"), WA_DIM }, + { WIDE("underline"), WA_UNDERLINE }, + { WIDE("standout"), WA_STANDOUT } +}; + +static colour_t colours[] = { + { WIDE("black"), COLOR_BLACK }, + { WIDE("red"), COLOR_RED }, + { WIDE("green"), COLOR_GREEN }, + { WIDE("yellow"), COLOR_YELLOW }, + { WIDE("blue"), COLOR_BLUE }, + { WIDE("magenta"), COLOR_MAGENTA }, + { WIDE("cyan"), COLOR_CYAN }, + { WIDE("white"), COLOR_WHITE } +}; + +int +attr_find(name, result) + const WCHAR *name; + attr_t *result; +{ +size_t i; + for (i = 0; i < sizeof(attrnames) / sizeof(*attrnames); i++) { + if (STRCMP(attrnames[i].an_name, name) == 0) { + *result = attrnames[i].an_value; + return 0; + } + } + + return -1; +} + +int +colour_find(name, result) + const WCHAR *name; + short *result; +{ +size_t i; + for (i = 0; i < sizeof(colours) / sizeof(*colours); i++) { + if (STRCMP(colours[i].co_name, name) == 0) { + *result = colours[i].co_value; + return 0; + } + } + + return -1; +} + +void +style_clear(sy) + style_t *sy; +{ + init_pair(sy->sy_pair, default_fg, default_bg); + sy->sy_attrs = WA_NORMAL; +} + +int +style_set(sy, fg, bg) + style_t *sy; + const WCHAR *fg, *bg; +{ + sy->sy_attrs = WA_NORMAL; + init_pair(sy->sy_pair, default_fg, default_bg); + return style_add(sy, fg, bg); +} + +int +style_add(sy, fg, bg) + style_t *sy; + const WCHAR *fg, *bg; +{ +attr_t at; +short colfg, colbg = default_bg; + + if (colour_find(fg, &colfg) == 0) { + if (bg && (colour_find(bg, &colbg) == -1)) + return -1; + + init_pair(sy->sy_pair, colfg, colbg); + return 0; + } + + if (attr_find(fg, &at) == -1) + return -1; + sy->sy_attrs |= at; + return 0; +} + +void +apply_styles() +{ + wbkgd(statwin, style_bg(sy_status)); + wattr_on(statwin, style_fg(sy_status), NULL); + drawstatus(WIDE("")); + + wbkgd(titwin, style_bg(sy_header)); + wattr_on(titwin, style_fg(sy_header), NULL); + drawheader(); +} + diff --git a/style.h b/style.h index 9afac1b..7bc0879 100644 --- a/style.h +++ b/style.h @@ -12,6 +12,7 @@ #define TTS_STYLE_H #include "tts_curses.h" +#include "wide.h" typedef struct style { short sy_pair; @@ -38,6 +39,8 @@ extern style_t sy_header, sy_selected, sy_date; +extern short default_fg, default_bg; + int attr_find(const WCHAR *name, attr_t *result); int colour_find(const WCHAR *name, short *result); diff --git a/tts.c b/tts.c index dc74e9d..9ae691f 100644 --- a/tts.c +++ b/tts.c @@ -77,74 +77,6 @@ static char statfile[PATH_MAX + 1]; static int load_file(const char *); -static tkey_t keys[] = { - { KEY_BREAK, WIDE("") }, - { KEY_DOWN, WIDE("") }, - { KEY_UP, WIDE("") }, - { KEY_LEFT, WIDE("") }, - { KEY_RIGHT, WIDE("") }, - { KEY_HOME, WIDE("") }, - { KEY_BACKSPACE, WIDE("") }, - { 0x7F, WIDE("") }, /* DEL */ - { KEY_F(0), WIDE("") }, - { KEY_F(1), WIDE("") }, - { KEY_F(2), WIDE("") }, - { KEY_F(3), WIDE("") }, - { KEY_F(4), WIDE("") }, - { KEY_F(5), WIDE("") }, - { KEY_F(6), WIDE("") }, - { KEY_F(7), WIDE("") }, - { KEY_F(8), WIDE("") }, - { KEY_F(9), WIDE("") }, - { KEY_F(10), WIDE("") }, - { KEY_F(11), WIDE("") }, - { KEY_F(12), WIDE("") }, - { KEY_F(13), WIDE("") }, - { KEY_F(14), WIDE("") }, - { KEY_F(15), WIDE("") }, - { KEY_F(16), WIDE("") }, - { KEY_F(17), WIDE("") }, - { KEY_F(18), WIDE("") }, - { KEY_F(19), WIDE("") }, - { KEY_F(20), WIDE("") }, - { KEY_F(21), WIDE("") }, - { KEY_F(22), WIDE("") }, - { KEY_F(23), WIDE("") }, - { KEY_F(24), WIDE("") }, - { KEY_NPAGE, WIDE("") }, - { KEY_PPAGE, WIDE("") }, - { '\001', WIDE("") }, - { '\002', WIDE("") }, - { '\003', WIDE("") }, - { '\004', WIDE("") }, - { '\005', WIDE("") }, - { '\006', WIDE("") }, - { '\007', WIDE("") }, - { '\010', WIDE("") }, - { '\011', WIDE("") }, - { '\011', WIDE("") }, - { '\012', WIDE("") }, - { '\013', WIDE("") }, - { '\014', WIDE("") }, - { '\015', WIDE("") }, - { '\016', WIDE("") }, - { '\017', WIDE("") }, - { '\020', WIDE("") }, - { '\021', WIDE("") }, - { '\022', WIDE("") }, - { '\023', WIDE("") }, - { '\024', WIDE("") }, - { '\025', WIDE("") }, - { '\026', WIDE("") }, - { '\027', WIDE("") }, - { '\030', WIDE("") }, - { '\031', WIDE("") }, - { ' ', WIDE("") }, - { KEY_ENTER, WIDE("") }, - { KEY_BACKSPACE, WIDE("") }, - { KEY_DC, WIDE("") } -}; - int pagestart; entry_t *curent; @@ -152,36 +84,6 @@ int showinv = 0; static WCHAR *macro_text, *macro_pos; -static attrname_t attrnames[] = { - { WIDE("normal"), WA_NORMAL }, - { WIDE("bold"), WA_BOLD }, - { WIDE("reverse"), WA_REVERSE }, - { WIDE("blink"), WA_BLINK }, - { WIDE("dim"), WA_DIM }, - { WIDE("underline"), WA_UNDERLINE }, - { WIDE("standout"), WA_STANDOUT } -}; - -static colour_t colours[] = { - { WIDE("black"), COLOR_BLACK }, - { WIDE("red"), COLOR_RED }, - { WIDE("green"), COLOR_GREEN }, - { WIDE("yellow"), COLOR_YELLOW }, - { WIDE("blue"), COLOR_BLUE }, - { WIDE("magenta"), COLOR_MAGENTA }, - { WIDE("cyan"), COLOR_CYAN }, - { WIDE("white"), COLOR_WHITE } -}; - -static short default_fg, default_bg; - -style_t sy_header = { 1, 0 }, - sy_status = { 2, 0 }, - sy_entry = { 3, 0 }, - sy_running = { 4, 0 }, - sy_selected = { 5, 0 }, - sy_date = { 6, 0 }; - time_t itime = 0; int show_billable = 0; @@ -537,198 +439,6 @@ struct kevent evs[2], rev; return 0; } -void -drawentries() -{ -int i, nlines; -int cline = 0; -time_t lastday = 0; -entry_t *en; -chtype oldbg; - - getmaxyx(listwin, nlines, i); - - TTS_TAILQ_FOREACH(en, &entries, en_entries) - en->en_flags.efl_visible = 0; - - en = TTS_TAILQ_FIRST(&entries); - for (i = 0; i < pagestart; i++) - if ((en = TTS_TAILQ_NEXT(en, en_entries)) == NULL) - return; - - for (; en; en = TTS_TAILQ_NEXT(en, en_entries)) { - time_t n; - int h, s, m; - WCHAR flags[10], stime[16], *p; - attr_t attrs = WA_NORMAL; - - if (!showinv && en->en_flags.efl_invoiced) - continue; - - oldbg = getbkgd(listwin); - - if (lastday != entry_day(en)) { - struct tm *lt; - WCHAR lbl[128]; - time_t itime = entry_time_for_day(entry_day(en), 1, 0), - ntime = entry_time_for_day(entry_day(en), 0, 0), - btime = entry_time_for_day(entry_day(en), 2, bill_increment); - int hi, mi, si, - hn, mn, sn, - hb, mb, sb, - ht, mt, st; - WCHAR hdrtext[256]; - - time_to_hms(itime, hi, mi, si); - time_to_hms(ntime, hn, mn, sn); - time_to_hms(btime, hb, mb, sb); - time_to_hms(itime + ntime, ht, mt, st); - - oldbg = getbkgd(listwin); - wbkgdset(listwin, style_bg(sy_entry)); - wattr_on(listwin, style_fg(sy_entry), NULL); - - wmove(listwin, cline, 0); - wclrtoeol(listwin); - - wbkgdset(listwin, oldbg); - wattr_off(listwin, style_fg(sy_entry), NULL); - - if (++cline >= nlines) - break; - - lastday = entry_day(en); - lt = localtime(&lastday); - - STRFTIME(lbl, WSIZEOF(lbl), WIDE("%A, %d %B %Y"), lt); - if (show_billable) - SNPRINTF(hdrtext, WSIZEOF(hdrtext), - WIDE("%-30"FMT_L"s [I:%02d:%02d:%02d / " - "N:%02d:%02d:%02d / T:%02d:%02d:%02d / " - "B:%02d:%02d:%02d]"), - lbl, hi, mi, si, hn, mn, sn, ht, mt, st, - hb, mb, sb); - else - SNPRINTF(hdrtext, WSIZEOF(hdrtext), - WIDE("%-30"FMT_L"s [I:%02d:%02d:%02d / " - "N:%02d:%02d:%02d / T:%02d:%02d:%02d]"), - lbl, hi, mi, si, hn, mn, sn, ht, mt, st); - - wattr_on(listwin, style_fg(sy_date), NULL); - wbkgdset(listwin, style_bg(sy_date)); - wmove(listwin, cline, 0); - WADDSTR(listwin, hdrtext); - wclrtoeol(listwin); - wattr_off(listwin, style_fg(sy_date), NULL); - wbkgdset(listwin, oldbg); - - if (++cline >= nlines) { - wbkgdset(listwin, oldbg); - wattr_off(listwin, style_fg(sy_date), NULL); - break; - } - - oldbg = getbkgd(listwin); - wbkgdset(listwin, style_bg(sy_entry)); - wattr_on(listwin, style_fg(sy_entry), NULL); - - wmove(listwin, cline, 0); - wclrtoeol(listwin); - - wbkgdset(listwin, oldbg); - wattr_off(listwin, style_fg(sy_entry), NULL); - - if (++cline >= nlines) - break; - } - - en->en_flags.efl_visible = 1; - wmove(listwin, cline, 0); - - attrs = style_fg(sy_entry); - - if (en->en_started && en == curent) - attrs = style_fg(sy_selected) | - (style_fg(sy_running) & ( - WA_STANDOUT | WA_UNDERLINE | - WA_REVERSE | WA_BLINK | WA_DIM | - WA_BOLD)); - else if (en->en_started) - attrs = style_fg(sy_running); - else if (en == curent) - attrs = style_fg(sy_selected); - - wbkgdset(listwin, ' ' | (attrs & ~WA_UNDERLINE)); - wattr_on(listwin, attrs, NULL); - - if (en == curent) { - WADDSTR(listwin, WIDE(" -> ")); - } else - WADDSTR(listwin, WIDE(" ")); - - n = en->en_secs; - if (en->en_started) - n += time(NULL) - en->en_started; - h = n / (60 * 60); - n %= (60 * 60); - m = n / 60; - n %= 60; - s = n; - - SNPRINTF(stime, WSIZEOF(stime), WIDE("%02d:%02d:%02d%c "), - h, m, s, (itime && (en == running)) ? '*' : ' '); - WADDSTR(listwin, stime); - - memset(flags, 0, sizeof(flags)); - p = flags; - - if (en->en_flags.efl_marked) - *p++ = 'M'; - else - *p++ = ' '; - - if (en->en_flags.efl_invoiced) - *p++ = 'I'; - else - *p++ = ' '; - - if (!en->en_flags.efl_nonbillable) - *p++ = 'B'; - else - *p++ = ' '; - - if (en->en_flags.efl_deleted) - *p++ = 'D'; - else - *p++ = ' '; - - if (*flags) { - WCHAR s[10]; - SNPRINTF(s, WSIZEOF(s), WIDE("%-5"FMT_L"s "), flags); - WADDSTR(listwin, s); - } else - WADDSTR(listwin, WIDE(" ")); - - WADDSTR(listwin, en->en_desc); - wclrtoeol(listwin); - wbkgdset(listwin, oldbg); - wattr_off(listwin, attrs, NULL); - - if (++cline >= nlines) - return; - } - - oldbg = getbkgd(listwin); - wattr_on(listwin, style_fg(sy_entry), NULL); - wbkgdset(listwin, style_bg(sy_entry)); - for (; cline < nlines; cline++) { - wmove(listwin, cline, 0); - wclrtoeol(listwin); - } - wattr_off(listwin, style_fg(sy_entry), NULL); - wbkgdset(listwin, oldbg); -} - int load() { @@ -902,59 +612,6 @@ entry_t *en; return 0; } -void -errbox(const WCHAR *msg, ...) -{ -va_list ap; - va_start(ap, msg); - verrbox(msg, ap); - va_end(ap); -} - -void -verrbox(msg, ap) - const WCHAR *msg; - va_list ap; -{ -WCHAR text[4096]; -WINDOW *ewin; - -#define ETITLE WIDE(" Error ") -#define ECONT WIDE(" ") -int width; -INT c; - - VSNPRINTF(text, WSIZEOF(text), msg, ap); - width = STRLEN(text); - - ewin = newwin(6, width + 4, - (LINES / 2) - ((1 + 2)/ 2), - (COLS / 2) - ((width + 2) / 2)); - leaveok(ewin, TRUE); - wborder(ewin, 0, 0, 0, 0, 0, 0, 0, 0); - - wattron(ewin, A_REVERSE | A_BOLD); - wmove(ewin, 0, (width / 2) - (WSIZEOF(ETITLE) - 1)/2); - WADDSTR(ewin, ETITLE); - wattroff(ewin, A_REVERSE | A_BOLD); - - wmove(ewin, 2, 2); - WADDSTR(ewin, text); - wattron(ewin, A_REVERSE | A_BOLD); - wmove(ewin, 4, (width / 2) - ((WSIZEOF(ECONT) - 1) / 2)); - WADDSTR(ewin, ECONT); - wattroff(ewin, A_REVERSE | A_BOLD); - - for (;;) { - if (WGETCH(ewin, &c) == ERR) - continue; - if (c == '\r') - break; - } - - delwin(ewin); -} - history_t * hist_new() { @@ -965,7 +622,8 @@ history_t *hi; return hi; } -void hist_add(hi, text) +void +hist_add(hi, text) history_t *hi; const WCHAR *text; { @@ -990,99 +648,6 @@ histent_t *hent; ++hi->hi_nents; } -/* - * Return the tkey_t for the key called .name, or NULL if such a key doesn't - * exist. - */ -tkey_t * -find_key(name) - const WCHAR *name; -{ -size_t i; - - for (i = 0; i < sizeof(keys) / sizeof(*keys); i++) - if (STRCMP(name, keys[i].ky_name) == 0) - return &keys[i]; - return NULL; -} - -/* - * Return the function_t for the function called .name, or NULL if such a - * function doesn't exist. - */ -function_t * -find_func(name) - const WCHAR *name; -{ -function_t *f; - for (f = funcs; f->fn_name; f++) - if (STRCMP(name, f->fn_name) == 0) - return f; - return NULL; -} - -/* - * Bind .keyname to run the function .funcname. If a binding for .keyname - * already exists, overwrite it. - * - * If .keyname is a single character, e.g. 'a', it is used as a key name - * directly, rather than being looked up in the key table. - */ -void -bind_key(keyname, funcname, is_macro) - const WCHAR *keyname, *funcname; -{ -tkey_t *key = NULL; -function_t *func; -binding_t *binding; -INT code; - - /* Find the key and the function */ - if (STRLEN(keyname) > 1) { - if ((key = find_key(keyname)) == NULL) { - errbox(WIDE("Unknown key \"%"FMT_L"s\""), keyname); - return; - } - code = key->ky_code; - } else - code = *keyname; - - if (!is_macro) { - if ((func = find_func(funcname)) == NULL) { - errbox(WIDE("Unknown function \"%"FMT_L"s\""), funcname); - return; - } - } - - /* Do we already have a binding for this key? */ - TTS_TAILQ_FOREACH(binding, &bindings, bi_entries) { - if (binding->bi_code == code) { - if (is_macro) { - binding->bi_func = NULL; - binding->bi_macro = STRDUP(funcname); - } else { - free(binding->bi_macro); - binding->bi_func = func; - } - return; - } - } - - /* No, add a new one */ - if ((binding = calloc(1, sizeof(*binding))) == NULL) - return; - - binding->bi_key = key; - binding->bi_code = code; - - if (is_macro) - binding->bi_macro = STRDUP(funcname); - else - binding->bi_func = func; - - TTS_TAILQ_INSERT_TAIL(&bindings, binding, bi_entries); -} - variable_t * find_variable(name) WCHAR const *name; @@ -1094,90 +659,6 @@ variable_t *v; return NULL; } -int -attr_find(name, result) - const WCHAR *name; - attr_t *result; -{ -size_t i; - for (i = 0; i < sizeof(attrnames) / sizeof(*attrnames); i++) { - if (STRCMP(attrnames[i].an_name, name) == 0) { - *result = attrnames[i].an_value; - return 0; - } - } - - return -1; -} - -int -colour_find(name, result) - const WCHAR *name; - short *result; -{ -size_t i; - for (i = 0; i < sizeof(colours) / sizeof(*colours); i++) { - if (STRCMP(colours[i].co_name, name) == 0) { - *result = colours[i].co_value; - return 0; - } - } - - return -1; -} - -void -style_clear(sy) - style_t *sy; -{ - init_pair(sy->sy_pair, default_fg, default_bg); - sy->sy_attrs = WA_NORMAL; -} - -int -style_set(sy, fg, bg) - style_t *sy; - const WCHAR *fg, *bg; -{ - sy->sy_attrs = WA_NORMAL; - init_pair(sy->sy_pair, default_fg, default_bg); - return style_add(sy, fg, bg); -} - -int -style_add(sy, fg, bg) - style_t *sy; - const WCHAR *fg, *bg; -{ -attr_t at; -short colfg, colbg = default_bg; - - if (colour_find(fg, &colfg) == 0) { - if (bg && (colour_find(bg, &colbg) == -1)) - return -1; - - init_pair(sy->sy_pair, colfg, colbg); - return 0; - } - - if (attr_find(fg, &at) == -1) - return -1; - sy->sy_attrs |= at; - return 0; -} - -void -apply_styles() -{ - wbkgd(statwin, style_bg(sy_status)); - wattr_on(statwin, style_fg(sy_status), NULL); - drawstatus(WIDE("")); - - wbkgd(titwin, style_bg(sy_header)); - wattr_on(titwin, style_fg(sy_header), NULL); - drawheader(); -} - static char *curfile; static int lineno, nerr; @@ -1282,52 +763,6 @@ char input[1024]; return 0; } -int -prduration(pr, hh, mm, ss) - WCHAR *pr; - int *hh, *mm, *ss; -{ -WCHAR *tstr; -int h, m, s; - if ((tstr = prompt(pr, WIDE("00:00:00"), NULL)) == NULL) - return -1; - - if (!*tstr) { - drawstatus(WIDE("No duration entered")); - free(tstr); - return -1; - } - - if (SSCANF(tstr, WIDE("%d:%d:%d"), &h, &m, &s) != 3) { - h = 0; - if (SSCANF(tstr, WIDE("%d:%d"), &m, &s) != 2) { - m = 0; - if (SSCANF(tstr, WIDE("%d"), &s) != 1) { - free(tstr); - drawstatus(WIDE("Invalid time format.")); - return -1; - } - } - } - - free(tstr); - - if (m >= 60) { - drawstatus(WIDE("Minutes cannot be more than 59.")); - return -1; - } - - if (s >= 60) { - drawstatus(WIDE("Seconds cannot be more than 59.")); - return -1; - } - - *hh = h; - *mm = m; - *ss = s; - return 0; -} - #ifdef USE_DARWIN_POWER static void prompt_sleep() diff --git a/ui.c b/ui.c index c9e44ec..1ea29fe 100644 --- a/ui.c +++ b/ui.c @@ -9,6 +9,7 @@ */ #include +#include #include "ui.h" #include "tts.h" @@ -315,3 +316,294 @@ end: ; return STRDUP(input); } +void +errbox(const WCHAR *msg, ...) +{ +va_list ap; + va_start(ap, msg); + verrbox(msg, ap); + va_end(ap); +} + +void +verrbox(msg, ap) + const WCHAR *msg; + va_list ap; +{ +WCHAR text[4096]; +WINDOW *ewin; + +#define ETITLE WIDE(" Error ") +#define ECONT WIDE(" ") +int width; +INT c; + + VSNPRINTF(text, WSIZEOF(text), msg, ap); + width = STRLEN(text); + + ewin = newwin(6, width + 4, + (LINES / 2) - ((1 + 2)/ 2), + (COLS / 2) - ((width + 2) / 2)); + leaveok(ewin, TRUE); + wborder(ewin, 0, 0, 0, 0, 0, 0, 0, 0); + + wattron(ewin, A_REVERSE | A_BOLD); + wmove(ewin, 0, (width / 2) - (WSIZEOF(ETITLE) - 1)/2); + WADDSTR(ewin, ETITLE); + wattroff(ewin, A_REVERSE | A_BOLD); + + wmove(ewin, 2, 2); + WADDSTR(ewin, text); + wattron(ewin, A_REVERSE | A_BOLD); + wmove(ewin, 4, (width / 2) - ((WSIZEOF(ECONT) - 1) / 2)); + WADDSTR(ewin, ECONT); + wattroff(ewin, A_REVERSE | A_BOLD); + + for (;;) { + if (WGETCH(ewin, &c) == ERR) + continue; + if (c == '\r') + break; + } + + delwin(ewin); +} + +void +drawentries() +{ +int i, nlines; +int cline = 0; +time_t lastday = 0; +entry_t *en; +chtype oldbg; + + getmaxyx(listwin, nlines, i); + + TTS_TAILQ_FOREACH(en, &entries, en_entries) + en->en_flags.efl_visible = 0; + + en = TTS_TAILQ_FIRST(&entries); + for (i = 0; i < pagestart; i++) + if ((en = TTS_TAILQ_NEXT(en, en_entries)) == NULL) + return; + + for (; en; en = TTS_TAILQ_NEXT(en, en_entries)) { + time_t n; + int h, s, m; + WCHAR flags[10], stime[16], *p; + attr_t attrs = WA_NORMAL; + + if (!showinv && en->en_flags.efl_invoiced) + continue; + + oldbg = getbkgd(listwin); + + if (lastday != entry_day(en)) { + struct tm *lt; + WCHAR lbl[128]; + time_t itime = entry_time_for_day(entry_day(en), 1, 0), + ntime = entry_time_for_day(entry_day(en), 0, 0), + btime = entry_time_for_day(entry_day(en), 2, bill_increment); + int hi, mi, si, + hn, mn, sn, + hb, mb, sb, + ht, mt, st; + WCHAR hdrtext[256]; + + time_to_hms(itime, hi, mi, si); + time_to_hms(ntime, hn, mn, sn); + time_to_hms(btime, hb, mb, sb); + time_to_hms(itime + ntime, ht, mt, st); + + oldbg = getbkgd(listwin); + wbkgdset(listwin, style_bg(sy_entry)); + wattr_on(listwin, style_fg(sy_entry), NULL); + + wmove(listwin, cline, 0); + wclrtoeol(listwin); + + wbkgdset(listwin, oldbg); + wattr_off(listwin, style_fg(sy_entry), NULL); + + if (++cline >= nlines) + break; + + lastday = entry_day(en); + lt = localtime(&lastday); + + STRFTIME(lbl, WSIZEOF(lbl), WIDE("%A, %d %B %Y"), lt); + if (show_billable) + SNPRINTF(hdrtext, WSIZEOF(hdrtext), + WIDE("%-30"FMT_L"s [I:%02d:%02d:%02d / " + "N:%02d:%02d:%02d / T:%02d:%02d:%02d / " + "B:%02d:%02d:%02d]"), + lbl, hi, mi, si, hn, mn, sn, ht, mt, st, + hb, mb, sb); + else + SNPRINTF(hdrtext, WSIZEOF(hdrtext), + WIDE("%-30"FMT_L"s [I:%02d:%02d:%02d / " + "N:%02d:%02d:%02d / T:%02d:%02d:%02d]"), + lbl, hi, mi, si, hn, mn, sn, ht, mt, st); + + wattr_on(listwin, style_fg(sy_date), NULL); + wbkgdset(listwin, style_bg(sy_date)); + wmove(listwin, cline, 0); + WADDSTR(listwin, hdrtext); + wclrtoeol(listwin); + wattr_off(listwin, style_fg(sy_date), NULL); + wbkgdset(listwin, oldbg); + + if (++cline >= nlines) { + wbkgdset(listwin, oldbg); + wattr_off(listwin, style_fg(sy_date), NULL); + break; + } + + oldbg = getbkgd(listwin); + wbkgdset(listwin, style_bg(sy_entry)); + wattr_on(listwin, style_fg(sy_entry), NULL); + + wmove(listwin, cline, 0); + wclrtoeol(listwin); + + wbkgdset(listwin, oldbg); + wattr_off(listwin, style_fg(sy_entry), NULL); + + if (++cline >= nlines) + break; + } + + en->en_flags.efl_visible = 1; + wmove(listwin, cline, 0); + + attrs = style_fg(sy_entry); + + if (en->en_started && en == curent) + attrs = style_fg(sy_selected) | + (style_fg(sy_running) & ( + WA_STANDOUT | WA_UNDERLINE | + WA_REVERSE | WA_BLINK | WA_DIM | + WA_BOLD)); + else if (en->en_started) + attrs = style_fg(sy_running); + else if (en == curent) + attrs = style_fg(sy_selected); + + wbkgdset(listwin, ' ' | (attrs & ~WA_UNDERLINE)); + wattr_on(listwin, attrs, NULL); + + if (en == curent) { + WADDSTR(listwin, WIDE(" -> ")); + } else + WADDSTR(listwin, WIDE(" ")); + + n = en->en_secs; + if (en->en_started) + n += time(NULL) - en->en_started; + h = n / (60 * 60); + n %= (60 * 60); + m = n / 60; + n %= 60; + s = n; + + SNPRINTF(stime, WSIZEOF(stime), WIDE("%02d:%02d:%02d%c "), + h, m, s, (itime && (en == running)) ? '*' : ' '); + WADDSTR(listwin, stime); + + memset(flags, 0, sizeof(flags)); + p = flags; + + if (en->en_flags.efl_marked) + *p++ = 'M'; + else + *p++ = ' '; + + if (en->en_flags.efl_invoiced) + *p++ = 'I'; + else + *p++ = ' '; + + if (!en->en_flags.efl_nonbillable) + *p++ = 'B'; + else + *p++ = ' '; + + if (en->en_flags.efl_deleted) + *p++ = 'D'; + else + *p++ = ' '; + + if (*flags) { + WCHAR s[10]; + SNPRINTF(s, WSIZEOF(s), WIDE("%-5"FMT_L"s "), flags); + WADDSTR(listwin, s); + } else + WADDSTR(listwin, WIDE(" ")); + + WADDSTR(listwin, en->en_desc); + wclrtoeol(listwin); + wbkgdset(listwin, oldbg); + wattr_off(listwin, attrs, NULL); + + if (++cline >= nlines) + return; + } + + oldbg = getbkgd(listwin); + wattr_on(listwin, style_fg(sy_entry), NULL); + wbkgdset(listwin, style_bg(sy_entry)); + for (; cline < nlines; cline++) { + wmove(listwin, cline, 0); + wclrtoeol(listwin); + } + wattr_off(listwin, style_fg(sy_entry), NULL); + wbkgdset(listwin, oldbg); +} + +int +prduration(pr, hh, mm, ss) + WCHAR *pr; + int *hh, *mm, *ss; +{ +WCHAR *tstr; +int h, m, s; + if ((tstr = prompt(pr, WIDE("00:00:00"), NULL)) == NULL) + return -1; + + if (!*tstr) { + drawstatus(WIDE("No duration entered")); + free(tstr); + return -1; + } + + if (SSCANF(tstr, WIDE("%d:%d:%d"), &h, &m, &s) != 3) { + h = 0; + if (SSCANF(tstr, WIDE("%d:%d"), &m, &s) != 2) { + m = 0; + if (SSCANF(tstr, WIDE("%d"), &s) != 1) { + free(tstr); + drawstatus(WIDE("Invalid time format.")); + return -1; + } + } + } + + free(tstr); + + if (m >= 60) { + drawstatus(WIDE("Minutes cannot be more than 59.")); + return -1; + } + + if (s >= 60) { + drawstatus(WIDE("Seconds cannot be more than 59.")); + return -1; + } + + *hh = h; + *mm = m; + *ss = s; + return 0; +} + From d239b1669bbc466c00cbf48e074fd35d0c7be46d Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Fri, 7 Mar 2014 23:50:13 +0000 Subject: [PATCH 19/51] Clean up power code. --- tts.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/tts.c b/tts.c index 9ae691f..af44462 100644 --- a/tts.c +++ b/tts.c @@ -109,13 +109,10 @@ static io_object_t notifier; static mach_port_t ioport; static io_connect_t root_port; -static volatile sig_atomic_t donesleep; -static time_t sleeptime; - -static void power_setup(struct kevent *); -static void power_handle(struct kevent *); -static void power_event(void *, io_service_t, natural_t, void *); -static void prompt_sleep(void); +static void power_setup (struct kevent *); +static void power_handle (struct kevent *); +static void power_event (void *, io_service_t, natural_t, void *); +static void prompt_sleep (time_t); static void power_setup(ev) @@ -175,7 +172,6 @@ power_event(ref, service, msgtype, arg) natural_t msgtype; { static time_t sleep_started; -time_t diff; switch (msgtype) { case kIOMessageSystemWillSleep: @@ -188,10 +184,7 @@ time_t diff; /* System has finished wake-up; calculate the sleep time and * prompt the user. */ - time(&diff); - diff -= sleep_started; - sleeptime += diff; - prompt_sleep(); + prompt_sleep(time(NULL) - sleep_started); break; } } @@ -765,7 +758,8 @@ char input[1024]; #ifdef USE_DARWIN_POWER static void -prompt_sleep() +prompt_sleep(sleeptime) + time_t sleeptime; { /* * We woke from sleep. If there's a running entry, prompt the user to @@ -775,8 +769,6 @@ prompt_sleep() WCHAR pr[128]; int h, m, s = 0; - donesleep = 0; - /* Only prompt if an entry is running */ if (!running) return; @@ -793,17 +785,14 @@ int h, m, s = 0; WIDE("Remove %02d:%02d:%02d time asleep from running entry?"), h, m, s); - if (!yesno(pr)) { - sleeptime = 0; + if (!yesno(pr)) return; - } /* * This is a bit of a fudge, but it has the desired effect. Alternatively * we could merge en_started into en_secs, then subtract that. */ running->en_started += sleeptime; - sleeptime = 0; } #endif /* USE_DARWIN_POWER */ From 003ac6cca4c322f65fc3024930a5ceea7e51f198 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Sat, 8 Mar 2014 00:30:40 +0000 Subject: [PATCH 20/51] Always use wide characters. --- bindings.c | 178 +++++++++++++++++++++++++------------------ bindings.h | 14 ++-- commands.c | 72 +++++++++--------- commands.h | 18 ++--- entry.c | 6 +- entry.h | 4 +- functions.c | 213 ++++++++++++++++++++++++++------------------------- functions.h | 6 +- str.c | 28 +++---- str.h | 4 +- style.c | 62 +++++++++------ style.h | 19 ++--- tts.c | 193 +++++++++++++++------------------------------- tts.h | 6 +- ui.c | 216 +++++++++++++++++++++++++++++++--------------------- ui.h | 21 ++--- variable.h | 4 +- wide.h | 70 ++--------------- 18 files changed, 546 insertions(+), 588 deletions(-) diff --git a/bindings.c b/bindings.c index 9115989..33f61e7 100644 --- a/bindings.c +++ b/bindings.c @@ -17,71 +17,71 @@ binding_list_t bindings = TTS_TAILQ_HEAD_INITIALIZER(bindings); static tkey_t keys[] = { - { KEY_BREAK, WIDE("") }, - { KEY_DOWN, WIDE("") }, - { KEY_UP, WIDE("") }, - { KEY_LEFT, WIDE("") }, - { KEY_RIGHT, WIDE("") }, - { KEY_HOME, WIDE("") }, - { KEY_BACKSPACE, WIDE("") }, - { 0x7F, WIDE("") }, /* DEL */ - { KEY_F(0), WIDE("") }, - { KEY_F(1), WIDE("") }, - { KEY_F(2), WIDE("") }, - { KEY_F(3), WIDE("") }, - { KEY_F(4), WIDE("") }, - { KEY_F(5), WIDE("") }, - { KEY_F(6), WIDE("") }, - { KEY_F(7), WIDE("") }, - { KEY_F(8), WIDE("") }, - { KEY_F(9), WIDE("") }, - { KEY_F(10), WIDE("") }, - { KEY_F(11), WIDE("") }, - { KEY_F(12), WIDE("") }, - { KEY_F(13), WIDE("") }, - { KEY_F(14), WIDE("") }, - { KEY_F(15), WIDE("") }, - { KEY_F(16), WIDE("") }, - { KEY_F(17), WIDE("") }, - { KEY_F(18), WIDE("") }, - { KEY_F(19), WIDE("") }, - { KEY_F(20), WIDE("") }, - { KEY_F(21), WIDE("") }, - { KEY_F(22), WIDE("") }, - { KEY_F(23), WIDE("") }, - { KEY_F(24), WIDE("") }, - { KEY_NPAGE, WIDE("") }, - { KEY_PPAGE, WIDE("") }, - { '\001', WIDE("") }, - { '\002', WIDE("") }, - { '\003', WIDE("") }, - { '\004', WIDE("") }, - { '\005', WIDE("") }, - { '\006', WIDE("") }, - { '\007', WIDE("") }, - { '\010', WIDE("") }, - { '\011', WIDE("") }, - { '\011', WIDE("") }, - { '\012', WIDE("") }, - { '\013', WIDE("") }, - { '\014', WIDE("") }, - { '\015', WIDE("") }, - { '\016', WIDE("") }, - { '\017', WIDE("") }, - { '\020', WIDE("") }, - { '\021', WIDE("") }, - { '\022', WIDE("") }, - { '\023', WIDE("") }, - { '\024', WIDE("") }, - { '\025', WIDE("") }, - { '\026', WIDE("") }, - { '\027', WIDE("") }, - { '\030', WIDE("") }, - { '\031', WIDE("") }, - { ' ', WIDE("") }, - { KEY_ENTER, WIDE("") }, - { KEY_BACKSPACE, WIDE("") }, - { KEY_DC, WIDE("") } + { KEY_BREAK, L"" }, + { KEY_DOWN, L"" }, + { KEY_UP, L"" }, + { KEY_LEFT, L"" }, + { KEY_RIGHT, L"" }, + { KEY_HOME, L"" }, + { KEY_BACKSPACE, L"" }, + { 0x7F, L"" }, /* DEL */ + { KEY_F(0), L"" }, + { KEY_F(1), L"" }, + { KEY_F(2), L"" }, + { KEY_F(3), L"" }, + { KEY_F(4), L"" }, + { KEY_F(5), L"" }, + { KEY_F(6), L"" }, + { KEY_F(7), L"" }, + { KEY_F(8), L"" }, + { KEY_F(9), L"" }, + { KEY_F(10), L"" }, + { KEY_F(11), L"" }, + { KEY_F(12), L"" }, + { KEY_F(13), L"" }, + { KEY_F(14), L"" }, + { KEY_F(15), L"" }, + { KEY_F(16), L"" }, + { KEY_F(17), L"" }, + { KEY_F(18), L"" }, + { KEY_F(19), L"" }, + { KEY_F(20), L"" }, + { KEY_F(21), L"" }, + { KEY_F(22), L"" }, + { KEY_F(23), L"" }, + { KEY_F(24), L"" }, + { KEY_NPAGE, L"" }, + { KEY_PPAGE, L"" }, + { '\001', L"" }, + { '\002', L"" }, + { '\003', L"" }, + { '\004', L"" }, + { '\005', L"" }, + { '\006', L"" }, + { '\007', L"" }, + { '\010', L"" }, + { '\011', L"" }, + { '\011', L"" }, + { '\012', L"" }, + { '\013', L"" }, + { '\014', L"" }, + { '\015', L"" }, + { '\016', L"" }, + { '\017', L"" }, + { '\020', L"" }, + { '\021', L"" }, + { '\022', L"" }, + { '\023', L"" }, + { '\024', L"" }, + { '\025', L"" }, + { '\026', L"" }, + { '\027', L"" }, + { '\030', L"" }, + { '\031', L"" }, + { ' ', L"" }, + { KEY_ENTER, L"" }, + { KEY_BACKSPACE, L"" }, + { KEY_DC, L"" } }; /* @@ -93,17 +93,17 @@ static tkey_t keys[] = { */ void bind_key(keyname, funcname, is_macro) - const WCHAR *keyname, *funcname; + const wchar_t *keyname, *funcname; { tkey_t *key = NULL; function_t *func; binding_t *binding; -INT code; +wint_t code; /* Find the key and the function */ - if (STRLEN(keyname) > 1) { + if (wcslen(keyname) > 1) { if ((key = find_key(keyname)) == NULL) { - errbox(WIDE("Unknown key \"%"FMT_L"s\""), keyname); + errbox(L"Unknown key \"%ls\"", keyname); return; } code = key->ky_code; @@ -112,7 +112,7 @@ INT code; if (!is_macro) { if ((func = find_func(funcname)) == NULL) { - errbox(WIDE("Unknown function \"%"FMT_L"s\""), funcname); + errbox(L"Unknown function \"%ls\"", funcname); return; } } @@ -122,7 +122,7 @@ INT code; if (binding->bi_code == code) { if (is_macro) { binding->bi_func = NULL; - binding->bi_macro = STRDUP(funcname); + binding->bi_macro = wcsdup(funcname); } else { free(binding->bi_macro); binding->bi_func = func; @@ -139,7 +139,7 @@ INT code; binding->bi_code = code; if (is_macro) - binding->bi_macro = STRDUP(funcname); + binding->bi_macro = wcsdup(funcname); else binding->bi_func = func; @@ -152,13 +152,43 @@ INT code; */ tkey_t * find_key(name) - const WCHAR *name; + const wchar_t *name; { size_t i; for (i = 0; i < sizeof(keys) / sizeof(*keys); i++) - if (STRCMP(name, keys[i].ky_name) == 0) + if (wcscmp(name, keys[i].ky_name) == 0) return &keys[i]; return NULL; } +void +bind_defaults(void) +{ + bind_key(L"?", L"help", 0); + bind_key(L"a", L"add", 0); + bind_key(L"A", L"add-old", 0); + bind_key(L"d", L"delete", 0); + bind_key(L"u", L"undelete", 0); + bind_key(L"q", L"quit", 0); + bind_key(L"", L"quit", 0); + bind_key(L"i", L"invoice", 0); + bind_key(L"b", L"billable", 0); + bind_key(L"m", L"mark", 0); + bind_key(L"U", L"unmarkall", 0); + bind_key(L"", L"startstop", 0); + bind_key(L"e", L"edit-desc", 0); + bind_key(L"\\", L"edit-time", 0); + bind_key(L"", L"showhide-inv", 0); + bind_key(L"c", L"copy", 0); + bind_key(L"+", L"add-time", 0); + bind_key(L"-", L"sub-time", 0); + bind_key(L"/", L"search", 0); + bind_key(L"$", L"sync", 0); + bind_key(L"", L"prev", 0); + bind_key(L"", L"next", 0); + bind_key(L":", L"execute", 0); + bind_key(L"M", L"merge", 0); + bind_key(L"r", L"interrupt", 0); + bind_key(L"R", L"interrupt", 0); +} diff --git a/bindings.h b/bindings.h index ce07811..1d4e916 100644 --- a/bindings.h +++ b/bindings.h @@ -16,15 +16,15 @@ #include "tailq.h" typedef struct tkey { - INT ky_code; - const WCHAR *ky_name; + wint_t ky_code; + const wchar_t *ky_name; } tkey_t; typedef struct binding { - INT bi_code; + wint_t bi_code; tkey_t *bi_key; function_t *bi_func; - WCHAR *bi_macro; + wchar_t *bi_macro; TTS_TAILQ_ENTRY(binding) bi_entries; } binding_t; @@ -32,7 +32,9 @@ typedef struct binding { typedef TTS_TAILQ_HEAD(bindlist, binding) binding_list_t; extern binding_list_t bindings; -tkey_t *find_key(const WCHAR *name); -void bind_key(const WCHAR *key, const WCHAR *func, int is_macro); +void bind_defaults(); +tkey_t *find_key(const wchar_t *name); +void bind_key(const wchar_t *key, const wchar_t *func, int is_macro); + #endif /* !TTS_BINDINGS_H */ diff --git a/commands.c b/commands.c index 4696625..3e501a5 100644 --- a/commands.c +++ b/commands.c @@ -14,20 +14,20 @@ #include "variable.h" static command_t commands[] = { - { WIDE("bind"), c_bind }, - { WIDE("macro"), c_macro }, - { WIDE("style"), c_style }, - { WIDE("set"), c_set }, + { L"bind", c_bind }, + { L"macro", c_macro }, + { L"style", c_style }, + { L"set", c_set }, { } }; command_t * find_command(name) - const WCHAR *name; + const wchar_t *name; { size_t i; for (i = 0; i < sizeof(commands) / sizeof(*commands); i++) - if (STRCMP(name, commands[i].cm_name) == 0) + if (wcscmp(name, commands[i].cm_name) == 0) return &commands[i]; return NULL; } @@ -35,36 +35,36 @@ size_t i; void c_style(argc, argv) size_t argc; - WCHAR **argv; + wchar_t **argv; { style_t *sy; -WCHAR *last, *tok; +wchar_t *last, *tok; if (argc < 3 || argc > 4) { - cmderr(WIDE("Usage: style [background]")); + cmderr(L"Usage: style [background]"); return; } - if (STRCMP(argv[1], WIDE("header")) == 0) + if (wcscmp(argv[1], L"header") == 0) sy = &sy_header; - else if (STRCMP(argv[1], WIDE("status")) == 0) + else if (wcscmp(argv[1], L"status") == 0) sy = &sy_status; - else if (STRCMP(argv[1], WIDE("entry")) == 0) + else if (wcscmp(argv[1], L"entry") == 0) sy = &sy_entry; - else if (STRCMP(argv[1], WIDE("selected")) == 0) + else if (wcscmp(argv[1], L"selected") == 0) sy = &sy_selected; - else if (STRCMP(argv[1], WIDE("running")) == 0) + else if (wcscmp(argv[1], L"running") == 0) sy = &sy_running; - else if (STRCMP(argv[1], WIDE("date")) == 0) + else if (wcscmp(argv[1], L"date") == 0) sy = &sy_date; else { - cmderr(WIDE("Unknown style item.")); + cmderr(L"Unknown style item."); return; } style_clear(sy); - for (tok = STRTOK(argv[2], WIDE(","), &last); tok != NULL; - tok = STRTOK(NULL, WIDE(","), &last)) { + for (tok = wcstok(argv[2], L",", &last); tok != NULL; + tok = wcstok(NULL, L",", &last)) { style_add(sy, tok, argv[3]); } @@ -74,10 +74,10 @@ WCHAR *last, *tok; void c_bind(argc, argv) size_t argc; - WCHAR **argv; + wchar_t **argv; { if (argc != 3) { - cmderr(WIDE("Usage: bind ")); + cmderr(L"Usage: bind "); return; } @@ -87,10 +87,10 @@ c_bind(argc, argv) void c_macro(argc, argv) size_t argc; - WCHAR **argv; + wchar_t **argv; { if (argc != 3) { - cmderr(WIDE("Usage: macro ")); + cmderr(L"Usage: macro "); return; } @@ -100,35 +100,35 @@ c_macro(argc, argv) void c_set(argc, argv) size_t argc; - WCHAR **argv; + wchar_t **argv; { variable_t *var; int val; if (argc != 3) { - cmderr(WIDE("Usage: set ")); + cmderr(L"Usage: set "); return; } if ((var = find_variable(argv[1])) == NULL) { - cmderr(WIDE("Unknown variable \"%"FMT_L"s\"."), argv[1]); + cmderr(L"Unknown variable \"%ls\".", argv[1]); return; } switch (var->va_type) { case VTYPE_BOOL: - if (STRCMP(argv[2], WIDE("true")) == 0 || - STRCMP(argv[2], WIDE("yes")) == 0 || - STRCMP(argv[2], WIDE("on")) == 0 || - STRCMP(argv[2], WIDE("1")) == 0) { + if (wcscmp(argv[2], L"true") == 0 || + wcscmp(argv[2], L"yes") == 0 || + wcscmp(argv[2], L"on") == 0 || + wcscmp(argv[2], L"1") == 0) { val = 1; - } else if (STRCMP(argv[2], WIDE("false")) == 0 || - STRCMP(argv[2], WIDE("no")) == 0 || - STRCMP(argv[2], WIDE("off")) == 0 || - STRCMP(argv[2], WIDE("0")) == 0) { + } else if (wcscmp(argv[2], L"false") == 0 || + wcscmp(argv[2], L"no") == 0 || + wcscmp(argv[2], L"off") == 0 || + wcscmp(argv[2], L"0") == 0) { val = 0; } else { - cmderr(WIDE("Invalid value for boolean: \"%"FMT_L"s\"."), argv[2]); + cmderr(L"Invalid value for boolean: \"%ls\".", argv[2]); return; } @@ -136,11 +136,11 @@ int val; break; case VTYPE_STRING: - *(WCHAR **)var->va_addr = STRDUP(argv[2]); + *(wchar_t **)var->va_addr = wcsdup(argv[2]); break; case VTYPE_INT: - *(int *)var->va_addr = STRTOL(argv[2], NULL, 0); + *(int *)var->va_addr = wcstol(argv[2], NULL, 0); break; } } diff --git a/commands.h b/commands.h index 22b1085..5c00c4f 100644 --- a/commands.h +++ b/commands.h @@ -16,18 +16,18 @@ #include "wide.h" typedef struct command { - const WCHAR *cm_name; - void (*cm_hdl) (size_t, WCHAR **); + const wchar_t *cm_name; + void (*cm_hdl) (size_t, wchar_t **); } command_t; -command_t *find_command(const WCHAR *); +command_t *find_command(const wchar_t *); -void c_bind (size_t, WCHAR **); -void c_style (size_t, WCHAR **); -void c_set (size_t, WCHAR **); -void c_macro (size_t, WCHAR **); +void c_bind (size_t, wchar_t **); +void c_style (size_t, wchar_t **); +void c_set (size_t, wchar_t **); +void c_macro (size_t, wchar_t **); -void cmderr (const WCHAR *, ...); -void vcmderr (const WCHAR *, va_list); +void cmderr (const wchar_t *, ...); +void vcmderr (const wchar_t *, va_list); #endif /* !TTS_COMMANDS_H */ diff --git a/entry.c b/entry.c index 6bcfefa..6226efe 100644 --- a/entry.c +++ b/entry.c @@ -23,18 +23,18 @@ entry_t *running; entry_t * entry_new(desc) - const WCHAR *desc; + const wchar_t *desc; { entry_t *en; if ((en = calloc(1, sizeof(*en))) == NULL) return NULL; - if (auto_nonbillable && STRSTR(desc, auto_nonbillable)) + if (auto_nonbillable && wcsstr(desc, auto_nonbillable)) en->en_flags.efl_nonbillable = 1; TTS_TAILQ_INSERT_HEAD(&entries, en, en_entries); - en->en_desc = STRDUP(desc); + en->en_desc = wcsdup(desc); time(&en->en_created); return en; diff --git a/entry.h b/entry.h index 54e33c0..651fa4d 100644 --- a/entry.h +++ b/entry.h @@ -17,7 +17,7 @@ #include "wide.h" typedef struct entry { - WCHAR *en_desc; + wchar_t *en_desc; int en_secs; time_t en_started; time_t en_created; @@ -37,7 +37,7 @@ extern entry_list entries; extern entry_t *running; -entry_t *entry_new (const WCHAR *); +entry_t *entry_new (const wchar_t *); void entry_start (entry_t *); void entry_stop (entry_t *); void entry_free (entry_t *); diff --git a/functions.c b/functions.c index 62acfd0..d91f9e3 100644 --- a/functions.c +++ b/functions.c @@ -20,30 +20,30 @@ #include "str.h" function_t funcs[] = { - { WIDE("help"), khelp, WIDE("display help screen") }, - { WIDE("add"), kadd, WIDE("add a new entry and start the timer") }, - { WIDE("add-old"), kaddold, WIDE("add a new entry and specify its duration") }, - { WIDE("delete"), kmarkdel, WIDE("delete the current entry") }, - { WIDE("undelete"), kundel, WIDE("undelete the current entry") }, - { WIDE("quit"), kquit, WIDE("exit TTS") }, - { WIDE("invoice"), kinvoiced, WIDE("toggle current entry as invoiced") }, - { WIDE("billable"), kbillable, WIDE("toggle current entry as billable") }, - { WIDE("mark"), kmark, WIDE("mark the current entry") }, - { WIDE("unmarkall"), kunmarkall, WIDE("unmark all entries") }, - { WIDE("startstop"), ktoggle, WIDE("start or stop the timer") }, - { WIDE("edit-desc"), keddesc, WIDE("edit the current entry's description") }, - { WIDE("edit-time"), kedtime, WIDE("edit the current entry's duration") }, - { WIDE("showhide-inv"), ktoggleinv, WIDE("show or hide invoiced entries") }, - { WIDE("copy"), kcopy, WIDE("copy the current entry's description to a new entry") }, - { WIDE("add-time"), kaddtime, WIDE("add time to the current entry") }, - { WIDE("sub-time"), kdeltime, WIDE("subtract time from the current entry") }, - { WIDE("search"), ksearch, WIDE("search for an entry by name") }, - { WIDE("sync"), ksync, WIDE("purge all deleted entries") }, - { WIDE("prev"), kup, WIDE("move to the previous entry") }, - { WIDE("next"), kdown, WIDE("move to the next entry") }, - { WIDE("execute"), kexec, WIDE("execute a configuration command") }, - { WIDE("merge"), kmerge, WIDE("merge marked entries into current entry") }, - { WIDE("interrupt"), kint, WIDE("split current entry into new entry")}, + { L"help", khelp, L"display help screen" }, + { L"add", kadd, L"add a new entry and start the timer" }, + { L"add-old", kaddold, L"add a new entry and specify its duration" }, + { L"delete", kmarkdel, L"delete the current entry" }, + { L"undelete", kundel, L"undelete the current entry" }, + { L"quit", kquit, L"exit TTS" }, + { L"invoice", kinvoiced, L"toggle current entry as invoiced" }, + { L"billable", kbillable, L"toggle current entry as billable" }, + { L"mark", kmark, L"mark the current entry" }, + { L"unmarkall", kunmarkall, L"unmark all entries" }, + { L"startstop", ktoggle, L"start or stop the timer" }, + { L"edit-desc", keddesc, L"edit the current entry's description" }, + { L"edit-time", kedtime, L"edit the current entry's duration" }, + { L"showhide-inv", ktoggleinv, L"show or hide invoiced entries" }, + { L"copy", kcopy, L"copy the current entry's description to a new entry" }, + { L"add-time", kaddtime, L"add time to the current entry" }, + { L"sub-time", kdeltime, L"subtract time from the current entry" }, + { L"search", ksearch, L"search for an entry by name" }, + { L"sync", ksync, L"purge all deleted entries" }, + { L"prev", kup, L"move to the previous entry" }, + { L"next", kdown, L"move to the next entry" }, + { L"execute", kexec, L"execute a configuration command" }, + { L"merge", kmerge, L"merge marked entries into current entry" }, + { L"interrupt", kint, L"split current entry into new entry"}, { } }; @@ -59,8 +59,8 @@ int ndel = 0; } if (ndel) { - WCHAR s[128]; - SNPRINTF(s, WSIZEOF(s), WIDE("Purge %d deleted entries?"), ndel); + wchar_t s[128]; + swprintf(s, wsizeof(s), L"Purge %d deleted entries?", ndel); if (yesno(s)) { ksync(); } @@ -72,9 +72,9 @@ int ndel = 0; void kadd() { -WCHAR *name; +wchar_t *name; entry_t *en; - name = prompt(WIDE("Description:"), NULL, NULL); + name = prompt(L"Description:", NULL, NULL); if (!name || !*name) { free(name); return; @@ -88,9 +88,9 @@ entry_t *en; void kaddold() { -WCHAR *name; +wchar_t *name; entry_t *en; - name = prompt(WIDE("Description:"), NULL, NULL); + name = prompt(L"Description:", NULL, NULL); if (!name || !*name) { free(name); @@ -151,7 +151,7 @@ int nmarked = 0; return; if (!curent) { - drawstatus(WIDE("No entries to delete.")); + drawstatus(L"No entries to delete."); return; } @@ -193,7 +193,7 @@ entry_t *prev = curent; } while (!showinv && prev->en_flags.efl_invoiced); if (prev == NULL) { - drawstatus(WIDE("Already at first entry.")); + drawstatus(L"Already at first entry."); return; } @@ -215,7 +215,7 @@ entry_t *next = curent; } while (!showinv && next->en_flags.efl_invoiced); if (next == NULL) { - drawstatus(WIDE("Already at last entry.")); + drawstatus(L"Already at last entry."); return; } @@ -244,7 +244,7 @@ int anymarked = 0; } if (!curent) { - drawstatus(WIDE("No entry selected.")); + drawstatus(L"No entry selected."); return; } @@ -300,7 +300,7 @@ int anymarked = 0; } if (!curent) { - drawstatus(WIDE("No entry selected.")); + drawstatus(L"No entry selected."); return; } @@ -314,14 +314,14 @@ int anymarked = 0; void keddesc() { -WCHAR *new; +wchar_t *new; if (!curent) { - drawstatus(WIDE("No entry selected.")); + drawstatus(L"No entry selected."); return; } - if ((new = prompt(WIDE("Description:"), curent->en_desc, NULL)) == NULL) + if ((new = prompt(L"Description:", curent->en_desc, NULL)) == NULL) return; free(curent->en_desc); @@ -332,12 +332,12 @@ WCHAR *new; void kedtime() { -WCHAR *new, old[64]; +wchar_t *new, old[64]; time_t n; int h, m, s; if (!curent) { - drawstatus(WIDE("No entry selected.")); + drawstatus(L"No entry selected."); return; } @@ -350,13 +350,13 @@ int h, m, s; n %= 60; s = n; - SNPRINTF(old, WSIZEOF(old), WIDE("%02d:%02d:%02d"), h, m, s); - if ((new = prompt(WIDE("Duration [HH:MM:SS]:"), old, NULL)) == NULL) + swprintf(old, wsizeof(old), L"%02d:%02d:%02d", h, m, s); + if ((new = prompt(L"Duration [HH:MM:SS]:", old, NULL)) == NULL) return; - if (!SSCANF(new, WIDE("%d:%d:%d"), &h, &m, &s)) { + if (!swscanf(new, L"%d:%d:%d", &h, &m, &s)) { free(new); - drawstatus(WIDE("Invalid duration.")); + drawstatus(L"Invalid duration."); } curent->en_secs = (h * 60 * 60) + (m * 60) + s; @@ -371,8 +371,7 @@ ktoggleinv() { entry_t *en = curent; showinv = !showinv; - drawstatus(WIDE("%"FMT_L"s invoiced entries."), - showinv ? L"Showing" : L"Hiding"); + drawstatus(L"%ls invoiced entries.", showinv ? L"Showing" : L"Hiding"); if (curent && !curent->en_flags.efl_invoiced) return; @@ -409,7 +408,7 @@ kcopy() entry_t *en; if (!curent) { - drawstatus(WIDE("No entry selected.")); + drawstatus(L"No entry selected."); return; } @@ -422,29 +421,29 @@ entry_t *en; void kaddtime() { -WCHAR *tstr; +wchar_t *tstr; int h = 0, m = 0, s = 0, secs; if (!curent) { - drawstatus(WIDE("No entry selected.")); + drawstatus(L"No entry selected."); return; } - if ((tstr = prompt(WIDE("Time to add ([[HH:]MM:]SS):"), NULL, NULL)) == NULL) + if ((tstr = prompt(L"Time to add ([[HH:]MM:]SS):", NULL, NULL)) == NULL) return; if (!*tstr) { - drawstatus(WIDE("")); + drawstatus(L""); free(tstr); return; } - if (SSCANF(tstr, WIDE("%d:%d:%d"), &h, &m, &s) != 3) { + if (swscanf(tstr, L"%d:%d:%d", &h, &m, &s) != 3) { h = 0; - if (SSCANF(tstr, WIDE("%d:%d"), &m, &s) != 2) { + if (swscanf(tstr, L"%d:%d", &m, &s) != 2) { m = 0; - if (SSCANF(tstr, WIDE("%d"), &s) != 1) { + if (swscanf(tstr, L"%d", &s) != 1) { free(tstr); - drawstatus(WIDE("Invalid time format.")); + drawstatus(L"Invalid time format."); return; } } @@ -453,12 +452,12 @@ int h = 0, m = 0, s = 0, secs; free(tstr); if (m >= 60) { - drawstatus(WIDE("Minutes cannot be more than 59.")); + drawstatus(L"Minutes cannot be more than 59."); return; } if (s >= 60) { - drawstatus(WIDE("Seconds cannot be more than 59.")); + drawstatus(L"Seconds cannot be more than 59."); return; } @@ -470,29 +469,29 @@ int h = 0, m = 0, s = 0, secs; void kdeltime() { -WCHAR *tstr; +wchar_t *tstr; int h = 0, m = 0, s = 0, secs; if (!curent) { - drawstatus(WIDE("No entry selected.")); + drawstatus(L"No entry selected."); return; } - if ((tstr = prompt(WIDE("Time to subtract, ([[HH:]MM:]SS):"), NULL, NULL)) == NULL) + if ((tstr = prompt(L"Time to subtract, ([[HH:]MM:]SS):", NULL, NULL)) == NULL) return; if (!*tstr) { - drawstatus(WIDE("")); + drawstatus(L""); free(tstr); return; } - if (SSCANF(tstr, WIDE("%d:%d:%d"), &h, &m, &s) != 3) { + if (swscanf(tstr, L"%d:%d:%d", &h, &m, &s) != 3) { h = 0; - if (SSCANF(tstr, WIDE("%d:%d"), &m, &s) != 2) { + if (swscanf(tstr, L"%d:%d", &m, &s) != 2) { m = 0; - if (SSCANF(tstr, WIDE("%d"), &s) != 1) { + if (swscanf(tstr, L"%d", &s) != 1) { free(tstr); - drawstatus(WIDE("Invalid time format.")); + drawstatus(L"Invalid time format."); return; } } @@ -500,12 +499,12 @@ int h = 0, m = 0, s = 0, secs; free(tstr); if (m >= 60) { - drawstatus(WIDE("Minutes cannot be more than 59.")); + drawstatus(L"Minutes cannot be more than 59."); return; } if (s >= 60) { - drawstatus(WIDE("Seconds cannot be more than 59.")); + drawstatus(L"Seconds cannot be more than 59."); return; } @@ -513,7 +512,7 @@ int h = 0, m = 0, s = 0, secs; secs = s + m*60 + h*60*60; if (curent->en_secs - secs < 0) { - drawstatus(WIDE("Remaining time cannot be less than zero.")); + drawstatus(L"Remaining time cannot be less than zero."); return; } @@ -526,11 +525,11 @@ kmerge() { entry_t *en, *ten; int nmarked = 0; -WCHAR pr[128]; +wchar_t pr[128]; int h, m, s = 0; if (!curent) { - drawstatus(WIDE("No entry selected.")); + drawstatus(L"No entry selected."); return; } @@ -547,7 +546,7 @@ int h, m, s = 0; } if (nmarked == 0) { - drawstatus(WIDE("No marked entries.")); + drawstatus(L"No marked entries."); return; } @@ -556,7 +555,7 @@ int h, m, s = 0; m = s / 60; s %= 60; - SNPRINTF(pr, WSIZEOF(pr), WIDE("Merge %d marked entries [%02d:%02d:%02d] into current entry?"), + swprintf(pr, wsizeof(pr), L"Merge %d marked entries [%02d:%02d:%02d] into current entry?", nmarked, h, m, s); if (!yesno(pr)) return; @@ -578,35 +577,35 @@ khelp() { WINDOW *hwin; size_t nhelp = 0; -WCHAR **help; -#define HTITLE WIDE(" TTS keys ") +wchar_t **help; +#define HTITLE L" TTS keys " size_t width = 0; size_t i; -INT c; +wint_t c; binding_t *bi; /* Count the number of bindings */ TTS_TAILQ_FOREACH(bi, &bindings, bi_entries) nhelp++; - help = calloc(nhelp, sizeof(const WCHAR *)); + help = calloc(nhelp, sizeof(const wchar_t *)); i = 0; TTS_TAILQ_FOREACH(bi, &bindings, bi_entries) { - WCHAR s[128], t[16]; + wchar_t s[128], t[16]; if (bi->bi_key) - SNPRINTF(t, WSIZEOF(t), WIDE("%"FMT_L"s"), bi->bi_key->ky_name); + swprintf(t, wsizeof(t), L"%ls", bi->bi_key->ky_name); else - SNPRINTF(t, WSIZEOF(t), WIDE("%"FMT_L"c"), bi->bi_code); + swprintf(t, wsizeof(t), L"%lc", bi->bi_code); if (bi->bi_macro) - SNPRINTF(s, WSIZEOF(s), WIDE("%-10"FMT_L"s execute macro: %"FMT_L"s"), + swprintf(s, wsizeof(s), L"%-10ls execute macro: %ls", t, bi->bi_macro); else - SNPRINTF(s, WSIZEOF(s), WIDE("%-10"FMT_L"s %"FMT_L"s (%"FMT_L"s)"), + swprintf(s, wsizeof(s), L"%-10ls %ls (%ls)", t, bi->bi_func->fn_desc, bi->bi_func->fn_name); - help[i] = STRDUP(s); + help[i] = wcsdup(s); i++; } @@ -614,8 +613,8 @@ binding_t *bi; nhelp = LINES - 6; for (i = 0; i < nhelp; i++) - if (STRLEN(help[i]) > width) - width = STRLEN(help[i]); + if (wcslen(help[i]) > width) + width = wcslen(help[i]); hwin = newwin(nhelp + 4, width + 4, (LINES / 2) - ((nhelp + 2) / 2), @@ -623,18 +622,18 @@ binding_t *bi; wborder(hwin, 0, 0, 0, 0, 0, 0, 0, 0); wattron(hwin, A_REVERSE | A_BOLD); - wmove(hwin, 0, (width / 2) - (WSIZEOF(HTITLE) - 1)/2); - WADDSTR(hwin, HTITLE); + wmove(hwin, 0, (width / 2) - (wsizeof(HTITLE) - 1)/2); + waddwstr(hwin, HTITLE); wattroff(hwin, A_REVERSE | A_BOLD); for (i = 0; i < nhelp; i++) { wmove(hwin, i + 2, 2); - WADDSTR(hwin, help[i]); + waddwstr(hwin, help[i]); } wrefresh(hwin); - while (WGETCH(hwin, &c) == ERR + while (wget_wch(hwin, &c) == ERR #ifdef KEY_RESIZE || (c == KEY_RESIZE) #endif @@ -652,7 +651,7 @@ void kmark() { if (!curent) { - drawstatus(WIDE("No entry selected.")); + drawstatus(L"No entry selected."); return; } @@ -675,11 +674,11 @@ kint() { time_t duration; entry_t *en; -WCHAR *name; +wchar_t *name; if (!itime) { if (!running) { - drawstatus(WIDE("No running entry.")); + drawstatus(L"No running entry."); return; } @@ -688,11 +687,11 @@ WCHAR *name; } if (!running) { - drawstatus(WIDE("No running entry.")); + drawstatus(L"No running entry."); return; } - name = prompt(WIDE("Description:"), NULL, NULL); + name = prompt(L"Description:", NULL, NULL); if (!name || !*name) { itime = 0; @@ -704,7 +703,7 @@ WCHAR *name; duration = time(NULL) - itime; } else { int h, m, s; - if (prduration(WIDE("Duration [HH:MM:SS]:"), &h, &m, &s) == -1) + if (prduration(L"Duration [HH:MM:SS]:", &h, &m, &s) == -1) return; duration = (h * 60 * 60) + (m * 60) + s; @@ -726,16 +725,16 @@ WCHAR *name; void ksearch() { -static WCHAR *lastsearch; -WCHAR *term; +static wchar_t *lastsearch; +wchar_t *term; entry_t *start, *cur; if (!curent) { - drawstatus(WIDE("No entries.")); + drawstatus(L"No entries."); return; } - if ((term = prompt(WIDE("Search:"), NULL, NULL)) == NULL) + if ((term = prompt(L"Search:", NULL, NULL)) == NULL) return; if (!*term) { @@ -754,16 +753,16 @@ entry_t *start, *cur; for (;;) { cur = TTS_TAILQ_NEXT(cur, en_entries); if (cur == NULL) { - drawstatus(WIDE("Search reached last entry, continuing from top.")); + drawstatus(L"Search reached last entry, continuing from top."); cur = TTS_TAILQ_FIRST(&entries); } if (cur == start) { - drawstatus(WIDE("No matches.")); + drawstatus(L"No matches."); break; } - if (STRSTR(cur->en_desc, term)) { + if (wcsstr(cur->en_desc, term)) { curent = cur; if (!showinv && cur->en_flags.efl_invoiced) showinv = 1; @@ -776,12 +775,12 @@ entry_t *start, *cur; void kexec() { -WCHAR *cmd; -WCHAR **args; +wchar_t *cmd; +wchar_t **args; command_t *cmds; size_t nargs; - if ((cmd = prompt(WIDE(":"), NULL, NULL)) == NULL || !*cmd) { + if ((cmd = prompt(L":", NULL, NULL)) == NULL || !*cmd) { free(cmd); return; } @@ -795,7 +794,7 @@ size_t nargs; } if ((cmds = find_command(args[0])) == NULL) { - drawstatus(WIDE("Unknown command.")); + drawstatus(L"Unknown command."); tokfree(&args); return; } @@ -810,11 +809,11 @@ size_t nargs; */ function_t * find_func(name) - const WCHAR *name; + const wchar_t *name; { function_t *f; for (f = funcs; f->fn_name; f++) - if (STRCMP(name, f->fn_name) == 0) + if (wcscmp(name, f->fn_name) == 0) return f; return NULL; } diff --git a/functions.h b/functions.h index 1ef87b2..9f1186e 100644 --- a/functions.h +++ b/functions.h @@ -39,13 +39,13 @@ void kmerge(void); void kint(void); typedef struct function { - const WCHAR *fn_name; + const wchar_t *fn_name; void (*fn_hdl) (void); - const WCHAR *fn_desc; + const wchar_t *fn_desc; } function_t; extern function_t funcs[]; -function_t *find_func(const WCHAR *name); +function_t *find_func(const wchar_t *name); #endif /* !TTS_FUNCTIONS_H */ diff --git a/str.c b/str.c index a489a91..1d2d33e 100644 --- a/str.c +++ b/str.c @@ -12,12 +12,12 @@ size_t tokenise(str, res) - const WCHAR *str; - WCHAR ***res; + const wchar_t *str; + wchar_t ***res; { int ntoks = 0; -const WCHAR *p, *q; -WCHAR *r; +const wchar_t *p, *q; +wchar_t *r; *res = NULL; p = str; @@ -28,7 +28,7 @@ WCHAR *r; int isbsl = 0; /* Skip leading whitespace */ - while (ISSPACE(*p)) + while (iswspace(*p)) p++; /* End of string - no more arguments */ @@ -64,21 +64,21 @@ WCHAR *r; qskip = 1; } else { /* Not quoted - just find the next whitespace */ - while (!ISSPACE(*q) && *q) + while (!iswspace(*q) && *q) q++; } /* Copy the argument (which is sz bytes long) into the result array */ sz = (q - p); - *res = realloc(*res, sizeof(WCHAR *) * (ntoks + 1)); - (*res)[ntoks] = malloc(sizeof(WCHAR) * (sz + 1)); - MEMCPY((*res)[ntoks], p, sz); + *res = realloc(*res, sizeof(wchar_t *) * (ntoks + 1)); + (*res)[ntoks] = malloc(sizeof(wchar_t) * (sz + 1)); + wmemcpy((*res)[ntoks], p, sz); /* Handle \ escapes */ for (r = (*res)[ntoks]; r < ((*res)[ntoks] + sz);) { if (!isbsl) { if (*r == '\\') { - MEMMOVE(r, r + 1, sz - (r - (*res)[ntoks])); + wmemmove(r, r + 1, sz - (r - (*res)[ntoks])); sz--; isbsl = 1; continue; @@ -106,7 +106,7 @@ WCHAR *r; if (qskip) q += qskip; - while (ISSPACE(*q)) + while (iswspace(*q)) q++; /* @@ -118,16 +118,16 @@ WCHAR *r; p = q; } - *res = realloc(*res, sizeof(WCHAR *) * (ntoks + 1)); + *res = realloc(*res, sizeof(wchar_t *) * (ntoks + 1)); (*res)[ntoks] = NULL; return ntoks; } void tokfree(vec) - WCHAR ***vec; + wchar_t ***vec; { -WCHAR **p; +wchar_t **p; for (p = (*vec); *p; p++) free(*p); free(*vec); diff --git a/str.h b/str.h index c7b88e6..c0823b0 100644 --- a/str.h +++ b/str.h @@ -15,7 +15,7 @@ #include "wide.h" -size_t tokenise(const WCHAR *, WCHAR ***result); -void tokfree(WCHAR ***); +size_t tokenise(const wchar_t *, wchar_t ***result); +void tokfree(wchar_t ***); #endif /* !TTS_STR_H */ diff --git a/style.c b/style.c index bca75a7..40ae1cc 100644 --- a/style.c +++ b/style.c @@ -22,34 +22,34 @@ style_t sy_header = { 1, 0 }, sy_date = { 6, 0 }; static attrname_t attrnames[] = { - { WIDE("normal"), WA_NORMAL }, - { WIDE("bold"), WA_BOLD }, - { WIDE("reverse"), WA_REVERSE }, - { WIDE("blink"), WA_BLINK }, - { WIDE("dim"), WA_DIM }, - { WIDE("underline"), WA_UNDERLINE }, - { WIDE("standout"), WA_STANDOUT } + { L"normal", WA_NORMAL }, + { L"bold", WA_BOLD }, + { L"reverse", WA_REVERSE }, + { L"blink", WA_BLINK }, + { L"dim", WA_DIM }, + { L"underline", WA_UNDERLINE }, + { L"standout", WA_STANDOUT } }; static colour_t colours[] = { - { WIDE("black"), COLOR_BLACK }, - { WIDE("red"), COLOR_RED }, - { WIDE("green"), COLOR_GREEN }, - { WIDE("yellow"), COLOR_YELLOW }, - { WIDE("blue"), COLOR_BLUE }, - { WIDE("magenta"), COLOR_MAGENTA }, - { WIDE("cyan"), COLOR_CYAN }, - { WIDE("white"), COLOR_WHITE } + { L"black", COLOR_BLACK }, + { L"red", COLOR_RED }, + { L"green", COLOR_GREEN }, + { L"yellow", COLOR_YELLOW }, + { L"blue", COLOR_BLUE }, + { L"magenta", COLOR_MAGENTA }, + { L"cyan", COLOR_CYAN }, + { L"white", COLOR_WHITE } }; int attr_find(name, result) - const WCHAR *name; + const wchar_t *name; attr_t *result; { size_t i; for (i = 0; i < sizeof(attrnames) / sizeof(*attrnames); i++) { - if (STRCMP(attrnames[i].an_name, name) == 0) { + if (wcscmp(attrnames[i].an_name, name) == 0) { *result = attrnames[i].an_value; return 0; } @@ -60,12 +60,12 @@ size_t i; int colour_find(name, result) - const WCHAR *name; + const wchar_t *name; short *result; { size_t i; for (i = 0; i < sizeof(colours) / sizeof(*colours); i++) { - if (STRCMP(colours[i].co_name, name) == 0) { + if (wcscmp(colours[i].co_name, name) == 0) { *result = colours[i].co_value; return 0; } @@ -85,7 +85,7 @@ style_clear(sy) int style_set(sy, fg, bg) style_t *sy; - const WCHAR *fg, *bg; + const wchar_t *fg, *bg; { sy->sy_attrs = WA_NORMAL; init_pair(sy->sy_pair, default_fg, default_bg); @@ -95,7 +95,7 @@ style_set(sy, fg, bg) int style_add(sy, fg, bg) style_t *sy; - const WCHAR *fg, *bg; + const wchar_t *fg, *bg; { attr_t at; short colfg, colbg = default_bg; @@ -119,10 +119,28 @@ apply_styles() { wbkgd(statwin, style_bg(sy_status)); wattr_on(statwin, style_fg(sy_status), NULL); - drawstatus(WIDE("")); + drawstatus(L""); wbkgd(titwin, style_bg(sy_header)); wattr_on(titwin, style_fg(sy_header), NULL); drawheader(); } +void +style_defaults(void) +{ + init_pair(1, default_fg, default_bg); + init_pair(2, default_fg, default_bg); + init_pair(3, default_fg, default_bg); + init_pair(4, default_fg, default_bg); + init_pair(5, default_fg, default_bg); + init_pair(6, default_fg, default_bg); + + style_set(&sy_header, L"reverse", NULL); + style_set(&sy_status, L"normal", NULL); + style_set(&sy_entry, L"normal", NULL); + style_set(&sy_selected, L"normal", NULL); + style_set(&sy_running, L"bold", NULL); + style_set(&sy_date, L"underline", NULL); + apply_styles(); +} diff --git a/style.h b/style.h index 7bc0879..2954895 100644 --- a/style.h +++ b/style.h @@ -20,15 +20,15 @@ typedef struct style { } style_t; #define style_fg(s) (COLOR_PAIR((s).sy_pair) | (s).sy_attrs) -#define style_bg(s) ((INT) ' ' | COLOR_PAIR((s).sy_pair) | ((s).sy_attrs & ~WA_UNDERLINE)) +#define style_bg(s) ((wint_t) ' ' | COLOR_PAIR((s).sy_pair) | ((s).sy_attrs & ~WA_UNDERLINE)) typedef struct attrname { - const WCHAR *an_name; + const wchar_t *an_name; attr_t an_value; } attrname_t; typedef struct colour { - const WCHAR *co_name; + const wchar_t *co_name; short co_value; } colour_t; @@ -41,13 +41,14 @@ extern style_t sy_header, extern short default_fg, default_bg; -int attr_find(const WCHAR *name, attr_t *result); -int colour_find(const WCHAR *name, short *result); +int attr_find (const wchar_t *name, attr_t *result); +int colour_find (const wchar_t *name, short *result); -void style_clear(style_t *); -int style_set(style_t *, const WCHAR *fg, const WCHAR *bg); -int style_add(style_t *, const WCHAR *fg, const WCHAR *bg); +void style_clear (style_t *); +int style_set (style_t *, const wchar_t *fg, const wchar_t *bg); +int style_add (style_t *, const wchar_t *fg, const wchar_t *bg); -void apply_styles(void); +void style_defaults (void); +void apply_styles (void); #endif /* !TTS_STYLE_H */ diff --git a/tts.c b/tts.c index af44462..c55c103 100644 --- a/tts.c +++ b/tts.c @@ -82,7 +82,7 @@ entry_t *curent; int showinv = 0; -static WCHAR *macro_text, *macro_pos; +static wchar_t *macro_text, *macro_pos; time_t itime = 0; @@ -91,15 +91,15 @@ int delete_advance = 1; int mark_advance = 1; int bill_advance = 0; int bill_increment = 0; -WCHAR *auto_nonbillable; +wchar_t *auto_nonbillable; variable_t variables[] = { - { WIDE("delete_advance"), VTYPE_BOOL, &delete_advance }, - { WIDE("mark_advance"), VTYPE_BOOL, &mark_advance }, - { WIDE("billable_advance"), VTYPE_BOOL, &bill_advance }, - { WIDE("show_billable"), VTYPE_BOOL, &show_billable }, - { WIDE("auto_non_billable"), VTYPE_STRING, &auto_nonbillable }, - { WIDE("bill_increment"), VTYPE_INT, &bill_increment }, + { L"delete_advance", VTYPE_BOOL, &delete_advance }, + { L"mark_advance", VTYPE_BOOL, &mark_advance }, + { L"billable_advance", VTYPE_BOOL, &bill_advance }, + { L"show_billable", VTYPE_BOOL, &show_billable }, + { L"auto_non_billable", VTYPE_STRING, &auto_nonbillable }, + { L"bill_increment", VTYPE_INT, &bill_increment }, { } }; @@ -242,88 +242,15 @@ struct kevent evs[2], rev; snprintf(statfile, sizeof(statfile), "%s/%s", pw->pw_dir, STATFILE); snprintf(rcfile, sizeof(rcfile), "%s/%s", pw->pw_dir, RCFILE); - initscr(); - in_curses = 1; - start_color(); -#ifdef HAVE_USE_DEFAULT_COLORS - use_default_colors(); -#endif - cbreak(); - noecho(); - nonl(); - nodelay(stdscr, TRUE); - - pair_content(0, &default_fg, &default_bg); - - refresh(); - - intrflush(stdscr, TRUE); - keypad(stdscr, TRUE); - leaveok(stdscr, TRUE); - - titwin = newwin(1, 0, 0, 0); - intrflush(titwin, FALSE); - keypad(titwin, TRUE); - leaveok(titwin, TRUE); - - statwin = newwin(1, 0, LINES - 1, 0); - intrflush(statwin, FALSE); - keypad(statwin, TRUE); - leaveok(statwin, TRUE); - - listwin = newwin(LINES - 2, 0, 1, 0); - intrflush(listwin, FALSE); - keypad(listwin, TRUE); - leaveok(listwin, TRUE); - - init_pair(1, default_fg, default_bg); - init_pair(2, default_fg, default_bg); - init_pair(3, default_fg, default_bg); - init_pair(4, default_fg, default_bg); - init_pair(5, default_fg, default_bg); - init_pair(6, default_fg, default_bg); - - style_set(&sy_header, WIDE("reverse"), NULL); - style_set(&sy_status, WIDE("normal"), NULL); - style_set(&sy_entry, WIDE("normal"), NULL); - style_set(&sy_selected, WIDE("normal"), NULL); - style_set(&sy_running, WIDE("bold"), NULL); - style_set(&sy_date, WIDE("underline"), NULL); - apply_styles(); + ui_init(); + style_defaults(); if (load_file(rcfile) == -1) { endwin(); return 1; } - curs_set(0); - - bind_key(WIDE("?"), WIDE("help"), 0); - bind_key(WIDE("a"), WIDE("add"), 0); - bind_key(WIDE("A"), WIDE("add-old"), 0); - bind_key(WIDE("d"), WIDE("delete"), 0); - bind_key(WIDE("u"), WIDE("undelete"), 0); - bind_key(WIDE("q"), WIDE("quit"), 0); - bind_key(WIDE(""), WIDE("quit"), 0); - bind_key(WIDE("i"), WIDE("invoice"), 0); - bind_key(WIDE("b"), WIDE("billable"), 0); - bind_key(WIDE("m"), WIDE("mark"), 0); - bind_key(WIDE("U"), WIDE("unmarkall"), 0); - bind_key(WIDE(""), WIDE("startstop"), 0); - bind_key(WIDE("e"), WIDE("edit-desc"), 0); - bind_key(WIDE("\\"), WIDE("edit-time"), 0); - bind_key(WIDE(""), WIDE("showhide-inv"), 0); - bind_key(WIDE("c"), WIDE("copy"), 0); - bind_key(WIDE("+"), WIDE("add-time"), 0); - bind_key(WIDE("-"), WIDE("sub-time"), 0); - bind_key(WIDE("/"), WIDE("search"), 0); - bind_key(WIDE("$"), WIDE("sync"), 0); - bind_key(WIDE(""), WIDE("prev"), 0); - bind_key(WIDE(""), WIDE("next"), 0); - bind_key(WIDE(":"), WIDE("execute"), 0); - bind_key(WIDE("M"), WIDE("merge"), 0); - bind_key(WIDE("r"), WIDE("interrupt"), 0); - bind_key(WIDE("R"), WIDE("interrupt"), 0); + bind_defaults(); /* * Make sure we can save (even if it's an empty file or nothing has @@ -333,7 +260,7 @@ struct kevent evs[2], rev; save(); drawheader(); - drawstatus(WIDE("")); + drawstatus(L""); if (!TTS_TAILQ_EMPTY(&entries)) { curent = TTS_TAILQ_FIRST(&entries); @@ -343,7 +270,7 @@ struct kevent evs[2], rev; } for (;;) { - INT c; + wint_t c; binding_t *bi; #ifdef USE_DARWIN_POWER struct timespec timeout; @@ -399,7 +326,7 @@ struct kevent evs[2], rev; continue; #endif - drawstatus(WIDE("")); + drawstatus(L""); TTS_TAILQ_FOREACH(bi, &bindings, bi_entries) { if (bi->bi_code != c) @@ -413,7 +340,7 @@ struct kevent evs[2], rev; goto next; } - drawstatus(WIDE("Unknown command.")); + drawstatus(L"Unknown command."); next: ; } @@ -421,7 +348,7 @@ struct kevent evs[2], rev; break; if (time(NULL) - laststatus >= 2) - drawstatus(WIDE("")); + drawstatus(L""); if (time(NULL) - lastsave > 60) save(); @@ -437,7 +364,7 @@ load() { FILE *f; char input[4096]; -WCHAR line[4096]; +wchar_t line[4096]; entry_t *en; TTS_TAILQ_FOREACH(en, &entries, en_entries) @@ -447,40 +374,40 @@ entry_t *en; if (errno == ENOENT) return 0; - errbox(WIDE("Can't read %s: %s"), statfile, strerror(errno)); + errbox(L"Can't read %s: %s", statfile, strerror(errno)); exit(1); } if (fgets(input, sizeof(input), f) == NULL) { - errbox(WIDE("Can't read %s: %s"), statfile, strerror(errno)); + errbox(L"Can't read %s: %s", statfile, strerror(errno)); fclose(f); exit(1); } - MBSTOWCS(line, input, WSIZEOF(line)); + mbstowcs(line, input, wsizeof(line)); - if (STRCMP(line, WIDE("#%RT/TTS V1\n"))) { - errbox(WIDE("Can't read %s: invalid magic signature"), statfile); + if (wcscmp(line, L"#%RT/TTS V1\n")) { + errbox(L"Can't read %s: invalid magic signature", statfile); fclose(f); exit(1); } while (fgets(input, sizeof(input), f)) { unsigned long cre, secs; - WCHAR flags[10], desc[4096], *p; + wchar_t flags[10], desc[4096], *p; entry_t *en; int i; - MBSTOWCS(line, input, WSIZEOF(line)); + mbstowcs(line, input, wsizeof(line)); - if (SSCANF(line, WIDE("#%%showinv %d\n"), &i) == 1) { + if (swscanf(line, L"#%%showinv %d\n", &i) == 1) { showinv = i ? 1 : 0; continue; } - if (SSCANF(line, WIDE("%lu %lu %9"FMT_L"[in-] %4095"FMT_L"[^\n]\n"), + if (swscanf(line, L"%lu %lu %9l[in-] %4095l[^\n]\n", &cre, &secs, flags, desc) != 4) { - errbox(WIDE("Can't read %s: invalid entry format"), statfile); + errbox(L"Can't read %s: invalid entry format", statfile); fclose(f); exit(1); } @@ -502,7 +429,7 @@ entry_t *en; break; default: - errbox(WIDE("Can't read %s: invalid flag"), statfile); + errbox(L"Can't read %s: invalid flag", statfile); fclose(f); exit(1); } @@ -510,7 +437,7 @@ entry_t *en; } if (ferror(f)) { - errbox(WIDE("Can't read %s: %s"), statfile, strerror(errno)); + errbox(L"Can't read %s: %s", statfile, strerror(errno)); fclose(f); exit(1); } @@ -530,31 +457,31 @@ entry_t *en; snprintf(p, sizeof(p), "%s_", statfile); if ((fd = open(p, O_WRONLY | O_CREAT, 0600)) == -1) { - errbox(WIDE("%s_: %s"), statfile, strerror(errno)); + errbox(L"%s_: %s", statfile, strerror(errno)); endwin(); exit(1); } if ((f = fdopen(fd, "w")) == NULL) { - errbox(WIDE("%s: %s"), p, strerror(errno)); + errbox(L"%s: %s", p, strerror(errno)); endwin(); exit(1); } - if (FPRINTF(f, WIDE("#%%RT/TTS V1\n")) == -1) { + if (fwprintf(f, L"#%%RT/TTS V1\n") == -1) { fclose(f); unlink(p); - errbox(WIDE("%s: write error (header): %s"), p, strerror(errno)); + errbox(L"%s: write error (header): %s", p, strerror(errno)); endwin(); exit(1); } - if (FPRINTF(f, WIDE("#%%showinv %d\n"), showinv) == -1) { + if (fwprintf(f, L"#%%showinv %d\n", showinv) == -1) { fclose(f); unlink(p); - errbox(WIDE("%s: write error (showinv): %s"), p, strerror(errno)); + errbox(L"%s: write error (showinv): %s", p, strerror(errno)); endwin(); exit(1); } @@ -563,7 +490,7 @@ entry_t *en; char flags[10], *fp = flags, wdesc[4096] = {}; time_t n; - WCSTOMBS(wdesc, en->en_desc, sizeof(wdesc)); + wcstombs(wdesc, en->en_desc, sizeof(wdesc)); memset(flags, 0, sizeof(flags)); if (en->en_flags.efl_invoiced) @@ -575,11 +502,11 @@ entry_t *en; if (en->en_started) n += time(NULL) - en->en_started; - if (FPRINTF(f, WIDE("%lu %lu %s %s\n"), + if (fwprintf(f, L"%lu %lu %s %s\n", (unsigned long) en->en_created, (unsigned long) n, *flags ? flags : "-", wdesc) == -1) { - errbox(WIDE("%s: write error (entry): %s"), p, strerror(errno)); + errbox(L"%s: write error (entry): %s", p, strerror(errno)); fclose(f); unlink(p); endwin(); @@ -589,14 +516,14 @@ entry_t *en; if (fclose(f) == EOF) { unlink(p); - errbox(WIDE("%s: write error (closing): %s"), p, strerror(errno)); + errbox(L"%s: write error (closing): %s", p, strerror(errno)); endwin(); exit(1); } if (rename(p, statfile) == -1) { unlink(p); - errbox(WIDE("%s: rename: %s"), statfile, strerror(errno)); + errbox(L"%s: rename: %s", statfile, strerror(errno)); endwin(); exit(1); } @@ -618,7 +545,7 @@ history_t *hi; void hist_add(hi, text) history_t *hi; - const WCHAR *text; + const wchar_t *text; { histent_t *hent; @@ -628,7 +555,7 @@ histent_t *hent; if ((hent = calloc(1, sizeof(*hent))) == NULL) return; - if ((hent->he_text = STRDUP(text)) == NULL) { + if ((hent->he_text = wcsdup(text)) == NULL) { free(hent); return; } @@ -643,11 +570,11 @@ histent_t *hent; variable_t * find_variable(name) - WCHAR const *name; + wchar_t const *name; { variable_t *v; for (v = variables; v->va_name; v++) - if (STRCMP(name, v->va_name) == 0) + if (wcscmp(name, v->va_name) == 0) return v; return NULL; } @@ -656,7 +583,7 @@ static char *curfile; static int lineno, nerr; void -cmderr(const WCHAR *msg, ...) +cmderr(const wchar_t *msg, ...) { va_list ap; @@ -667,16 +594,16 @@ va_list ap; void vcmderr(msg, ap) - const WCHAR *msg; + const wchar_t *msg; va_list ap; { nerr++; if (curfile) { - WCHAR s[1024]; + wchar_t s[1024]; char t[1024]; - VSNPRINTF(s, WSIZEOF(t), msg, ap); - WCSTOMBS(t, s, sizeof(t)); + vswprintf(s, wsizeof(t), msg, ap); + wcstombs(t, s, sizeof(t)); if (in_curses) { endwin(); @@ -718,13 +645,13 @@ char input[1024]; while (fgets(input, sizeof(input), s)) { size_t nargs; - WCHAR **args; + wchar_t **args; command_t *cmds; - WCHAR line[1024]; + wchar_t line[1024]; ++lineno; - MBSTOWCS(line, input, WSIZEOF(line)); + mbstowcs(line, input, wsizeof(line)); if (line[0] == '#') continue; @@ -736,7 +663,7 @@ char input[1024]; } if ((cmds = find_command(args[0])) == NULL) { - cmderr(WIDE("Unknown command \"%"FMT_L"s\"."), args[0]); + cmderr(L"Unknown command \"%ls\".", args[0]); nerr++; tokfree(&args); continue; @@ -766,7 +693,7 @@ prompt_sleep(sleeptime) * subtract the time spent sleeping, in case they forgot to turn off * the timer. */ -WCHAR pr[128]; +wchar_t pr[128]; int h, m, s = 0; /* Only prompt if an entry is running */ @@ -781,8 +708,8 @@ int h, m, s = 0; m = s / 60; s %= 60; - SNPRINTF(pr, WSIZEOF(pr), - WIDE("Remove %02d:%02d:%02d time asleep from running entry?"), + swprintf(pr, wsizeof(pr), + L"Remove %02d:%02d:%02d time asleep from running entry?", h, m, s); if (!yesno(pr)) @@ -798,7 +725,7 @@ int h, m, s = 0; void input_macro(s) - WCHAR *s; + wchar_t *s; { free(macro_text); macro_text = macro_pos = NULL; @@ -806,12 +733,12 @@ input_macro(s) if (!s) return; - macro_text = macro_pos = STRDUP(s); + macro_text = macro_pos = wcsdup(s); } int input_char(c) - WCHAR *c; + wchar_t *c; { if (macro_pos) { if (*macro_pos) { @@ -822,5 +749,5 @@ input_char(c) macro_text = macro_pos = NULL; } - return GETCH(c); + return get_wch(c); } diff --git a/tts.h b/tts.h index b1e779e..9e30d88 100644 --- a/tts.h +++ b/tts.h @@ -29,7 +29,7 @@ extern int delete_advance; extern int mark_advance; extern int bill_advance; extern int bill_increment; -extern WCHAR *auto_nonbillable; +extern wchar_t *auto_nonbillable; /* * Global state. @@ -49,7 +49,7 @@ int save(void); #define NHIST 50 typedef struct histent { - WCHAR *he_text; + wchar_t *he_text; TTS_TAILQ_ENTRY(histent) he_entries; } histent_t; typedef TTS_TAILQ_HEAD(hentlist, histent) hentlist_t; @@ -60,7 +60,7 @@ typedef struct history { } history_t; history_t *hist_new(void); -void hist_add(history_t *, WCHAR const *); +void hist_add(history_t *, wchar_t const *); extern history_t *searchhist; extern history_t *prompthist; diff --git a/ui.c b/ui.c index 1ea29fe..0b47d62 100644 --- a/ui.c +++ b/ui.c @@ -18,6 +18,46 @@ WINDOW *titwin, *statwin, *listwin; int in_curses; +void +ui_init(void) +{ + initscr(); + in_curses = 1; + start_color(); +#ifdef HAVE_USE_DEFAULT_COLORS + use_default_colors(); +#endif + cbreak(); + noecho(); + nonl(); + nodelay(stdscr, TRUE); + + pair_content(0, &default_fg, &default_bg); + + refresh(); + + intrflush(stdscr, TRUE); + keypad(stdscr, TRUE); + leaveok(stdscr, TRUE); + + titwin = newwin(1, 0, 0, 0); + intrflush(titwin, FALSE); + keypad(titwin, TRUE); + leaveok(titwin, TRUE); + + statwin = newwin(1, 0, LINES - 1, 0); + intrflush(statwin, FALSE); + keypad(statwin, TRUE); + leaveok(statwin, TRUE); + + listwin = newwin(LINES - 2, 0, 1, 0); + intrflush(listwin, FALSE); + keypad(listwin, TRUE); + leaveok(listwin, TRUE); + + curs_set(0); +} + /* * Move the cursor to the next entry after an operation like mark or deleted. * If there are no suitable entries after this one, move it backwards instead. @@ -70,24 +110,24 @@ entry_t *en; void drawheader() { -WCHAR title[64]; +wchar_t title[64]; - SNPRINTF(title, WSIZEOF(title), WIDE("TTS %s - Type '?' for help"), + swprintf(title, wsizeof(title), L"TTS %s - Type '?' for help", tts_version); wmove(titwin, 0, 0); - WADDSTR(titwin, title); + waddwstr(titwin, title); if (itime > 0) { - WCHAR str[128]; + wchar_t str[128]; int h, m, s; time_t passed = time(NULL) - itime; time_to_hms(passed, h, m, s); - SNPRINTF(str, WSIZEOF(str), WIDE(" *** MARK INTERRUPT: %02d:%02d:%02d ***"), + swprintf(str, wsizeof(str), L" *** MARK INTERRUPT: %02d:%02d:%02d ***", h, m, s); wattron(titwin, A_BOLD); - WADDSTR(titwin, str); + waddwstr(titwin, str); wattroff(titwin, A_BOLD); } wclrtoeol(titwin); @@ -96,21 +136,21 @@ WCHAR title[64]; void vdrawstatus(msg, ap) - const WCHAR *msg; + const wchar_t *msg; va_list ap; { -WCHAR s[1024]; - VSNPRINTF(s, WSIZEOF(s), msg, ap); +wchar_t s[1024]; + vswprintf(s, wsizeof(s), msg, ap); wmove(statwin, 0, 0); - WADDSTR(statwin, s); + waddwstr(statwin, s); wclrtoeol(statwin); wrefresh(statwin); time(&laststatus); } void -drawstatus(const WCHAR *msg, ...) +drawstatus(const wchar_t *msg, ...) { va_list ap; va_start(ap, msg); @@ -120,10 +160,10 @@ va_list ap; int yesno(msg) - const WCHAR *msg; + const wchar_t *msg; { WINDOW *pwin; -INT c; +wint_t c; pwin = newwin(1, COLS, LINES - 1, 0); keypad(pwin, TRUE); @@ -133,8 +173,8 @@ INT c; wbkgd(pwin, style_bg(sy_status)); wmove(pwin, 0, 0); - WADDSTR(pwin, msg); - WADDSTR(pwin, WIDE(" [y/N]? ")); + waddwstr(pwin, msg); + waddwstr(pwin, L" [y/N]? "); wattroff(pwin, A_BOLD); while (input_char(&c) == ERR @@ -151,13 +191,13 @@ INT c; return (c == 'Y' || c == 'y') ? 1 : 0; } -WCHAR * +wchar_t * prompt(msg, def, hist) - const WCHAR *msg, *def; + const wchar_t *msg, *def; history_t *hist; { WINDOW *pwin; -WCHAR input[256]; +wchar_t input[256]; size_t pos = 0; histent_t *histpos = NULL; @@ -166,8 +206,8 @@ histent_t *histpos = NULL; memset(input, 0, sizeof(input)); if (def) { - STRNCPY(input, def, WSIZEOF(input) - 1); - pos = STRLEN(input); + wcsncpy(input, def, wsizeof(input) - 1); + pos = wcslen(input); } pwin = newwin(1, COLS, LINES - 1, 0); @@ -178,17 +218,17 @@ histent_t *histpos = NULL; wattron(pwin, A_BOLD); wmove(pwin, 0, 0); - WADDSTR(pwin, msg); + waddwstr(pwin, msg); wattroff(pwin, A_BOLD); curs_set(1); for (;;) { - INT c; - wmove(pwin, 0, STRLEN(msg) + 1); - WADDSTR(pwin, input); + wint_t c; + wmove(pwin, 0, wcslen(msg) + 1); + waddwstr(pwin, input); wclrtoeol(pwin); - wmove(pwin, 0, STRLEN(msg) + 1 + pos); + wmove(pwin, 0, wcslen(msg) + 1 + pos); wrefresh(pwin); if (input_char(&c) == ERR) @@ -203,21 +243,21 @@ histent_t *histpos = NULL; case 0x7F: case 0x08: if (pos) { - if (pos == STRLEN(input)) + if (pos == wcslen(input)) input[--pos] = 0; else { - int i = STRLEN(input); + int i = wcslen(input); pos--; - MEMCPY(input + pos, input + pos + 1, STRLEN(input) - pos); + wmemcpy(input + pos, input + pos + 1, wcslen(input) - pos); input[i] = 0; } } break; case KEY_DC: - if (pos < STRLEN(input)) { - int i = STRLEN(input); - MEMCPY(input + pos, input + pos + 1, STRLEN(input) - pos); + if (pos < wcslen(input)) { + int i = wcslen(input); + wmemcpy(input + pos, input + pos + 1, wcslen(input) - pos); input[i] = 0; } break; @@ -228,7 +268,7 @@ histent_t *histpos = NULL; break; case KEY_RIGHT: - if (pos < STRLEN(input)) + if (pos < wcslen(input)) pos++; break; @@ -239,7 +279,7 @@ histent_t *histpos = NULL; case KEY_END: case 0x05: /* ^E */ - pos = STRLEN(input); + pos = wcslen(input); break; case 0x07: /* ^G */ @@ -273,8 +313,8 @@ histent_t *histpos = NULL; } - STRNCPY(input, histpos->he_text, WSIZEOF(input) - 1); - pos = STRLEN(input); + wcsncpy(input, histpos->he_text, wsizeof(input) - 1); + pos = wcslen(input); break; case KEY_DOWN: @@ -290,13 +330,13 @@ histent_t *histpos = NULL; histpos = TTS_TAILQ_NEXT(histpos, he_entries); - STRNCPY(input, histpos->he_text, WSIZEOF(input) - 1); - pos = STRLEN(input); + wcsncpy(input, histpos->he_text, wsizeof(input) - 1); + pos = wcslen(input); break; default: - if (pos != STRLEN(input)) { - MEMMOVE(input + pos + 1, input + pos, STRLEN(input) - pos); + if (pos != wcslen(input)) { + wmemmove(input + pos + 1, input + pos, wcslen(input) - pos); input[pos++] = c; } else { input[pos++] = c; @@ -313,11 +353,11 @@ end: ; wtouchln(statwin, 0, 1, 1); wrefresh(statwin); hist_add(hist, input); - return STRDUP(input); + return wcsdup(input); } void -errbox(const WCHAR *msg, ...) +errbox(const wchar_t *msg, ...) { va_list ap; va_start(ap, msg); @@ -327,19 +367,19 @@ va_list ap; void verrbox(msg, ap) - const WCHAR *msg; + const wchar_t *msg; va_list ap; { -WCHAR text[4096]; +wchar_t text[4096]; WINDOW *ewin; -#define ETITLE WIDE(" Error ") -#define ECONT WIDE(" ") +#define ETITLE L" Error " +#define ECONT L" " int width; -INT c; +wint_t c; - VSNPRINTF(text, WSIZEOF(text), msg, ap); - width = STRLEN(text); + vswprintf(text, wsizeof(text), msg, ap); + width = wcslen(text); ewin = newwin(6, width + 4, (LINES / 2) - ((1 + 2)/ 2), @@ -348,19 +388,19 @@ INT c; wborder(ewin, 0, 0, 0, 0, 0, 0, 0, 0); wattron(ewin, A_REVERSE | A_BOLD); - wmove(ewin, 0, (width / 2) - (WSIZEOF(ETITLE) - 1)/2); - WADDSTR(ewin, ETITLE); + wmove(ewin, 0, (width / 2) - (wsizeof(ETITLE) - 1)/2); + waddwstr(ewin, ETITLE); wattroff(ewin, A_REVERSE | A_BOLD); wmove(ewin, 2, 2); - WADDSTR(ewin, text); + waddwstr(ewin, text); wattron(ewin, A_REVERSE | A_BOLD); - wmove(ewin, 4, (width / 2) - ((WSIZEOF(ECONT) - 1) / 2)); - WADDSTR(ewin, ECONT); + wmove(ewin, 4, (width / 2) - ((wsizeof(ECONT) - 1) / 2)); + waddwstr(ewin, ECONT); wattroff(ewin, A_REVERSE | A_BOLD); for (;;) { - if (WGETCH(ewin, &c) == ERR) + if (wget_wch(ewin, &c) == ERR) continue; if (c == '\r') break; @@ -391,7 +431,7 @@ chtype oldbg; for (; en; en = TTS_TAILQ_NEXT(en, en_entries)) { time_t n; int h, s, m; - WCHAR flags[10], stime[16], *p; + wchar_t flags[10], stime[16], *p; attr_t attrs = WA_NORMAL; if (!showinv && en->en_flags.efl_invoiced) @@ -401,7 +441,7 @@ chtype oldbg; if (lastday != entry_day(en)) { struct tm *lt; - WCHAR lbl[128]; + wchar_t lbl[128]; time_t itime = entry_time_for_day(entry_day(en), 1, 0), ntime = entry_time_for_day(entry_day(en), 0, 0), btime = entry_time_for_day(entry_day(en), 2, bill_increment); @@ -409,7 +449,7 @@ chtype oldbg; hn, mn, sn, hb, mb, sb, ht, mt, st; - WCHAR hdrtext[256]; + wchar_t hdrtext[256]; time_to_hms(itime, hi, mi, si); time_to_hms(ntime, hn, mn, sn); @@ -432,24 +472,24 @@ chtype oldbg; lastday = entry_day(en); lt = localtime(&lastday); - STRFTIME(lbl, WSIZEOF(lbl), WIDE("%A, %d %B %Y"), lt); + wcsftime(lbl, wsizeof(lbl), L"%A, %d %B %Y", lt); if (show_billable) - SNPRINTF(hdrtext, WSIZEOF(hdrtext), - WIDE("%-30"FMT_L"s [I:%02d:%02d:%02d / " - "N:%02d:%02d:%02d / T:%02d:%02d:%02d / " - "B:%02d:%02d:%02d]"), - lbl, hi, mi, si, hn, mn, sn, ht, mt, st, - hb, mb, sb); + swprintf(hdrtext, wsizeof(hdrtext), + L"%-30ls [I:%02d:%02d:%02d / " + L"N:%02d:%02d:%02d / T:%02d:%02d:%02d / " + L"B:%02d:%02d:%02d]", + lbl, hi, mi, si, hn, mn, sn, ht, mt, st, + hb, mb, sb); else - SNPRINTF(hdrtext, WSIZEOF(hdrtext), - WIDE("%-30"FMT_L"s [I:%02d:%02d:%02d / " - "N:%02d:%02d:%02d / T:%02d:%02d:%02d]"), - lbl, hi, mi, si, hn, mn, sn, ht, mt, st); + swprintf(hdrtext, wsizeof(hdrtext), + L"%-30ls [I:%02d:%02d:%02d / " + L"N:%02d:%02d:%02d / T:%02d:%02d:%02d]", + lbl, hi, mi, si, hn, mn, sn, ht, mt, st); wattr_on(listwin, style_fg(sy_date), NULL); wbkgdset(listwin, style_bg(sy_date)); wmove(listwin, cline, 0); - WADDSTR(listwin, hdrtext); + waddwstr(listwin, hdrtext); wclrtoeol(listwin); wattr_off(listwin, style_fg(sy_date), NULL); wbkgdset(listwin, oldbg); @@ -494,9 +534,9 @@ chtype oldbg; wattr_on(listwin, attrs, NULL); if (en == curent) { - WADDSTR(listwin, WIDE(" -> ")); + waddwstr(listwin, L" -> "); } else - WADDSTR(listwin, WIDE(" ")); + waddwstr(listwin, L" "); n = en->en_secs; if (en->en_started) @@ -507,9 +547,9 @@ chtype oldbg; n %= 60; s = n; - SNPRINTF(stime, WSIZEOF(stime), WIDE("%02d:%02d:%02d%c "), + swprintf(stime, wsizeof(stime), L"%02d:%02d:%02d%c ", h, m, s, (itime && (en == running)) ? '*' : ' '); - WADDSTR(listwin, stime); + waddwstr(listwin, stime); memset(flags, 0, sizeof(flags)); p = flags; @@ -535,13 +575,13 @@ chtype oldbg; *p++ = ' '; if (*flags) { - WCHAR s[10]; - SNPRINTF(s, WSIZEOF(s), WIDE("%-5"FMT_L"s "), flags); - WADDSTR(listwin, s); + wchar_t s[10]; + swprintf(s, wsizeof(s), L"%-5ls ", flags); + waddwstr(listwin, s); } else - WADDSTR(listwin, WIDE(" ")); + waddwstr(listwin, L" "); - WADDSTR(listwin, en->en_desc); + waddwstr(listwin, en->en_desc); wclrtoeol(listwin); wbkgdset(listwin, oldbg); wattr_off(listwin, attrs, NULL); @@ -563,27 +603,27 @@ chtype oldbg; int prduration(pr, hh, mm, ss) - WCHAR *pr; + wchar_t *pr; int *hh, *mm, *ss; { -WCHAR *tstr; +wchar_t *tstr; int h, m, s; - if ((tstr = prompt(pr, WIDE("00:00:00"), NULL)) == NULL) + if ((tstr = prompt(pr, L"00:00:00", NULL)) == NULL) return -1; if (!*tstr) { - drawstatus(WIDE("No duration entered")); + drawstatus(L"No duration entered"); free(tstr); return -1; } - if (SSCANF(tstr, WIDE("%d:%d:%d"), &h, &m, &s) != 3) { + if (swscanf(tstr, L"%d:%d:%d", &h, &m, &s) != 3) { h = 0; - if (SSCANF(tstr, WIDE("%d:%d"), &m, &s) != 2) { + if (swscanf(tstr, L"%d:%d", &m, &s) != 2) { m = 0; - if (SSCANF(tstr, WIDE("%d"), &s) != 1) { + if (swscanf(tstr, L"%d", &s) != 1) { free(tstr); - drawstatus(WIDE("Invalid time format.")); + drawstatus(L"Invalid time format."); return -1; } } @@ -592,12 +632,12 @@ int h, m, s; free(tstr); if (m >= 60) { - drawstatus(WIDE("Minutes cannot be more than 59.")); + drawstatus(L"Minutes cannot be more than 59."); return -1; } if (s >= 60) { - drawstatus(WIDE("Seconds cannot be more than 59.")); + drawstatus(L"Seconds cannot be more than 59."); return -1; } diff --git a/ui.h b/ui.h index 005ac7e..648bf35 100644 --- a/ui.h +++ b/ui.h @@ -21,17 +21,18 @@ extern WINDOW *titwin, *statwin, *listwin; extern int in_curses; extern int showinv; -void cursadvance(void); +void ui_init (void); -void drawstatus (const WCHAR *msg, ...); -void vdrawstatus (const WCHAR *msg, va_list); -void drawheader (void); -void drawentries (void); +void cursadvance (void); +void drawstatus (const wchar_t *msg, ...); +void vdrawstatus (const wchar_t *msg, va_list); +void drawheader (void); +void drawentries (void); -WCHAR *prompt (WCHAR const *, WCHAR const *, history_t *); -int prduration (WCHAR *prompt, int *h, int *m, int *s); -int yesno (WCHAR const *); -void errbox (WCHAR const *, ...); -void verrbox (WCHAR const *, va_list); +wchar_t *prompt (wchar_t const *, wchar_t const *, history_t *); +int prduration (wchar_t *prompt, int *h, int *m, int *s); +int yesno (wchar_t const *); +void errbox (wchar_t const *, ...); +void verrbox (wchar_t const *, va_list); #endif /* !TTS_UI_H */ diff --git a/variable.h b/variable.h index 8cb8447..691c9c1 100644 --- a/variable.h +++ b/variable.h @@ -14,7 +14,7 @@ #include "wide.h" typedef struct variable { - WCHAR const *va_name; + wchar_t const *va_name; int va_type; void *va_addr; } variable_t; @@ -23,6 +23,6 @@ typedef struct variable { #define VTYPE_BOOL 2 #define VTYPE_STRING 3 -variable_t *find_variable(const WCHAR *name); +variable_t *find_variable(const wchar_t *name); #endif /* !TTS_VARIABLE_H */ diff --git a/wide.h b/wide.h index 61ab2c8..129fb02 100644 --- a/wide.h +++ b/wide.h @@ -11,74 +11,14 @@ #ifndef TTS_WIDE_H #define TTS_WIDE_H +#include + #include "config.h" #include "tts_curses.h" -#ifdef HAVE_CURSES_ENHANCED -# include +#define wsizeof(s) (sizeof(s) / sizeof(wchar_t)) -# define WPFX(x) wcs##x -# define WIDE(x) L##x -# define ISX(x) isw##x -# define WCHAR wchar_t -# define FMT_L "l" -# define SNPRINTF swprintf -# define VSNPRINTF vswprintf -# define SSCANF swscanf -# define MEMCPY wmemcpy -# define MEMMOVE wmemmove -# define MBSTOWCS mbstowcs -# define WCSTOMBS wcstombs -# define FPRINTF fwprintf -# define STRTOK wcstok - -# define GETCH get_wch -# define WGETCH wget_wch -# define ADDSTR addwstr -# define WADDSTR waddwstr -# define INT wint_t -#else -# define WPFX(x) str##x -# define WIDE(x) x -# define ISX(x) is##x -# define WCHAR char -# define FMT_L -# define SNPRINTF snprintf -# define VSNPRINTF vsnprintf -# define SSCANF sscanf -# define MEMCPY memcpy -# define MEMMOVE memmove -# define MBSTOWCS strncpy -# define WCSTOMBS strncpy -# define FPRINTF fprintf -# define STRTOK strtok_r - -# define ADDSTR addstr -# define WADDSTR waddstr -# define INT int - -# define NEED_TTS_WGETCH -extern int tts_wgetch(WINDOW *, int *); - -# define WGETCH tts_wgetch -# define GETCH(c) tts_wgetch(stdscr,c) -#endif - -#define STRLEN WPFX(len) -#define STRCMP WPFX(cmp) -#define STRNCMP WPFX(ncmp) -#define STRCPY WPFX(cpy) -#define STRNCPY WPFX(ncpy) -#define STRSTR WPFX(str) -#define STRFTIME WPFX(ftime) -#define STRDUP WPFX(dup) -#define STRTOL WPFX(tol) - -#define ISSPACE ISX(space) - -#define WSIZEOF(s) (sizeof(s) / sizeof(WCHAR)) - -int input_char(WCHAR *); -void input_macro(WCHAR *); +int input_char(wchar_t *); +void input_macro(wchar_t *); #endif /* !TTS_WIDE_H */ From f25e283f21e1883ac0a438815f3f42c97862c30d Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Sat, 8 Mar 2014 00:50:11 +0000 Subject: [PATCH 21/51] Fix NetBSD and non-ncurses build. Simplify CPPFLAGS. --- Makefile.in | 4 +- aclocal.m4 | 10 +- config.guess | 1558 +++++++++++++++++++++++++++++++++++++++++++ config.sub | 1788 ++++++++++++++++++++++++++++++++++++++++++++++++++ configure | 165 ++++- configure.ac | 17 + str.c | 3 + style.c | 16 +- ui.c | 2 +- 9 files changed, 3513 insertions(+), 50 deletions(-) create mode 100755 config.guess create mode 100755 config.sub diff --git a/Makefile.in b/Makefile.in index d582022..f407378 100644 --- a/Makefile.in +++ b/Makefile.in @@ -12,9 +12,7 @@ VPATH = @top_srcdir@ CC = @CC@ MAKEDEPEND = @CC@ -M -# _GNU_SOURCE is required for wcsdup() on older version of glibc that don't -# implement XPG7. -CPPFLAGS = @CPPFLAGS@ -D_XOPEN_SOURCE=700 -D_XOPEN_SOURCE_EXTENDED -D__EXTENSIONS__ +CPPFLAGS = @CPPFLAGS@ -D_XOPEN_SOURCE=700 -D_XOPEN_SOURCE_EXTENDED CFLAGS = @CFLAGS@ -I@top_srcdir@ -I@top_builddir@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ diff --git a/aclocal.m4 b/aclocal.m4 index 33a37ac..83aca16 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -108,7 +108,7 @@ # HAVE_CURSES_ENHANCED and ax_cv_curses_enhanced are defined if the # library supports the X/Open Enhanced Curses definition. In particular, # the wide-character types attr_t, cchar_t and wint_t, the functions -# wattr_set() and wget_wch() and the macros WA_NORMAL and _XOPEN_CURSES +# wattr_set() and wget_wch() and the macros WA_BOLD and _XOPEN_CURSES # are checked. The Ncurses library does NOT conform to this definition, # although NcursesW does. # @@ -228,7 +228,7 @@ AC_DEFUN([AX_WITH_CURSES], [ chtype a = A_BOLD; int b = KEY_LEFT; chtype c = COLOR_PAIR(1) & A_COLOR; - attr_t d = WA_NORMAL; + attr_t d = WA_BOLD; cchar_t e; wint_t f; int g = getattrs(stdscr); @@ -259,7 +259,7 @@ AC_DEFUN([AX_WITH_CURSES], [ chtype a = A_BOLD; int b = KEY_LEFT; chtype c = COLOR_PAIR(1) & A_COLOR; - attr_t d = WA_NORMAL; + attr_t d = WA_BOLD; cchar_t e; wint_t f; int g = getattrs(stdscr); @@ -290,7 +290,7 @@ AC_DEFUN([AX_WITH_CURSES], [ chtype a = A_BOLD; int b = KEY_LEFT; chtype c = COLOR_PAIR(1) & A_COLOR; - attr_t d = WA_NORMAL; + attr_t d = WA_BOLD; cchar_t e; wint_t f; int g = getattrs(stdscr); @@ -443,7 +443,7 @@ AC_DEFUN([AX_WITH_CURSES], [ chtype a = A_BOLD; int b = KEY_LEFT; chtype c = COLOR_PAIR(1) & A_COLOR; - attr_t d = WA_NORMAL; + attr_t d = WA_BOLD; cchar_t e; wint_t f; initscr(); diff --git a/config.guess b/config.guess new file mode 100755 index 0000000..b79252d --- /dev/null +++ b/config.guess @@ -0,0 +1,1558 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2013 Free Software Foundation, Inc. + +timestamp='2013-06-10' + +# This file 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. +# +# 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 . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# +# Please send patches with a ChangeLog entry to config-patches@gnu.org. + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2013 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case "${UNAME_SYSTEM}" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval $set_cc_for_build + cat <<-EOF > $dummy.c + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="gnulibc1" ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + else + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; + or1k:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + or32:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-${LIBC} + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-${LIBC} + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-${LIBC} + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-${LIBC} + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval $set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + fi + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.sub b/config.sub new file mode 100755 index 0000000..8b612ab --- /dev/null +++ b/config.sub @@ -0,0 +1,1788 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2013 Free Software Foundation, Inc. + +timestamp='2013-04-24' + +# This file 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. +# +# 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 . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches with a ChangeLog entry to config-patches@gnu.org. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2013 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 \ + | or1k | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i386-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or1k-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/configure b/configure index ffcc0f5..51fc83a 100755 --- a/configure +++ b/configure @@ -638,6 +638,14 @@ CPPFLAGS LDFLAGS CFLAGS CC +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build target_alias host_alias build_alias @@ -1288,6 +1296,10 @@ Fine tuning of the installation directories: _ACEOF cat <<\_ACEOF + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi @@ -2101,6 +2113,122 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers config.h" +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + + +case $host_os in + darwin*) + CPPFLAGS="$CPPFLAGS -D_DARWIN_USE_64_BIT_INODE=1" + ;; + linux*) + CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64" + ;; + netbsd*) + CPPFLAGS="$CPPFLAGS -D_NETBSD_SOURCE" + ;; + solaris*) + CPPFLAGS="-D__EXTENSIONS__ -D_XOPEN_SOURCE=700 -D_FILE_OFFSET_BITS=64" + ;; +esac + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -2890,35 +3018,6 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu -ac_aux_dir= -for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do - if test -f "$ac_dir/install-sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f "$ac_dir/install.sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - elif test -f "$ac_dir/shtool"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/shtool install -c" - break - fi -done -if test -z "$ac_aux_dir"; then - as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 -fi - -# These three variables are undocumented and unsupported, -# and are intended to be withdrawn in a future Autoconf release. -# They can cause serious problems if a builder's source tree is in a directory -# whose full name contains unusual characters. -ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. -ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. -ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. - - # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: @@ -3120,7 +3219,7 @@ main () chtype a = A_BOLD; int b = KEY_LEFT; chtype c = COLOR_PAIR(1) & A_COLOR; - attr_t d = WA_NORMAL; + attr_t d = WA_BOLD; cchar_t e; wint_t f; int g = getattrs(stdscr); @@ -3184,7 +3283,7 @@ main () chtype a = A_BOLD; int b = KEY_LEFT; chtype c = COLOR_PAIR(1) & A_COLOR; - attr_t d = WA_NORMAL; + attr_t d = WA_BOLD; cchar_t e; wint_t f; int g = getattrs(stdscr); @@ -3248,7 +3347,7 @@ main () chtype a = A_BOLD; int b = KEY_LEFT; chtype c = COLOR_PAIR(1) & A_COLOR; - attr_t d = WA_NORMAL; + attr_t d = WA_BOLD; cchar_t e; wint_t f; int g = getattrs(stdscr); @@ -3612,7 +3711,7 @@ main () chtype a = A_BOLD; int b = KEY_LEFT; chtype c = COLOR_PAIR(1) & A_COLOR; - attr_t d = WA_NORMAL; + attr_t d = WA_BOLD; cchar_t e; wint_t f; initscr(); diff --git a/configure.ac b/configure.ac index 6d691a2..246165a 100644 --- a/configure.ac +++ b/configure.ac @@ -3,6 +3,23 @@ AC_INIT([RT/TTS], [D.84.0], [felicity@loreley.flyingparchment.org.uk]) AC_CONFIG_SRCDIR([tts.c]) AC_CONFIG_HEADERS([config.h]) +AC_CANONICAL_HOST + +case $host_os in + darwin*) + CPPFLAGS="$CPPFLAGS -D_DARWIN_USE_64_BIT_INODE=1" + ;; + linux*) + CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64" + ;; + netbsd*) + CPPFLAGS="$CPPFLAGS -D_NETBSD_SOURCE" + ;; + solaris*) + CPPFLAGS="-D__EXTENSIONS__ -D_FILE_OFFSET_BITS=64" + ;; +esac + AC_PROG_CC AC_PROG_INSTALL diff --git a/str.c b/str.c index 1d2d33e..ca4836f 100644 --- a/str.c +++ b/str.c @@ -8,6 +8,9 @@ * warranty. */ +#include +#include + #include "str.h" size_t diff --git a/style.c b/style.c index 40ae1cc..9479876 100644 --- a/style.c +++ b/style.c @@ -22,23 +22,23 @@ style_t sy_header = { 1, 0 }, sy_date = { 6, 0 }; static attrname_t attrnames[] = { - { L"normal", WA_NORMAL }, - { L"bold", WA_BOLD }, + { L"normal", 0 }, + { L"bold", WA_BOLD }, { L"reverse", WA_REVERSE }, { L"blink", WA_BLINK }, - { L"dim", WA_DIM }, + { L"dim", WA_DIM }, { L"underline", WA_UNDERLINE }, { L"standout", WA_STANDOUT } }; static colour_t colours[] = { { L"black", COLOR_BLACK }, - { L"red", COLOR_RED }, + { L"red", COLOR_RED }, { L"green", COLOR_GREEN }, { L"yellow", COLOR_YELLOW }, - { L"blue", COLOR_BLUE }, + { L"blue", COLOR_BLUE }, { L"magenta", COLOR_MAGENTA }, - { L"cyan", COLOR_CYAN }, + { L"cyan", COLOR_CYAN }, { L"white", COLOR_WHITE } }; @@ -79,7 +79,7 @@ style_clear(sy) style_t *sy; { init_pair(sy->sy_pair, default_fg, default_bg); - sy->sy_attrs = WA_NORMAL; + sy->sy_attrs = 0; } int @@ -87,7 +87,7 @@ style_set(sy, fg, bg) style_t *sy; const wchar_t *fg, *bg; { - sy->sy_attrs = WA_NORMAL; + sy->sy_attrs = 0; init_pair(sy->sy_pair, default_fg, default_bg); return style_add(sy, fg, bg); } diff --git a/ui.c b/ui.c index 0b47d62..30b00d6 100644 --- a/ui.c +++ b/ui.c @@ -432,7 +432,7 @@ chtype oldbg; time_t n; int h, s, m; wchar_t flags[10], stime[16], *p; - attr_t attrs = WA_NORMAL; + attr_t attrs = 0; if (!showinv && en->en_flags.efl_invoiced) continue; From e8ccd681e301b81e0f641e1bd6c31c695593a6aa Mon Sep 17 00:00:00 2001 From: River Tarnell Date: Sat, 8 Mar 2014 01:00:30 +0000 Subject: [PATCH 22/51] Don't spin-loop in prompt(). --- tts.c | 7 ++++--- ui.c | 4 ++-- wide.h | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/tts.c b/tts.c index c55c103..a22e3e1 100644 --- a/tts.c +++ b/tts.c @@ -320,7 +320,7 @@ struct kevent evs[2], rev; } #endif - while (input_char(&c) != ERR) { + while (input_char(stdscr, &c) != ERR) { #ifdef KEY_RESIZE if (c == KEY_RESIZE) continue; @@ -737,7 +737,8 @@ input_macro(s) } int -input_char(c) +input_char(win, c) + WINDOW *win; wchar_t *c; { if (macro_pos) { @@ -749,5 +750,5 @@ input_char(c) macro_text = macro_pos = NULL; } - return get_wch(c); + return wget_wch(win, c); } diff --git a/ui.c b/ui.c index 30b00d6..99181f5 100644 --- a/ui.c +++ b/ui.c @@ -177,7 +177,7 @@ wint_t c; waddwstr(pwin, L" [y/N]? "); wattroff(pwin, A_BOLD); - while (input_char(&c) == ERR + while (input_char(pwin, &c) == ERR #ifdef KEY_RESIZE || (c == KEY_RESIZE) #endif @@ -231,7 +231,7 @@ histent_t *histpos = NULL; wmove(pwin, 0, wcslen(msg) + 1 + pos); wrefresh(pwin); - if (input_char(&c) == ERR) + if (input_char(pwin, &c) == ERR) continue; switch (c) { diff --git a/wide.h b/wide.h index 129fb02..dc4ddcb 100644 --- a/wide.h +++ b/wide.h @@ -18,7 +18,7 @@ #define wsizeof(s) (sizeof(s) / sizeof(wchar_t)) -int input_char(wchar_t *); -void input_macro(wchar_t *); +int input_char (WINDOW *, wchar_t *); +void input_macro (wchar_t *); #endif /* !TTS_WIDE_H */ From 5739ca900ff83b7caaeb381126a48775b9d3ebef Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Sat, 8 Mar 2014 11:27:06 +0000 Subject: [PATCH 23/51] Remove obsolete comment. --- str.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/str.c b/str.c index ca4836f..9082c4f 100644 --- a/str.c +++ b/str.c @@ -45,9 +45,6 @@ wchar_t *r; p++; while (*++q) { - /* Handle escaping with backslash; currently works but the \ isn't - * removed from the string. - */ if (!isbsl && (*q == '\\')) { isbsl = 1; continue; From bf84f9a054abc7c586b6f903f47398cc9c9c7ddd Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Sat, 8 Mar 2014 11:29:01 +0000 Subject: [PATCH 24/51] Fix memory leak when re-setting variable. --- commands.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/commands.c b/commands.c index 3e501a5..aa25478 100644 --- a/commands.c +++ b/commands.c @@ -8,6 +8,8 @@ * warranty. */ +#include + #include "commands.h" #include "style.h" #include "bindings.h" @@ -136,6 +138,7 @@ int val; break; case VTYPE_STRING: + free(*(wchar_t **)var->va_addr); *(wchar_t **)var->va_addr = wcsdup(argv[2]); break; From a5dd2e4ae566cf54b02f5d525f24e2beeab594e7 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Sat, 8 Mar 2014 11:31:08 +0000 Subject: [PATCH 25/51] Fix crash on executing unknown command. --- commands.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/commands.c b/commands.c index aa25478..0cdfcf5 100644 --- a/commands.c +++ b/commands.c @@ -27,10 +27,10 @@ command_t * find_command(name) const wchar_t *name; { -size_t i; - for (i = 0; i < sizeof(commands) / sizeof(*commands); i++) - if (wcscmp(name, commands[i].cm_name) == 0) - return &commands[i]; +command_t *c; + for (c = commands; c->cm_name; c++) + if (wcscmp(name, c->cm_name) == 0) + return c; return NULL; } From c0df452c043bd32aab31a076eb37abbf1a85cb3f Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Sat, 8 Mar 2014 11:37:52 +0000 Subject: [PATCH 26/51] Provide error for invalid number in c_set(). --- commands.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/commands.c b/commands.c index 0cdfcf5..4dc1855 100644 --- a/commands.c +++ b/commands.c @@ -106,6 +106,7 @@ c_set(argc, argv) { variable_t *var; int val; +wchar_t *p = NULL; if (argc != 3) { cmderr(L"Usage: set "); @@ -143,7 +144,13 @@ int val; break; case VTYPE_INT: - *(int *)var->va_addr = wcstol(argv[2], NULL, 0); + val = wcstol(argv[2], &p, 0); + if (!*argv[2] || *p) { + cmderr(L"Invalid number \"%ls\"", argv[2]); + break; + } + + *(int *)var->va_addr = val; break; } } From 34712e643c1fb47216d035e2703aacf64003d4fe Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Sat, 8 Mar 2014 12:18:22 +0000 Subject: [PATCH 27/51] New time format: "1h30m7s". This is fairly flexible, so you could say 10s1h, or even 1h1h1h (which is equivalent to 3h). Time parsing is now implemented by a single function, so there should be no inconsistencies. The old [[HH:]MM:]SS syntax is still supported, but not used in prompts. --- Makefile.in | 2 +- functions.c | 111 ++++++++-------------------------------------------- str.c | 78 ++++++++++++++++++++++++++++++++++++ str.h | 6 ++- ui.c | 49 +++++++++-------------- ui.h | 2 +- 6 files changed, 119 insertions(+), 129 deletions(-) diff --git a/Makefile.in b/Makefile.in index f407378..1324e86 100644 --- a/Makefile.in +++ b/Makefile.in @@ -12,7 +12,7 @@ VPATH = @top_srcdir@ CC = @CC@ MAKEDEPEND = @CC@ -M -CPPFLAGS = @CPPFLAGS@ -D_XOPEN_SOURCE=700 -D_XOPEN_SOURCE_EXTENDED +CPPFLAGS = @CPPFLAGS@ -D_XOPEN_SOURCE_EXTENDED CFLAGS = @CFLAGS@ -I@top_srcdir@ -I@top_builddir@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ diff --git a/functions.c b/functions.c index d91f9e3..2ee9194 100644 --- a/functions.c +++ b/functions.c @@ -332,9 +332,7 @@ wchar_t *new; void kedtime() { -wchar_t *new, old[64]; time_t n; -int h, m, s; if (!curent) { drawstatus(L"No entry selected."); @@ -344,22 +342,13 @@ int h, m, s; n = curent->en_secs; if (curent->en_started) n += time(NULL) - curent->en_started; - h = n / (60 * 60); - n %= (60 * 60); - m = n / 60; - n %= 60; - s = n; - swprintf(old, wsizeof(old), L"%02d:%02d:%02d", h, m, s); - if ((new = prompt(L"Duration [HH:MM:SS]:", old, NULL)) == NULL) - return; - - if (!swscanf(new, L"%d:%d:%d", &h, &m, &s)) { - free(new); + if ((n = prduration(L"Duration:", n)) == (time_t) -1) { drawstatus(L"Invalid duration."); + return; } - curent->en_secs = (h * 60 * 60) + (m * 60) + s; + curent->en_secs = n; if (curent->en_started) time(&curent->en_started); @@ -421,47 +410,17 @@ entry_t *en; void kaddtime() { -wchar_t *tstr; -int h = 0, m = 0, s = 0, secs; +time_t secs; if (!curent) { drawstatus(L"No entry selected."); return; } - if ((tstr = prompt(L"Time to add ([[HH:]MM:]SS):", NULL, NULL)) == NULL) - return; - - if (!*tstr) { - drawstatus(L""); - free(tstr); + if ((secs = prduration(L"Time to add:", 0)) == (time_t) -1) { + drawstatus(L"Invalid time format."); return; } - if (swscanf(tstr, L"%d:%d:%d", &h, &m, &s) != 3) { - h = 0; - if (swscanf(tstr, L"%d:%d", &m, &s) != 2) { - m = 0; - if (swscanf(tstr, L"%d", &s) != 1) { - free(tstr); - drawstatus(L"Invalid time format."); - return; - } - } - } - - free(tstr); - - if (m >= 60) { - drawstatus(L"Minutes cannot be more than 59."); - return; - } - - if (s >= 60) { - drawstatus(L"Seconds cannot be more than 59."); - return; - } - - secs = s + m*60 + h*60*60; curent->en_secs += secs; save(); } @@ -469,48 +428,19 @@ int h = 0, m = 0, s = 0, secs; void kdeltime() { -wchar_t *tstr; -int h = 0, m = 0, s = 0, secs; +time_t secs; if (!curent) { drawstatus(L"No entry selected."); return; } - if ((tstr = prompt(L"Time to subtract, ([[HH:]MM:]SS):", NULL, NULL)) == NULL) - return; - - if (!*tstr) { - drawstatus(L""); - free(tstr); - return; - } - - if (swscanf(tstr, L"%d:%d:%d", &h, &m, &s) != 3) { - h = 0; - if (swscanf(tstr, L"%d:%d", &m, &s) != 2) { - m = 0; - if (swscanf(tstr, L"%d", &s) != 1) { - free(tstr); - drawstatus(L"Invalid time format."); - return; - } - } - } - - free(tstr); - if (m >= 60) { - drawstatus(L"Minutes cannot be more than 59."); - return; - } - - if (s >= 60) { - drawstatus(L"Seconds cannot be more than 59."); + if ((secs = prduration(L"Time to subtract:", 0)) == (time_t) -1) { + drawstatus(L"Invalid time format."); return; } entry_account(curent); - secs = s + m*60 + h*60*60; if (curent->en_secs - secs < 0) { drawstatus(L"Remaining time cannot be less than zero."); return; @@ -526,7 +456,8 @@ kmerge() entry_t *en, *ten; int nmarked = 0; wchar_t pr[128]; -int h, m, s = 0; +wchar_t *ct; +int s = 0; if (!curent) { drawstatus(L"No entry selected."); @@ -550,13 +481,11 @@ int h, m, s = 0; return; } - h = s / (60 * 60); - s %= (60 * 60); - m = s / 60; - s %= 60; + ct = maketime(s); + swprintf(pr, wsizeof(pr), L"Merge %d marked entries [%ls] into current entry?", + nmarked, ct); + free(ct); - swprintf(pr, wsizeof(pr), L"Merge %d marked entries [%02d:%02d:%02d] into current entry?", - nmarked, h, m, s); if (!yesno(pr)) return; @@ -699,15 +628,7 @@ wchar_t *name; return; } - if (itime) { - duration = time(NULL) - itime; - } else { - int h, m, s; - if (prduration(L"Duration [HH:MM:SS]:", &h, &m, &s) == -1) - return; - - duration = (h * 60 * 60) + (m * 60) + s; - } + duration = time(NULL) - itime; itime = 0; running->en_secs += (time(NULL) - running->en_started); diff --git a/str.c b/str.c index 9082c4f..98c29ff 100644 --- a/str.c +++ b/str.c @@ -133,3 +133,81 @@ wchar_t **p; free(*vec); } +time_t +parsetime(tm) + wchar_t *tm; +{ +int h = 0, m = 0, s = 0; +time_t i = 0, r = 0; + +/* The empty string is not a valid duration */ + if (!*tm) + return (time_t) -1; +/* Check for "hh:mm:ss" or "mm:ss" */ + if (swscanf(tm, L"%d:%d:%d", &h, &m, &s) == 3) + return (h * 60 * 60) + (m * 60) + s; + + if (swscanf(tm, L"%d:%d", &m, &s) == 2) + return (m * 60) + s; + +/* + * The string could either be a format like 3h10m, or a simle number like 47 + * (meaning seconds), which is also handled here. This is effectively an + * implementation of atoi with special meaning for 'h', 'm' and 's' characters. + * + * Note that we make no attempt to handle overflow. + */ + for (; *tm; tm++) { + switch (*tm) { + case L'h': + r += i * (60 * 60); + i = 0; + continue; + + case L'm': + r += i * 60; + i = 0; + continue; + + case L's': + r += i; + i = 0; + continue; + } + + if (wcschr(L"0123456789", *tm) == NULL) + return (time_t) -1; + + i *= 10; + i += *tm - L'0'; + } + + return r + i; +} + +wchar_t * +maketime(tm) + time_t tm; +{ +wchar_t res[64] = {}; +wchar_t t[16]; + + if (tm >= (60 * 60)) { + swprintf(t, wsizeof(t), L"%dh", tm / (60 * 60)); + wcslcat(res, t, sizeof(res)); + tm %= (60 * 60); + } + + if (tm >= 60) { + swprintf(t, wsizeof(t), L"%dm", tm / 60); + wcslcat(res, t, sizeof(res)); + tm %= 60; + } + + if (tm) { + swprintf(t, wsizeof(t), L"%ds", tm); + wcslcat(res, t, sizeof(res)); + } + + return wcsdup(res); +} diff --git a/str.h b/str.h index c0823b0..857d03f 100644 --- a/str.h +++ b/str.h @@ -15,7 +15,9 @@ #include "wide.h" -size_t tokenise(const wchar_t *, wchar_t ***result); -void tokfree(wchar_t ***); +size_t tokenise (const wchar_t *, wchar_t ***result); +void tokfree (wchar_t ***); +time_t parsetime (wchar_t *); +wchar_t *maketime (time_t); #endif /* !TTS_STR_H */ diff --git a/ui.c b/ui.c index 99181f5..7b51771 100644 --- a/ui.c +++ b/ui.c @@ -14,6 +14,7 @@ #include "ui.h" #include "tts.h" #include "style.h" +#include "str.h" WINDOW *titwin, *statwin, *listwin; int in_curses; @@ -601,15 +602,23 @@ chtype oldbg; wbkgdset(listwin, oldbg); } -int -prduration(pr, hh, mm, ss) +time_t +prduration(pr, def) wchar_t *pr; - int *hh, *mm, *ss; + time_t def; { +wchar_t *defstr = NULL; wchar_t *tstr; -int h, m, s; - if ((tstr = prompt(pr, L"00:00:00", NULL)) == NULL) +time_t ret; + + defstr = maketime(def); + + if ((tstr = prompt(pr, defstr, NULL)) == NULL) { + free(defstr); return -1; + } + + free(defstr); if (!*tstr) { drawstatus(L"No duration entered"); @@ -617,33 +626,13 @@ int h, m, s; return -1; } - if (swscanf(tstr, L"%d:%d:%d", &h, &m, &s) != 3) { - h = 0; - if (swscanf(tstr, L"%d:%d", &m, &s) != 2) { - m = 0; - if (swscanf(tstr, L"%d", &s) != 1) { - free(tstr); - drawstatus(L"Invalid time format."); - return -1; - } - } + if ((ret = parsetime(tstr)) == (time_t) -1) { + free(tstr); + drawstatus(L"Invalid time format."); + return -1; } free(tstr); - if (m >= 60) { - drawstatus(L"Minutes cannot be more than 59."); - return -1; - } - - if (s >= 60) { - drawstatus(L"Seconds cannot be more than 59."); - return -1; - } - - *hh = h; - *mm = m; - *ss = s; - return 0; + return ret; } - diff --git a/ui.h b/ui.h index 648bf35..a32602f 100644 --- a/ui.h +++ b/ui.h @@ -30,7 +30,7 @@ void drawheader (void); void drawentries (void); wchar_t *prompt (wchar_t const *, wchar_t const *, history_t *); -int prduration (wchar_t *prompt, int *h, int *m, int *s); +time_t prduration (wchar_t *prompt, time_t def); int yesno (wchar_t const *); void errbox (wchar_t const *, ...); void verrbox (wchar_t const *, va_list); From 0bf6dd576663979b2c330e35c00b979773203592 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Sat, 8 Mar 2014 12:31:58 +0000 Subject: [PATCH 28/51] Escape macro bodies when displaying in help. --- functions.c | 8 +++++--- str.c | 44 +++++++++++++++++++++++++++++++++++++++++++- str.h | 3 ++- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/functions.c b/functions.c index 2ee9194..eafa4ba 100644 --- a/functions.c +++ b/functions.c @@ -527,10 +527,12 @@ binding_t *bi; else swprintf(t, wsizeof(t), L"%lc", bi->bi_code); - if (bi->bi_macro) + if (bi->bi_macro) { + wchar_t *esc = escstr(bi->bi_macro); swprintf(s, wsizeof(s), L"%-10ls execute macro: %ls", - t, bi->bi_macro); - else + t, esc); + free(esc); + } else swprintf(s, wsizeof(s), L"%-10ls %ls (%ls)", t, bi->bi_func->fn_desc, bi->bi_func->fn_name); diff --git a/str.c b/str.c index 98c29ff..397105c 100644 --- a/str.c +++ b/str.c @@ -135,7 +135,7 @@ wchar_t **p; time_t parsetime(tm) - wchar_t *tm; + const wchar_t *tm; { int h = 0, m = 0, s = 0; time_t i = 0, r = 0; @@ -211,3 +211,45 @@ wchar_t t[16]; return wcsdup(res); } + +wchar_t * +escstr(s) + const wchar_t *s; +{ +wchar_t *ret, *p; + + if ((ret = calloc(sizeof(wchar_t), wcslen(s) * 2 + 1)) == NULL) + return NULL; + + for (p = ret; *s; s++) { + switch (*s) { + case '\\': + *p++ = L'\\'; + *p++ = L'\\'; + continue; + case '\n': + *p++ = L'\\'; + *p++ = L'n'; + continue; + case '\t': + *p++ = L'\\'; + *p++ = L't'; + continue; + case '\v': + *p++ = L'\\'; + *p++ = L'v'; + continue; + case '\r': + *p++ = L'\\'; + *p++ = L'r'; + continue; + case '"': + *p++ = L'\\'; + *p++ = L'"'; + continue; + } + + *p++ = *s; + } + return ret; +} diff --git a/str.h b/str.h index 857d03f..47d65c2 100644 --- a/str.h +++ b/str.h @@ -17,7 +17,8 @@ size_t tokenise (const wchar_t *, wchar_t ***result); void tokfree (wchar_t ***); -time_t parsetime (wchar_t *); +time_t parsetime (const wchar_t *); wchar_t *maketime (time_t); +wchar_t *escstr (const wchar_t *); #endif /* !TTS_STR_H */ From 0959aad655df416b090e56fa7adac7e19ce2ccb7 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Sat, 8 Mar 2014 12:54:05 +0000 Subject: [PATCH 29/51] Prompt support in macros: $[Text]. --- tts.c | 48 ++++++++++++++++++++++++++++++++++++++++-------- ttsrc.sample | 7 ++++++- 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/tts.c b/tts.c index a22e3e1..23d9b0e 100644 --- a/tts.c +++ b/tts.c @@ -741,14 +741,46 @@ input_char(win, c) WINDOW *win; wchar_t *c; { - if (macro_pos) { - if (*macro_pos) { - *c = *macro_pos++; - return 0; - } - free(macro_text); - macro_text = macro_pos = NULL; +wchar_t *pr, *s, *r; + if (!macro_pos) + return wget_wch(win, c); + + if (!*macro_pos) { + input_macro(NULL); + return wget_wch(win, c); } - return wget_wch(win, c); + if (macro_pos[0] != '$' || macro_pos[1] != '[') { + *c = *macro_pos++; + return 0; + } + +/* Handle $[prompt string] escapes */ + pr = calloc(sizeof(wchar_t), wcslen(macro_pos) - 1); + for (r = pr, s = macro_pos + 2; ; s++) { + if (*s == '\0') { + cmderr(L"Unterminated $[ prompt in macro"); + input_macro(NULL); + return wget_wch(win, c); + } + + if (*s == ']') + break; + + *r++ = *s; + } + + s++; + + macro_pos = NULL; + r = prompt(pr, NULL, NULL); + free(pr); + + pr = calloc(sizeof(wchar_t), wcslen(r) + wcslen(s) + 1); + wcscpy(pr, r); + wcscat(pr, s); + free(macro_text); + macro_text = macro_pos = pr; + *c = *macro_pos++; + return 0; } diff --git a/ttsrc.sample b/ttsrc.sample index 51a8f1d..b4a860c 100644 --- a/ttsrc.sample +++ b/ttsrc.sample @@ -49,7 +49,12 @@ bind k prev # string which will be executed as if it was typed. For example, the # following macro would add a new entry called "test", and set its timer to # 30 minutes. -#macro t "atest\n+30:00\n" +#macro t "atest\n+30m\n" + +# Macros can also prompt for input from the user using $[Prompt string]; the +# $[...] will be replaced with the user's input. For example, this macro will +# prompt for the name of a new entry, then set its duration to 30m: +#macro t "a$[Description:]\n+30m\n" #### Styling # From 684c581b3226f898781adc7516acf193f7a3ba8f Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Sat, 8 Mar 2014 12:57:35 +0000 Subject: [PATCH 30/51] Second argument to input_char() is wint_t, not wchar_t. --- tts.c | 2 +- wide.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tts.c b/tts.c index 23d9b0e..cc36bea 100644 --- a/tts.c +++ b/tts.c @@ -739,7 +739,7 @@ input_macro(s) int input_char(win, c) WINDOW *win; - wchar_t *c; + wint_t *c; { wchar_t *pr, *s, *r; if (!macro_pos) diff --git a/wide.h b/wide.h index dc4ddcb..2ef92ab 100644 --- a/wide.h +++ b/wide.h @@ -18,7 +18,7 @@ #define wsizeof(s) (sizeof(s) / sizeof(wchar_t)) -int input_char (WINDOW *, wchar_t *); +int input_char (WINDOW *, wint_t *); void input_macro (wchar_t *); #endif /* !TTS_WIDE_H */ From 7c26144e319f9e39af2b1e05437e8cf8bf1589c6 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Sat, 8 Mar 2014 13:03:19 +0000 Subject: [PATCH 31/51] Provide compat functions for wcsl{cpy,cat}(). --- Makefile.in | 2 +- config.h.in | 9 +++++ configure | 11 +++--- configure.ac | 2 +- str.c | 6 ++-- wcslcpy.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 118 insertions(+), 10 deletions(-) create mode 100644 wcslcpy.c diff --git a/Makefile.in b/Makefile.in index 1324e86..28dfdb6 100644 --- a/Makefile.in +++ b/Makefile.in @@ -19,7 +19,7 @@ LIBS = @LIBS@ INSTALL = @INSTALL@ OBJS = tts.o wide.o entry.o ui.o functions.o commands.o bindings.o \ - str.o style.o + str.o style.o wcslcpy.o prefix = @prefix@ exec_prefix = @exec_prefix@ diff --git a/config.h.in b/config.h.in index b2d7e01..9cd0677 100644 --- a/config.h.in +++ b/config.h.in @@ -24,6 +24,9 @@ /* Define to 1 if you have the `IORegisterForSystemPower' function. */ #undef HAVE_IOREGISTERFORSYSTEMPOWER +/* Define to 1 if you have the `m' library (-lm). */ +#undef HAVE_LIBM + /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H @@ -69,6 +72,12 @@ /* Define to 1 if you have the `use_default_colors' function. */ #undef HAVE_USE_DEFAULT_COLORS +/* Define to 1 if you have the `wcslcat' function. */ +#undef HAVE_WCSLCAT + +/* Define to 1 if you have the `wcslcpy' function. */ +#undef HAVE_WCSLCPY + /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT diff --git a/configure b/configure index 51fc83a..c8e2e7e 100755 --- a/configure +++ b/configure @@ -2225,7 +2225,7 @@ case $host_os in CPPFLAGS="$CPPFLAGS -D_NETBSD_SOURCE" ;; solaris*) - CPPFLAGS="-D__EXTENSIONS__ -D_XOPEN_SOURCE=700 -D_FILE_OFFSET_BITS=64" + CPPFLAGS="-D__EXTENSIONS__ -D_FILE_OFFSET_BITS=64" ;; esac @@ -3872,12 +3872,13 @@ fi oLIBS="$LIBS" LIBS="$LIBS $CURSES_LIB" -for ac_func in use_default_colors +for ac_func in use_default_colors wcslcpy wcslcat do : - ac_fn_c_check_func "$LINENO" "use_default_colors" "ac_cv_func_use_default_colors" -if test "x$ac_cv_func_use_default_colors" = xyes; then : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF -#define HAVE_USE_DEFAULT_COLORS 1 +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi diff --git a/configure.ac b/configure.ac index 246165a..1821d75 100644 --- a/configure.ac +++ b/configure.ac @@ -26,7 +26,7 @@ AC_PROG_INSTALL AX_WITH_CURSES oLIBS="$LIBS" LIBS="$LIBS $CURSES_LIB" -AC_CHECK_FUNCS([use_default_colors]) +AC_CHECK_FUNCS([use_default_colors wcslcpy wcslcat]) LIBS="$oLIBS" AC_CHECK_HEADERS([IOKit/pwr_mgt/IOPMLib.h]) diff --git a/str.c b/str.c index 397105c..7227deb 100644 --- a/str.c +++ b/str.c @@ -194,19 +194,19 @@ wchar_t t[16]; if (tm >= (60 * 60)) { swprintf(t, wsizeof(t), L"%dh", tm / (60 * 60)); - wcslcat(res, t, sizeof(res)); + wcslcat(res, t, wsizeof(res)); tm %= (60 * 60); } if (tm >= 60) { swprintf(t, wsizeof(t), L"%dm", tm / 60); - wcslcat(res, t, sizeof(res)); + wcslcat(res, t, wsizeof(res)); tm %= 60; } if (tm) { swprintf(t, wsizeof(t), L"%ds", tm); - wcslcat(res, t, sizeof(res)); + wcslcat(res, t, wsizeof(res)); } return wcsdup(res); diff --git a/wcslcpy.c b/wcslcpy.c new file mode 100644 index 0000000..df007ba --- /dev/null +++ b/wcslcpy.c @@ -0,0 +1,98 @@ +/* $NetBSD: strlcpy.c,v 1.3 2007/06/04 18:19:27 christos Exp $ */ +/* $OpenBSD: strlcpy.c,v 1.7 2003/04/12 21:56:39 millert Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE + * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include "config.h" + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +#ifndef HAVE_WCSLCPY +size_t +wcslcpy(dst, src, siz) + wchar_t *dst; + wchar_t const *src; + size_t siz; +{ +wchar_t *d = dst; +const wchar_t *s = src; +size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) { + do { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} +#endif + +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +#ifndef HAVE_WCSLCAT +size_t +wcslcat(wchar_t *dst, const wchar_t *src, size_t siz) +{ +wchar_t *d = dst; +const wchar_t *s = src; +size_t n = siz; +size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ +} +#endif + From 1758e63f6b2335d6db04dc2aac5fe093ada3f22a Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Sat, 8 Mar 2014 13:05:44 +0000 Subject: [PATCH 32/51] Fix wcslcpy compat. --- wcslcpy.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/wcslcpy.c b/wcslcpy.c index df007ba..d57cdd9 100644 --- a/wcslcpy.c +++ b/wcslcpy.c @@ -20,13 +20,14 @@ #include #include #include +#include #include "config.h" /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). - * Returns strlen(src); if retval >= siz, truncation occurred. + * Returns wcslen(src); if retval >= siz, truncation occurred. */ #ifndef HAVE_WCSLCPY size_t @@ -62,8 +63,8 @@ size_t n = siz; /* * Appends src to string dst of size siz (unlike strncat, siz is the * full size of dst, not space left). At most siz-1 characters - * will be copied. Always NUL terminates (unless siz <= strlen(dst)). - * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * will be copied. Always NUL terminates (unless siz <= wcslen(dst)). + * Returns wcslen(src) + MIN(siz, wcslen(initial dst)). * If retval >= siz, truncation occurred. */ #ifndef HAVE_WCSLCAT @@ -82,7 +83,7 @@ size_t dlen; n = siz - dlen; if (n == 0) - return(dlen + strlen(s)); + return(dlen + wcslen(s)); while (*s != '\0') { if (n != 1) { *d++ = *s; From 2e643825733274159c612701c1c1ea7caac5112c Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Sat, 8 Mar 2014 13:08:55 +0000 Subject: [PATCH 33/51] Prototype wcsl* --- tts.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tts.h b/tts.h index 9e30d88..d3eab40 100644 --- a/tts.h +++ b/tts.h @@ -65,4 +65,12 @@ void hist_add(history_t *, wchar_t const *); extern history_t *searchhist; extern history_t *prompthist; +#ifndef HAVE_WCSLCPY +size_t wcslcat(wchar_t *s1, const wchar_t *s2, size_t n); +#endif + +#ifndef HAVE_WCSLCAT +size_t wcslcpy(wchar_t *s1, const wchar_t *s2, size_t n); +#endif + #endif /* !TTS_H */ From 1ea26690e58d9c1fc6c32ad3c477b77b594c0331 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Sat, 8 Mar 2014 13:09:14 +0000 Subject: [PATCH 34/51] Include tts.h for wcs* prototypes. --- str.c | 1 + 1 file changed, 1 insertion(+) diff --git a/str.c b/str.c index 7227deb..99be83b 100644 --- a/str.c +++ b/str.c @@ -12,6 +12,7 @@ #include #include "str.h" +#include "tts.h" size_t tokenise(str, res) From 2af789884ee2bc1d341d1c9da04265cec3dac65c Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Sat, 8 Mar 2014 13:26:35 +0000 Subject: [PATCH 35/51] Use new time format in day headers. --- ui.c | 64 +++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/ui.c b/ui.c index 7b51771..d8a6d54 100644 --- a/ui.c +++ b/ui.c @@ -443,19 +443,13 @@ chtype oldbg; if (lastday != entry_day(en)) { struct tm *lt; wchar_t lbl[128]; - time_t itime = entry_time_for_day(entry_day(en), 1, 0), - ntime = entry_time_for_day(entry_day(en), 0, 0), - btime = entry_time_for_day(entry_day(en), 2, bill_increment); - int hi, mi, si, - hn, mn, sn, - hb, mb, sb, - ht, mt, st; + wchar_t *itime = maketime(entry_time_for_day(entry_day(en), 1, 0)), + *ntime = maketime(entry_time_for_day(entry_day(en), 0, 0)), + *btime = maketime(entry_time_for_day(entry_day(en), 2, bill_increment)), + *ttime = maketime(entry_time_for_day(entry_day(en), 1, 0) + + entry_time_for_day(entry_day(en), 0, 0)); wchar_t hdrtext[256]; - - time_to_hms(itime, hi, mi, si); - time_to_hms(ntime, hn, mn, sn); - time_to_hms(btime, hb, mb, sb); - time_to_hms(itime + ntime, ht, mt, st); + int n = 0; oldbg = getbkgd(listwin); wbkgdset(listwin, style_bg(sy_entry)); @@ -474,18 +468,40 @@ chtype oldbg; lt = localtime(&lastday); wcsftime(lbl, wsizeof(lbl), L"%A, %d %B %Y", lt); - if (show_billable) - swprintf(hdrtext, wsizeof(hdrtext), - L"%-30ls [I:%02d:%02d:%02d / " - L"N:%02d:%02d:%02d / T:%02d:%02d:%02d / " - L"B:%02d:%02d:%02d]", - lbl, hi, mi, si, hn, mn, sn, ht, mt, st, - hb, mb, sb); - else - swprintf(hdrtext, wsizeof(hdrtext), - L"%-30ls [I:%02d:%02d:%02d / " - L"N:%02d:%02d:%02d / T:%02d:%02d:%02d]", - lbl, hi, mi, si, hn, mn, sn, ht, mt, st); + swprintf(hdrtext, wsizeof(hdrtext), L"%-30ls [", lbl); + + if (*itime) { + wcslcat(hdrtext, L"I:", wsizeof(hdrtext)); + wcslcat(hdrtext, itime, wsizeof(hdrtext)); + free(itime); + n++; + } + + if (*ntime) { + if (n++) + wcslcat(hdrtext, L" ", wsizeof(hdrtext)); + wcslcat(hdrtext, L"N:", wsizeof(hdrtext)); + wcslcat(hdrtext, ntime, wsizeof(hdrtext)); + free(ntime); + } + + if (*ttime) { + if (n++) + wcslcat(hdrtext, L" ", wsizeof(hdrtext)); + wcslcat(hdrtext, L"T:", wsizeof(hdrtext)); + wcslcat(hdrtext, ttime, wsizeof(hdrtext)); + free(ttime); + } + + if (*btime) { + if (n++) + wcslcat(hdrtext, L" ", wsizeof(hdrtext)); + wcslcat(hdrtext, L"B:", wsizeof(hdrtext)); + wcslcat(hdrtext, btime, wsizeof(hdrtext)); + free(btime); + } + + wcslcat(hdrtext, L"]", wsizeof(hdrtext)); wattr_on(listwin, style_fg(sy_date), NULL); wbkgdset(listwin, style_bg(sy_date)); From 0479ee0f89ec8cad0c3fc147e043e2060f34d067 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Sat, 8 Mar 2014 13:49:19 +0000 Subject: [PATCH 36/51] Configurable time format. --- functions.c | 2 +- str.c | 30 +++++++++++++++++++++++++----- str.h | 7 ++++++- tts.c | 2 ++ tts.h | 2 ++ ttsrc.sample | 9 +++++++++ ui.c | 40 ++++++++++++++++++---------------------- 7 files changed, 63 insertions(+), 29 deletions(-) diff --git a/functions.c b/functions.c index eafa4ba..61007a6 100644 --- a/functions.c +++ b/functions.c @@ -481,7 +481,7 @@ int s = 0; return; } - ct = maketime(s); + ct = maketime(s, time_format); swprintf(pr, wsizeof(pr), L"Merge %d marked entries [%ls] into current entry?", nmarked, ct); free(ct); diff --git a/str.c b/str.c index 99be83b..5813606 100644 --- a/str.c +++ b/str.c @@ -174,6 +174,9 @@ time_t i = 0, r = 0; r += i; i = 0; continue; + + case L' ': + continue; } if (wcschr(L"0123456789", *tm) == NULL) @@ -187,29 +190,46 @@ time_t i = 0, r = 0; } wchar_t * -maketime(tm) +maketime(tm, fmt) time_t tm; { wchar_t res[64] = {}; wchar_t t[16]; + if (fmt == TIME_HMS) { + int h, m, s; + time_to_hms(tm, h, m, s); + swprintf(t, wsizeof(t), L"%02d:%02d:%02d", + h, m, s); + return wcsdup(t); + } + + if (fmt == TIME_HM) { + int h, m, s; + time_to_hms(tm, h, m, s); + swprintf(t, wsizeof(t), L"%02d:%02d", h, m); + return wcsdup(t); + } + if (tm >= (60 * 60)) { - swprintf(t, wsizeof(t), L"%dh", tm / (60 * 60)); + swprintf(t, wsizeof(t), L"%2dh ", tm / (60 * 60)); wcslcat(res, t, wsizeof(res)); tm %= (60 * 60); } if (tm >= 60) { - swprintf(t, wsizeof(t), L"%dm", tm / 60); + swprintf(t, wsizeof(t), L"%2dm ", tm / 60); wcslcat(res, t, wsizeof(res)); tm %= 60; } - if (tm) { - swprintf(t, wsizeof(t), L"%ds", tm); + if (fmt == TIME_AHMS && tm) { + swprintf(t, wsizeof(t), L"%2ds ", tm); wcslcat(res, t, wsizeof(res)); } + res[wcslen(res) - 1] = '\0'; + return wcsdup(res); } diff --git a/str.h b/str.h index 47d65c2..575a72f 100644 --- a/str.h +++ b/str.h @@ -15,10 +15,15 @@ #include "wide.h" +#define TIME_HMS 0 /* HH:MM:SS */ +#define TIME_HM 1 /* HH:MM */ +#define TIME_AHMS 2 /* 1h10m37s */ +#define TIME_AHM 3 /* 1h10w */ + size_t tokenise (const wchar_t *, wchar_t ***result); void tokfree (wchar_t ***); time_t parsetime (const wchar_t *); -wchar_t *maketime (time_t); +wchar_t *maketime (time_t, int format); wchar_t *escstr (const wchar_t *); #endif /* !TTS_STR_H */ diff --git a/tts.c b/tts.c index cc36bea..1a2b9ad 100644 --- a/tts.c +++ b/tts.c @@ -92,6 +92,7 @@ int mark_advance = 1; int bill_advance = 0; int bill_increment = 0; wchar_t *auto_nonbillable; +int time_format; variable_t variables[] = { { L"delete_advance", VTYPE_BOOL, &delete_advance }, @@ -100,6 +101,7 @@ variable_t variables[] = { { L"show_billable", VTYPE_BOOL, &show_billable }, { L"auto_non_billable", VTYPE_STRING, &auto_nonbillable }, { L"bill_increment", VTYPE_INT, &bill_increment }, + { L"time_format", VTYPE_INT, &time_format }, { } }; diff --git a/tts.h b/tts.h index d3eab40..21db178 100644 --- a/tts.h +++ b/tts.h @@ -73,4 +73,6 @@ size_t wcslcat(wchar_t *s1, const wchar_t *s2, size_t n); size_t wcslcpy(wchar_t *s1, const wchar_t *s2, size_t n); #endif +extern int time_format; + #endif /* !TTS_H */ diff --git a/ttsrc.sample b/ttsrc.sample index b4a860c..da11815 100644 --- a/ttsrc.sample +++ b/ttsrc.sample @@ -11,6 +11,15 @@ #set mark_advance 1 #set delete_advance 1 +# Select the time format used in the display; value can be from 0 to 3. +# +# 0: 10:03:37 (default) +# 1: 10:03 +# 2: 10h 3m 37s +# 3: 10h 3m +# +#set time_format 0 + #### Billing options # # If set, show billable time in each daily summary. diff --git a/ui.c b/ui.c index d8a6d54..48c6ef7 100644 --- a/ui.c +++ b/ui.c @@ -119,13 +119,12 @@ wchar_t title[64]; waddwstr(titwin, title); if (itime > 0) { - wchar_t str[128]; - int h, m, s; + wchar_t str[128], *tm; time_t passed = time(NULL) - itime; - time_to_hms(passed, h, m, s); - swprintf(str, wsizeof(str), L" *** MARK INTERRUPT: %02d:%02d:%02d ***", - h, m, s); + tm = maketime(passed, time_format); + swprintf(str, wsizeof(str), L" *** MARK INTERRUPT: %ls ***", tm); + free(tm); wattron(titwin, A_BOLD); waddwstr(titwin, str); @@ -431,9 +430,9 @@ chtype oldbg; for (; en; en = TTS_TAILQ_NEXT(en, en_entries)) { time_t n; - int h, s, m; wchar_t flags[10], stime[16], *p; attr_t attrs = 0; + wchar_t *etime; if (!showinv && en->en_flags.efl_invoiced) continue; @@ -443,11 +442,11 @@ chtype oldbg; if (lastday != entry_day(en)) { struct tm *lt; wchar_t lbl[128]; - wchar_t *itime = maketime(entry_time_for_day(entry_day(en), 1, 0)), - *ntime = maketime(entry_time_for_day(entry_day(en), 0, 0)), - *btime = maketime(entry_time_for_day(entry_day(en), 2, bill_increment)), + wchar_t *itime = maketime(entry_time_for_day(entry_day(en), 1, 0), time_format), + *ntime = maketime(entry_time_for_day(entry_day(en), 0, 0), time_format), + *btime = maketime(entry_time_for_day(entry_day(en), 2, bill_increment), time_format), *ttime = maketime(entry_time_for_day(entry_day(en), 1, 0) + - entry_time_for_day(entry_day(en), 0, 0)); + entry_time_for_day(entry_day(en), 0, 0), time_format); wchar_t hdrtext[256]; int n = 0; @@ -473,33 +472,33 @@ chtype oldbg; if (*itime) { wcslcat(hdrtext, L"I:", wsizeof(hdrtext)); wcslcat(hdrtext, itime, wsizeof(hdrtext)); - free(itime); n++; } + free(itime); if (*ntime) { if (n++) wcslcat(hdrtext, L" ", wsizeof(hdrtext)); wcslcat(hdrtext, L"N:", wsizeof(hdrtext)); wcslcat(hdrtext, ntime, wsizeof(hdrtext)); - free(ntime); } + free(ntime); if (*ttime) { if (n++) wcslcat(hdrtext, L" ", wsizeof(hdrtext)); wcslcat(hdrtext, L"T:", wsizeof(hdrtext)); wcslcat(hdrtext, ttime, wsizeof(hdrtext)); - free(ttime); } + free(ttime); if (*btime) { if (n++) wcslcat(hdrtext, L" ", wsizeof(hdrtext)); wcslcat(hdrtext, L"B:", wsizeof(hdrtext)); wcslcat(hdrtext, btime, wsizeof(hdrtext)); - free(btime); } + free(btime); wcslcat(hdrtext, L"]", wsizeof(hdrtext)); @@ -558,14 +557,11 @@ chtype oldbg; n = en->en_secs; if (en->en_started) n += time(NULL) - en->en_started; - h = n / (60 * 60); - n %= (60 * 60); - m = n / 60; - n %= 60; - s = n; - swprintf(stime, wsizeof(stime), L"%02d:%02d:%02d%c ", - h, m, s, (itime && (en == running)) ? '*' : ' '); + etime = maketime(n, time_format); + swprintf(stime, wsizeof(stime), L"%8ls%c ", + *etime ? etime : L"0m", (itime && (en == running)) ? '*' : ' '); + free(etime); waddwstr(listwin, stime); memset(flags, 0, sizeof(flags)); @@ -627,7 +623,7 @@ wchar_t *defstr = NULL; wchar_t *tstr; time_t ret; - defstr = maketime(def); + defstr = maketime(def, TIME_AHMS); if ((tstr = prompt(pr, defstr, NULL)) == NULL) { free(defstr); From 49651c90a2871973d2a86b5519cca5a0e1c0647a Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Sat, 8 Mar 2014 13:58:21 +0000 Subject: [PATCH 37/51] Honour user's time format when editing entry duration. --- str.h | 7 +++++++ ui.c | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/str.h b/str.h index 575a72f..9ea533e 100644 --- a/str.h +++ b/str.h @@ -20,6 +20,13 @@ #define TIME_AHMS 2 /* 1h10m37s */ #define TIME_AHM 3 /* 1h10w */ +#define TIMEFMT_FOR_EDIT(f) \ + ( (f) == TIME_HMS ? TIME_HMS \ + : (f) == TIME_HM ? TIME_HMS \ + : (f) == TIME_AHMS ? TIME_AHMS \ + : (f) == TIME_AHM ? TIME_AHMS \ + : 0) + size_t tokenise (const wchar_t *, wchar_t ***result); void tokfree (wchar_t ***); time_t parsetime (const wchar_t *); diff --git a/ui.c b/ui.c index 48c6ef7..40a269f 100644 --- a/ui.c +++ b/ui.c @@ -623,7 +623,7 @@ wchar_t *defstr = NULL; wchar_t *tstr; time_t ret; - defstr = maketime(def, TIME_AHMS); + defstr = maketime(def, TIMEFMT_FOR_EDIT(time_format)); if ((tstr = prompt(pr, defstr, NULL)) == NULL) { free(defstr); From 86f643dc0ef23c70223799a70a0d0b745b5fb313 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Mon, 31 Mar 2014 02:08:17 +0100 Subject: [PATCH 38/51] Add mailing list info to README. --- README | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README b/README index 163e90f..5fca8c2 100644 --- a/README +++ b/README @@ -36,4 +36,10 @@ After starting with 'tts', type '?' for help. ### Contact -Send questions/comments/bugs/patches to . +There is a mailing list for TTS users. To subscribe to it, send mail to + with "subscribe tts" in the body. Announcements of +new releases and important changes will be posted to this list. + +Alternatively, to report problems or request features, use the GitHub issue +tracker at . This requires that you +have a GitHub account From 7ff1070bb7650b5219a900c9cea8d3a03656c79c Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Tue, 27 May 2014 12:18:10 +0100 Subject: [PATCH 39/51] Fix bling_import.pl error message. --- bling_import.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bling_import.pl b/bling_import.pl index ed644df..b72ab19 100755 --- a/bling_import.pl +++ b/bling_import.pl @@ -89,7 +89,7 @@ while () { if ($res->is_success) { my $resp = decode_json($res->content); if (defined($resp->{description})) { - print "Failed to Bling [$desc]: " . $resp->description . "\n"; + print "Failed to Bling [$desc]: " . $resp->{description} . "\n"; } else { if ($flags eq "-") { $flags = "i"; From c0074a61d29406bcfa167a14efef5889ac1ba504 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Tue, 18 Nov 2014 15:48:14 +0000 Subject: [PATCH 40/51] prompt(): handle tab characters --- ui.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/ui.c b/ui.c index 40a269f..23fbdc7 100644 --- a/ui.c +++ b/ui.c @@ -225,10 +225,26 @@ histent_t *histpos = NULL; for (;;) { wint_t c; + int i, inpos; wmove(pwin, 0, wcslen(msg) + 1); - waddwstr(pwin, input); + for (i = 0; i < wcslen(input); i++) { + if (input[i] == L'\t') + waddwstr(pwin, L" "); + else { + wchar_t s[] = { input[i], '\0' }; + waddwstr(pwin, s); + } + } + i--; + wclrtoeol(pwin); - wmove(pwin, 0, wcslen(msg) + 1 + pos); + for (i = 0, inpos = 0; i < wcslen(input) && i < pos; i++) + if (input[i] == L'\t') + inpos += 8; + else + inpos++; + + wmove(pwin, 0, wcslen(msg) + 1 + inpos); wrefresh(pwin); if (input_char(pwin, &c) == ERR) From a91ce6326d32a0f3200355ad4792849fa4cf8ba1 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Tue, 12 Apr 2016 10:12:44 +0100 Subject: [PATCH 41/51] str.c: missing #include --- str.c | 1 + 1 file changed, 1 insertion(+) diff --git a/str.c b/str.c index 5813606..4c7a42b 100644 --- a/str.c +++ b/str.c @@ -10,6 +10,7 @@ #include #include +#include #include "str.h" #include "tts.h" From bf5a894fc23beae1b631c5fbbb7ea54dfb33b813 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Tue, 12 Apr 2016 10:13:21 +0100 Subject: [PATCH 42/51] .gitignore: update --- .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index b6b25c1..94c5ae3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,12 @@ +*.o *.swp *~ +/Makefile +/config.h +/config.log +/config.status +/tts +/vers.c /build /autom4te.cache /doconf From e73d4f8a103fd4bd854e9900e6156c27fd13f4b1 Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Tue, 23 May 2017 09:42:45 +0100 Subject: [PATCH 43/51] bling_import.pl: fix LWP import --- bling_import.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/bling_import.pl b/bling_import.pl index b72ab19..f2e0551 100755 --- a/bling_import.pl +++ b/bling_import.pl @@ -20,6 +20,7 @@ use warnings; use strict; +use LWP::Protocol::https; use LWP::UserAgent; use URI::Escape qw/uri_escape/; use POSIX qw/strftime/; From 75750530a7bd730c9d4a3f057dea10f2b4222089 Mon Sep 17 00:00:00 2001 From: Liss Tarnell Date: Tue, 27 Jun 2017 15:13:57 +0100 Subject: [PATCH 44/51] update README and add a screenshot --- README | 33 ++++++++++++++++++++++----------- screenshot.png | Bin 0 -> 118242 bytes 2 files changed, 22 insertions(+), 11 deletions(-) create mode 100755 screenshot.png diff --git a/README b/README index 5fca8c2..2c7760d 100644 --- a/README +++ b/README @@ -1,8 +1,21 @@ TTS - Time-tracking software ============================ -TTS is a simple, text-based (curses) time-tracking application. For more -details, see the website at . +TTS is a simple, text-based (curses) time-tracking application. It allows you +to track the time you spend working by client, project, etc. to allow accurate +invoicing of clients or reporting to a corporate time-tracking system. It +uses a simple text format to store data which can easily be parsed to export +data to another system automatically. Entries can be added in bulk or in real +time using a timer, and invoiced and non-billable entries are tracked. +Entries can optionally be rounded up to a minimum billing increment. + +Screenshot +---------- + +![A screenshot of TTS in use](screenshot.png) + +Installation +------------ TTS has been tested on FreeBSD, NetBSD, Solaris, Cygwin and Linux, with the following caveats: @@ -21,7 +34,8 @@ TTS uses autoconf and can be built as follows: After starting with 'tts', type '?' for help. -### Quick start: +Quick start +----------- * Press 'a' to add a new entry, and enter its name. The timer starts running. * Press space to toggle the timer on and off. @@ -34,12 +48,9 @@ After starting with 'tts', type '?' for help. start the interrupt timer. When you're done with the other thing, press 'r' again to assign the interrupt time to a new entry. -### Contact +Contact +------- -There is a mailing list for TTS users. To subscribe to it, send mail to - with "subscribe tts" in the body. Announcements of -new releases and important changes will be posted to this list. - -Alternatively, to report problems or request features, use the GitHub issue -tracker at . This requires that you -have a GitHub account +To report problems or request features, please use the GitHub issue tracker at +. This requires that you have a GitHub +account. diff --git a/screenshot.png b/screenshot.png new file mode 100755 index 0000000000000000000000000000000000000000..49207ac3634dd591f54c09812e825c251dc53cfb GIT binary patch literal 118242 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� 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

u1(GL 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 E4_CoHS^xk5 literal 0 HcmV?d00001 From 000a019648cfbb9cb57ead683d35242b4210c3f4 Mon Sep 17 00:00:00 2001 From: Liss Tarnell Date: Tue, 27 Jun 2017 15:14:11 +0100 Subject: [PATCH 45/51] README: -> README.md --- README => README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename README => README.md (100%) diff --git a/README b/README.md similarity index 100% rename from README rename to README.md From 6c853f1b95c1f7faef1dbb5f51c135ff2260a1bb Mon Sep 17 00:00:00 2001 From: Liss Tarnell Date: Mon, 25 Sep 2017 13:14:35 +0100 Subject: [PATCH 46/51] configure: raise error if curses is not found --- configure | 5 +++++ configure.ac | 3 +++ 2 files changed, 8 insertions(+) diff --git a/configure b/configure index c8e2e7e..a1fefe0 100755 --- a/configure +++ b/configure @@ -3870,6 +3870,11 @@ fi LIBS=$ax_saved_LIBS +if test "x$ax_cv_curses" != xyes; then : + + as_fn_error $? "XSI/SVR4 curses is required to compile TTS" "$LINENO" 5 + +fi oLIBS="$LIBS" LIBS="$LIBS $CURSES_LIB" for ac_func in use_default_colors wcslcpy wcslcat diff --git a/configure.ac b/configure.ac index 1821d75..cb16ad1 100644 --- a/configure.ac +++ b/configure.ac @@ -24,6 +24,9 @@ AC_PROG_CC AC_PROG_INSTALL AX_WITH_CURSES +AS_IF([test "x$ax_cv_curses" != xyes], [ + AC_ERROR([XSI/SVR4 curses is required to compile TTS]) +]) oLIBS="$LIBS" LIBS="$LIBS $CURSES_LIB" AC_CHECK_FUNCS([use_default_colors wcslcpy wcslcat]) From e37b9118078743890cd3e0d81a70efd14aa11abb Mon Sep 17 00:00:00 2001 From: Liss Tarnell Date: Mon, 25 Sep 2017 13:18:23 +0100 Subject: [PATCH 47/51] kmerge: remove extraneous '?' in merge prompt --- functions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functions.c b/functions.c index 61007a6..4365f1f 100644 --- a/functions.c +++ b/functions.c @@ -482,7 +482,7 @@ int s = 0; } ct = maketime(s, time_format); - swprintf(pr, wsizeof(pr), L"Merge %d marked entries [%ls] into current entry?", + swprintf(pr, wsizeof(pr), L"Merge %d marked entries [%ls] into current entry", nmarked, ct); free(ct); From b4e2a8e6cf90e3c255daf19fecb00a625b37f385 Mon Sep 17 00:00:00 2001 From: Liss Tarnell Date: Mon, 25 Sep 2017 13:24:40 +0100 Subject: [PATCH 48/51] functions.c: do not allow entry titles containing only whitespace --- functions.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/functions.c b/functions.c index 4365f1f..b037878 100644 --- a/functions.c +++ b/functions.c @@ -47,6 +47,22 @@ function_t funcs[] = { { } }; +static int +valid_description(d) + const wchar_t *d; +{ + if (!d) + return 0; + + while (iswspace(*d)) + d++; + + if (!*d) + return 0; + + return 1; +} + void kquit() { @@ -75,10 +91,12 @@ kadd() wchar_t *name; entry_t *en; name = prompt(L"Description:", NULL, NULL); - if (!name || !*name) { + + if (!valid_description(name)) { free(name); return; } + en = entry_new(name); entry_start(en); curent = en; @@ -92,7 +110,7 @@ wchar_t *name; entry_t *en; name = prompt(L"Description:", NULL, NULL); - if (!name || !*name) { + if (!valid_description(name)) { free(name); return; } @@ -622,9 +640,9 @@ wchar_t *name; return; } - name = prompt(L"Description:", NULL, NULL); + name = prompt(L"Description ( to abandon interrupt):", NULL, NULL); - if (!name || !*name) { + if (!valid_description(name)) { itime = 0; free(name); return; From b473a74c9d61e524398271f506d6fd42bbaff82c Mon Sep 17 00:00:00 2001 From: Liss Tarnell Date: Mon, 25 Sep 2017 13:25:23 +0100 Subject: [PATCH 49/51] configure.ac: bump version to D.84.1 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index cb16ad1..6c5bed9 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ([2.69]) -AC_INIT([RT/TTS], [D.84.0], [felicity@loreley.flyingparchment.org.uk]) +AC_INIT([RT/TTS], [D.84.1], [ft@le-fay.org]) AC_CONFIG_SRCDIR([tts.c]) AC_CONFIG_HEADERS([config.h]) From be5a5c6a416a0609e84d8a63578977093f69c20e Mon Sep 17 00:00:00 2001 From: Liss Tarnell Date: Mon, 25 Sep 2017 13:25:58 +0100 Subject: [PATCH 50/51] configure.ac: RT/TTS -> TTS --- configure | 42 +++++++++++++++++++++--------------------- configure.ac | 2 +- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/configure b/configure index a1fefe0..cdcb1f0 100755 --- a/configure +++ b/configure @@ -1,8 +1,8 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for RT/TTS D.84.0. +# Generated by GNU Autoconf 2.69 for RT/TTS D.84.1. # -# Report bugs to . +# Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -266,11 +266,11 @@ fi $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else - $as_echo "$0: Please tell bug-autoconf@gnu.org and -$0: felicity@loreley.flyingparchment.org.uk about your -$0: system, including any error possibly output before this -$0: message. Then install a modern shell, or manually run -$0: the script under such a shell if you do have one." + $as_echo "$0: Please tell bug-autoconf@gnu.org and ft@le-fay.org +$0: about your system, including any error possibly output +$0: before this message. Then install a modern shell, or +$0: manually run the script under such a shell if you do +$0: have one." fi exit 1 fi @@ -580,9 +580,9 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='RT/TTS' PACKAGE_TARNAME='rt-tts' -PACKAGE_VERSION='D.84.0' -PACKAGE_STRING='RT/TTS D.84.0' -PACKAGE_BUGREPORT='felicity@loreley.flyingparchment.org.uk' +PACKAGE_VERSION='D.84.1' +PACKAGE_STRING='RT/TTS D.84.1' +PACKAGE_BUGREPORT='ft@le-fay.org' PACKAGE_URL='' ac_unique_file="tts.c" @@ -1240,7 +1240,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures RT/TTS D.84.0 to adapt to many kinds of systems. +\`configure' configures RT/TTS D.84.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1305,7 +1305,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of RT/TTS D.84.0:";; + short | recursive ) echo "Configuration of RT/TTS D.84.1:";; esac cat <<\_ACEOF @@ -1329,7 +1329,7 @@ Some influential environment variables: Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. -Report bugs to . +Report bugs to . _ACEOF ac_status=$? fi @@ -1392,7 +1392,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -RT/TTS configure D.84.0 +RT/TTS configure D.84.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1664,9 +1664,9 @@ $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} -( $as_echo "## ------------------------------------------------------ ## -## Report this to felicity@loreley.flyingparchment.org.uk ## -## ------------------------------------------------------ ##" +( $as_echo "## ---------------------------- ## +## Report this to ft@le-fay.org ## +## ---------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac @@ -1761,7 +1761,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by RT/TTS $as_me D.84.0, which was +It was created by RT/TTS $as_me D.84.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -4871,7 +4871,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by RT/TTS $as_me D.84.0, which was +This file was extended by RT/TTS $as_me D.84.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -4927,13 +4927,13 @@ $config_files Configuration headers: $config_headers -Report bugs to ." +Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -RT/TTS config.status D.84.0 +RT/TTS config.status D.84.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 6c5bed9..6d7e993 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ([2.69]) -AC_INIT([RT/TTS], [D.84.1], [ft@le-fay.org]) +AC_INIT([TTS], [D.84.1], [ft@le-fay.org]) AC_CONFIG_SRCDIR([tts.c]) AC_CONFIG_HEADERS([config.h]) From 4436927dcb01837d02911bf6cf59f3018d651370 Mon Sep 17 00:00:00 2001 From: Liss Tarnell Date: Mon, 25 Sep 2017 13:26:36 +0100 Subject: [PATCH 51/51] configure: rebuild --- configure | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/configure b/configure index cdcb1f0..3551ac0 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for RT/TTS D.84.1. +# Generated by GNU Autoconf 2.69 for TTS D.84.1. # # Report bugs to . # @@ -578,10 +578,10 @@ MFLAGS= MAKEFLAGS= # Identity of this package. -PACKAGE_NAME='RT/TTS' -PACKAGE_TARNAME='rt-tts' +PACKAGE_NAME='TTS' +PACKAGE_TARNAME='tts' PACKAGE_VERSION='D.84.1' -PACKAGE_STRING='RT/TTS D.84.1' +PACKAGE_STRING='TTS D.84.1' PACKAGE_BUGREPORT='ft@le-fay.org' PACKAGE_URL='' @@ -1240,7 +1240,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures RT/TTS D.84.1 to adapt to many kinds of systems. +\`configure' configures TTS D.84.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1288,7 +1288,7 @@ Fine tuning of the installation directories: --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] - --docdir=DIR documentation root [DATAROOTDIR/doc/rt-tts] + --docdir=DIR documentation root [DATAROOTDIR/doc/tts] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] @@ -1305,7 +1305,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of RT/TTS D.84.1:";; + short | recursive ) echo "Configuration of TTS D.84.1:";; esac cat <<\_ACEOF @@ -1392,7 +1392,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -RT/TTS configure D.84.1 +TTS configure D.84.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1761,7 +1761,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by RT/TTS $as_me D.84.1, which was +It was created by TTS $as_me D.84.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -4871,7 +4871,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by RT/TTS $as_me D.84.1, which was +This file was extended by TTS $as_me D.84.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -4933,7 +4933,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -RT/TTS config.status D.84.1 +TTS config.status D.84.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\"