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;
+      }
+    }
+  }
+}
+