Sindbad~EG File Manager

Current Path : /usr/home/beeson/MathXpert/Engine/
Upload File :
Current File : /usr/home/beeson/MathXpert/Engine/verify.c

//
//  verify.c
//  MathXpert Calculus Assistant
//  Code to verify conditions on parameters to messages
//
//  Created by Michael Beeson on 5/31/24.
//  6.18.24 wrote  preDocument(char *message)
//  6.19.24  added symbolWindowResized
//  6.21.24  changed parameter to symbolWindowResized
//  6.30.24 corrected it on parameter messages
//  7.9.24  added new message graphMoved
//  7.13.24  added doublezoomin and doublezoomout
//  7.25.24  changed the parameter for askPointSlope
//  8.8.24   made initGraphDocFromLibrary accept languagenumber
//  8.9.24   fixed typo in error message on graphWindowResized
//  8.10.24  askPointSlope doesn't have 'index' now, so removed uninitialized variable
//  8.18.24  added setupAndCheckGraph
//  8.23.24  added drawAll
//  9.8.24  added circularAspect
// 10.19.24  added setGraphPaper
// 10.21.24  added toggleErase
// 10.24.24  added parameterIncrementChanged and updateParameters
// 11.9.24   corrected verify on setGraphPaper
// 12.2.24   added zoomAtPoint
// 1.1.25 added ADDSERIES
// 1.9.25  added "initAndAutoFinish"  to legalPreDocMessages
// 3.9.25  added changeGraphLineWidth
// 3.10.25  changed verify on updateParameters and changeGraphLineWidth to accept doubles
// 3.14.25  changed verify on updateParameters to read all three fields even if it doesn't check the third one


#include <stdio.h>
#include "tdefn.h"   // MAXTOPICS
#include "heap.h"
#include "heaps.h"
#include "terms.h"
#include "proverdl.h"
#include "model.h"   //  operation
#include "defns.h"
#include "vaux.h"
#include "arith.h"
#include "polyval.h"
#include "graphstr.h"
#include "parser.h"
#include "mpdoc.h"
#include "ProblemLibrary.h"
#include "natlang.h"
#include "mtext.h"  // MAXMENUS
#include "verify.h"
#include "probtype.h"



typedef struct { const char *line[10];  /* fixed size to avoid needing malloc */
                 int nlines;
               } message;   // needed by execute.h
#include "checkarg.h"  // needed by execute.h
#include "execute.h"   // finished
#include "getarg.h"   // needs_arg
#include "optable.h"   // access_optable

static int legal_commandID(int commandID)
// return 0 if it is legal, 1 if not
{
  operation op;
  op.choice = commandID & 15;  // lowest 4 bits
  op.choice += 1;   // so op.choice is between 1 and 16 now
             // set bits 13,14,15 of commandID to zero as well as all bits to the left of that
             //  there will be more bits to the left as ints are larger than 16 bits
  commandID = commandID >> 5;  //commandID | 0x1fff;
  op.men = (commandID & 0xff) -1;  // see opcommand, which this inverts
            // Now, is there really such a command?
  if( op.choice <= 0 || op.choice > 16  || op.men > MAXMENUS)
     return 1;
  actualop code = access_optable(op.men)[op.choice-1];
  if(code == NULL)
     return 0;
  return 1;
}

static int specifies_language(char *errbuf, char *param)
// return 0 if param specifies a supported language, either by number or case-insensitive name
  { int language_number;
    int nfields = sscanf(param,"%d", &language_number);
    if(nfields == 1)
       { if(0 <= language_number && language_number < MAXLANGUAGES)
            { strcpy(errbuf,"OK");
              return 0;
            }
         else
            { sprintf(errbuf,"%d is not the number of a supported language",language_number);
              return 1;
            }
        }
    // so nfields was 0, param isn't a number
    language_number = get_language_number(param);
     // returns ENGLISH if param is not the name of a supported language
    if(strcmp(param,"english") && language_number == ENGLISH)
       { sprintf(errbuf,"%s is not a supported language.",param);
         return 1;
       }
    return 0;
  }

static char *legalPreDocMessages[] =
// these messages will trigger the creation of a new document in main()
{
  "parseAndDisplay",
  "asknProblems",
  "askProblemsText",
  "askSubjectStrings",
  "askTopicStrings",
  "askProblemsSVG",
  "initSymbolDocFromLibrary",
  "initGraphDocFromLibrary",
  "setLanguage",
  "setupAndCheckGraph",
  "setupAndCheckSymbol",
  "randomProblem",
  "initAndAutoFinish"
};

int preDocument(char *message)
// return 1 if message is legal to send as a first message, i.e. with no hashed document retrieved
{ int k;
  for(k=0;k< sizeof(legalPreDocMessages)/sizeof(char*);k++)
     { if (!strcmp(message,legalPreDocMessages[k]))
           return 1;
     }
  return 0;
}

// These arrays are only for documentation:
#if 0
static char *symbolicMessages[] =
{
  "autoStep",
  "showStep",
  "autoFinish",
  "finished",
  "undo",
  "hint",
  "selectMenuChoice",
  "initAndAutoFinish",
  "initSymbolDocFromLibrary",
  "selectedRectangleSymbol",
  "execOpWithArg",
  "startSolving"
};

static char *graphMessages[] =
{
  "graphButton",
  "selectedRectangleGraph",
  "incrementActiveParameter",
  "decrementActiveParameter",
  "incrementParameter",
  "decrementParameter",
  "horizontalzoomout",
  "horizontalzoomin",
  "verticalzoomout",
  "verticalzoomin",
  "doublezoomout",
  "doublezoomin",
  "zoomAtPoint",
  "graphMoved",
  "toggleDirectionField",
  "toggleErase",
  "drawAll",
  "circularAspect",
  "setGraphPaper",
  "updateParameters"
};

static char *ajaxMessages[] =
{
  "checkArg",
  "unSelectRectangle",
  "destroyDocument",
  "graphTitleMoved",
  "askPointSlope",
  "activeParameterChanged",
  "parameterIncrementChanged"
};
#endif 


int verify(char *message, char *param, char *errbuf, int errbufsize)
/* state is one of the identifiers in the first lines of verify.h.
message must be a legal message, i.e., one the Engine can process when the receiving
document is in the specified state.  If not then put an error message in errbuf, in plain
English, not SVG, and return 1.

If so, then check if param contains the correct number and type of arguments in the correct format,
and perform not-too-difficult checks on the values themselves.
If something is incorrect, put an error message and return 1.  If it seems OK,
return 0 with "OK" in errbuf.
The message might still be rejected when it's actually processed, e.g. if it asks by
number for a problem that doesn't exist, etc.

All the error messages are meant for developers only, not end-users, so there is no
need to translate them into other languages.  Developers must read English.
*/
{
  if(param == NULL)
    { strcpy(errbuf, "Parameter cannot be NULL.");
      return 1;
    }
/*_______________________________________________________*/
  //  Messages to which the response is sendSymbolDocument:
  //  first the messages (from buttons) that don't actually need a parameter
  if(!strcmp(message,"autoStep") ||
     !strcmp(message,"showStep") ||
     !strcmp(message,"autoFinish") ||
     !strcmp(message,"undo") ||
     !strcmp(message,"hint") ||
     !strcmp(message,"finished")
    )
       { strcpy(errbuf,"OK");   // per the spec
         return 0;   // "dummy"  will be supplied for the param so it doesn't even have to be non-NULL
       }
  if(!strcmp(message,"selectMenuChoice"))
    { if(strlen(param) >= 10)
         { strcpy(errbuf,"Parameter to selectMenuChoice too long.  It is expected to be the string form of an integer, the command ID of a operation.");
           return 1;
         }
      int commandID;
      int nfields = sscanf(param,"%d",&commandID);
      if(nfields != 1)
         { strcpy(errbuf,"Parameter to selectMenuChoice is expected to be the string form of an integer, the command ID of a operation.");
           return 1;
         }
      if( legal_commandID(commandID))
         { strcpy(errbuf,"OK");
           return 0;
         }
     strcpy(errbuf,"Parameter to selectMenuChoice is expected to be the string form of an integer, the command ID of a operation. The Engine received an integer, but not one that encodes an operation.");
     return 1;
    }
  if(!strcmp(message,"initAndAutoFinish") ||
     !strcmp(message,"initSymbolDocFromLibrary)")
    )
       {
         int topicnumber, problemnumber,reasonstart,windowwidth;
         char languagename[64];
         int nfields = sscanf(param,"%d+%d+%d+%d +%s",&topicnumber,&problemnumber,&reasonstart,&windowwidth,languagename);
         if(nfields < 5)
            { strcpy(errbuf, "Incorrect parameter to initSymbolDocFromLibrary. ");
              strcat(errbuf, "Need topicnumber+problemnumber+reasonstart+width+languagename.");
              strcat(errbuf, "languagename as a string, lowercase.");
              strcat(errbuf, "reasonstart and windowwidth in CSS pixels.");
              return 1;
            }
         // Now check that the specified topic and problemnumber are valid
         if(! SYMBOLTOPIC(topicnumber))
            { sprintf(errbuf, "Incorrect parameter to initSymbolDocFromLibrary.  Supplied topic number %d is not a valid symbolic topic",topicnumber);
              return 1;
            }
         int nProblems = getnProblems(topicnumber);
         if(problemnumber > nProblems)
            { sprintf(errbuf, "problemnumber %d too large for topic %d\n", problemnumber,topicnumber);
              return 1;
            }
         strcpy(errbuf,"OK");
         return 0;
       }
  if( !strcmp(message, "selectedRectangleSymbol"))
       {
         int left,top,width,height,lineleft,linetop;
         double linewidth,lineheight;
         int windowwidth, windowheight;
         int nfields = sscanf(param, "[%d,%d,%d,%d,%d,%d,%lf,%lf,%d,%d]",
                              &left,&top,&width,&height,&lineleft,&linetop,
                              &linewidth,&lineheight,&windowwidth,&windowheight);
         if (nfields != 10)
            nfields = sscanf(param, "[%dpx,%dpx,%dpx,%dpx,%dpx,%dx,%lfpx,%lfpx,%dpx,%dpx]", &left,&top,&width,&height,&lineleft,&linetop,
               &linewidth,&lineheight,&windowwidth,&windowheight);
         if(nfields != 10)
            {
              strcpy(errbuf, "selectedRectangleSymbol parameter was incorrectly formatted. ");
               strcat(errbuf, "The expected format is [left,top,width,height,lineleft,linetop,linewidth,lineheight,windowwidth,windowheight].");
              return 1;
            }
         if(width <= 0 || height <= 0)
            { strcpy(errbuf,"parameter to selectedRectangleSymbol failed to specify positive width and height.");
              return 1;
            }
         // we don't further check that the numbers are reasonable.
         strcpy(errbuf,"OK");
         return 0;
       }
  if(!strcmp(message, "execOpWithArg"))
       {
         char inputArgText[256];
         int commandID;
         int nfields = sscanf(param,"%d+%s",&commandID,inputArgText);
         if(nfields != 2)
            { strcpy(errbuf, "parameter to execOpWithArg should be a number (commandID) followed by plus sign followed by a string.");
              return 1;
            }
         if(! legal_commandID(commandID))
            { sprintf(errbuf,"%d is not a legal commandID.",commandID);
              return 1;
            }
         strcpy(errbuf,"OK");
         return 0;
       }
   if(!strcmp(message, "setLanguage"))  // response is sendSymbolDocument
       {  // The parameter is either the number of the language, e.g. FRENCH, or its english name,
          //  e.g. "french".
          return specifies_language(errbuf,param);
       }
   if(!strcmp(message, "symbolWindowResized")) // response is sendSymbolDocument
       {  // param is three numbers, width+height+reasonstart, separated by a + sign
          int windowWidth, windowHeight,reasonstart;
          int nfields = sscanf(param, "%d+%d+%d",&windowWidth,&windowHeight,&reasonstart);
          if(nfields < 2 || windowWidth <= 0 || windowHeight <= 0 || reasonstart <= 0)
             { strcpy(errbuf, "Parameter to symbolWindowResized should be three positive integers, separated by plus signs.");
               return 1;
             }
          return 0;
       }
   if(!strcmp(message, "graphWindowResized")) // response is sendSymbolDocument
       {  // param is two numbers, [width,height], separated by a + sign
          int graphwidth, windowheight;
          int nfields = sscanf(param, "[%d,%d]",&graphwidth,&windowheight);
          if (nfields != 2)
              nfields = sscanf(param, "[%dpx,%dpx]", &graphwidth,&windowheight);
          if(nfields < 2 || graphwidth <= 0 || windowheight <= 0 )
             { strcpy(errbuf, "Parameter to graphWindowResized should be two positive integers, in brackets [width,height]; or both in pixels.");
               return 1;
             }
          return 0;
       }
/*____________________________________________________________________*/
/* Messages that concern getting a problem from the MathXpert Problem Library  */

   if(!strcmp(message, "asknProblems"))
      { // no parameter necessary
        strcpy(errbuf,"OK");
        return 0;
      }
   if(!strcmp(message,"askTopicStrings")  ||
      !strcmp(message,"askSubjectStrings")
     )
      {  // param is supposed to specify the language
         return specifies_language(errbuf,param);
      }
   if(!strcmp(message,"askProblemsSVG") ||
      !strcmp(message,"askProblemsText")
     )
      { // param should be  either a topic number or a topic string, a quoted topic name as in tdefn.h
        int topicnumber;
        int nfields = sscanf(param,"%d",&topicnumber);
        if (nfields == 0)  // param contains a string
           topicnumber = stringToTopic(param);
        if (!SUPPORTED_TOPIC(topicnumber))
           { sprintf(errbuf, "Param to askProblemsSVG did not contain a supported topic.");
             return 1;  // error
           }
        return 0;  // it was a supported topicnumber
      }
  
/*_____________________________________________________________________*/
/*  Message to initialize a symbol view once we have a (topic and) problem from the Problem Library */
  if(!strcmp(message, "initSymbolDocFromLibrary"))
     { // parameter must have the form topicnumber+problemnumber+reasonstart+windowwidth+language
       int topicnumber, problemnumber,reasonstart,windowwidth;
       char languagename[64];
       int nfields = sscanf(param,"%d+%d+%d+%d +%s",&topicnumber,&problemnumber,&reasonstart,&windowwidth,languagename);
       if(nfields < 5)
        { sprintf(errbuf, "Incorrect parameter to message initSymbolDocFromLibrary.");
          strcat(errbuf, "Need topicnumber+problemnumber+reasonstart+width+language.");
          strcat(errbuf, "Language is given by a string, e.g., french. ");
          return 1;
        }
      if (!SYMBOLTOPIC(topicnumber) || !SUPPORTED_TOPIC(topicnumber))
           { sprintf(errbuf, "%d is not a symbolic topic.",topicnumber);
             return 1;  // error
           }
      if(reasonstart <  60 || reasonstart > windowwidth-60)
           { sprintf(errbuf, "reasonstart must be at least 60 and less than windowwidth-60. You sent %d.",reasonstart);
             return 1;
           }
      if(windowwidth < 0)
           { sprintf(errbuf, "window width must be positive.");
             return 1;
           }
      if(specifies_language(errbuf, languagename) != 0)
           { sprintf(errbuf,"%s does not specify a supported language.",languagename);
             return 1;
           }
       // Now, is the specified problemnumber legal for the specified topic?
      int nProblems = getnProblems(topicnumber);
      if(problemnumber > nProblems)
         { sprintf(errbuf,"problemnumber %d too large for topic %d\n", problemnumber,topicnumber);
           return 1;
         }
      strcpy(errbuf,"OK");
      return 0;
     }

/*______________________________________________________________________*/
/* Messages to which the response is sendGraphDocument   */
   if(!strcmp(message,"initGraphDocFromLibrary"))
      {  /* parameter must have the form topicnumber+problemnumber+language+width+height */
         /* language can be given by name or by number   */
         /* First we check the language */
         int windowwidth, windowheight, topicnumber,languagenumber,problemnumber;
         int nfields = sscanf(param,"%d+%d+%d+%d+%d",
                    &topicnumber,
                    &problemnumber,
                    &languagenumber,
                    &windowwidth,
                    &windowheight
                    );
         if(nfields < 5)
           { char languagename[33];
             int languagenumber;
             nfields = sscanf(param,"%d+%d+%32[^+]+%d+%d",
                    &topicnumber,
                    &problemnumber,
                    languagename,
                    &windowwidth,
                    &windowheight
                    );
             if(nfields == 5)
                 languagenumber = get_language_number(languagename);
             else   //   if(nfields < 5),  perhaps language was given by number
                {   nfields = sscanf(param,"%d+%d+%d+%d+%d",
                    &topicnumber,
                    &problemnumber,
                    &languagenumber,
                    &windowwidth,
                    &windowheight
                    );
                }
             if(nfields < 5 )
                { sprintf(errbuf,"Incorrect parameter to initGraphDocFromLibrary.");
                  printf("Need topicnumber+problemnumber+language+windowwidth+windowheight");
                  return 1;
                }
           }
         // languagenumber is OK now,  whether it was passed or computed
         if(!SUPPORTED_TOPIC(topicnumber) || !GRAPH_TOPIC(topicnumber))
            { sprintf(errbuf, "%d is not a graph topic.",topicnumber);
              return 1;  // error
            }
         int nProblems = getnProblems(topicnumber);
         if(problemnumber > nProblems)
            { sprintf(errbuf,"problemnumber %d too large for topic %d\n", problemnumber,topicnumber);
              return 1;
            }
         if(windowwidth < 0)
           { sprintf(errbuf, "window width must be positive.");
             return 1;
           }
         if(windowheight < 0)
           { sprintf(errbuf, "window height must be positive.");
             return 1;
           }
         strcpy(errbuf,"OK");
         return 0;
      }
   if(!strcmp(message,"graphButton"))
      { int windowwidth,windowheight;
        int nfields = sscanf(param,"%u+%u",&windowwidth,&windowheight);
        if(nfields != 2)
           { sprintf(errbuf,"Parameter of graphButton message must be windowwidth and windowheight, separated by a plus sign.");
             return 1;
           }
        if(windowwidth < 0)
           { sprintf(errbuf, "window width must be positive.");
             return 1;
           }
        if(windowheight < 0)
           { sprintf(errbuf, "window height must be positive.");
             return 1;
           }
        strcpy(errbuf,"OK");
        return 0;
      }
   
   if(!strcmp(message,"zoomAtPoint"))
      { int graphwidth,height;
        double x,y,scroll;
        int nfields = sscanf(param,"[%lf,%lf,%lf,%d,%d]",&scroll,&x,&y,&graphwidth,&height);
        if(nfields == 5)
           { strcpy(errbuf,"OK");
             return 0;
           }
        if(nfields == 5)
           { strcpy(errbuf,"graphMoved parameter should be [scroll,x,y,graphwidth,windowheight], where scroll is the zoom factor and (x,y) the zoom center in viewport coordintes.  The viewport is the rectangle containing all the graphs but not the Toolbar.");
             return 1;
           }
        strcpy(errbuf,"zoomAtPoint parameter was incorrectly formatted. ");
        strcat(errbuf,"It should be  [scroll,x,y,graphwidth,windowheight], with the  last four in pixel coordinates, where scroll is the zoom factor and (x,y) the zoom center in viewport coordintes.  The viewport is the rectangle containing all the graphs but not the Toolbar.");
        return 1;
      }
   if(!strcmp(message,"graphMoved"))
      { int index,graphwidth,height;
        double x,y;
        int nfields = sscanf(param,"[%d,%lf,%lf,%d,%d]",&index,&x,&y,&graphwidth,&height);
        if(nfields == 5 && 0 <= index && index < MAXGRAPHS)
           { strcpy(errbuf,"OK");
             return 0;
           }
        if(nfields == 5)
           { strcpy(errbuf,"graphMoved parameter should be [whichgraph,x,y,graphwidth,windowheight], where whichgraph must be at least zero and less than MAXGRAPHS.");
             return 1;
           }
        strcpy(errbuf,"graphMoved parameter was incorrectly formatted. ");
        strcat(errbuf,"It should be  [whichgraph,deltax,deltay,graphwidth,windowheight], with the  last four in pixel coordinates.");
        return 1;
      }
      
   if(!strcmp(message,"selectedRectangleGraph"))
       { /* parameter has the form
            [whichgraph,left,top,width,height,toolbarwidth,windowwidth,windowheight]
         */
           int whichgraph,left,top,width,height;
           int toolbarwidth, windowwidth, windowheight;
           int nfields = sscanf(param, "[%d,%d,%d,%d,%d,%d,%d,%d]", &whichgraph,&left,&top,&width,&height,&toolbarwidth,&windowwidth,&windowheight);
           if (nfields != 8)
              nfields = sscanf(param, "[%d,%dpx,%dpx,%dpx,%dpx,%dpx,%dpx,%dpx]", &whichgraph,&left,&top,&width,&height,&toolbarwidth,&windowwidth,&windowheight);
           if(nfields != 8)
             {
               strcpy(errbuf,"selectedRectangleGraph parameter was incorrectly formatted. ");
               strcat(errbuf,"It should be a list of integers  [whichgraph,left,top,width,height,toolbarwidth,windowwidth,windowheight]");
               return 1;
             }
           if(width <= 0 || height <= 0)
             { strcpy(errbuf,"parameter to selectedRectangleGraph failed to specify positive width and height.\n");
               return 1;
             }
           strcpy(errbuf,"OK");
           return 0;
        }

if(
    !strcmp(message, "incrementActiveParameter") ||
    !strcmp(message, "decrementActiveParameter") ||
    !strcmp(message, "horizontalzoomout") ||
    !strcmp(message, "horizontalzoomin") ||
    !strcmp(message, "verticalzoomout") ||
    !strcmp(message, "verticalzoomin") ||
    !strcmp(message, "doublezoomout") ||
    !strcmp(message, "doublezoomin") ||
    !strcmp(message, "toggleDirectionField") ||
    !strcmp(message, "toggleErase") ||
    !strcmp(message, "circularAspect") ||
    !strcmp(message, "setGraphPaper")
  )
    { int windowwidth, windowheight;
      int nfields = sscanf(param,"%u+%u",&windowwidth,&windowheight);
      if(nfields != 2)
         { sprintf(errbuf,"Parameter of %s message must be windowwidth and windowheight, separated by a plus sign.", message);
           return 1;
         }
      if(windowwidth < 0)
         { sprintf(errbuf, "window width must be positive.");
           return 1;
         }
      if(windowheight < 0)
         { sprintf(errbuf, "window height must be positive.");
           return 1;
         }
      strcpy(errbuf,"OK");
      return 0;
    }
  if(
     !strcmp(message, "incrementParameter") ||
     !strcmp(message, "decrementParameter")
    )
    {
      int windowwidth, windowheight,index;
      int nfields = sscanf(param,"%u+%u+%u",&windowwidth,&windowheight, &index);
      if(nfields != 3)
         { sprintf(errbuf,"Parameter of %s message must be windowwidth and windowheight and the index of the parameter, separated by plus signs.", message);
           return 1;
         }
      if(windowwidth <= 0)
         { sprintf(errbuf, "window width must be positive.");
           return 1;
         }
      if(windowheight <= 0)
         { sprintf(errbuf, "window height must be positive.");
           return 1;
         }
      if(index < 0)
         { sprintf(errbuf, "index of parameter must be nonnegative.");
           return 1;
         }
      strcpy(errbuf,"OK");
      return 0;
    }
 if(!strcmp(message, "setGraphPaper"))
    {
      int windowwidth, windowheight,index, whichgraph;
      int nfields = sscanf(param,"%u+%u+%u+%u",&windowwidth,&windowheight, &index, &whichgraph);
      if(nfields == 4 && whichgraph <= 0)
         { sprintf(errbuf,"Last parameter of %s message should specify a graph number, which must be nonnegative and correspond to an existing graph.", message);
           return 1;
         }
      if(nfields < 3)
         { sprintf(errbuf,"Parameter of %s message should be windowwidth and windowheight and the index of the new graphpaper, separated by plus signs.", message);
           return 1;
         }
      if(windowwidth <= 0)
         { sprintf(errbuf, "window width must be positive.");
           return 1;
         }
      if(windowheight <= 0)
         { sprintf(errbuf, "window height must be positive.");
           return 1;
         }
      if(index < 0)
         { sprintf(errbuf, "index of the new graph paper must be nonnegative.");
           return 1;
         }
      strcpy(errbuf,"OK");
      return 0;
    }
 if( !strcmp(message, "updateParameters"))
    { double width, height;
      char data[500];
      int nfields = sscanf(param,"%lf+%lf+%s", &width, &height,data);
      if(nfields != 3)
        { sprintf(errbuf,"Parameter of updateParameters message should be windowwidth and windowheight and data encoding the parameters array, separated by plus signs. See adjustParameters.js.");
          return 1;
        }
     if(width <= 0)
         { sprintf(errbuf, "window width must be positive.");
           return 1;
         }
     if(height <= 0)
         { sprintf(errbuf, "window height must be positive.");
           return 1;
         }
     // but verify does not attempt to decode the parameters
     return 0;
    }
if( !strcmp(message, "changeGraphLineWidth"))
    { double width, height;
      int newLineWidth;
      int nfields = sscanf(param,"%lf+%lf+%d", &width, &height,&newLineWidth);
      if(nfields != 3)
        { sprintf(errbuf,"Parameter of changeGraphLineWidth message should be windowwidth and windowheight and newLineWidth, separated by plus signs.");
          return 1;
        }
     if(width <= 0)
         { sprintf(errbuf, "window width must be positive.");
           return 1;
         }
     if(height <= 0)
         { sprintf(errbuf, "window height must be positive.");
           return 1;
         }
     if(newLineWidth <= 0)
         { sprintf(errbuf, "newLineWidth must be positive.");
           return 1;
         }
     return 0;
    }

/*  Ajax messages (which do not require sending the whole document in responses) */

 if(!strcmp(message, "randomProblem"))
    { int problemtype, topicIn ;
      int nfields = sscanf(param, "%d+%d", &problemtype,&topicIn);
      if(nfields != 2)
         { sprintf(errbuf,"Incorrect parameter to randomProblem: %s",param);
           return 1;
         }
      // topicIn can be anything.  It is only used for symbolic problemtypes
      // and then only to see if complex numbers are allowed.
      // problemtype must belong to the following array;
      int symbolicProblemtypes[] =
         { SIMPLIFY,
           FACTOR,
           SOLVE_EQUATION,
           INEQUALITIES,
           LINEAR_EQUATIONS,
           TRIG_IDENTITY,
           LIMITS,
           DIFFERENTIATE,
           DIFFERENTIATE_FROM_DEFN,
           INTEGRATION,
           IMPROPER_INTEGRATION,
           IMPLICIT_DIFF,
           RELATED_RATES,
           MINMAX,
           ADDSERIES,
           TESTCONVERGENCE,
           POWERSERIES
         };
       int graphProblemtypes[] =
         {
           // Now the graph problemtypes, which are really mainchoices,
           // i.e. from mainchoi.h rather than probtype.h
           ORDINARY,           /*  y=f(x) */
           COMPARE_SAME,       /* two graphs on the same axes */
           COMPARE_DIFFERENT,  /* two graphs on different axes */
           MC_INEQ,            /*  y < f(x) or f(x) < y < g(x) */
           MC_SET,             /*  arbitrary relation with shaded interior */
           PARAMETRIC,
           POLAR_CIRCULAR,     /* axes drawn as circles and radial lines */
           POLYROOT,           /* graph complex roots of a polynomial */
           ODE,                /* graph y' = f(x,y)                   */
           ODE2,               /* Two odes  y' = f(x,y) and x'= g(x,y)  */
                               /* Drawing is over a parameter interval, one
                                direction only, but direction fields work. */
           ODESYSTEM,          /* graphically solve an ode x'=f(t,x,y), y'= g(t,x,y) */
                               /* if t does not occur, mainchoice should be ODE2 instead */
                               /*  direction fields don't work */
           HDE,                /*  poly(derivs of y) = f(x,y), linear in highest y-deriv */
                               /*  draws in both directions, direction fields don't work */
           RELATION,           /*  with equality rather than <   */
           COMPAREDERIV,
           COMPAREDERIVS,
           RIEMANNSUMS,
           TRAPEZOIDRULE,
           SIMPSONSRULE
         };
       int n = sizeof(symbolicProblemtypes)/sizeof(int);
       for(int k=0;k<n;k++)
          { if(symbolicProblemtypes[k] == problemtype)
                return 0; // param is OK
          }
        n = sizeof(graphProblemtypes)/sizeof(int);
       for(int k=0;k<n;k++)
          { if(graphProblemtypes[k] == problemtype)
                return 0; // param is OK
          }
       sprintf(errbuf,"Incorrect parameter to randomProblem: %s",param);
       return 1;
    }
           
 if(!strcmp(message,"graphTitleMoved"))
    { int index=1,nfields;  // initialize index to avoid a warning message
             // although it is not logically necessary, the compiler doesn't realize it
      double x1,y1,x2,y2;
      nfields = sscanf(param,"[%d,%lf,%lf,%lf,%lf",&index,&x1,&y1,&x2,&y2);
      if(nfields != 5 || index < 0 || index >= MAXGRAPHS)
         { sprintf(errbuf,"Incorrect parameter to graphTitleMoved: %s",param);
           return 1;
         }
      return 0;
   }
 if(!strcmp(message,"askPointSlope"))
    { int nfields;
      double x1,y1;
      nfields = sscanf(param,"[%lf,%lf",&x1,&y1);
      if(nfields != 2 )
         { sprintf(errbuf,"Incorrect parameter to askPointSlope: %s",param);
           return 1;
         }
      return 0;
   }

 if(!strcmp(message, "checkArg"))
    { int c2;
     if(strlen(param) > 512)
         { strcpy(errbuf,"Text entered is too long.  500 characters max");
           return 1;
         }
      int nfields = sscanf(param,"%d",&c2);
      char *rest = strchr(param, '+');
      if(nfields != 1 || c2 < 0 || rest == NULL)
         { strcpy(errbuf,"parameter to checkArg message should be integer+text");
           return 1;
         }
      ++rest;
      if(*rest == '\0' || *rest == ' ')
         { strcpy(errbuf,"parameter to checkArg message should be integer+text");
           return 1;
         }
      strcpy(errbuf,"OK");
      return 0;
    }
 if(!strcmp(message, "unSelectRectangle"))
    { // no parameter and no response
      strcpy(errbuf,"OK");
      return 0;
    }
 if(!strcmp(message,"parameterIncrementChanged"))
    {
      int index;
      double newIncrement;
      int nfields = sscanf(param,"%d+%lf",&index,&newIncrement);
      if(nfields != 2)
         { strcpy(errbuf,"parameter to parameterIncrementChanged message should be index+newIncrement");
           return 1;
         }
      if(newIncrement <= 0)
         { strcpy(errbuf, "parameter increment must be positive");
           return 1;
         }
      if(index < 0)
         { strcpy(errbuf, "parameter index must be non-negative");
           return 1;
         }
      strcpy(errbuf,"OK");
      return 0;
    }
if(!strcmp(message,"activeParameterChanged"))
    {
      int windowwidth, windowheight, index;
      int nfields = sscanf(param,"%d+%u+%u",&index,&windowwidth,&windowheight);
      if(nfields != 3)
         { strcpy(errbuf,"parameter to activeParameterChanged message should be index+graphwidth+windowheight");
           return 1;
         }
      if(index < 0)
         { strcpy(errbuf, "parameter index must be non-negative");
           return 1;
         }
      strcpy(errbuf,"OK");
      return 0;
    }

  /* Messages for typing in your own problem */
  if(!strcmp(message,"parseAndDisplay"))
    { // parameter is text to attempt to parse.  You can type anything.
      return 0;
    }
  if(!strcmp(message,"setupAndCheckSymbol"))
    {
    /* parameter has the form  "problemtext"+problemtype+
             language+width+height+topic+toolbarWidth.
       problemtype is a number, one of the values in probtype.h (but not all values
       there are supported).  */
       
      char languagename[33];
      char problemtext[MAXPROBLEMTEXT];
      int windowwidth, windowheight,problemtype,topic,toolbarWidth,languagenumber;
      char format_string[50];
      snprintf(format_string,
               sizeof(format_string),
               "\"%%%d[^\"]\"+%%d+%%d+%%d+%%d+%%d+%%d",
               MAXPROBLEMTEXT - 1);
      int nfields = sscanf(param, format_string,
                          problemtext,
                          &problemtype,
                          &languagenumber,
                          &windowwidth,
                          &windowheight,
                          &topic,
                          &toolbarWidth
                          );
        if(nfields < 7)
           { snprintf(format_string, sizeof(format_string), "\"%%%d[^\"]\"+%%d+%%32[^+]+%%d+%%d+%%d+%%d", MAXPROBLEMTEXT - 1);
        
             nfields = sscanf(param, format_string,
                          problemtext,
                          &problemtype,
                          languagename,
                          &windowwidth,
                          &windowheight,
                          &topic,
                          &toolbarWidth
                          );
             
            if(nfields < 7)
               { printf("Incorrect parameter to setupAndCheckGraph\n");
                 printf("Need \"problemtext\"+problemtype+language+windowwidth+windowheight+topic+toolbarWidth");
                 return 1;
               }
            languagenumber = get_language_number(languagename);
            return 0;
          }
    }
  if(!strcmp(message,"setupAndCheckGraph"))
    {   char languagename[33];
        char problemtext[MAXPROBLEMTEXT];
        int windowwidth, windowheight,graphtype,languagenumber;
        char format_string[50];
        snprintf(format_string, sizeof(format_string), "\"%%%d[^\"]\"+%%d+%%d+%%d+%%d", MAXPROBLEMTEXT - 1);
        int nfields = sscanf(param, format_string,
                          problemtext,
                          &graphtype,
                          &languagenumber,
                          &windowwidth,
                          &windowheight
                          );
        if(nfields < 5)
           { snprintf(format_string, sizeof(format_string), "\"%%%d[^\"]\"+%%d+%%32[^+]+%%d+%%d", MAXPROBLEMTEXT - 1);
        
             nfields = sscanf(param, format_string,
                          problemtext,
                          &graphtype,
                          languagename,
                          &windowwidth,
                          &windowheight
                          );
             
            if(nfields < 5)
               { printf("Incorrect parameter to setupAndCheckGraph\n");
                 printf("Need \"problemtext\"+graphtype+language+windowwidth+windowheight");
                 return 1;
               }
            languagenumber = get_language_number(languagename);
            return 0;
          }
     }
  if(!strcmp(message, "drawAll"))
     { int graphwidth, height;
       int nfields = sscanf(param, "%d+%d",  &graphwidth, &height);
       if (nfields != 2)
          { printf("Incorrect parameter to drawAll\n");
            printf("Need graphwidth+windowheight\n");
            return 1;
          }
       if( graphwidth <= 0 || height <= 0)
          { printf("Parameter to drawAll must specify positive numbers.\n");
            printf("The engine received %s\n", param);
            return 1;
          }
       return 0;
     }
  if(!strcmp(message, "startSolving"))
     { int width, height,topic;
       int nfields = sscanf(param, "%d+%d+%d", &width, &height,&topic);
       if(nfields != 3)
          { nfields = sscanf(param, "%d+%d",  &width, &height);
            if (nfields != 2)
               { printf("Incorrect parameter to drawAll\n");
                 printf("Need width+height\n");
                 return 1;
               }
          }
       if( width <= 0 || height <= 0)
          { printf("Parameter to startSolving must specify positive numbers.\n");
            printf("The engine received %s\n", param);
            return 1;
          }
       return 0;
     }

  if(!strcmp(message, "destroyDocument"))
    { return 0;
    }
  sprintf(errbuf,"message %s not verified", message);
  return 1;
}

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists