home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesaaiok.zip / source / MESASOLV.CPP < prev    next >
C/C++ Source or Header  |  1995-11-22  |  15KB  |  473 lines

  1. // we are including all the PM header files here.  Please replace with you
  2. // stock "Include all the OS/2 PM stuff" include file
  3. #define INCL_WIN
  4.  
  5. extern "C"
  6. {
  7. #include <os2.h>
  8. }
  9.  
  10. // include the Mesa AddIn header file
  11. #include "extaddin.h"
  12. #include <string.h>
  13. #include <stdio.h>                 // added for printf
  14. #include <stdlib.h>
  15.  
  16. // to avoid the C++ name mangling, let's define the names of the external
  17. // function here
  18.  
  19. extern "C"
  20. {
  21. void AddInInit(void *);
  22. void AddInFree(void *);
  23. }
  24.  
  25.  
  26. #include "mesasolv.h"
  27. #include "model.h"
  28. #include "range.h"
  29. #include "solver.h"
  30. #include "addin.h"
  31.  
  32. // a couple of global values
  33. AddIn *thisAddIn = NULL;
  34. int solverMenuId = 0;
  35. HWND *theHwnds = NULL;
  36. int count = 0;
  37.  
  38. // the data needed in the goal seeker.
  39. struct _solveData {
  40.    int type;
  41.    Model *md;
  42.    Solver *sp;
  43.    ULONG idTimer;
  44. };
  45.  
  46.  
  47. // this is the procedure that processes the "goal seeker" Dialog
  48. MRESULT EXPENTRY SolvDlgProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
  49. {
  50.    MRESULT ret = (MRESULT) 0L;
  51.    _solveData *sd = (_solveData *)WinQueryWindowULong(hwnd,QWL_USER);
  52.    char buffer[100];
  53.    int tmp, x;
  54.    Address ad;
  55.  
  56.     switch (msg) {
  57.     case WM_INITDLG:
  58.             x = 0;  // add itself to the array of hwnds
  59.             while (x < count && theHwnds[x]) {
  60.                x++;
  61.             } /* endwhile */
  62.  
  63.             if (x == count) {
  64.                 count *= 2;
  65.                 theHwnds = (HWND *)realloc(theHwnds,count*sizeof(HWND));
  66.             } /* endif */
  67.  
  68.             theHwnds[x] = hwnd;
  69.  
  70.             sd = new _solveData;
  71.             WinSetWindowULong(hwnd,QWL_USER,(ULONG) sd);
  72.             sd->md = new Model(-1);
  73.             sd->sp = NULL;
  74.  
  75.             ad=thisAddIn->getCurrentAddress();
  76.  
  77.             if(! sd->md->getBlob("SOLVER_CHNGCELL",100,buffer))
  78.                 sd->md->addressToString(ad,buffer,100);
  79.             WinSetDlgItemText(hwnd,DID_CHANGECELL,buffer);
  80.  
  81.             if(! sd->md->getBlob("SOLVER_FINALCELL",100,buffer))
  82.                 sd->md->addressToString(ad,buffer,100);
  83.             WinSetDlgItemText(hwnd,DID_SETCELL,buffer);
  84.  
  85.             if(! sd->md->getBlob("SOLVER_PREC",100,buffer))
  86.                 strcpy(buffer,"0.0001");
  87.             WinSetDlgItemText(hwnd,DID_PRECISION,buffer);
  88.  
  89.             if(! sd->md->getBlob("SOLVER_FVAL",100,buffer))
  90.                 strcpy(buffer,"0.0");
  91.             WinSetDlgItemText(hwnd,DID_FINALVALUE,buffer);
  92.  
  93.             if(! sd->md->getBlob("SOLVER_TYPE",100,buffer))
  94.                 sd->type = 0;
  95.             else
  96.                 sd->type = atoi(buffer);
  97.  
  98.             if (sd->type < 0 || sd->type > 2) {
  99.                sd->type = 0;
  100.             } /* endif */
  101.  
  102.             WinSendDlgItemMsg(hwnd,sd->type+DID_VALUE,BM_SETCHECK,(PVOID)TRUE,0L);
  103.  
  104.             sd->md->getName(buffer,100);
  105.             WinSetDlgItemText(hwnd,DID_MODELNAME,buffer);
  106.  
  107.             WinEnableWindow(WinWindowFromID(hwnd,DID_STOP),FALSE);
  108.             WinEnableWindow(WinWindowFromID(hwnd,DID_START),TRUE);
  109.        break;
  110.     case WM_CONTROL:
  111.         switch (SHORT1FROMMP(mp1)) {
  112.         case DID_MINIMUM:
  113.            sd->type = 1;
  114.            break;
  115.         case DID_MAXIMUM:
  116.            sd->type = 2;
  117.            break;
  118.         case DID_VALUE:
  119.            sd->type = 0;
  120.            break;
  121.         default:
  122.             return WinDefDlgProc ( hwnd,msg,mp1,mp2 ) ;
  123.         } // end switch
  124.        break;
  125.     case WM_COMMAND:
  126.        switch (LOUSHORT(mp1)) {
  127.        case DID_START:
  128.           {
  129.             Address adc,ads;
  130.             double prec,fv;
  131.             int type;
  132.  
  133.             WinQueryDlgItemText(hwnd,DID_CHANGECELL,100,buffer);
  134.             sd->md->setBlob("SOLVER_CHNGCELL",strlen(buffer)+1,buffer);
  135.             adc = sd->md->stringToAddress(buffer);
  136.             WinQueryDlgItemText(hwnd,DID_SETCELL,100,buffer);
  137.             sd->md->setBlob("SOLVER_FINALCELL",strlen(buffer)+1,buffer);
  138.             ads = sd->md->stringToAddress(buffer);
  139.  
  140.             WinQueryDlgItemText(hwnd,DID_FINALVALUE,100,buffer);
  141.             sd->md->setBlob("SOLVER_FVAL",strlen(buffer)+1,buffer);
  142.             fv = strtod(buffer,NULL);
  143.             WinQueryDlgItemText(hwnd,DID_PRECISION,100,buffer);
  144.             sd->md->setBlob("SOLVER_PREC",strlen(buffer)+1,buffer);
  145.             prec = strtod(buffer,NULL);
  146.  
  147.             sprintf(buffer,"%d",sd->type);
  148.             sd->md->setBlob("SOLVER_TYPE",strlen(buffer)+1,buffer);
  149.  
  150.             sd->sp = new Solver(*sd->md,adc,ads,prec,sd->type,fv);
  151.  
  152.             WinEnableWindow(WinWindowFromID(hwnd,DID_START),FALSE);
  153.             WinEnableWindow(WinWindowFromID(hwnd,DID_STOP),TRUE);
  154.  
  155.             sd->idTimer = WinStartTimer(WinQueryAnchorBlock(hwnd),hwnd,TID_USERMAX - 50,500);
  156.           }
  157.           break;
  158.       case DID_STOP:
  159.           WinStopTimer(WinQueryAnchorBlock(hwnd),hwnd,TID_USERMAX - 50);
  160.           if (sd->sp) {
  161.               if(sd->sp->isError())
  162.                  WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,sd->sp->getError(),"Goal Seeker Error!",
  163.                      24L,MB_OK | MB_ERROR);
  164.               else if (sd->sp->percentComplete() > 99 ) {
  165.                  DosBeep(1440,100);
  166.               } else {
  167.                  sd->sp->stop();
  168.                  WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,sd->sp->getError(),"Goal Seeker Error!",
  169.                      24L,MB_OK | MB_ERROR);
  170.                }
  171.               delete sd->sp;
  172.               sd->sp = NULL;
  173.           }
  174.           WinEnableWindow(WinWindowFromID(hwnd,DID_STOP),FALSE);
  175.           WinEnableWindow(WinWindowFromID(hwnd,DID_START),TRUE);
  176.           break;
  177.        default:
  178.          ret = WinDefDlgProc(hwnd,msg,mp1,mp2);
  179.          break;
  180.        } /* endswitch */
  181.        break;
  182.     case WM_TIMER:
  183.        if ((ULONG)mp1 == sd->idTimer) {
  184.           if (sd->sp && (sd->sp->isError() || (sd->sp->percentComplete() > 99 ))) {
  185.              WinStopTimer(WinQueryAnchorBlock(hwnd),hwnd,TID_USERMAX - 50);
  186.              sd -> idTimer = 0;
  187.              WinPostMsg(hwnd,WM_COMMAND,MPFROMSHORT(DID_STOP),0L);
  188.           } /* endif */
  189.        } else {
  190.           WinDefDlgProc(hwnd,msg,mp1,mp2);
  191.        } /* endif */
  192.        break;
  193.     case WM_GETMODELPTR:
  194.        return (MPARAM)sd->md;
  195.        break;
  196.     case WM_CLOSE:
  197.        for (x = 0; x < count ; x++) {   // remove from the hwnd Array
  198.           if (theHwnds[x] == hwnd) {
  199.              theHwnds[x] = NULL;
  200.           } /* endif */
  201.        } /* endfor */
  202.  
  203.        if (sd->sp) {
  204.           delete sd->sp;
  205.        } /* endif */
  206.        if (sd->md) {
  207.           delete sd->md;
  208.        } /* endif */
  209.        delete sd;
  210.        WinDismissDlg(hwnd,DID_OK);
  211.        break;
  212.     default:
  213.         ret = WinDefDlgProc(hwnd,msg,mp1,mp2);
  214.       break;
  215.     } /* endswitch */
  216.  
  217.     return ret;
  218. }
  219.  
  220. // this routine is called by Mesa when it needs to either check to see if a menu
  221. // item should be enabled or disabled or if if the command should be executed
  222. // A command may be passed to the call-back function even if the command is not
  223. // recognized by the call-back.  Ignore commands that your AddIn does not know
  224. // about and return a 0 for all commands that you do not recognize
  225. int myMenuCallBackRoutine(int command,int function)
  226. {
  227.    int ret = 0; // the default return value
  228.    HWND hwnd;
  229.  
  230.    switch (function)
  231.    {
  232.       // execute the command
  233.    case 0:
  234.          if (command == solverMenuId) {
  235.              int x = 0;
  236.              Model mo(-1);
  237.              int found = 0;
  238.              // check to see if the model already has a solver open for it
  239.              for (x = 0;x < count ; x++ ) {
  240.                 if (theHwnds[x] && (*(Model *)WinSendMsg(theHwnds[x],WM_GETMODELPTR,0,0) ==  mo)) {
  241.                    found = 1;
  242.                    hwnd = theHwnds[x];
  243.                 } /* endif */
  244.              } /* endfor */
  245.  
  246.              if (!found) {
  247.                  hwnd = WinLoadDlg(HWND_DESKTOP,thisAddIn-> getActiveWindow(),
  248.                       SolvDlgProc,(HMODULE)thisAddIn->getHandle(),ID_DLG_GOALSEEK,0L);
  249.              } else {
  250.                  WinSetFocus(HWND_DESKTOP,hwnd);
  251.              } /* endif */
  252.           }
  253.       break;
  254.  
  255.       // return 1 if the menu should be enabled or a 0 if this command
  256.       // is disabled or
  257.       // if we do not recognize this command.  All other values are
  258.       // reserved.
  259.       case 1:
  260.          // only activate when there is a window
  261.          if ((command == solverMenuId) && thisAddIn -> getActiveWindow())
  262.                ret = 1;
  263.          break;
  264.  
  265.       // open the help screen
  266.       case 2:
  267.          break;
  268.    }
  269.  
  270.    return ret;
  271. }
  272.  
  273. // this function will be called whenever a model is closed
  274. int aboutToClose(void *model_handle)
  275. {
  276.    int x = 0;
  277.    Model mo((int)model_handle);
  278.     HWND hwnd;
  279.  
  280.  
  281.    // check to see if the model already has a solver open for it
  282.    for (x = 0;x < count ; x++ ) {
  283.        if (theHwnds[x] && (*(Model *)WinSendMsg(theHwnds[x],WM_GETMODELPTR,0,0) ==  mo)) {
  284.            WinDismissDlg(theHwnds[x],0);  // if so, close it
  285.             theHwnds[x] = NULL;
  286.        } /* endif */
  287.     } /* endfor */
  288.  
  289.     return 0;
  290. }
  291.  
  292. void BeepFunction(int numParam, void *stack, void *model_handle)
  293. {
  294.     Model *mo = new Model((int) model_handle);
  295.     int x;
  296.  
  297.     if (numParam != 2) {  // the number of parameters is incorrect
  298.         for (x = 0; x < numParam ; x++ ) { // clear the stack
  299.             MesaAddInValue aiv;
  300.             mo -> initAddInValue(aiv);
  301.             mo -> popValue(stack,aiv);
  302.             mo -> freeAddInValue(aiv);
  303.         } // endfor
  304.         mo->pushError(stack,21);   // push the error on the stack
  305.                              // 21 is incorrect number of parameters
  306.     } else {
  307.         double a,b;
  308.         int error = 0;
  309.         if (mo->popValue(stack,a)) error = 1;  // pop the duration
  310.         if (mo->popValue(stack,b)) error = 1;  // pop the frequency
  311.         if (!error) {  // if none of the parameters was in error,
  312.             int d = a,f = b;      // Beep
  313.             DosBeep(f,d);
  314.             mo->pushValue(stack,"BEEP");  // We need to push something onto the stack
  315.         } else {
  316.             mo->pushError(stack,26); // push an error onto the stack
  317.         } // endif
  318.     } // endif
  319.  
  320.     delete mo;
  321. }
  322.  
  323. void numIn(int numParam, void *stack, void *model_handle)
  324. {
  325.     Model *mo = new Model((int) model_handle);
  326.     MesaAddInValue aiv, aiv2;
  327.     MesaAddInValue *ap;
  328.     int count = 0;
  329.  
  330.  
  331.     if (numParam != 2) { // incorrect number of parameters
  332.         for (int x = 0; x < numParam ; x++ ) { // clear the stack
  333.             mo -> initAddInValue(aiv);
  334.             mo -> popValue(stack,aiv);
  335.             mo -> freeAddInValue(aiv);
  336.         } // endfor
  337.         mo->pushError(stack,21);   // push the error on the stack
  338.         delete mo;
  339.         return;
  340.     } // endif
  341.  
  342.     mo -> initAddInValue(aiv);
  343.     mo -> initAddInValue(aiv2);
  344.  
  345.     mo -> popValue(stack,aiv);  // get the array
  346.     mo -> popValue(stack,aiv2); // get the search value
  347.  
  348.     ap = aiv.array;
  349.  
  350.     for (int r = 0; r < aiv.rows ; r++ ) {  // increment throught the rows and columns
  351.         for (int c = 0; c < aiv.cols ; c++ ) {
  352.             if (ap->type == aiv2.type) {
  353.                 switch (ap->type) {
  354.                 case errorValueMesaAddInType:
  355.                     if (ap->error == aiv2.error) {
  356.                         count++;
  357.                     } // endif
  358.                     break;
  359.                 case stringValueMesaAddInType:
  360.                     if (!strcmp(ap->string,aiv2.string)) {
  361.                         count++;
  362.                     } // endif
  363.                     break;
  364.                 case numberValueMesaAddInType:
  365.                     if (ap->number == aiv2.number) {
  366.                         count++;
  367.                     } // endif
  368.                     break;
  369.                 } // endswitch
  370.             } // endif
  371.             ap++;
  372.         } // endfor
  373.     } // endfor
  374.  
  375.  
  376.     mo -> freeAddInValue(aiv);
  377.     mo -> freeAddInValue(aiv2);
  378.  
  379.     double result = count;
  380.     mo -> pushValue(stack,count); // push the rsult onto the stack
  381.     delete mo;
  382. }
  383.  
  384. void layername(int numParam, void *stack, void *model_handle)
  385. {
  386.     Model *mo = new Model((int) model_handle);
  387.     int x;
  388.     double d;
  389.     char buffer[1000];
  390.  
  391.     if (numParam != 1) {  // this only takes one parameter
  392.         for (x = 0; x < numParam ; x++ ) { // clear the stack
  393.             MesaAddInValue aiv;
  394.             mo -> initAddInValue(aiv);
  395.             mo -> popValue(stack,aiv);
  396.             mo -> freeAddInValue(aiv);
  397.         } // endfor
  398.         mo->pushError(stack,21);   // push the error on
  399.                              // 21 is incorrect number of parameters
  400.     } else {
  401.         double a,b;
  402.         int error = 0;
  403.         if (mo->popValue(stack,d)) error = 1;  // pop a value off
  404.                                            // if it isn;t a number, mthe parameter is wrong
  405.         if (!error) {
  406.             int l = d;
  407.             Address ad(0,0,l); // create an address out of the result
  408.             mo -> addressToString(ad,buffer,1000);  // make it into a string, the string is of the form
  409.                                  // "[$LAYERNAME]$A$1"
  410.             char * c=strrchr(buffer,']');
  411.             *c = 0;          // Make it into "[$LAYERNAME"
  412.             mo->pushValue(stack,&buffer[2]); // push it on the stack
  413.         } else {
  414.             mo->pushError(stack,26);
  415.         } // endif
  416.     } // endif
  417.  
  418.     delete mo;
  419. }
  420.  
  421. // initialize everything needed by this addin
  422. void AddInInit(void *handle)
  423. {
  424.     // create an AddIn object from the handle
  425.     thisAddIn = new AddIn((int)handle);
  426.  
  427.     // check the version number.  This addin only works with 116 or higher
  428.     if (thisAddIn->version() < 116) {
  429.         return;   // don't regiser any new features
  430.     } // endif
  431.  
  432.     // If there is a Menu... (DOK apps might not have a Menu)
  433.     if (thisAddIn->getMenu())  {
  434.        // Add the Goal seeker to the menu
  435.        solverMenuId = thisAddIn -> addMenuItem("~Goal Seeker...");
  436.  
  437.        // Register a menu call back so we can get that command when pressed
  438.        thisAddIn -> registerMenuCallBackFunction(myMenuCallBackRoutine);
  439.     } // endif
  440.  
  441.     // space to hold the dialog window handles
  442.     count = 1;
  443.     theHwnds = (HWND *)malloc(sizeof(HWND)*count);
  444.     theHwnds[0]=NULL;
  445.  
  446.     // When workbooks are closed we want to close the solver window
  447.     thisAddIn -> registerAboutToCloseFunction(aboutToClose);
  448.  
  449.     // Register some AddIn functions
  450.     thisAddIn -> registerFunction("NUMIN(","NUMIN","NUMIN(ITEM,RANGE)",
  451.                     "Counts the number of times ITEM appears in the range",
  452.                     "NUMIN(12,A1:C25)",0,numIn);
  453.     thisAddIn -> registerFunction("LAYERNAME(","LAYERNAME","LAYERNAME(LAYER)",
  454.                    "Returns the string representation of the layer",
  455.                    "LAYERNAME(THISLAYER)",
  456.                    0,layername);
  457.     thisAddIn -> registerFunction("BEEP(","BEEP","BEEP(FREQUENCY,DURATION)",
  458.         "Beeps at the specified frequency (hz) for the specified duration (milliseconds)",
  459.         "BEEP(1440,100)",
  460.         0,BeepFunction);
  461.  
  462. }
  463.  
  464.  
  465. // we need to free the hwnd list because all of those windows are now closed
  466. void AddInFree(void *)
  467. {
  468.     free(theHwnds);
  469.     delete thisAddIn;
  470. }
  471.  
  472.  
  473.