1 #include "RichEdit.h"
2 
3 namespace Upp {
4 
HasNumbering(const RichPara::Format & f)5 bool HasNumbering(const RichPara::Format& f)
6 {
7 	if(f.after_number.GetCount() || f.before_number.GetCount())
8 		return true;
9 	for(int i = 0; i < 8; i++)
10 		if(f.number[i] != RichPara::NUMBER_NONE)
11 			return true;
12 	return false;
13 }
14 
RemoveBullet(bool backspace)15 bool RichEdit::RemoveBullet(bool backspace)
16 {
17 	RichPos p = text.GetRichPos(cursor);
18 	if((backspace ? p.posinpara : p.paralen) == 0 &&
19 	   (p.format.bullet != RichPara::BULLET_NONE || HasNumbering(p.format))) {
20 	    Style();
21 		RichText::FormatInfo nobullet;
22 		nobullet.paravalid = RichText::NUMBERING|RichText::BULLET;
23 		nobullet.charvalid = 0;
24 		ApplyFormatInfo(nobullet);
25 		return true;
26 	}
27 	return false;
28 }
29 
Key(dword key,int count)30 bool RichEdit::Key(dword key, int count)
31 {
32 	useraction = true;
33 	NextUndo();
34 	if(CursorKey(key, count))
35 		return true;
36 	if(IsReadOnly())
37 		return false;
38 	switch(key) {
39 	case K_CTRL_BACKSPACE:
40 		if(RemoveSelection(true)) return true;
41 		if(cursor > 0 && IsW(text[cursor - 1])) {
42 			int c = cursor;
43 			ReadFormat();
44 			MoveWordLeft(false);
45 			if(InvalidRange(cursor, c))
46 				return true;
47 			Remove(cursor, c - cursor);
48 			objectpos = -1;
49 			FinishNF();
50 			return true;
51 		}
52 	case K_BACKSPACE:
53 	case K_SHIFT_BACKSPACE:
54 		if(RemoveSelection(true)) return true;
55 		if(RemoveBullet(true)) break;
56 		if(cursor <= 0 || RemoveSpecial(cursor, cursor - 1, true))
57 			return true;
58 		anchor = --cursor;
59 		begtabsel = false;
60 		if(cursor > 0) {
61 			RichPos p = text.GetRichPos(cursor - 1);
62 			if(p.format.bullet != RichPara::BULLET_NONE || HasNumbering(p.format)) {
63 				Remove(cursor, 1, true);
64 				break;
65 			}
66 		}
67 		Remove(cursor, 1);
68 		break;
69 	case K_DELETE:
70 		if(RemoveSelection()) return true;
71 		if(cursor < text.GetLength() && !RemoveSpecial(cursor, cursor + 1, false))
72 			Remove(cursor, 1, true);
73 		break;
74 	case K_INSERT:
75 		overwrite = !overwrite;
76 		PlaceCaret();
77 		break;
78 	case K_CTRL_DELETE:
79 		if(RemoveSelection()) return true;
80 		if(cursor < text.GetLength()) {
81 			int c = cursor;
82 			if(IsW(text[c]))
83 				MoveWordRight(false);
84 			else
85 				cursor++;
86 			if(InvalidRange(cursor, c))
87 				return true;
88 			Remove(c, cursor - c);
89 			cursor = anchor = c;
90 			begtabsel = false;
91 			break;
92 		}
93 		break;
94 	case K_CTRL_Z:
95 		Undo();
96 		return true;
97 	case K_SHIFT_CTRL_Z:
98 		Redo();
99 		return true;
100 	case K_ENTER: {
101 			if(singleline)
102 				return false;
103 			if(!RemoveSelection() && InsertLineSpecial())
104 				return true;
105 			if(RemoveBullet(false))
106 				break;
107 			RichText::FormatInfo f = formatinfo;
108 			InsertLine();
109 			formatinfo = f;
110 			ShowFormat();
111 			FinishNF();
112 		}
113 		return true;
114 	case K_CTRL_ENTER:
115 		{
116 			int c = GetCursor(), l = GetLength();
117 			RichObject object;
118 			while(c < l) {
119 				RichPos p = text.GetRichPos(c);
120 				object = p.object;
121 				if(object || p.chr > ' ')
122 					break;
123 				c++;
124 			}
125 			if(object) {
126 				NextUndo();
127 				objectpos = c;
128 				RichObject o = object;
129 				o.DefaultAction(context);
130 				if(o.GetSerialId() != object.GetSerialId())
131 					ReplaceObject(o);
132 				return true;
133 			}
134 		}
135 		return false;
136 	case K_F9:
137 		EvaluateFields();
138 		break;
139 	case K_F3:
140 		Find();
141 		break;
142 	case K_CTRL_H:
143 		Hyperlink();
144 		break;
145 	case K_CTRL_Q:
146 		IndexEntry();
147 		break;
148 	case K_ESCAPE:
149 		CloseFindReplace();
150 		return false;
151 	case K_CTRL_C:
152 	case K_CTRL_INSERT:
153 		Copy();
154 		return true;
155 	case K_CTRL_X:
156 	case K_SHIFT_DELETE:
157 		Cut();
158 		return true;
159 	case K_CTRL_V:
160 	case K_SHIFT_INSERT:
161 		Paste();
162 		return true;
163 	case K_SHIFT_CTRL_SPACE:
164 	case K_CTRL_SPACE:
165 		key = 160;
166 	case K_TAB:
167 		if(cursorp.table && cursorp.posintab == cursorp.tablen) {
168 			TableInsertRow();
169 			return true;
170 		}
171 		if(cursorp.table && cursorp.posincell == cursorp.celllen) {
172 			cursor = anchor = cursor + 1;
173 			begtabsel = false;
174 			break;
175 		}
176 	default:
177 		if(key >= K_ALT_0 && key <= K_ALT_9) {
178 			ApplyStyleKey(key - K_ALT_0);
179 			return true;
180 		}
181 		if(key >= (K_SHIFT|K_ALT_0) && key <= (K_SHIFT|K_ALT_9)) {
182 			ApplyStyleKey(key - (K_SHIFT|K_ALT_0) + 10);
183 			return true;
184 		}
185 		if(key == K_SHIFT_SPACE)
186 			key = ' ';
187 		if(key == 9 || key >= 32 && key < 65536) {
188 			RichPara::Format f;
189 			if(IsSelection()) {
190 				f = text.GetRichPos(min(cursor, anchor)).format;
191 				RemoveSelection();
192 			}
193 			else
194 				f = formatinfo;
195 			RichPara p;
196 			p.format = f;
197 			p.Cat(WString(key, count), f);
198 			RichText txt;
199 			txt.SetStyles(text.GetStyles());
200 			txt.Cat(p);
201 			if(overwrite) {
202 				RichPos p = text.GetRichPos(cursor);
203 				if(p.posinpara < p.paralen)
204 					Remove(cursor, 1);
205 			}
206 			Filter(txt);
207 			Insert(cursor, txt, true);
208 			Move(cursor + count, false);
209 			break;
210 		}
211 		return false;
212 	}
213 	objectpos = -1;
214 	Finish();
215 	return true;
216 }
217 
218 }
219