File: macro.c

package info (click to toggle)
aoeui 1.7%2B20160302.git4e5dee9-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 532 kB
  • sloc: ansic: 6,860; makefile: 294; sh: 11
file content (121 lines) | stat: -rw-r--r-- 2,618 bytes parent folder | download | duplicates (4)
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
/* Copyright 2007, 2008 Peter Klausler.  See COPYING for license. */
#include "all.h"

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

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;
}

Boolean_t macro_end_recording(Unicode_t chop)
{
	char *raw;
	size_t n;

	if (!recording)
		return FALSE;
	n = buffer_raw(macbuf, &raw, recording->start,
		       recording->bytes);
	while (n) {
		size_t 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 TRUE;
}

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

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

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);
	RELEASE(macro);
}

Unicode_t macro_getch(void)
{
	Unicode_t ch;

	if (playing) {
		char *p;
		size_t 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-- > 1)
				playing->at = 0;
			else
				playing = playing->suspended;
	} else {
		ch = window_getch();
		if (!IS_ERROR_CODE(ch) && recording) {
			char buf[8];
			size_t n = unicode_utf8(buf, ch);
			buffer_insert(macbuf, buf,
				      recording->start + recording->bytes,
				      n);
			recording->bytes += n;
		}
	}
	return ch;
}