Mercurial > ~dholland > hg > ag > index.cgi
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/dsl/query.cpp Sat Dec 22 17:52:45 2007 -0500 @@ -0,0 +1,347 @@ +/***** + + AnaGram Programming Examples + + A Dos Script Language + Query Table Module + + Copyright 1993 Parsifal Software. All Rights Reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + +*****/ + +#include "query.h" +#include "screen.h" +#include "symbol.h" +#include "util.h" +#include "edit.h" +#include <ctype.h> +#include <stdlib.h> + +#if defined(__MSDOS__) || defined(__WINDOWS__) +#include <conio.h> +#else +/* This is only meant to compile, not run. (Unix) */ +static int getch(void) { return '?'; } +#endif + +// Editing keystrokes + +#define BACKSPACE '\b' +#define BACKTAB 271 +#define LEFT 331 +#define DELETE 339 +#define ESCAPE 27 +#define DOWN 336 +#define RIGHT 333 +#define TAB '\t' +#define UP 328 +#define HOME 327 +#define END 335 + + +void perform_action(action_pointer); + +int get_key(void) { + int key = getch(); + if (key == 0) key = 256 + getch(); + if (key == 3) { + printf("\n^C"); + exit(1); + } + return key; +} + +void expand_formula(const int *s) { + ++sa; + while (*s) { + switch (st[*s].type) { + case value_type: + case string_type: { + sa << st[*s].data.text; + break; + } + case integer_type: { + sa.printf("%d", st[*s].data.integer); + break; + } + default: { + sa << sd[*s]; + } + } + s++; + } +} + +screen_rect &operator << (screen_rect &r, const int *s) { + expand_formula(s); + r << (sa--).top(); + return r; +} + +// Query Table Class + +// Constructor + +query_table::query_table(stack<query_item> &qs, screen_descriptor *scd) { + int i = 0; + int j; + + title = scd->title; + color = scd->color; + entry_color = scd->entry_color; + highlight_color = scd->highlight_color; + height = scd->height; + width = scd-> width; + if (scd->pos.x >= 0) + window_box = at(scd->pos.x,scd->pos.y).rect(width,height,0); + else window_box = at(0,0).rect(width,height,11); + height -= 2; + width -= 4; + window = window_box.rect(width,height); + previous = contents(window_box); + + nq = size(qs); // Number of fields + q = new query_item[nq]; // Query items + sr = new screen_rect[nq]; // screen position + field_color = new unsigned char[nq]; // color + + + j = nq; + for (j = nq, i = 0; j--; i++) { + unsigned index; + q[i] = qs[j]; + if (q[i].value == NULL) continue; + index = q[i].id; + release(st[index]); + st[index].type = value_type; + expand_formula(q[i].value); + st[index].data.text = copy(sa--); + } + current_field = 0; + resize(); +} + + +// Destructor + +query_table::~query_table() { + window_box << previous; + delete [] previous; + delete [] q; + delete [] sr; + delete [] field_color; +} + +query_table &query_table::resize(void) { + int bw; // bar width + int i; // index query lines + int ln; // line number + + int blank_lines; + int justification_points; + int undistributed_blanks; + + + // Vertical justification calculations + + blank_lines = height - 2 - nq; + justification_points = nq + 1; + + nbl = blank_lines/justification_points; //number of blank lines + + undistributed_blanks = + blank_lines - justification_points*nbl; + + title_line = undistributed_blanks/4; + exp_line = height -1 - title_line; + undistributed_blanks -= 2*title_line; + + first_line = undistributed_blanks/2 + nbl + 1; // first line location + + +// Calculate horizontal spacing + + pw = 0; // prompt width + dw = width/2; // data width + for (i = 0; i < nq; i++) { + int qw; // width of prompt-this query + expand_formula(q[i].prompt); + qw = size(sa--); // width + if (qw > pw) pw = qw; // max prompt width + } + pw += 2; // extra space + bw = pw + dw; // bar width + if (bw > width) bw = width; + dw = bw - pw; // maybe reduce data width + px = (width - bw)/2; // left position of prompt + dx = px + pw; // left position of data + + +// Set up data windows + + ln = first_line; // ln is line number + for (i = 0; i < nq; i++) { + int id = q[i].id; // Variable id + if (id) sr[i] = window.line(dx, ln, dw); // If data field + else { // Otherwise button + expand_formula(q[i].prompt); // Expand prompt to get size + sr[i] = window.line(px,ln, size(sa--)); + } + ln += nbl + 1; + } + return *this; +} + + +// Refresh query table display + +query_table &query_table::refresh(void) { + int ln = first_line; + int k; // Index queries + screen_rect msg_line; + + +// Reset field colors + + for (k = 0; k < nq; k++) field_color[k] = entry_color; + field_color[current_field] = highlight_color; + + +// Display prompts and initial values + + for (k = 0; k < nq; k++) { + int id = q[k].id; + + sr[k].tint(field_color[k]); + msg_line = window.line(px,ln,width); + msg_line << q[k].prompt; + if (id) { // Data field + if (q[k].value) { + expand_formula(q[k].value); + release(st[id]); + st[id].data.text = copy(sa--); + } + sr[k] << st[q[k].id].data.text; + } + ln += nbl + 1; + } + sr[current_field].set_cursor(); + + +// Display explanation line + + msg_line = window.line(0,exp_line, width, 10); + msg_line << q[current_field].explanation; + + return *this; +} + + +int query_table::edit_line(void) { + int key; + + if (current_field >= nq || q[current_field].id == 0) { + return get_key(); + } + + line_edit_buffer buf(st[q[current_field].id].data.text,100); + + while (1) { + sr[current_field] << buf; // Update display + key = get_key(); + switch (key) { + case HOME: + home(buf); + break; + case END: + end(buf); + break; + case LEFT: + --buf; + break; + case RIGHT: + ++buf; + break; + case DELETE: + ~buf; + break; + case BACKSPACE: + if (buf.index() == 0) break; + ~(--buf); + break; + case TAB: + case BACKTAB: + case UP: + case DOWN: + case '\r': { + unsigned index = q[current_field].id; + if (buf.changes) { + st[index].data.text = memdup((char *) buf, 1+strlen(buf)); + delete [] q[current_field].value; + q[current_field].value = NULL; + } + } + case ESCAPE: + return key; + default: + if (current_field < nq && key >= ' ' && key < 255) buf << key; + break; + } + } +} + +void display_queries(screen_descriptor *scd) { + protect_display save_screen; + + query_table qt(qs,scd); + qt.window_box << char_cell(' ',qt.color); + qt.window = box(qt.window_box); + screen_rect title_line = qt.window.line(0,qt.title_line,qt.width,10); + title_line << qt.title; + + while (1) { + int key; + qt.refresh(); + key = qt.edit_line(); + switch (key) { + case BACKTAB: + case UP: + qt.current_field += qt.nq - 1; + qt.current_field %= qt.nq; + break; + case TAB: + case DOWN: + qt.current_field++; + qt.current_field %= qt.nq; + break; + case '\r': { + int id = qt.q[qt.current_field].id; + action_pointer ap = qt.q[qt.current_field].action; + if (id) { + qt.current_field++; + qt.current_field %= qt.nq; + break; + } + if (ap.pointer) perform_action(ap); + return; + } + } + } +} +