long y;
} t_position;
+typedef char t_bitflag;
+
+// connects is a bitflag that encodes which sides the segment is connected to
+// it seems reasonable to use (1 << orientation)
+// UP = 1
+// LEFT = 2
+// DOWN = 4
+// RIGHT = 8
typedef struct s_node_segment
{
t_position position;
- t_symbol symbol;
+ t_bitflag connects;
} t_node_segment;
typedef struct s_node
} t_windows;
t_node *add_node(t_vec *nodes, t_state set_state);
+void remove_node(t_vec *nodes, t_node *to_remove);
t_mosfet *add_mosfet(t_vec *mosfets, t_type type, t_position pos, t_orientation orient);
t_node *get_node_by_id(t_vec *nodes, t_id id);
t_mosfet *get_mosfet_by_id(t_vec *mosfets, t_id id);
void draw_single(WINDOW *command_win, t_vec *nodes, const t_mosfet *mosfet);
void schema_draw_mosfet(WINDOW *schematics_win, t_vec *nodes, const t_mosfet *mosfet);
void schema_draw_node(WINDOW *schematics_win, const t_node *node);
+void schema_draw_segment(WINDOW *schematics_win, const t_node_segment *segment);
void update_nodes(t_vec *nodes, t_vec *mosfets);
int should_open(t_vec *nodes, const t_mosfet *mosfet);
return ;
}
-t_symbol seg_symbol_to_print(t_symbol seg_symbol)
+t_symbol seg_connects_to_symbol(t_bitflag connects)
{
- if (seg_symbol == 'd' || seg_symbol == 'u')
- return (ACS_VLINE);
- else if (seg_symbol == 'r' || seg_symbol == 'l')
- return (ACS_HLINE);
- else
- return (seg_symbol);
+ switch (connects)
+ {
+ case 0x1: return ('^');
+ case 0x2: return ('<');
+ case 0x4: return ('v');
+ case 0x8: return ('>');
+ case 0x3: return (ACS_LRCORNER);
+ case 0x6: return (ACS_URCORNER);
+ case 0xC: return (ACS_ULCORNER);
+ case 0x9: return (ACS_LLCORNER);
+ case 0x5: return (ACS_VLINE);
+ case 0xA: return (ACS_HLINE);
+ case 0x7: return (ACS_RTEE);
+ case 0xE: return (ACS_TTEE);
+ case 0xD: return (ACS_LTEE);
+ case 0xB: return (ACS_BTEE);
+ case 0xF: return (ACS_PLUS);
+ default: return ('\0');
+ }
+}
+
+void schema_draw_segment(WINDOW *schematics_win, const t_node_segment *segment)
+{
+ t_symbol symbol;
+
+ symbol = seg_connects_to_symbol(segment->connects);
+ if (symbol != '\0')
+ mvwaddch(schematics_win, segment->position.y, segment->position.x, symbol);
+ return ;
}
void schema_draw_node(WINDOW *schematics_win, const t_node *node)
{
const t_node_segment *seg;
size_t i;
- t_symbol symbol;
wattron(schematics_win, COLOR_PAIR(get_state_color(node->state)));
i = 0;
while (i < node->segments.size)
{
seg = ft_vec_caccess(&node->segments, i);
- symbol = seg_symbol_to_print(seg->symbol);
- if (symbol != ' ')
- {
- mvwaddch(schematics_win, seg->position.y, seg->position.x, symbol);
- }
+ schema_draw_segment(schematics_win, seg);
++i;
}
wattroff(schematics_win, COLOR_PAIR(get_state_color(node->state)));
return (res);
}
+static int pos_is_equal(t_position pos1, t_position pos2)
+{
+ return ((pos1.x == pos2.x) && (pos1.y == pos2.y));
+}
+
void add_terminal_segment(t_node *node, t_mosfet *mosfet, t_terminal term)
{
t_node_segment segment;
if (term == source)
{
segment.position = pos_add(mosfet_channel_rel_pos(mosfet), mosfet_up_rel_pos(mosfet));
- if (mosfet->orientation == LEFT)
- segment.symbol = 'd';
- else if (mosfet->orientation == DOWN)
- segment.symbol = 'r';
- else if (mosfet->orientation == RIGHT)
- segment.symbol = 'u';
- else if (mosfet->orientation == UP)
- segment.symbol = 'l';
+ segment.connects = 1 << ((mosfet->orientation + 1) % 4);
}
else if (term == drain)
{
segment.position = pos_sub(mosfet_channel_rel_pos(mosfet), mosfet_up_rel_pos(mosfet));
- if (mosfet->orientation == LEFT)
- segment.symbol = 'u';
- else if (mosfet->orientation == DOWN)
- segment.symbol = 'l';
- else if (mosfet->orientation == RIGHT)
- segment.symbol = 'd';
- else if (mosfet->orientation == UP)
- segment.symbol = 'r';
+ segment.connects = 1 << ((mosfet->orientation + 3) % 4);
}
else if (term == gate)
{
segment.position = pos_sub(segment.position, mosfet_channel_rel_pos(mosfet));
- if (mosfet->orientation == LEFT)
- segment.symbol = 'r';
- else if (mosfet->orientation == DOWN)
- segment.symbol = 'u';
- else if (mosfet->orientation == RIGHT)
- segment.symbol = 'l';
- else if (mosfet->orientation == UP)
- segment.symbol = 'd';
+ segment.connects = 1 << ((mosfet->orientation + 2) % 4);
}
segment.position = pos_add(segment.position, mosfet->position);
ft_vec_append(&node->segments, &segment);
}
}
+t_node_segment *find_node_seg_at_pos(t_node *node, t_position pos)
+{
+ size_t i;
+ t_node_segment *seg;
+
+ i = 0;
+ while (i < node->segments.size)
+ {
+ seg = ft_vec_access(&node->segments, i);
+ if (pos_is_equal(seg->position, pos))
+ return (seg);
+ ++i;
+ }
+ return (NULL);
+}
+
+t_node *find_node_at_pos(t_vec *nodes, t_position pos)
+{
+ size_t i;
+ t_node *node;
+
+ i = 0;
+ while (i < nodes->size)
+ {
+ node = ft_vec_access(nodes, i);
+ if (find_node_seg_at_pos(node, pos))
+ return (node);
+ ++i;
+ }
+ return (NULL);
+}
+
+t_bitflag merge_connect(t_bitflag connects1, t_bitflag connects2)
+{
+ return (connects1 | connects2);
+}
+
+int place_segment(WINDOW *schematics_win, t_node *node, t_node_segment *prediction)
+{
+ char ch;
+ t_node_segment tmp;
+
+ wmove(schematics_win, prediction->position.y, prediction->position.x);
+ ch = wgetch(schematics_win);
+ tmp = *prediction;
+ if (ch == 'l')
+ {
+ tmp.connects = 1 << LEFT;
+ ++tmp.position.x;
+ prediction->connects = merge_connect(prediction->connects, 1 << RIGHT);
+ }
+ else if (ch == 'k')
+ {
+ tmp.connects = 1 << DOWN;
+ --tmp.position.y;
+ prediction->connects = merge_connect(prediction->connects, 1 << UP);
+ }
+ else if (ch == 'j')
+ {
+ tmp.connects = 1 << UP;
+ ++tmp.position.y;
+ prediction->connects = merge_connect(prediction->connects, 1 << DOWN);
+ }
+ else if (ch == 'h')
+ {
+ tmp.connects = 1 << RIGHT;
+ --tmp.position.x;
+ prediction->connects = merge_connect(prediction->connects, 1 << LEFT);
+ }
+ else
+ return (1); // The choice not to ungetch is deliberate, because it felt weird sing it
+ ft_vec_append(&node->segments, prediction);
+ schema_draw_segment(schematics_win, prediction);
+ *prediction = tmp;
+ return (0);
+}
+
+int cmp_seg(const void *v_seg1, const void *v_seg2)
+{
+ const t_node_segment *seg1;
+ const t_node_segment *seg2;
+
+ seg1 = v_seg1;
+ seg2 = v_seg2;
+ if (seg1->position.x != seg2->position.x)
+ return ((seg1->position.x > seg2->position.x) - (seg1->position.x < seg2->position.x));
+ if (seg1->position.y != seg2->position.y)
+ return ((seg1->position.y > seg2->position.y) - (seg1->position.x < seg2->position.x));
+ return (0);
+}
+
+void schema_user_draw_node(WINDOW *schematics_win, t_vec *nodes, t_vec *mosfets, t_position pos)
+{
+ t_node *chosen_node;
+ t_node *end_node;
+ t_node_segment seg;
+ t_node_segment *merge_seg;
+ size_t index;
+
+ chosen_node = find_node_at_pos(nodes, pos);
+ if (!chosen_node)
+ {
+ chosen_node = add_node(nodes, floating);
+ seg.position = pos;
+ seg.connects = 0;
+ }
+ else
+ {
+ // I'm finding the seg twice here
+ seg = *find_node_seg_at_pos(chosen_node, pos);
+ ft_vec_find_index(&chosen_node->segments, &seg, &index, cmp_seg);
+ ft_vec_erase(&chosen_node->segments, index, NULL);
+ }
+ while (!place_segment(schematics_win, chosen_node, &seg));
+ if (chosen_node->segments.size == 0)
+ {
+ remove_node(nodes, chosen_node);
+ return ;
+ }
+ end_node = find_node_at_pos(nodes, seg.position);
+ if (end_node)
+ {
+ merge_seg = find_node_seg_at_pos(end_node, seg.position);
+ merge_seg->connects = merge_connect(merge_seg->connects, seg.connects);
+ if (end_node->id != chosen_node->id)
+ merge_nodes(nodes, mosfets, chosen_node, end_node);
+ schema_draw_segment(schematics_win, merge_seg);
+ }
+ else
+ {
+ ft_vec_append(&chosen_node->segments, &seg);
+ schema_draw_segment(schematics_win, &seg);
+ }
+ wmove(schematics_win, seg.position.y, seg.position.x);
+ return ;
+}
+
int handle_key_press(int ch, WINDOW *schematics_win, t_vec *nodes, t_vec *mosfets)
{
t_position pos;
wmove(schematics_win, --pos.y, pos.x);
else if (ch == 't')
schema_add_mosfet(schematics_win, nodes, mosfets, pos);
+ else if (ch == 'c')
+ schema_user_draw_node(schematics_win, nodes, mosfets, pos);
return (0);
}