all repos — kuro @ 5040da40fc3dfc7f26527ba52a866e960eb5f83a

multiwindow text editor thing for plan9 with simple client VM and 9p interface

node.c (raw)

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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include "dat.h"
#include "fns.h"


void node_setup(Node* self, Handler* handlers, KuroMemory* memory) {
  if (self) {
    self->handlers = handlers;
    self->memory = memory;
    self->cpu = chancreate(sizeof(Instruction), 0);
    self->status = chancreate(sizeof(WindowStatus), 0);
  }
}
void node_loop(void* data) {
  Node* self = (Node*)data;
  Instruction x;

  for (;;) {
    recv(self->cpu, &x);
    if (self->handlers[x.opcode]) {
      (*(self->handlers[x.opcode]))(self, x.data);
      switch(self->memory->status) {
        case KURO_QUITS:
		  nbsend(self->status, 0);
          threadexits(0);
        default:
          break;
      }
      flushimage(self->memory->screen->display, 1);
    }
  }
}

void node_execute(Node* self) {
  threadcreate(node_loop, self, 1024);
}

Node* create_node(char* filename) {

  initdraw(nil, nil, "kuro");
  unlockdisplay(display);

  KuroMemory* self = (KuroMemory*)malloc(sizeof(KuroMemory));
  Node* node = (Node*)malloc(sizeof(Node));
  Handler* handlers = (Handler*)malloc(TOTAL_OPCODES * sizeof(Handler*));

  node_setup(node, handlers, self);

  self->img = screen;
  self->screen = _screen;
  if (filename) {
    strcpy(self->filepath, filename);
  }

  /* node_execute runs the node on a separate thread */
  node_execute(node);

  return node;
}

void supervise_node(Node* self) {

  Mousectl* mctl;
  Keyboardctl* kctl;
  Mouse mouse;
  int resize[2];
  WindowStatus status;
  Rune kbd;

  if ((mctl = initmouse(nil, screen)) == nil) {
    sysfatal("couldn't initialize mctl");
  }
  if ((kctl = initkeyboard(nil)) == nil) {
    sysfatal("couldn't initialize kctl");
  }

  Alt alts[TOTAL_PORTS + 1] = {
    {mctl->c, &mouse, CHANRCV},
    {mctl->resizec, resize, CHANRCV},
    {kctl->c, &kbd, CHANRCV},
    {self->status, &status, CHANRCV},
    {nil, nil, CHANEND}
  };

  for (;;) {
    switch (alt(alts)) {
      case PORT_MOUSE:
        print("got a mouse event");
        break;
      case PORT_RESIZE:
        /*if (getwindow(display, Refnone) < 0)
          sysfatal("couldn't resize");*/
        print("got a resize event");
        break;
      case PORT_KBD:
        print("got a keypress");
        break;
      case PORT_STATUS:
        switch(status) {
          case KURO_QUITS:
            print("VM died - let's clean up the data");
            goto cleanup;
          default:
            break;
        }
        break;
    }
  }
cleanup:
  node_cleanup(self);
}

void node_cleanup(Node* self) {
  if (self) {
    memory_cleanup(self->memory);
    chanfree(self->cpu);
    chanfree(self->status);
    /* TODO: send message on self->fd to tell the server to remove us from NodeTable and filetree */
    /* handlers array is shared between all the nodes */
    free(self);
  }
}

void memory_cleanup(KuroMemory* self) {
  if (self) {
    /* do we need to free the img and screen? */
  }
}