summaryrefslogtreecommitdiffstats
path: root/contrib/replxx/src/killring.hxx
blob: 0baf108e73e534f5b1b9c4760e21bd48994ff86f (plain)
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
#ifndef REPLXX_KILLRING_HXX_INCLUDED
#define REPLXX_KILLRING_HXX_INCLUDED 1

#include <vector>

#include "unicodestring.hxx"

namespace replxx {

class KillRing {
	static const int capacity = 10;
	int size;
	int index;
	char indexToSlot[10];
	std::vector<UnicodeString> theRing;

public:
	enum action { actionOther, actionKill, actionYank };
	action lastAction;

	KillRing()
		: size(0)
		, index(0)
		, lastAction(actionOther) {
		theRing.reserve(capacity);
	}

	void kill(const char32_t* text, int textLen, bool forward) {
		if (textLen == 0) {
			return;
		}
		UnicodeString killedText(text, textLen);
		if (lastAction == actionKill && size > 0) {
			int slot = indexToSlot[0];
			int currentLen = static_cast<int>(theRing[slot].length());
			UnicodeString temp;
			if ( forward ) {
				temp.append( theRing[slot].get(), currentLen ).append( killedText.get(), textLen );
			} else {
				temp.append( killedText.get(), textLen ).append( theRing[slot].get(), currentLen );
			}
			theRing[slot] = temp;
		} else {
			if (size < capacity) {
				if (size > 0) {
					memmove(&indexToSlot[1], &indexToSlot[0], size);
				}
				indexToSlot[0] = size;
				size++;
				theRing.push_back(killedText);
			} else {
				int slot = indexToSlot[capacity - 1];
				theRing[slot] = killedText;
				memmove(&indexToSlot[1], &indexToSlot[0], capacity - 1);
				indexToSlot[0] = slot;
			}
			index = 0;
		}
	}

	UnicodeString* yank() { return (size > 0) ? &theRing[indexToSlot[index]] : 0; }

	UnicodeString* yankPop() {
		if (size == 0) {
			return 0;
		}
		++index;
		if (index == size) {
			index = 0;
		}
		return &theRing[indexToSlot[index]];
	}
};

}

#endif