about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--main.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/main.c b/main.c
index 42c9d8a..b59ff96 100644
--- a/main.c
+++ b/main.c
@@ -190,6 +190,7 @@ main(int argc, char *argv[])
 	fd_set rd;
 	XSetWindowAttributes wa;
 	unsigned int mask;
+	Bool readstdin = True;
 	Window w;
 	XEvent ev;
 
@@ -283,7 +284,8 @@ main(int argc, char *argv[])
 Mainloop:
 	while(running) {
 		FD_ZERO(&rd);
-		FD_SET(STDIN_FILENO, &rd);
+		if(readstdin)
+			FD_SET(STDIN_FILENO, &rd);
 		FD_SET(ConnectionNumber(dpy), &rd);
 
 		i = select(ConnectionNumber(dpy) + 1, &rd, 0, 0, 0);
@@ -299,11 +301,13 @@ Mainloop:
 						(handler[ev.type])(&ev); /* call handler */
 				}
 			}
-			if(FD_ISSET(STDIN_FILENO, &rd)) {
+			if(readstdin && FD_ISSET(STDIN_FILENO, &rd)) {
 				i = n = 0;
 				for(;;) {
 					if((i = getchar()) == EOF) {
-						stext[0] = 0;
+						/* broken pipe/end of producer */
+						readstdin = False;
+						strcpy(stext, "broken pipe");
 						goto Mainloop;
 					}
 					if(i == '\n' || n >= sizeof(stext) - 1)
ercase' href='/akkartik/mu/commit/068error-byte.subx?h=main&id=333525360b22f3d3ea31db46a4d2f1b4edbfebdb'>33352536 ^
79328f9a ^
8188bbbc ^
33352536 ^

8188bbbc ^
79328f9a ^



33352536 ^

79328f9a ^


33352536 ^
79328f9a ^


33352536 ^
79328f9a ^

33352536 ^

79328f9a ^


33352536 ^
79328f9a ^


33352536 ^
79328f9a ^


33352536 ^
f2cd405d ^
79328f9a ^
33352536 ^

79328f9a ^
f2cd405d ^
79328f9a ^
33352536 ^
79328f9a ^


33352536 ^
79328f9a ^


33352536 ^
79328f9a ^

33352536 ^
79328f9a ^


33352536 ^
79328f9a ^


33352536 ^
79328f9a ^




33352536 ^

79328f9a ^


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91






                                                                                                                                                 
                        


                                                                                                                                                                            

                                        
                                                                                                                                                                       


                                          
                            
                  
pre { line-height: 125%; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .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 */
import css/selectorparser
import css/values
import html/dom
import html/tags

# Container to hold a style and a node.
# Pseudo-elements are implemented using StyledNode objects without nodes. Input
# elements are implemented as internal "pseudo-elements."
#
# To avoid having to invalidate the entire tree on pseudo-class changes, each
# node holds a list of nodes their CSS values depend on. (This list may include
# the node itself.) In addition, nodes also store each value valid for
# dependency d. These are then used for checking the validity of StyledNodes.
#
# In other words - say we have to apply the author stylesheets of the following
# document:
#
# <style>
# div:hover { color: red; }
# :not(input:checked) + p { display: none; }
# </style>
# <div>This div turns red on hover.</div>
# <input type=checkbox>
# <p>This paragraph is only shown when the checkbox above is checked.
#
# That produces the following dependency graph (simplified):
# div -> div (hover)
# p -> input (checked)
#
# Then, to check if a node has been invalidated, we just iterate over all
# recorded dependencies of each StyledNode, and check if their registered value
# of the pseudo-class still matches that of its associated element.
#
# So in our example, for div we check if div's :hover pseudo-class has changed,
# for p we check whether input's :checked pseudo-class has changed.

type
  StyledType* = enum
    STYLED_ELEMENT, STYLED_TEXT

  DependencyType* = enum
    DEPEND_HOVER, DEPEND_CHECKED, DEPEND_FOCUS

  DependencyInfo* = object
    # All nodes we depend on, for each dependency type d.
    nodes*: array[DependencyType, seq[StyledNode]]
    # Previous value. The owner StyledNode is marked as invalid when one of
    # these no longer matches the DOM value.
    prev: array[DependencyType, bool]

  StyledNode* = ref object
    parent*: StyledNode
    node*: Node
    pseudo*: PseudoElem #TODO this should be in element only
    case t*: StyledType
    of STYLED_TEXT:
      text*: string
    of STYLED_ELEMENT:
      computed*: CSSComputedValues
      children*: seq[StyledNode]
      depends*: DependencyInfo

iterator branch*(node: StyledNode): StyledNode {.inline.} =
  var node = node
  while node != nil:
    yield node
    node = node.parent

iterator children_rev*(node: StyledNode): StyledNode {.inline.} =
  for i in countdown(node.children.high, 0):
    yield node.children[i]

func isDomElement*(styledNode: StyledNode): bool {.inline.} =
  styledNode.t == STYLED_ELEMENT and styledNode.pseudo == PSEUDO_NONE

func checked(element: Element): bool =
  if element.tagType == TAG_INPUT:
    let input = HTMLInputElement(element)
    result = input.checked

func isValid*(styledNode: StyledNode): bool =
  if styledNode.t == STYLED_TEXT:
    return true
  if styledNode.node != nil and Element(styledNode.node).invalid:
    return false
  for d in DependencyType:
    for child in styledNode.depends.nodes[d]:
      assert child.node != nil
      let elem = Element(child.node)
      case d
      of DEPEND_HOVER:
        if child.depends.prev[d] != elem.hover:
          return false
      of DEPEND_CHECKED:
        if child.depends.prev[d] != elem.checked:
          return false
      of DEPEND_FOCUS:
        let focus = elem.document.focus == elem
        if child.depends.prev[d] != focus:
          return false
  return true

proc applyDependValues*(styledNode: StyledNode) =
  let elem = Element(styledNode.node)
  styledNode.depends.prev[DEPEND_HOVER] = elem.hover
  styledNode.depends.prev[DEPEND_CHECKED] = elem.checked
  let focus = elem.document.focus == elem
  styledNode.depends.prev[DEPEND_FOCUS] = focus
  elem.invalid = false

proc addDependency*(styledNode, dep: StyledNode, t: DependencyType) =
  if dep notin styledNode.depends.nodes[t]:
    styledNode.depends.nodes[t].add(dep)

func newStyledElement*(parent: StyledNode, element: Element, computed: CSSComputedValues, reg: sink DependencyInfo): StyledNode =
  result = StyledNode(t: STYLED_ELEMENT, computed: computed, node: element, parent: parent)
  result.depends = reg
  result.parent = parent

func newStyledElement*(parent: StyledNode, element: Element): StyledNode =
  result = StyledNode(t: STYLED_ELEMENT, node: element, parent: parent)
  result.parent = parent

# Root
func newStyledElement*(element: Element): StyledNode =
  result = StyledNode(t: STYLED_ELEMENT, node: element)

func newStyledElement*(parent: StyledNode, pseudo: PseudoElem, computed: CSSComputedValues, reg: sink DependencyInfo): StyledNode =
  result = StyledNode(t: STYLED_ELEMENT, computed: computed, pseudo: pseudo, parent: parent)
  result.depends = reg
  result.parent = parent

func newStyledElement*(parent: StyledNode, pseudo: PseudoElem, computed: CSSComputedValues): StyledNode =
  result = StyledNode(t: STYLED_ELEMENT, computed: computed, pseudo: pseudo, parent: parent)
  result.parent = parent

func newStyledText*(parent: StyledNode, text: string): StyledNode =
  result = StyledNode(t: STYLED_TEXT, text: text, parent: parent)
  result.parent = parent

func newStyledText*(parent: StyledNode, text: Text): StyledNode =
  result = StyledNode(t: STYLED_TEXT, text: text.data, node: text, parent: parent)
  result.parent = parent