File: macro.c

package info (click to toggle)
aoeui 1.1.1-1
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 348 kB
  • ctags: 487
  • sloc: ansic: 5,248; makefile: 67
file content (120 lines) | stat: -rw-r--r-- 2,517 bytes parent folder | download
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
#include "all.h"

struct macro {
	int start, bytes, at, repeat;
	struct macro *next, *suspended;
};

struct macro *function_key[FUNCTION_KEYS+1];

static struct buffer *macbuf;
static struct macro *macros;
static struct macro *recording, *playing;

struct macro *macro_record(void)
{
	struct macro *new;
	if (!macbuf)
		macbuf = buffer_create(NULL);
	new = allocate0(sizeof *new);
	new->next = macros;
	new->start = buffer_bytes(macbuf);
	return macros = recording = new;
}

int macro_end_recording(unsigned chop)
{
	char *raw;
	unsigned n;

	if (!recording)
		return 0;
	n = buffer_raw(macbuf, &raw, recording->start,
		       recording->bytes);
	while (n) {
		unsigned lastlen = utf8_length_backwards(raw+n-1, n);
		n -= lastlen;
		if (utf8_unicode(raw+n, lastlen) == chop)
			break;
	}
	buffer_delete(macbuf, recording->start + n, recording->bytes - n);
	recording->bytes = n;
	recording->at = recording->bytes; /* not playing */
	recording = NULL;
	return 1;
}

static int macro_is_playing(struct macro *macro)
{
	return macro && macro->at < macro->bytes;
}

int macro_play(struct macro *macro, int repeat)
{
	if (!macro ||
	    macro_is_playing(macro) ||
	    !macro->bytes)
		return 0;
	macro->suspended = playing;
	macro->at = 0;
	macro->repeat = repeat;
	playing = macro;
	return 1;
}

void macros_abort(void)
{
	for (; playing; playing = playing->suspended)
		playing->at = playing->bytes;
}

void macro_free(struct macro *macro)
{
	struct macro *previous = NULL, *mac, *next;
	if (!macro)
		return;
	if (recording)
		recording = NULL;
	else if (macro_is_playing(macro))
		macros_abort();
	for (mac = macros; mac != macro; previous = mac, mac = next) {
		next = mac->next;
		if (mac == macro)
			if (previous)
				previous->next = next;
			else
				macros = next;
		else if (mac->start > macro->start)
			mac->start -= macro->bytes;
	}
	buffer_delete(macbuf, macro->start, macro->bytes);
	allocate(macro, 0);
}

int macro_getch(void)
{
	int ch;

	if (playing) {
		char *p;
		unsigned n = buffer_raw(macbuf, &p, playing->start + playing->at,
					playing->bytes - playing->at);
		ch = utf8_unicode(p, n = utf8_length(p, n));
		if ((playing->at += n) == playing->bytes)
			if (playing->repeat-- > 0)
				playing->at = 0;
			else
				playing = playing->suspended;
	} else {
		ch = window_getch();
		if (ch >= 0 && recording) {
			char buf[8];
			int n = utf8_out(buf, ch);
			buffer_insert(macbuf, buf,
				      recording->start + recording->bytes,
				      n);
			recording->bytes += n;
		}
	}
	return ch;
}