Mercurial > ~dholland > hg > ag > index.cgi
comparison examples/dsl/query.cpp @ 0:13d2b8934445
Import AnaGram (near-)release tree into Mercurial.
author | David A. Holland |
---|---|
date | Sat, 22 Dec 2007 17:52:45 -0500 |
parents | |
children | ec2b657edf13 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:13d2b8934445 |
---|---|
1 /***** | |
2 | |
3 AnaGram Programming Examples | |
4 | |
5 A Dos Script Language | |
6 Query Table Module | |
7 | |
8 Copyright 1993 Parsifal Software. All Rights Reserved. | |
9 | |
10 This software is provided 'as-is', without any express or implied | |
11 warranty. In no event will the authors be held liable for any damages | |
12 arising from the use of this software. | |
13 | |
14 Permission is granted to anyone to use this software for any purpose, | |
15 including commercial applications, and to alter it and redistribute it | |
16 freely, subject to the following restrictions: | |
17 | |
18 1. The origin of this software must not be misrepresented; you must not | |
19 claim that you wrote the original software. If you use this software | |
20 in a product, an acknowledgment in the product documentation would be | |
21 appreciated but is not required. | |
22 2. Altered source versions must be plainly marked as such, and must not be | |
23 misrepresented as being the original software. | |
24 3. This notice may not be removed or altered from any source distribution. | |
25 | |
26 *****/ | |
27 | |
28 #include "query.h" | |
29 #include "screen.h" | |
30 #include "symbol.h" | |
31 #include "util.h" | |
32 #include "edit.h" | |
33 #include <ctype.h> | |
34 #include <stdlib.h> | |
35 | |
36 #if defined(__MSDOS__) || defined(__WINDOWS__) | |
37 #include <conio.h> | |
38 #else | |
39 /* This is only meant to compile, not run. (Unix) */ | |
40 static int getch(void) { return '?'; } | |
41 #endif | |
42 | |
43 // Editing keystrokes | |
44 | |
45 #define BACKSPACE '\b' | |
46 #define BACKTAB 271 | |
47 #define LEFT 331 | |
48 #define DELETE 339 | |
49 #define ESCAPE 27 | |
50 #define DOWN 336 | |
51 #define RIGHT 333 | |
52 #define TAB '\t' | |
53 #define UP 328 | |
54 #define HOME 327 | |
55 #define END 335 | |
56 | |
57 | |
58 void perform_action(action_pointer); | |
59 | |
60 int get_key(void) { | |
61 int key = getch(); | |
62 if (key == 0) key = 256 + getch(); | |
63 if (key == 3) { | |
64 printf("\n^C"); | |
65 exit(1); | |
66 } | |
67 return key; | |
68 } | |
69 | |
70 void expand_formula(const int *s) { | |
71 ++sa; | |
72 while (*s) { | |
73 switch (st[*s].type) { | |
74 case value_type: | |
75 case string_type: { | |
76 sa << st[*s].data.text; | |
77 break; | |
78 } | |
79 case integer_type: { | |
80 sa.printf("%d", st[*s].data.integer); | |
81 break; | |
82 } | |
83 default: { | |
84 sa << sd[*s]; | |
85 } | |
86 } | |
87 s++; | |
88 } | |
89 } | |
90 | |
91 screen_rect &operator << (screen_rect &r, const int *s) { | |
92 expand_formula(s); | |
93 r << (sa--).top(); | |
94 return r; | |
95 } | |
96 | |
97 // Query Table Class | |
98 | |
99 // Constructor | |
100 | |
101 query_table::query_table(stack<query_item> &qs, screen_descriptor *scd) { | |
102 int i = 0; | |
103 int j; | |
104 | |
105 title = scd->title; | |
106 color = scd->color; | |
107 entry_color = scd->entry_color; | |
108 highlight_color = scd->highlight_color; | |
109 height = scd->height; | |
110 width = scd-> width; | |
111 if (scd->pos.x >= 0) | |
112 window_box = at(scd->pos.x,scd->pos.y).rect(width,height,0); | |
113 else window_box = at(0,0).rect(width,height,11); | |
114 height -= 2; | |
115 width -= 4; | |
116 window = window_box.rect(width,height); | |
117 previous = contents(window_box); | |
118 | |
119 nq = size(qs); // Number of fields | |
120 q = new query_item[nq]; // Query items | |
121 sr = new screen_rect[nq]; // screen position | |
122 field_color = new unsigned char[nq]; // color | |
123 | |
124 | |
125 j = nq; | |
126 for (j = nq, i = 0; j--; i++) { | |
127 unsigned index; | |
128 q[i] = qs[j]; | |
129 if (q[i].value == NULL) continue; | |
130 index = q[i].id; | |
131 release(st[index]); | |
132 st[index].type = value_type; | |
133 expand_formula(q[i].value); | |
134 st[index].data.text = copy(sa--); | |
135 } | |
136 current_field = 0; | |
137 resize(); | |
138 } | |
139 | |
140 | |
141 // Destructor | |
142 | |
143 query_table::~query_table() { | |
144 window_box << previous; | |
145 delete [] previous; | |
146 delete [] q; | |
147 delete [] sr; | |
148 delete [] field_color; | |
149 } | |
150 | |
151 query_table &query_table::resize(void) { | |
152 int bw; // bar width | |
153 int i; // index query lines | |
154 int ln; // line number | |
155 | |
156 int blank_lines; | |
157 int justification_points; | |
158 int undistributed_blanks; | |
159 | |
160 | |
161 // Vertical justification calculations | |
162 | |
163 blank_lines = height - 2 - nq; | |
164 justification_points = nq + 1; | |
165 | |
166 nbl = blank_lines/justification_points; //number of blank lines | |
167 | |
168 undistributed_blanks = | |
169 blank_lines - justification_points*nbl; | |
170 | |
171 title_line = undistributed_blanks/4; | |
172 exp_line = height -1 - title_line; | |
173 undistributed_blanks -= 2*title_line; | |
174 | |
175 first_line = undistributed_blanks/2 + nbl + 1; // first line location | |
176 | |
177 | |
178 // Calculate horizontal spacing | |
179 | |
180 pw = 0; // prompt width | |
181 dw = width/2; // data width | |
182 for (i = 0; i < nq; i++) { | |
183 int qw; // width of prompt-this query | |
184 expand_formula(q[i].prompt); | |
185 qw = size(sa--); // width | |
186 if (qw > pw) pw = qw; // max prompt width | |
187 } | |
188 pw += 2; // extra space | |
189 bw = pw + dw; // bar width | |
190 if (bw > width) bw = width; | |
191 dw = bw - pw; // maybe reduce data width | |
192 px = (width - bw)/2; // left position of prompt | |
193 dx = px + pw; // left position of data | |
194 | |
195 | |
196 // Set up data windows | |
197 | |
198 ln = first_line; // ln is line number | |
199 for (i = 0; i < nq; i++) { | |
200 int id = q[i].id; // Variable id | |
201 if (id) sr[i] = window.line(dx, ln, dw); // If data field | |
202 else { // Otherwise button | |
203 expand_formula(q[i].prompt); // Expand prompt to get size | |
204 sr[i] = window.line(px,ln, size(sa--)); | |
205 } | |
206 ln += nbl + 1; | |
207 } | |
208 return *this; | |
209 } | |
210 | |
211 | |
212 // Refresh query table display | |
213 | |
214 query_table &query_table::refresh(void) { | |
215 int ln = first_line; | |
216 int k; // Index queries | |
217 screen_rect msg_line; | |
218 | |
219 | |
220 // Reset field colors | |
221 | |
222 for (k = 0; k < nq; k++) field_color[k] = entry_color; | |
223 field_color[current_field] = highlight_color; | |
224 | |
225 | |
226 // Display prompts and initial values | |
227 | |
228 for (k = 0; k < nq; k++) { | |
229 int id = q[k].id; | |
230 | |
231 sr[k].tint(field_color[k]); | |
232 msg_line = window.line(px,ln,width); | |
233 msg_line << q[k].prompt; | |
234 if (id) { // Data field | |
235 if (q[k].value) { | |
236 expand_formula(q[k].value); | |
237 release(st[id]); | |
238 st[id].data.text = copy(sa--); | |
239 } | |
240 sr[k] << st[q[k].id].data.text; | |
241 } | |
242 ln += nbl + 1; | |
243 } | |
244 sr[current_field].set_cursor(); | |
245 | |
246 | |
247 // Display explanation line | |
248 | |
249 msg_line = window.line(0,exp_line, width, 10); | |
250 msg_line << q[current_field].explanation; | |
251 | |
252 return *this; | |
253 } | |
254 | |
255 | |
256 int query_table::edit_line(void) { | |
257 int key; | |
258 | |
259 if (current_field >= nq || q[current_field].id == 0) { | |
260 return get_key(); | |
261 } | |
262 | |
263 line_edit_buffer buf(st[q[current_field].id].data.text,100); | |
264 | |
265 while (1) { | |
266 sr[current_field] << buf; // Update display | |
267 key = get_key(); | |
268 switch (key) { | |
269 case HOME: | |
270 home(buf); | |
271 break; | |
272 case END: | |
273 end(buf); | |
274 break; | |
275 case LEFT: | |
276 --buf; | |
277 break; | |
278 case RIGHT: | |
279 ++buf; | |
280 break; | |
281 case DELETE: | |
282 ~buf; | |
283 break; | |
284 case BACKSPACE: | |
285 if (buf.index() == 0) break; | |
286 ~(--buf); | |
287 break; | |
288 case TAB: | |
289 case BACKTAB: | |
290 case UP: | |
291 case DOWN: | |
292 case '\r': { | |
293 unsigned index = q[current_field].id; | |
294 if (buf.changes) { | |
295 st[index].data.text = memdup((char *) buf, 1+strlen(buf)); | |
296 delete [] q[current_field].value; | |
297 q[current_field].value = NULL; | |
298 } | |
299 } | |
300 case ESCAPE: | |
301 return key; | |
302 default: | |
303 if (current_field < nq && key >= ' ' && key < 255) buf << key; | |
304 break; | |
305 } | |
306 } | |
307 } | |
308 | |
309 void display_queries(screen_descriptor *scd) { | |
310 protect_display save_screen; | |
311 | |
312 query_table qt(qs,scd); | |
313 qt.window_box << char_cell(' ',qt.color); | |
314 qt.window = box(qt.window_box); | |
315 screen_rect title_line = qt.window.line(0,qt.title_line,qt.width,10); | |
316 title_line << qt.title; | |
317 | |
318 while (1) { | |
319 int key; | |
320 qt.refresh(); | |
321 key = qt.edit_line(); | |
322 switch (key) { | |
323 case BACKTAB: | |
324 case UP: | |
325 qt.current_field += qt.nq - 1; | |
326 qt.current_field %= qt.nq; | |
327 break; | |
328 case TAB: | |
329 case DOWN: | |
330 qt.current_field++; | |
331 qt.current_field %= qt.nq; | |
332 break; | |
333 case '\r': { | |
334 int id = qt.q[qt.current_field].id; | |
335 action_pointer ap = qt.q[qt.current_field].action; | |
336 if (id) { | |
337 qt.current_field++; | |
338 qt.current_field %= qt.nq; | |
339 break; | |
340 } | |
341 if (ap.pointer) perform_action(ap); | |
342 return; | |
343 } | |
344 } | |
345 } | |
346 } | |
347 |