home *** CD-ROM | disk | FTP | other *** search
/ ftp.sunet.sepub/pictures / 2014.11.ftp.sunet.se-pictures.tar / ftp.sunet.se / pub / pictures / ACiD-artpacks / programs / unix / editors / gimp-plugins-unstable-0_99_23_tar.gz / gimp-plugins-unstable-0_99_23_tar / gimp-plugins-unstable-0.99.23 / gimptcl / gtclPDB.c < prev    next >
C/C++ Source or Header  |  1998-02-20  |  14KB  |  541 lines

  1. /***************************************************
  2.  * file: gtclPDB.c
  3.  *
  4.  * Copyright (c) 1996 Eric L. Hernes (erich@rrnet.com)
  5.  * All rights reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions and the following disclaimer.
  12.  * 2. The name of the author may not be used to endorse or promote products
  13.  *    derived from this software withough specific prior written permission
  14.  *
  15.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  16.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  17.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  18.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  19.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  24.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25.  *
  26.  * $Id: gtclPDB.c,v 1.1 1998/02/20 10:41:04 yosh Exp $
  27.  */
  28.  
  29. #include <ctype.h>
  30. #include <tcl.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <libgimp/gimp.h>
  34. #include "gtcl.h"
  35.  
  36. char *GtclProcs = NULL;
  37.  
  38. static char *proc_types[] = {
  39.   "undefined",
  40.   "plug-in",
  41.   "Extension",
  42. };
  43.  
  44. static char *param_types[] = {
  45.   "int32",
  46.   "int16",
  47.   "int8",
  48.   "float",
  49.   "string",
  50.   "int32array",
  51.   "int16array",
  52.   "int8array",
  53.   "floatarray",
  54.   "stringarray",
  55.   "color",
  56.   "region",
  57.   "display",
  58.   "image",
  59.   "layer",
  60.   "channel",
  61.   "drawable",
  62.   "selection",
  63.   "boundary",
  64.   "path",
  65.   "status",
  66.   "end"
  67. };
  68.  
  69. static int str_to_typeenum(char *type);
  70. static int list_to_pdef(Tcl_Interp *interp, char *list, GParamDef *p);
  71.  
  72. /*
  73.  * add the procedural-database to a Tcl Interpreter
  74.  */
  75. int
  76. Gtcl_PDBInit(Tcl_Interp *interp){
  77.   char **proc_list;
  78.   char *proc_name;
  79.   char *proc_blurb;
  80.   char *proc_help;
  81.   char *proc_author;
  82.   char *proc_copyright;
  83.   char *proc_date;
  84.   int proc_type;
  85.   int nparams;
  86.   int nreturn_vals;
  87.   GParamDef *params, *return_vals;
  88.   int num_procs, i, j;
  89.   char whole_proc[4096];
  90.   char arglist[1024];
  91.   char carglist[1024];
  92.   char **theproc_list;
  93.  
  94.   Tcl_PkgProvide(interp, "GtclPDB", "1.0");
  95.   gimp_query_database (".*", ".*", ".*", ".*", ".*", ".*", ".*",
  96.                &num_procs, &proc_list);
  97.   theproc_list = (char **)malloc(num_procs * sizeof(char *));
  98.  
  99.   for (i = 0; i < num_procs; i++) {
  100.     memset(whole_proc, 0, sizeof(whole_proc));
  101.     memset(arglist, 0, sizeof(arglist));
  102.     memset(carglist, 0, (sizeof(carglist)));
  103.     proc_name = strdup (proc_list[i]);
  104.         /*  fprintf(stderr, "(proc %d/%d %s)\n", i, num_procs, proc_name);*/
  105.       /*  lookup the procedure  */
  106.     if(gimp_query_procedure(proc_name, &proc_blurb, &proc_help, &proc_author,
  107.                 &proc_copyright, &proc_date, &proc_type,
  108.                 &nparams, &nreturn_vals,
  109.                 ¶ms, &return_vals) == TRUE) {
  110.       cvtfrom(proc_name);
  111.       theproc_list[i] = (char *)malloc(strlen(proc_name)+1);
  112.       strcpy(theproc_list[i], proc_name);
  113.       /*      fprintf(stderr, "adding %d `%s' -> `%s' %d\n", i, proc_name,
  114.           theproc_list[i], strlen(proc_name)); */
  115.       sprintf(carglist, "gimp-run-procedure %s ", proc_name);
  116.       for(j=0;j<nparams;j++){
  117.     if (strcmp(params[j].name, "run_mode")==0){
  118.       strcat(carglist, "1 ");
  119.     } else {
  120.      char vname[30];
  121.      sprintf(vname, "%s%d", params[j].name, j);
  122.       strcat(arglist, vname);
  123.       strcat(arglist, " ");
  124.       strcat(carglist, "$");
  125.       strcat(carglist, vname);
  126.       strcat(carglist, " ");
  127.     }
  128.       }
  129.       sprintf(whole_proc, "proc {%s} {%s} {\n   global env\n   set env(GimpPDBCmd) %s\n   update\n   return [%s]\n}\n\n",
  130.           proc_name, arglist, proc_name, carglist);
  131. #if 0
  132.       fprintf(stderr, "%s", whole_proc);
  133. #endif
  134.       Tcl_GlobalEval(interp, whole_proc);
  135.       free(proc_name);
  136.  
  137.       g_free(proc_blurb);
  138.       g_free(proc_help);
  139.       g_free(proc_author);
  140.       g_free(proc_copyright);
  141.       g_free(proc_date);
  142.       g_free(params);
  143.       g_free(return_vals);
  144.  
  145.     }
  146.   }
  147.   GtclProcs = Tcl_Merge(num_procs, theproc_list);
  148.   /*  fprintf(stderr, "%s", GtclProcs);*/
  149.   for(i=0;i<num_procs;i++) free(theproc_list[i]);
  150.   free(theproc_list);
  151.  
  152.   return TCL_OK;
  153. }
  154.  
  155. /*
  156.  * run a procedure from the PDB, really the heart of
  157.  * this thing... Virtually everything goes through here.
  158.  */
  159. int
  160. Gtcl_GimpRunProc(ClientData data, Tcl_Interp *interp, int ac, char *av[]){
  161.   GParam *par, *vals;
  162.   char *p_blurb, *p_help, *p_author, *p_copy, *p_date, **rv_a;
  163.   int p_type, p_npar, p_nrv;
  164.   GParamDef *p_par, *p_rv;
  165.   char *p_name;
  166.   int i;
  167.  
  168.   if (ac < 2) {
  169.     Tcl_SetResult(interp, "gimp-run-procedure: too few arguments",
  170.                         TCL_STATIC);
  171.     return TCL_ERROR;
  172.   }
  173.  
  174.   rv_a=(char **)NULL;
  175.   p_name = strdup(av[1]);
  176.  
  177.   /* first try the name as given */
  178.   if (gimp_query_procedure(p_name, &p_blurb, &p_help, &p_author, &p_copy,
  179.                &p_date, &p_type, &p_npar, &p_nrv, &p_par,
  180.                &p_rv) == FALSE) {
  181.     /* nope?, try `tr - _` */
  182.     cvtto(p_name);
  183.     if (gimp_query_procedure(p_name, &p_blurb, &p_help, &p_author, &p_copy,
  184.                  &p_date, &p_type, &p_npar, &p_nrv, &p_par,
  185.                  &p_rv) == FALSE) {
  186.       Tcl_SetResult(interp, "gimp-run-procedure invalid command: ",
  187.             TCL_STATIC);
  188.       Tcl_AppendResult(interp, p_name, (char *)NULL);
  189.       return TCL_ERROR;
  190.     }
  191.   }
  192.  
  193.   ac-=2; /* subtract off own name and the proc name */
  194.  
  195.   if (ac != p_npar){
  196.     Tcl_SetResult(interp, "gimp-run-procedure: ", TCL_STATIC);
  197.     Tcl_AppendResult(interp, p_name, " : Wrong # args\n",
  198.              "usage: ", p_name, (char *)NULL);
  199.     for (i=0;i<p_npar;i++){
  200.       Tcl_AppendResult(interp, " ", p_par[i].name, (char *)NULL);
  201.     }
  202.     return TCL_ERROR;
  203.   }
  204.  
  205.   par = (GParam *)malloc(sizeof(GParam)*ac);
  206.   for(i=0;i<p_npar;i++){
  207.     par[i].type = p_par[i].type;
  208.   }
  209.   if(Argv_to_GParam(interp, p_name, p_npar, av+2, par)==TCL_ERROR){
  210.     free(par);
  211.     return TCL_ERROR;
  212.   }
  213.  
  214.   DPRINTF(1,(stderr, "\nGimp PDB Running: (%s:", p_name));
  215.  
  216.   vals = gimp_run_procedure2 (p_name, &p_nrv, p_npar, par);
  217.   if (! vals) {
  218.     Tcl_SetResult(interp, "pdb: no status returned from", TCL_STATIC);
  219.     Tcl_AppendResult(interp, p_name, (char *)NULL);
  220.     free(par);
  221.     return TCL_ERROR;
  222.   }
  223.  
  224.   DPRINTF(1,(stderr, " returned %d)\n", vals[0].data.d_status));
  225.   switch (vals[0].data.d_status) {
  226.   case STATUS_EXECUTION_ERROR:
  227.     gimp_destroy_params (vals, p_nrv);
  228.     free(par);
  229.     Tcl_SetResult(interp, "pdb: exec failed for ", TCL_STATIC);
  230.     cvtfrom(p_name);
  231.     Tcl_AppendResult(interp, p_name, (char *)NULL);
  232.     return TCL_ERROR;
  233.     break;
  234.   case STATUS_CALLING_ERROR:
  235.     gimp_destroy_params (vals, p_nrv);
  236.  
  237.     Tcl_SetResult(interp, "pdb: invalid arguments for ", TCL_STATIC);
  238.     Tcl_AppendResult(interp, p_name, (char *)NULL);
  239.     return TCL_ERROR;
  240.     break;
  241.   case STATUS_SUCCESS:
  242.     rv_a=(char **)malloc(sizeof(char *)*p_nrv-1);
  243.     if(GParam_to_Argv(interp, p_name, p_nrv-1, &vals[1], rv_a)==TCL_ERROR){
  244.       gimp_destroy_params (vals, p_nrv);
  245.       return TCL_ERROR;
  246.     }
  247.   }
  248.   
  249.   if(p_nrv==2){
  250.     Tcl_SetResult(interp, rv_a[0], TCL_VOLATILE);
  251.   } else {
  252.     char *t;
  253.     t=Tcl_Merge(p_nrv-1, rv_a);
  254.     Tcl_SetResult(interp, t, TCL_DYNAMIC);
  255.   }
  256.  
  257.   for(i=0;i<p_nrv-1;i++){
  258.     free(rv_a[i]);
  259.   }
  260.  
  261.   free((char *)rv_a);
  262.   free(par);
  263.   g_free(p_blurb);
  264.   g_free(p_help);
  265.   g_free(p_author);
  266.   g_free(p_copy);
  267.   g_free(p_date);
  268.   g_free(p_par);
  269.   g_free(p_rv);
  270.   gimp_destroy_params (vals, p_nrv);
  271.  
  272.   return TCL_OK;
  273. }
  274.  
  275. /*
  276.  * query the database for info on a procedure
  277.  */
  278. int
  279. Gtcl_QueryDBProc(ClientData data, Tcl_Interp *interp, int ac, char *av[]){
  280.   char *blurb, *help, *author, *copyright, *date, **tl0, *tl1[3];
  281.   char *t, *p_name;
  282.   int type, npar, nrv, i;
  283.   GParamDef *par_d, *rv_d;
  284.  
  285.   if (ac!=2) {
  286.     Tcl_SetResult(interp, "gimp-query-dbproc: wrong # arguments", TCL_STATIC);
  287.     return TCL_ERROR;
  288.   }
  289.   p_name = strdup(av[1]);
  290.   cvtto(p_name);
  291.   if(gimp_query_procedure(av[1], &blurb, &help, &author, ©right,
  292.               &date, &type, &npar, &nrv, &par_d, &rv_d) == FALSE) {
  293.     if(gimp_query_procedure(p_name, &blurb, &help, &author, ©right,
  294.                 &date, &type, &npar, &nrv, &par_d, &rv_d)
  295.        == FALSE) {
  296.       Tcl_SetResult(interp, "gimp-query-dbproc: invalid command: ",
  297.             TCL_STATIC);
  298.       Tcl_AppendResult(interp, av[1], (char *)NULL);
  299.       return TCL_ERROR;
  300.     }
  301.   }
  302.   free(p_name);
  303.   Tcl_AppendElement(interp, av[1]);
  304.   Tcl_AppendElement(interp, blurb);
  305.   Tcl_AppendElement(interp, help);
  306.   Tcl_AppendElement(interp, author);
  307.   Tcl_AppendElement(interp, copyright);
  308.   Tcl_AppendElement(interp, date);
  309.   Tcl_AppendElement(interp, proc_types[type]);
  310.   tl0=(char**)malloc(sizeof(char*) * npar);
  311.   for(i=0;i<npar;i++){
  312.     tl1[0]=param_types[par_d[i].type];
  313.     tl1[1]=par_d[i].name;
  314.     tl1[2]=par_d[i].description;
  315.     t=Tcl_Merge(3, tl1);
  316.     tl0[i]=t;
  317.   }
  318.   t = Tcl_Merge(npar, tl0);
  319.   Tcl_AppendElement(interp, t);
  320.   Tcl_Free(t);
  321.   for(i=0;i<npar;i++)
  322.     Tcl_Free(tl0[i]);
  323.   free(tl0);
  324.  
  325.   tl0=(char**)malloc(sizeof(char*) * nrv);
  326.   for(i=0;i<nrv;i++){
  327.     tl1[0]=param_types[rv_d[i].type];
  328.     tl1[1]=rv_d[i].name;
  329.     tl1[2]=rv_d[i].description;
  330.     t=Tcl_Merge(3, tl1);
  331.     tl0[i]=t;
  332.   }
  333.   t = Tcl_Merge(nrv, tl0);
  334.   Tcl_AppendElement(interp, t);
  335.   Tcl_Free(t);
  336.   for(i=0;i<nrv;i++)
  337.     Tcl_Free(tl0[i]);
  338.   free(tl0);
  339.  
  340.   g_free(blurb);
  341.   g_free(help);
  342.   g_free(author);
  343.   g_free(copyright);
  344.   g_free(date);
  345.   g_free(par_d);
  346.   g_free(rv_d);
  347.   return TCL_OK;
  348. }
  349.  
  350. /*
  351.  * query the database for any or all procedures
  352.  */
  353. int
  354. Gtcl_QueryDB(ClientData data, Tcl_Interp *interp, int ac, char *av[]){
  355.   char **procs, *r, *p_name;
  356.   int nproc, i;
  357.   if(ac != 8) {
  358.     Tcl_SetResult(interp, "gimp-query-db: wrong # args", TCL_STATIC);
  359.     return TCL_ERROR;
  360.   }
  361.   p_name = strdup(av[1]);
  362.   cvtto(p_name);
  363.   gimp_query_database (p_name, av[2], av[3], av[4], av[5], av[6], av[7],
  364.                &nproc, &procs);
  365.   free(p_name);
  366.   for(i=0;i<nproc;i++){
  367.     cvtfrom(procs[i]);
  368.   }
  369.   r=Tcl_Merge(nproc, procs);
  370.   for(i=1;i<nproc;i++){
  371.     free(procs[i]);
  372.   }
  373.   free(procs);
  374.   Tcl_SetResult(interp, r, TCL_DYNAMIC);
  375.   return TCL_OK;
  376. }
  377.  
  378. /*
  379.  * install a procedure in the database
  380.  */
  381. int
  382. Gtcl_InstallProc(ClientData data, Tcl_Interp *interp, int ac, char *av[]){
  383.   GParamDef *args_p, *rets_p;
  384.   char **args, **rets;
  385.   int narg, nret, i, type;
  386.  
  387.   if(ac!=12){
  388.     Tcl_SetResult(interp, "gimp-install-procedure: wrong # args:\n",
  389.           TCL_STATIC);
  390.     Tcl_AppendResult(interp, "usage: ", av[0],
  391.              " <name> <blurb> <help> <author> <copyright> <date> "
  392.              "<menu-path> <image-types> <type> <args> <retvals>",
  393.              (char *)NULL);
  394.     return(TCL_ERROR);
  395.   }
  396.  
  397.   if (strncasecmp("plug", av[9], 4)==0){
  398.     type=PROC_PLUG_IN;
  399.   } else if (strcasecmp("extension", av[9])==0){
  400.     type=PROC_EXTENSION;
  401.   } else {
  402.     Tcl_SetResult(interp, "unknown procedure type: `", TCL_STATIC);
  403.     Tcl_AppendResult(interp, av[9], "'", (char *)NULL);
  404.     return TCL_ERROR;
  405.   }
  406.  
  407.   if (Tcl_SplitList(interp, av[10], &narg, &args)==TCL_ERROR) {
  408.     return(TCL_ERROR);
  409.   }
  410.   if (Tcl_SplitList(interp, av[11], &nret, &rets)==TCL_ERROR) {
  411.     return(TCL_ERROR);
  412.   }
  413.   args_p=(GParamDef*)malloc(sizeof(GParamDef)*narg);
  414.   rets_p=(GParamDef*)malloc(sizeof(GParamDef)*nret);
  415.  
  416.   for(i=0;i<narg;i++){
  417.     if (list_to_pdef(interp, args[i], &args_p[i])== TCL_ERROR){
  418.       return TCL_ERROR;
  419.     }
  420.   }
  421.  
  422.   for(i=0;i<nret;i++){
  423.     if (list_to_pdef(interp, rets[i], &rets_p[i])== TCL_ERROR){
  424.       return TCL_ERROR;
  425.     }
  426.   }
  427. #if 0
  428.   fprintf(stderr, "proc_inst: %s [arg: %d] [ret: %d]\n", av[1], narg, nret);
  429.  
  430.   fprintf(stderr, "g_i_p(n=%s,\n      b=%s,\n      h=%s,\n      a=%s,\n",
  431.       av[1], av[2], av[3], av[4]);
  432.   fprintf(stderr, "      c=%s,\n      d=%s,\n      m=%s,\n      i=%s,\n",
  433.       av[5], av[6], av[7], av[8]);
  434.   fprintf(stderr, "      t=%d,\n     np=%d,\n     nr=%d)\n",
  435.       type, narg, nret);
  436. #endif
  437.   gimp_install_procedure(av[1], av[2], av[3], av[4], av[5], av[6], av[7],
  438.              av[8], type, narg, nret, args_p, rets_p);
  439.   free(args_p);
  440.   free(rets_p);
  441.   return TCL_OK;
  442. }
  443.  
  444. /*
  445.  * the libgimp dispatcher -- needed for plugins
  446.  */
  447. int
  448. Gtcl_GimpMain(ClientData data, Tcl_Interp *interp, int argc, char *argv[]){
  449.   char **av, **av0, *av1;
  450.   int ac0, i;
  451.   av1=Tcl_GetVar(interp, "argv", TCL_GLOBAL_ONLY);
  452.   Tcl_SplitList(interp, av1, &ac0, &av0);
  453.   av=(char **)malloc(sizeof(char*)*ac0+1);
  454.  
  455.   av[0] = Tcl_GetVar(interp, "argv0", TCL_GLOBAL_ONLY);
  456.   for(i=0;i<ac0;i++){
  457.     av[i+1]=av0[i];
  458.   }
  459.   gimp_main(ac0+1, av);
  460.   free((char*)av);
  461.   free((char*)av0);
  462.   return TCL_OK;
  463. }
  464.  
  465. /*
  466.  * get/set runtime data from the gimp program
  467.  * for running with last args
  468.  */
  469. int
  470. Gtcl_SetData(ClientData data, Tcl_Interp *interp, int ac, char *av[]){
  471.   if(ac!=3){
  472.     Tcl_SetResult(interp, "gimp-set-data: wrong # args:\n",
  473.           TCL_STATIC);
  474.     Tcl_AppendResult(interp, "usage: ", av[0],
  475.              " <key> <value>", (char *)NULL);
  476.     return(TCL_ERROR);
  477.   }
  478.   gimp_set_data(av[1], av[2], strlen(av[2]));
  479.   return TCL_OK;
  480. }
  481.  
  482. int
  483. Gtcl_GetData(ClientData data, Tcl_Interp *interp, int ac, char *av[]){
  484.   char tmp[1024];
  485.  
  486.   memset(tmp, 0, 1024);
  487.  
  488.   if(ac!=2){
  489.     Tcl_SetResult(interp, "gimp-get-data: wrong # args:\n",
  490.           TCL_STATIC);
  491.     Tcl_AppendResult(interp, "usage: ", av[0],
  492.              " <key>", (char *)NULL);
  493.     return(TCL_ERROR);
  494.   }
  495.   gimp_get_data(av[1], tmp);
  496.  
  497.   Tcl_SetResult(interp, tmp, TCL_VOLATILE);
  498.   return TCL_OK;
  499. }
  500.  
  501. /*
  502.  * static conveninence functions...
  503.  */
  504.  
  505. /*
  506.  * translate a 3 element list into a ParamDef structure
  507.  */
  508. static int
  509. list_to_pdef(Tcl_Interp *interp, char *list, GParamDef *p){
  510.   char **l;
  511.   int n, t;
  512.   if(Tcl_SplitList(interp, list, &n, &l)==TCL_ERROR){
  513.     return TCL_ERROR;
  514.   }
  515.   if(n!=3) {
  516.     Tcl_SetResult(interp, "ParamDef wasn't 3 elements", TCL_STATIC);
  517.     return TCL_ERROR;
  518.   }
  519.  
  520.   if((t=str_to_typeenum(l[0]))==-1) {
  521.     Tcl_SetResult(interp, "ParamDef: unknown type `", TCL_STATIC);
  522.     Tcl_AppendResult(interp, l[0], "'", (char *)NULL);
  523.     return(TCL_ERROR);
  524.   }
  525.   p->type=t;
  526.   p->name=strdup(l[1]);
  527.   p->description=strdup(l[2]);
  528.   Tcl_Free((char *)l);
  529.   return TCL_OK;
  530. }
  531.  
  532. static int
  533. str_to_typeenum(char *type){
  534.   int i;
  535.   for(i=0;i<sizeof(param_types);i++)
  536.     if(strcasecmp(type, param_types[i])==0) return i;
  537.   return -1;
  538. }
  539.  
  540.  
  541.