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