about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorJames Booth <boothj5@gmail.com>2017-03-24 19:53:41 +0000
committerJames Booth <boothj5@gmail.com>2017-03-24 19:53:41 +0000
commitb19e02db91b6fc1fc56242953f1c48c4d84a1e8b (patch)
tree146286502166ce8d4c30bed162f6251148544f6c
parentf1a5d12950301d762c3a2465c768676730229eab (diff)
parent91bc302acfebea5aec70513401fec2b5d0f57a87 (diff)
downloadprofani-tty-b19e02db91b6fc1fc56242953f1c48c4d84a1e8b.tar.gz
Merge remote-tracking branch 'edoiks/upstream'
-rw-r--r--src/config/theme.c3
-rw-r--r--src/config/theme.h1
-rw-r--r--src/ui/console.c1
-rw-r--r--src/ui/statusbar.c3
4 files changed, 8 insertions, 0 deletions
diff --git a/src/config/theme.c b/src/config/theme.c
index 2d418f73..5a44e370 100644
--- a/src/config/theme.c
+++ b/src/config/theme.c
@@ -104,6 +104,7 @@ theme_init(const char *const theme_name)
     g_hash_table_insert(defaults, strdup("statusbar.brackets"),      strdup("cyan"));
     g_hash_table_insert(defaults, strdup("statusbar.active"),        strdup("cyan"));
     g_hash_table_insert(defaults, strdup("statusbar.new"),           strdup("white"));
+    g_hash_table_insert(defaults, strdup("statusbar.time"),          strdup("white"));
     g_hash_table_insert(defaults, strdup("me"),                      strdup("yellow"));
     g_hash_table_insert(defaults, strdup("them"),                    strdup("green"));
     g_hash_table_insert(defaults, strdup("receipt.sent"),            strdup("red"));
@@ -755,6 +756,7 @@ theme_attrs(theme_item_t attrs)
     case THEME_STATUS_BRACKET:          _theme_prep_fgnd("statusbar.brackets",      lookup_str, &bold); break;
     case THEME_STATUS_ACTIVE:           _theme_prep_fgnd("statusbar.active",        lookup_str, &bold); break;
     case THEME_STATUS_NEW:              _theme_prep_fgnd("statusbar.new",           lookup_str, &bold); break;
+    case THEME_STATUS_TIME:             _theme_prep_fgnd("statusbar.time",          lookup_str, &bold); break;
     case THEME_ME:                      _theme_prep_fgnd("me",                      lookup_str, &bold); break;
     case THEME_THEM:                    _theme_prep_fgnd("them",                    lookup_str, &bold); break;
     case THEME_RECEIPT_SENT:            _theme_prep_fgnd("receipt.sent",            lookup_str, &bold); break;
@@ -843,6 +845,7 @@ theme_attrs(theme_item_t attrs)
     case THEME_STATUS_BRACKET:
     case THEME_STATUS_ACTIVE:
     case THEME_STATUS_NEW:
+    case THEME_STATUS_TIME:
         _theme_prep_bgnd("statusbar", "blue", lookup_str);
         break;
     default:
diff --git a/src/config/theme.h b/src/config/theme.h
index 6e9d13eb..747eace1 100644
--- a/src/config/theme.h
+++ b/src/config/theme.h
@@ -69,6 +69,7 @@ typedef enum {
     THEME_STATUS_BRACKET,
     THEME_STATUS_ACTIVE,
     THEME_STATUS_NEW,
+    THEME_STATUS_TIME,
     THEME_ME,
     THEME_THEM,
     THEME_ROOMINFO,
diff --git a/src/ui/console.c b/src/ui/console.c
index 64f44c52..4c24b450 100644
--- a/src/ui/console.c
+++ b/src/ui/console.c
@@ -2224,6 +2224,7 @@ cons_theme_properties(void)
     _cons_theme_bar_prop(THEME_STATUS_BRACKET, "statusbar.brackets");
     _cons_theme_bar_prop(THEME_STATUS_ACTIVE, "statusbar.active");
     _cons_theme_bar_prop(THEME_STATUS_NEW, "statusbar.new");
+    _cons_theme_bar_prop(THEME_STATUS_TIME, "statusbar.time");
 
     _cons_theme_prop(THEME_TIME, "main.time");
     _cons_theme_prop(THEME_TEXT, "main.text");
diff --git a/src/ui/statusbar.c b/src/ui/statusbar.c
index d19b5618..7998d7b4 100644
--- a/src/ui/statusbar.c
+++ b/src/ui/statusbar.c
@@ -459,6 +459,7 @@ _status_bar_draw(void)
     last_time = g_date_time_new_now(tz);
 
     int bracket_attrs = theme_attrs(THEME_STATUS_BRACKET);
+    int time_attrs = theme_attrs(THEME_STATUS_TIME);
 
     char *time_pref = prefs_get_string(PREF_TIME_STATUSBAR);
     if (g_strcmp0(time_pref, "off") != 0) {
@@ -468,7 +469,9 @@ _status_bar_draw(void)
         wattron(status_bar, bracket_attrs);
         mvwaddch(status_bar, 0, 1, '[');
         wattroff(status_bar, bracket_attrs);
+        wattron(status_bar, time_attrs);
         mvwprintw(status_bar, 0, 2, date_fmt);
+        wattroff(status_bar, time_attrs);
         wattron(status_bar, bracket_attrs);
         mvwaddch(status_bar, 0, 2 + len, ']');
         wattroff(status_bar, bracket_attrs);
ktick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
#ifndef TERMIOS_H
#define TERMIOS_H

//This file will also be included by C library.

typedef unsigned char       cc_t;
typedef unsigned int        speed_t;
typedef unsigned int        tcflag_t;

#define NCCS 32

struct termios {
    tcflag_t c_iflag;        // input mode flags
    tcflag_t c_oflag;        // output mode flags
    tcflag_t c_cflag;        // control mode flags
    tcflag_t c_lflag;        // local mode flags
    cc_t c_line;             // line discipline
    cc_t c_cc[NCCS];         // control characters
    speed_t c_ispeed;        // input speed
    speed_t c_ospeed;        // output speed

  };

// c_cc characters
#define VINTR 0
#define VQUIT 1
#define VERASE 2
#define VKILL 3
#define VEOF 4
#define VTIME 5
#define VMIN 6
#define VSWTC 7
#define VSTART 8
#define VSTOP 9
#define VSUSP 10
#define VEOL 11
#define VREPRINT 12
#define VDISCARD 13
#define VWERASE 14
#define VLNEXT 15
#define VEOL2 16

// c_iflag bits
#define IGNBRK        0000001
#define BRKINT        0000002
#define IGNPAR        0000004
#define PARMRK        0000010
#define INPCK        0000020
#define ISTRIP        0000040
#define INLCR        0000100
#define IGNCR        0000200
#define ICRNL        0000400
#define IUCLC        0001000
#define IXON        0002000
#define IXANY        0004000
#define IXOFF        0010000
#define IMAXBEL        0020000
#define IUTF8        0040000

// c_oflag bits
#define OPOST        0000001
#define OLCUC        0000002
#define ONLCR        0000004
#define OCRNL        0000010
#define ONOCR        0000020
#define ONLRET        0000040
#define OFILL        0000100
#define OFDEL        0000200
#define NLDLY        0000400
#define   NL0        0000000
#define   NL1        0000400
#define CRDLY     span>{
      // Primitive Recipe Checks
      case COPY: {
        if (SIZE(inst.products) != SIZE(inst.ingredients)) {
          raise << maybe(get(Recipe, r).name) << "ingredients and products should match in '" << inst.original_string << "'\n" << end();
          break;
        }
        for (int i = 0; i < SIZE(inst.ingredients); ++i) {
          if (!types_coercible(inst.products.at(i), inst.ingredients.at(i))) {
            raise << maybe(get(Recipe, r).name) << "can't copy '" << inst.ingredients.at(i).original_string << "' to '" << inst.products.at(i).original_string << "'; types don't match\n" << end();
            goto finish_checking_instruction;
          }
        }
        break;
      }
      // End Primitive Recipe Checks
      default: {
        // Defined Recipe Checks
        // End Defined Recipe Checks
      }
    }
    finish_checking_instruction:;
  }
}

:(scenario copy_checks_reagent_count)
% Hide_errors = true;
def main [
  1:number <- copy 34, 35
]
+error: main: ingredients and products should match in '1:number <- copy 34, 35'

:(scenario write_scalar_to_array_disallowed)
% Hide_errors = true;
def main [
  1:array:number <- copy 34
]
+error: main: can't copy '34' to '1:array:number'; types don't match

:(scenario write_scalar_to_array_disallowed_2)
% Hide_errors = true;
def main [
  1:number, 2:array:number <- copy 34, 35
]
+error: main: can't copy '35' to '2:array:number'; types don't match

:(scenario write_scalar_to_address_disallowed)
% Hide_errors = true;
def main [
  1:address:number <- copy 34
]
+error: main: can't copy '34' to '1:address:number'; types don't match

:(scenario write_address_to_number_allowed)
def main [
  1:address:number <- copy 12/unsafe
  2:number <- copy 1:address:number
]
+mem: storing 12 in location 2
$error: 0

:(scenario write_boolean_to_number_allowed)
def main [
  1:boolean <- copy 1/true
  2:number <- copy 1:boolean
]
+mem: storing 1 in location 2
$error: 0

:(scenario write_number_to_boolean_allowed)
def main [
  1:number <- copy 34
  2:boolean <- copy 1:number
]
+mem: storing 34 in location 2
$error: 0

:(code)
// types_match with some leniency
bool types_coercible(const reagent& to, const reagent& from) {
  if (types_match(to, from)) return true;
  if (is_mu_address(from) && is_mu_number(to)) return true;
  if (is_mu_boolean(from) && is_mu_number(to)) return true;
  if (is_mu_number(from) && is_mu_boolean(to)) return true;
  // End types_coercible Special-cases
  return false;
}

bool types_match(const reagent& to, const reagent& from) {
  // to sidestep type-checking, use /unsafe in the source.
  // this will be highlighted in red inside vim. just for setting up some tests.
  if (is_unsafe(from)) return true;
  if (is_literal(from)) {
    if (is_mu_array(to)) return false;
    // End Matching Types For Literal(to)
    // allow writing 0 to any address
    if (is_mu_address(to)) return from.name == "0";
    if (!to.type) return false;
    if (to.type->value == get(Type_ordinal, "boolean"))
      return boolean_matches_literal(to, from);
    return size_of(to) == 1;  // literals are always scalars
  }
  return types_strictly_match(to, from);
}

bool boolean_matches_literal(const reagent& to, const reagent& from) {
  if (!is_literal(from)) return false;
  if (!to.type) return false;
  if (to.type->value != get(Type_ordinal, "boolean")) return false;
  return from.name == "0" || from.name == "1";
}

// copy arguments because later layers will want to make changes to them
// without perturbing the caller
bool types_strictly_match(reagent/*copy*/ to, reagent/*copy*/ from) {
  // End Preprocess types_strictly_match(reagent to, reagent from)
  if (is_literal(from) && to.type->value == get(Type_ordinal, "number")) return true;
  // to sidestep type-checking, use /unsafe in the source.
  // this will be highlighted in red inside vim. just for setting up some tests.
  if (is_unsafe(from)) return true;
  // '_' never raises type error
  if (is_dummy(to)) return true;
  if (!to.type) return !from.type;
  return types_strictly_match(to.type, from.type);
}

// two types match if the second begins like the first
// (trees perform the same check recursively on each subtree)
bool types_strictly_match(const type_tree* to, const type_tree* from) {
  if (!to) return true;
  if (!from) return to->value == 0;
  if (from->value == -1) return from->name == to->name;
  if (to->value != from->value) return false;
  return types_strictly_match(to->left, from->left) && types_strictly_match(to->right, from->right);
}

void test_unknown_type_does_not_match_unknown_type() {
  reagent a("a:foo");
  reagent b("b:bar");
  CHECK(!types_strictly_match(a, b));
}

void test_unknown_type_matches_itself() {
  reagent a("a:foo");
  reagent b("b:foo");
  CHECK(types_strictly_match(a, b));
}

bool is_unsafe(const reagent& r) {
  return has_property(r, "unsafe");
}

bool is_mu_array(reagent/*copy*/ r) {
  // End Preprocess is_mu_array(reagent r)
  if (!r.type) return false;
  if (is_literal(r)) return false;
  return r.type->value == get(Type_ordinal, "array");
}

bool is_mu_address(reagent/*copy*/ r) {
  // End Preprocess is_mu_address(reagent r)
  if (!r.type) return false;
  if (is_literal(r)) return false;
  return r.type->value == get(Type_ordinal, "address");
}

bool is_mu_boolean(reagent/*copy*/ r) {
  // End Preprocess is_mu_boolean(reagent r)
  if (!r.type) return false;
  if (is_literal(r)) return false;
  return r.type->value == get(Type_ordinal, "boolean");
}

bool is_mu_number(reagent/*copy*/ r) {
  // End Preprocess is_mu_number(reagent r)
  if (!r.type) return false;
  if (is_literal(r)) {
    if (!r.type) return false;
    return r.type->name == "literal-fractional-number"
        || r.type->name == "literal";
  }
  if (r.type->value == get(Type_ordinal, "character")) return true;  // permit arithmetic on unicode code points
  return r.type->value == get(Type_ordinal, "number");
}

bool is_mu_scalar(reagent/*copy*/ r) {
  if (!r.type) return false;
  if (is_literal(r))
    return !r.type || r.type->name != "literal-string";
  if (is_mu_array(r)) return false;
  return size_of(r) == 1;
}