瀏覽代碼

revert r35194: nviz requires lib/form

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@35199 15284696-431f-4ddb-bdfa-cd5b030d7da7
Martin Landa 16 年之前
父節點
當前提交
af41c8ffdc
共有 10 個文件被更改,包括 3831 次插入0 次删除
  1. 1 0
      lib/Makefile
  2. 39 0
      lib/form/Makefile
  3. 308 0
      lib/form/form.c
  4. 158 0
      lib/form/form.tcl
  5. 253 0
      lib/form/generate.c
  6. 1417 0
      lib/form/html_library.tcl
  7. 1418 0
      lib/form/html_library_grass.tcl
  8. 31 0
      lib/form/license.terms
  9. 203 0
      lib/form/open.c
  10. 3 0
      lib/form/todo

+ 1 - 0
lib/Makefile

@@ -20,6 +20,7 @@ SUBDIRS = \
 	db \
 	external \
 	fonts \
+	form \
 	imagery \
 	cluster \
 	proj \

+ 39 - 0
lib/form/Makefile

@@ -0,0 +1,39 @@
+MODULE_TOPDIR = ../..
+
+include $(MODULE_TOPDIR)/include/Make/Vars.make
+
+MOD_OBJS = generate.o open.o
+
+LIB_NAME = $(FORM_LIBNAME)
+
+include $(MODULE_TOPDIR)/include/Make/Lib.make
+
+EXTRA_LIBS=$(GISLIB) $(DBMILIB)
+EXTRA_CFLAGS = $(XCFLAGS) $(TCLINCDIR) $(TKINCDIR)
+
+FORMDIR=$(ARCH_DISTDIR)/etc/form
+FORM=$(FORMDIR)/form.tcl
+FORMPROG=$(FORMDIR)/form
+HTMLLIB=$(FORMDIR)/html_library.tcl
+
+ifneq ($(TCLTKLIBS),)
+    GTCLTKFORM = $(HTMLLIB) $(FORM) $(FORMPROG) 
+endif
+
+default: lib $(GTCLTKFORM)
+
+$(FORMDIR):
+	if [ ! -d $@ ]; then $(MKDIR) $@; fi
+
+$(HTMLLIB): html_library_grass.tcl
+	$(MAKE) $(FORMDIR)
+	$(INSTALL_DATA) $< $@
+
+$(FORM): form.tcl
+	$(MAKE) $(FORMDIR)
+	$(INSTALL_DATA) $< $@
+
+$(FORMPROG): $(OBJDIR)/form.o
+	$(MAKE) $(FORMDIR)
+	$(CC) $(LDFLAGS) -o $@ $(OBJDIR)/form.o $(DBMILIB) $(GISLIB) $(DATETIMELIB) \
+				$(TCLTKLIBPATH) $(TCLTKLIBS) $(MATHLIB) $(XDRLIB)

+ 308 - 0
lib/form/form.c

@@ -0,0 +1,308 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <tcl.h>
+#include <tk.h>
+#include <locale.h>
+#include <grass/gis.h>
+#include <grass/dbmi.h>
+#include <grass/form.h>
+
+/* Structure to store column names and values */
+typedef struct
+{
+    char *name;
+    int ctype;
+    char *value;
+} COLUMN;
+
+static char *Drvname, *Dbname, *Tblname, *Key;
+
+static COLUMN *Columns = NULL;
+static int allocatedRows = 0;	/* allocated space */
+static int nRows = 0;
+
+/* Start new sql update */
+int reset_values(ClientData cdata, Tcl_Interp * interp, int argc,
+		 char *argv[])
+{
+    nRows = 0;
+    Drvname = NULL;
+    Dbname = NULL;
+    Tblname = NULL;
+    Key = NULL;
+
+    return TCL_OK;
+}
+
+int set_value(ClientData cdata, Tcl_Interp * interp, int argc, char *argv[])
+{
+    G_debug(2, "set_value(): %s %s", argv[1], argv[2]);
+
+    if (strcmp(argv[1], F_DRIVER_FNAME) == 0) {
+	Drvname = G_store(argv[2]);
+    }
+    else if (strcmp(argv[1], F_DATABASE_FNAME) == 0) {
+	Dbname = G_store(argv[2]);
+    }
+    else if (strcmp(argv[1], F_TABLE_FNAME) == 0) {
+	Tblname = G_store(argv[2]);
+    }
+    else if (strcmp(argv[1], F_KEY_FNAME) == 0) {
+	Key = G_store(argv[2]);
+    }
+    else {
+	if (nRows == allocatedRows) {
+	    allocatedRows += 100;
+	    Columns =
+		(COLUMN *) G_realloc(Columns,
+				     (allocatedRows) * sizeof(COLUMN));
+	}
+	Columns[nRows].name = G_store(argv[1]);
+	Columns[nRows].value = G_store(argv[2]);
+	nRows++;
+    }
+
+    return TCL_OK;
+}
+
+/* Update table, use the data previously stored by set_value() */
+int submit(ClientData cdata, Tcl_Interp * interp, int argc, char *argv[])
+{
+    int i, first, ncols, found, col, sqltype, keyval = 0, ret;
+    char buf[2001];
+    dbString sql, table_name, strval;
+    dbDriver *driver;
+    dbHandle handle;
+    dbTable *table;
+    dbColumn *column;
+
+    G_debug(2, "submit()");
+
+    db_init_string(&sql);
+    db_init_string(&table_name);
+    db_init_string(&strval);
+
+    /* Check if all internal values are set */
+    if (Drvname == NULL || Dbname == NULL || Tblname == NULL || Key == NULL) {
+	G_warning("db connection was not set by form\n");
+	sprintf(buf, "set submit_msg \"db connection was not set by form.\"");
+	Tcl_Eval(interp, buf);
+	Tcl_Eval(interp, "set submit_result 0");
+	return TCL_OK;
+    }
+
+    /* Get column types */
+    G_debug(2, "Open driver");
+    driver = db_start_driver(Drvname);
+    if (driver == NULL) {
+	G_warning("Cannot open driver\n");
+	sprintf(buf, "set submit_msg \"Cannot open driver '%s'\"", Drvname);
+	Tcl_Eval(interp, buf);
+	Tcl_Eval(interp, "set submit_result 0");
+	return TCL_OK;
+    }
+    G_debug(2, "Driver opened");
+
+    db_init_handle(&handle);
+    db_set_handle(&handle, Dbname, NULL);
+    G_debug(2, "Open database");
+    if (db_open_database(driver, &handle) != DB_OK) {
+	G_warning("Cannot open database\n");
+	db_shutdown_driver(driver);
+	sprintf(buf,
+		"set submit_msg \"Cannot open database '%s' by driver '%s'\"",
+		Dbname, Drvname);
+	Tcl_Eval(interp, buf);
+	Tcl_Eval(interp, "set submit_result 0");
+	return TCL_OK;
+    }
+    G_debug(2, "Database opened");
+
+    db_set_string(&table_name, Tblname);
+    if (db_describe_table(driver, &table_name, &table) != DB_OK) {
+	G_warning("Cannot describe table\n");
+	db_shutdown_driver(driver);
+	db_close_database(driver);
+	sprintf(buf, "set submit_msg \"Cannot describe table '%s'\"",
+		Tblname);
+	Tcl_Eval(interp, buf);
+	Tcl_Eval(interp, "set submit_result 0");
+	return TCL_OK;
+    }
+    ncols = db_get_table_number_of_columns(table);
+
+    /* For each column get ctype */
+    for (i = 0; i < nRows; i++) {
+	found = 0;
+	for (col = 0; col < ncols; col++) {
+	    /* get keyval */
+	    if (G_strcasecmp(Columns[i].name, Key) == 0) {
+		keyval = atoi(Columns[i].value);
+	    }
+	    column = db_get_table_column(table, col);
+	    if (G_strcasecmp(db_get_column_name(column), Columns[i].name) ==
+		0) {
+		sqltype = db_get_column_sqltype(column);
+		Columns[i].ctype = db_sqltype_to_Ctype(sqltype);
+		found = 1;
+		break;
+	    }
+	}
+	if (!found && (G_strcasecmp(Columns[i].name, F_ENCODING) != 0)) {
+	    G_warning("Cannot find column type");
+	    db_close_database(driver);
+	    db_shutdown_driver(driver);
+	    sprintf(buf, "set submit_msg \"Cannot find column type\"");
+	    Tcl_Eval(interp, buf);
+	    Tcl_Eval(interp, "set submit_result 0");
+	    return TCL_OK;
+	}
+    }
+
+    /* Construct update statement */
+    sprintf(buf, "update %s set ", Tblname);
+    db_set_string(&sql, buf);
+
+    first = 1;
+    for (i = 0; i < nRows; i++) {
+	G_debug(3, "Index = %d of %d Name = %s, Key = %s", i, nRows,
+		Columns[i].name, Key);
+	if (G_strcasecmp(Columns[i].name, Key) == 0)
+	    continue;
+
+	if (G_strcasecmp(Columns[i].name, F_ENCODING) == 0) {
+
+	    G_debug(3, "GRASS_DB_ENCODING env-var is '%s', col val is '%s'",
+		    G__getenv("GRASS_DB_ENCODING"), Columns[i].value);
+
+	    if ((strlen(Columns[i].value) == 0) ||
+		G_strcasecmp(Columns[i].value,
+			     G__getenv("GRASS_DB_ENCODING")) == 0)
+		continue;
+	    else {
+		G_setenv("GRASS_DB_ENCODING", Columns[i].value);
+		G_debug(3, "Set env var GRASS_DB_ENCODING to '%s'",
+			Columns[i].value);
+		if (Tcl_SetSystemEncoding(interp, Columns[i].value) ==
+		    TCL_ERROR) {
+		    G_warning
+			("Could not set Tcl system encoding to '%s' (%s)",
+			 Columns[i].value, interp->result);
+		}
+	    }
+	    continue;
+	}
+
+	if (!first) {
+	    db_append_string(&sql, ", ");
+	}
+	if (strlen(Columns[i].value) == 0) {
+	    sprintf(buf, "%s = null", Columns[i].name);
+	}
+	else {
+	    if (Columns[i].ctype == DB_C_TYPE_INT ||
+		Columns[i].ctype == DB_C_TYPE_DOUBLE) {
+		sprintf(buf, "%s = %s", Columns[i].name, Columns[i].value);
+	    }
+	    else {
+		memset(buf, '\0', strlen(buf));
+		ret = Tcl_UtfToExternal(interp,
+					Tcl_GetEncoding(interp,
+							G__getenv
+							("GRASS_DB_ENCODING")),
+					Columns[i].value,
+					strlen(Columns[i].value), 0, NULL,
+					buf, 2000, NULL, NULL, NULL);
+
+		if (ret != TCL_OK) {
+		    G_warning("Could not convert UTF to external.");
+		    db_set_string(&strval, Columns[i].value);
+		}
+		else {
+		    db_set_string(&strval, buf);
+		}
+
+		db_double_quote_string(&strval);
+		sprintf(buf, "%s = '%s'", Columns[i].name,
+			db_get_string(&strval));
+	    }
+	}
+	db_append_string(&sql, buf);
+	first = 0;
+    }
+
+    sprintf(buf, " where %s = %d", Key, keyval);
+    db_append_string(&sql, buf);
+
+    G_debug(2, "SQL: %s", db_get_string(&sql));
+
+    /* Update table */
+    ret = db_execute_immediate(driver, &sql);
+
+    db_close_database(driver);
+    db_shutdown_driver(driver);
+
+    if (ret != DB_OK) {
+	G_warning("Cannot update table");
+	Tcl_VarEval(interp, "set submit_msg \"Cannot update table:\n",
+		    db_get_error_msg(), "\"", NULL);
+	Tcl_Eval(interp, "set submit_result 0");
+    }
+    else {
+	Tcl_Eval(interp, "set submit_msg \"Record successfully updated\"");
+	Tcl_Eval(interp, "set submit_result 1");
+    }
+
+    return TCL_OK;
+}
+
+/* 
+ *  Form 
+ */
+int Tcl_AppInit(Tcl_Interp * interp)
+{
+    if (Tcl_Init(interp) == TCL_ERROR)
+	return TCL_ERROR;
+
+    if (Tk_Init(interp) == TCL_ERROR)
+	return TCL_ERROR;
+
+    Tcl_StaticPackage(interp, "Tk", Tk_Init, Tk_SafeInit);
+
+    /*
+     * Call Tcl_CreateCommand for application-specific commands, if
+     * they weren't already created by the init procedures called above.
+     */
+
+    Tcl_CreateCommand(interp, "submit", (Tcl_CmdProc *) submit,
+		      (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
+    Tcl_CreateCommand(interp, "set_value",
+		      (Tcl_CmdProc *) set_value,
+		      (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
+    Tcl_CreateCommand(interp, "reset_values",
+		      (Tcl_CmdProc *) reset_values,
+		      (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
+    /*
+     * Specify a user-specific startup file to invoke if the application
+     * is run interactively.  Typically the startup file is "~/.apprc"
+     * where "app" is the name of the application.  If this line is deleted
+     * then no user-specific startup file will be run under any conditions.
+     */
+
+    Tcl_SetVar(interp, "tcl_rcFileName", "~/.grassformrc", TCL_GLOBAL_ONLY);
+    return TCL_OK;
+}
+
+int main(int argc, char *argv[])
+{
+    G_gisinit("form");
+    G_debug(2, "Form: main()");
+
+    Tk_Main(argc, argv, Tcl_AppInit);
+    return 0;
+}

+ 158 - 0
lib/form/form.tcl

@@ -0,0 +1,158 @@
+lappend auto_path $env(GISBASE)/bwidget
+package require -exact BWidget 1.2.1 
+#package require http
+
+set formpath $env(GISBASE)/etc/form
+source $formpath/html_library.tcl
+
+proc create_submit_msg { formid  }  {
+    global submit_result submit_msg formf
+
+    destroy $formf($formid).sbw 
+    destroy $formf($formid).sbt
+
+    if { $submit_result == 1 } { set color "green" } else { set color "red" }
+    set sbw [ScrolledWindow $formf($formid).sbw -relief sunken -borderwidth 2]
+    set sbt [text $formf($formid).sbt -height 3 -width 20 -foreground $color ]
+    pack $sbw $sbt -fill x
+    $sbw setwidget $sbt
+    $sbt insert end $submit_msg
+    $sbt configure -state disabled
+}
+
+proc add_form { formid title } {
+    global nb formf html
+
+    set form($formid) [$nb insert end $formid -text $title]
+    $nb raise $formid
+    set formf($formid) [ frame $form($formid).frm ]
+    set formsw($formid) [ScrolledWindow $formf($formid).sw -relief sunken -borderwidth 2]
+    set formtxt($formid) [ text $formf($formid).txt -height 5 -width 20 ]
+    pack $formf($formid) $formsw($formid) $formtxt($formid) -fill both -expand yes
+    $formsw($formid) setwidget $formtxt($formid)
+    HMinit_win $formtxt($formid)
+    HMparse_html $html "HMrender $formtxt($formid)"
+    $formtxt($formid) configure -state disabled
+}
+
+proc clear_nb { }  {
+    global submit_msg
+ 
+    set submit_msg ""
+  
+    foreach frm [ .nb pages ] {
+        .nb delete $frm
+    }
+}
+
+proc HMsubmit_form {win param query} {
+    global submit_result submit_msg
+
+    regexp -- {\.nb\.f(.+)\.frm\.txt} $win r formid 
+    #puts "win = $win formid = $formid"
+
+    reset_values
+    foreach {col val} $query {
+        #puts "$col : $val" 
+        set_value $col $val 
+    }
+
+    submit $formid
+    #puts "result = $submit_result msg = $submit_msg" 
+    create_submit_msg $formid   
+}
+
+proc make_form {} {
+	global nb
+
+	set nb [NoteBook .nb]
+	$nb configure -width 300 -height 500
+	pack .nb -fill both -expand yes
+}
+
+proc close_form {} {
+	global form_open
+	wm withdraw .
+	set form_open false
+}
+
+proc process_command {} {
+	global env
+	global child_recv child_send 
+	global form_open encoding_val frmid
+	global html
+
+	if {[eof $child_recv]} {
+		exit 0
+	}
+
+	set cmd [read $child_recv 1]
+
+	switch $cmd {
+		O {
+			if {! $form_open} {
+				wm state . normal
+				set form_open true
+			}
+			#  Read title 
+			set length [gets $child_recv]
+			set child_title [read $child_recv $length]
+
+			#  Read html 
+			set length [gets $child_recv]
+			set child_html [read $child_recv $length]
+
+			set child_html [encoding convertfrom $encoding_val $child_html]
+
+			#  Insert new page 
+			set html $child_html
+			add_form $frmid $child_title
+
+			puts -nonewline $child_send O
+			flush $child_send
+			incr frmid
+		}
+		C {	#  clear old forms 
+			clear_nb
+			puts -nonewline $child_send O
+			flush $child_send
+		}
+		D {	#  done! 
+			clear_nb
+			puts -nonewline $child_send O
+			flush $child_send
+
+			destroy .
+			exit 0
+		}
+	}
+}
+
+make_form
+
+wm protocol . WM_DELETE_WINDOW close_form
+
+bind . <Destroy> { if { "%W" == "."} { close_form } }
+
+set submit_result ""
+set submit_msg ""
+set html ""
+
+set frmid 0
+set form_open true
+
+set child_recv stdin
+set child_send stdout
+
+set encoding_val [exec g.gisenv GRASS_DB_ENCODING]
+if {$encoding_val == ""} {
+	set encoding_val [encoding system]
+}
+
+if {[catch {encoding system $encoding_val}]} {
+	puts stderr "Could not set Tcl system encoding to $encoding_val"
+}
+
+fconfigure $child_recv -buffering none -encoding binary -translation binary
+
+fileevent $child_recv readable process_command

+ 253 - 0
lib/form/generate.c

@@ -0,0 +1,253 @@
+#include <stdlib.h>
+#include <string.h>
+#include <grass/gis.h>
+#include <grass/dbmi.h>
+#include <grass/form.h>
+
+/* Generate form in HTML/TXT format.
+ *  Pointer to resulting string is stored to 'form'. This string must be freed by application.
+ *
+ *  returns: -1 error 
+ *            0 success
+ */
+int
+F_generate(char *drvname, char *dbname, char *tblname, char *key, int keyval,
+	   char *frmname, char *frmmapset,
+	   int edit_mode, int format, char **form)
+{
+    int col, ncols, ctype, sqltype, more;
+    char buf[5000], buf1[100];
+    const char *colname;
+    dbString sql, html, str;
+    dbDriver *driver;
+    dbHandle handle;
+    dbCursor cursor;
+    dbTable *table;
+    dbColumn *column;
+    dbValue *value;
+
+    int i = 0;
+
+    /* see /usr/lib/tcl8.4/encoding/ */
+    static char *encoding_list[] = {
+	"utf-8",
+	"ascii",
+	"iso8859-1",
+	"iso8859-2",
+	"iso8859-15",
+	"iso2022-jp",
+	"koi8-r",
+	"euc-jp",
+	NULL
+    };
+    const char *enc_env;
+
+    G__read_env();
+    enc_env = G__getenv("GRASS_DB_ENCODING");
+
+    /* TODO: support 'format' (txt, html), currently html only */
+
+    G_debug(2,
+	    "F_generate(): drvname = '%s', dbname = '%s'\n      tblname = '%s', key = '%s', keyval = %d\n"
+	    "    form = '%s', form_mapset = '%s'\n      edit_mode = %d",
+	    drvname, dbname, tblname, key, keyval, frmname, frmmapset,
+	    edit_mode);
+
+    db_init_string(&sql);
+    db_init_string(&html);	/* here is the result stored */
+    db_init_string(&str);
+
+    G_debug(2, "Open driver");
+    driver = db_start_driver(drvname);
+    if (driver == NULL) {
+	G_warning("Cannot open driver\n");
+	sprintf(buf, "Cannot open driver '%s'<BR>", drvname);
+	*form = G_store(buf);
+	return -1;
+    }
+    G_debug(2, "Driver opened");
+
+    db_init_handle(&handle);
+    db_set_handle(&handle, dbname, NULL);
+    G_debug(2, "Open database");
+    if (db_open_database(driver, &handle) != DB_OK) {
+	G_warning("Cannot open database\n");
+	db_shutdown_driver(driver);
+	sprintf(buf, "Cannot open database '%s' by driver '%s'<BR>", dbname,
+		drvname);
+	*form = G_store(buf);
+	return -1;
+    }
+    G_debug(2, "Database opened");
+
+    /* TODO: test if table exist first, but this should be tested by application befor
+     *        F_generate() is called, because it may be correct (connection defined in DB
+     *        but table does not exist) */
+
+    sprintf(buf, "select * from %s where %s = %d", tblname, key, keyval);
+    G_debug(2, "%s", buf);
+    db_set_string(&sql, buf);
+    if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) {
+	G_warning("Cannot open select cursor\n");
+	db_close_database(driver);
+	db_shutdown_driver(driver);
+	sprintf(buf,
+		"Cannot open select cursor:<BR>'%s'<BR>on database '%s' by driver '%s'<BR>",
+		db_get_string(&sql), dbname, drvname);
+	*form = G_store(buf);
+	return -1;
+    }
+    G_debug(2, "Select Cursor opened");
+
+    table = db_get_cursor_table(&cursor);
+
+    if (db_fetch(&cursor, DB_NEXT, &more) != DB_OK) {
+	G_warning("Cannot fetch next record\n");
+	db_close_cursor(&cursor);
+	db_close_database(driver);
+	db_shutdown_driver(driver);
+	*form = G_store("Cannot fetch next record");
+	return -1;
+    }
+
+    if (!more) {
+	G_warning("No database record");
+	if (format == F_HTML) {
+	    *form = G_store("No record selected.<BR>");
+	}
+	else {
+	    *form = G_store("No record selected.");
+	}
+    }
+    else {
+	ncols = db_get_table_number_of_columns(table);
+
+	/* Start form */
+	if (format == F_HTML) {
+	    if (edit_mode == F_EDIT) {
+		db_append_string(&html, "<FORM>");
+
+		sprintf(buf, "<INPUT type=hidden name=%s value=\"%s\">",
+			F_DRIVER_FNAME, drvname);
+		db_append_string(&html, buf);
+		/* Note: because html_library.tcl failes to parse
+		 *  <INPUT name=abc value='dbname=xxx'> and returnes
+		 *  name="xxx" value="dbname=xxx" order of value and name parameters is changed */
+		sprintf(buf, "<INPUT type=hidden value=\"%s\" name=%s>",
+			dbname, F_DATABASE_FNAME);
+		db_append_string(&html, buf);
+		sprintf(buf, "<INPUT type=hidden name=%s value=\"%s\">",
+			F_TABLE_FNAME, tblname);
+		db_append_string(&html, buf);
+		sprintf(buf, "<INPUT type=hidden name=%s value=\"%s\">",
+			F_KEY_FNAME, key);
+		db_append_string(&html, buf);
+
+	    }
+
+	    for (col = 0; col < ncols; col++) {
+		column = db_get_table_column(table, col);
+		sqltype = db_get_column_sqltype(column);
+		ctype = db_sqltype_to_Ctype(sqltype);
+		value = db_get_column_value(column);
+		db_convert_value_to_string(value, sqltype, &str);
+		colname = db_get_column_name(column);
+
+		G_debug(2, "%s: %s", colname, db_get_string(&str));
+
+		if (edit_mode == F_VIEW) {
+		    sprintf(buf, "<B>%s : </B> %s <BR>", colname,
+			    db_get_string(&str));
+		    db_append_string(&html, buf);
+		}
+		else {
+		    sprintf(buf, "<B>%s : </B>", colname);
+		    db_append_string(&html, buf);
+
+		    if (G_strcasecmp(colname, key) == 0) {
+			sprintf(buf,
+				"%s<BR> <INPUT type=hidden name=%s value=\"%s\">",
+				db_get_string(&str), colname,
+				db_get_string(&str));
+		    }
+		    else {
+			switch (ctype) {
+			case DB_C_TYPE_INT:
+			    sprintf(buf1, "20");
+			    break;
+			case DB_C_TYPE_DOUBLE:
+			    sprintf(buf1, "30");
+			    break;
+			case DB_C_TYPE_STRING:
+			    sprintf(buf1, "%d", db_get_column_length(column));
+			    break;
+			case DB_C_TYPE_DATETIME:
+			    sprintf(buf1, "20");
+			    break;
+			}
+			sprintf(buf,
+				"<INPUT type=text size=%s name=%s value=\"%s\"><BR>",
+				buf1, colname, db_get_string(&str));
+		    }
+		    db_append_string(&html, buf);
+		}
+	    }
+
+	    if (edit_mode == F_EDIT) {
+		sprintf(buf,
+			"<HR>   Assume data encoding as:<BR><BR><SELECT NAME=%s SIZE=4><HR><BR>",
+			F_ENCODING);
+		db_append_string(&html, buf);
+
+		i = 0;
+		while (encoding_list[i] != NULL) {
+
+		    if (G_strcasecmp(encoding_list[i], enc_env) == 0)
+			sprintf(buf, "<OPTION VALUE=\"%s\" SELECTED>%s",
+				encoding_list[i], encoding_list[i]);
+		    else
+			sprintf(buf, "<OPTION VALUE=\"%s\">%s",
+				encoding_list[i], encoding_list[i]);
+		    ++i;
+		    db_append_string(&html, buf);
+		}
+
+		sprintf(buf, "</SELECT>");
+		db_append_string(&html, buf);
+	    }
+
+	    /* Close form */
+	    if (edit_mode == F_EDIT) {
+		db_append_string(&html, "</FORM>");
+	    }
+	}
+	else {			/* F_TXT */
+	    for (col = 0; col < ncols; col++) {
+		column = db_get_table_column(table, col);
+		sqltype = db_get_column_sqltype(column);
+		ctype = db_sqltype_to_Ctype(sqltype);
+		value = db_get_column_value(column);
+		db_convert_value_to_string(value, sqltype, &str);
+		colname = db_get_column_name(column);
+
+		G_debug(2, "%s: %s", colname, db_get_string(&str));
+
+		sprintf(buf, "%s : %s\n", colname, db_get_string(&str));
+		db_append_string(&html, buf);
+	    }
+	}
+    }
+    G_debug(2, "FORM STRING:\n%s\n", db_get_string(&html));
+
+    db_close_cursor(&cursor);
+    db_close_database(driver);
+    db_shutdown_driver(driver);
+
+    *form = G_store(db_get_string(&html));
+
+    db_free_string(&sql);
+    db_free_string(&html);
+    db_free_string(&str);
+
+    return 0;
+}

文件差異過大導致無法顯示
+ 1417 - 0
lib/form/html_library.tcl


文件差異過大導致無法顯示
+ 1418 - 0
lib/form/html_library_grass.tcl


+ 31 - 0
lib/form/license.terms

@@ -0,0 +1,31 @@
+Sun Microsystems, Inc.  The following terms apply to all files
+associated with the software unless explicitly disclaimed in individual
+files.
+
+The authors hereby grant permission to use, copy, modify, distribute,
+and license this software and its documentation for any purpose, provided
+that existing copyright notices are retained in all copies and that this
+notice is included verbatim in any distributions. No written agreement,
+license, or royalty fee is required for any of the authorized uses.
+Modifications to this software may be copyrighted by their authors
+and need not follow the licensing terms described here, provided that
+the new terms are clearly indicated on the first page of each file where
+they apply.
+
+IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
+FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
+DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
+IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
+NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+MODIFICATIONS.
+
+RESTRICTED RIGHTS: Use, duplication or disclosure by the government
+is subject to the restrictions as set forth in subparagraph (c) (1) (ii)
+of the Rights in Technical Data and Computer Software Clause as DFARS
+252.227-7013 and FAR 52.227-19.

+ 203 - 0
lib/form/open.c

@@ -0,0 +1,203 @@
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <grass/gis.h>
+#include <grass/dbmi.h>
+#include <grass/form.h>
+
+#ifdef HAVE_SOCKET
+#include <sys/types.h>
+#ifdef __MINGW32__
+#include <winsock.h>
+
+#else /*__MINGW32__*/
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#endif /*__MINGW32__*/
+#endif /*HAVE_SOCKET */
+
+#ifdef HAVE_SOCKET
+static int make_socketpair(int *);
+#endif
+
+int first = 1;
+
+/* the pipe to send data to GUI */
+FILE *parent_send, *parent_recv;
+
+#ifdef HAVE_SOCKET
+int pipefd[2];
+
+#define	pfd	pipefd[1]	/* parent's end */
+#define	cfd	pipefd[0]	/* child's end */
+
+#endif /*HAVE_SOCKET */
+
+/* Open new form
+ *
+ *  returns: 0 success
+ */
+#ifdef __MINGW32__
+int F_open(char *title, char *html)
+{
+    G_fatal_error("F_open is not supported on Windows");
+    return 1;
+}
+#else
+int F_open(char *title, char *html)
+{
+    /* parent */
+    int c;
+
+    /* common */
+    static int pid;
+
+#ifndef HAVE_SOCKET
+    static int p1[2], p2[2];
+#endif /*HAVE_SOCKET */
+    int length;
+
+    /* child */
+
+    G_debug(2, "F_open(): title = %s", title);
+
+    if (first) {
+#ifdef HAVE_SOCKET
+	if (make_socketpair(pipefd) < 0)
+	    G_fatal_error("Cannot make socket pair");
+#else
+	if (pipe(p1) < 0 || pipe(p2) < 0)
+	    G_fatal_error("Cannot open pipe");
+#endif /*HAVE_SOCKET */
+
+	if ((pid = fork()) < 0)
+	    G_fatal_error("Cannot create fork");
+    }
+
+    if (pid == 0) {		/* Child */
+	char command[2000], script[2000];
+
+	G_debug(2, "CHILD");
+
+	/* Note: If you are forking in a Tk based apllication  you
+	 *       must  execl  before  doing any window operations in the
+	 *       child or you will receive an error from the  X server */
+
+	close(0);
+	close(1);
+
+#ifndef HAVE_SOCKET
+	close(p1[1]);
+	close(p2[0]);
+	if (dup(p1[0]) != 0)
+	    G_fatal_error("Form: cannot dup() input");
+	if (dup(p2[1]) != 1)
+	    G_fatal_error("Form: cannot dup() output");
+
+#else
+	close(pfd);
+	if (dup(cfd) != 0)
+	    G_fatal_error("Form: cannot dup() input");
+	if (dup(cfd) != 1)
+	    G_fatal_error("Form: cannot dup() output");
+
+#endif /*HAVE_SOCKET */
+
+
+
+	sprintf(command, "%s/etc/form/form", G_gisbase());
+	sprintf(script, "%s/etc/form/form.tcl", G_gisbase());
+
+	execl(command, "form", "-f", script, NULL);
+
+	G_debug(2, "CHILD END\n");
+	exit(0);
+
+    }
+    else {			/* Parent */
+	G_debug(2, "PARENT");
+
+	if (first) {
+#ifndef HAVE_SOCKET
+	    parent_send = fdopen(p1[1], "w");
+	    close(p1[0]);
+	    parent_recv = fdopen(p2[0], "r");
+	    close(p2[1]);
+#else
+	    close(cfd);
+	    parent_send = fdopen(pfd, "w");
+	    parent_recv = fdopen(pfd, "r");
+#endif /*HAVE_SOCKET */
+	    first = 0;
+	}
+
+	G_debug(2, "PARENT HTML:\n%s\n", html);
+
+	fprintf(parent_send, "O");
+	length = strlen(title);
+	fprintf(parent_send, "%d\n", length);
+	fprintf(parent_send, "%s", title);
+	length = strlen(html);
+	fprintf(parent_send, "%d\n", length);
+	fprintf(parent_send, "%s", html);
+	fflush(parent_send);
+	G_debug(2, "PARENT: Request sent\n");
+
+	/* Wait for response */
+	c = fgetc(parent_recv);
+	G_debug(2, "PARENT: received %c\n", c);
+    }
+
+    return 0;
+}
+#endif
+
+/* Clear old forms from window
+ *
+ */
+void F_clear(void)
+{
+    char c;
+
+    G_debug(2, "F_clear()");
+
+    if (first)
+	return;
+
+    fprintf(parent_send, "C");
+    fflush(parent_send);
+    c = fgetc(parent_recv);
+    G_debug(2, "PARENT: received %c\n", c);
+}
+
+void F_close(void)
+{
+    char c;
+
+    G_debug(2, "F_close()");
+
+    if (first)
+	return;
+
+    fprintf(parent_send, "D");
+    fflush(parent_send);
+    c = fgetc(parent_recv);
+    G_debug(2, "PARENT: received %c\n", c);
+
+    first = 1;
+}
+
+#ifdef HAVE_SOCKET
+static int make_socketpair(int *fd)
+{
+    int n;
+
+    if ((n = socketpair(AF_UNIX, SOCK_STREAM, IPPROTO_IP, fd)) < 0)
+	return -1;
+    else
+	return 0;
+}
+
+#endif

+ 3 - 0
lib/form/todo

@@ -0,0 +1,3 @@
+Support special characters:
+< > " & 
+in form entries.