/* file: launcher.c */
/*********************************************************************\
 *                                                                   *
 * Simple program launcher for windows.  The single argument is a    *
 * filename which contains a list of zero or more programs to run.   *
 * The mapping between program name and executable name is in the    *
 * profile (.ini)                                                    *
 *                                                                   *
\*********************************************************************/ 

#include <windows.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <commdlg.h>
#include <dlgs.h>

/* define strings for .ini file */
#define SECTION "Mappings"
#define PROFILE "launcher.ini"

/* comment out the following for internal library version */
/* #define REMOTE_CONFIG 1  */

/* name of the help file */
#define HELPFILE "launcher.hlp"

/* forward references */
UINT CALLBACK OpenFileHook(HWND,UINT,WPARAM,LPARAM);
int GetParams(HFILE,char *, int, char *, int, int *); 

/* entry point */
int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance,
                   LPSTR CmdLine, int nCmdShow)
{
  
  HFILE hFile;
  char keyword[512];
  char params[512];
  char PgmPath[512];
  char cmd[512];
  int cflag;
#ifdef REMOTE_CONFIG
  OPENFILENAME openfn;
#endif  
  UINT retval;
  
  /* open the file named on the command line */
  hFile = _lopen(CmdLine,READ);
  if (hFile == HFILE_ERROR) return(0);          /* quietly bomb on error */
  
  /* loop read, map/configure and launching applications */
  while(GetParams(hFile,keyword,sizeof(keyword),
                  params,sizeof(params),&cflag) != -1) {
   
   /* check for empty keyword */
   if (*keyword == '\0') continue;
   
   /* is this a request to launch or configure? */
   if (cflag) {
#ifdef REMOTE_CONFIG
    memset(&openfn,0,sizeof(OPENFILENAME));     /* clear the structure */
    openfn.lStructSize = sizeof(OPENFILENAME);  /* set the required fields */
    openfn.hwndOwner = NULL;
  
    /* go get the filename */ 
    PgmPath[0] = '\0';
    openfn.hInstance = hInstance;
    (FARPROC) (openfn.lpfnHook) = 
      MakeProcInstance((FARPROC) OpenFileHook,hInstance);
    openfn.lpstrFilter = 
       "Programs (*.exe)\000*.exe\000Batch Files (*.bat)\000\
*.bat\000DOS applications (*.PIF)\000*.pif\000All files (*.*)\000*.*\000";
    openfn.lpstrFile = PgmPath;
    openfn.nMaxFile = sizeof(PgmPath);
    openfn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST | 
                   OFN_FILEMUSTEXIST | OFN_ENABLEHOOK;
    if (!(GetOpenFileName(&openfn))) {
     FreeProcInstance((FARPROC) openfn.lpfnHook);
     return(1);
    }
    FreeProcInstance((FARPROC) openfn.lpfnHook);
    
    /* write the entry in the .ini file */
    WritePrivateProfileString(SECTION,keyword,PgmPath,PROFILE);
#else
    MessageBox(NULL,"Can't re-configure this internal library machine.",
                    "Launcher Configure Error",MB_ICONSTOP);
#endif
   }
   
   /* otherwise, launch the program */
   else {
    GetPrivateProfileString(SECTION,keyword,"~",
                            PgmPath,sizeof(PgmPath),PROFILE);
    if (*PgmPath != '~') {
     sprintf(cmd,"%s %s",PgmPath,params);
     if((retval = WinExec(cmd,SW_SHOW)) < 32) {
      sprintf(keyword,"Error launching: %s (code=%d)",PgmPath,retval);
      MessageBox(NULL,keyword,"Launcher Error",MB_ICONSTOP);
      return(101);
     }
    }
    else {
     MessageBox(NULL,"Unknown application. Make sure the launcher\
 configuration is correct.","Launcher Configure Error",MB_ICONSTOP);
     return(101);
    }
   }   
  }
  
  /* all done */
  return(100);
}  

/* gets the parameters from the next line in the input file, returns */
/* -1 at end of file */
int GetParams(HFILE hFile,char *keyword,int klen,
              char *params,int plen,int *cflag) 
{ 
  register i;
  
  /* scan off leading whitespace, get one byte at a time */
  for(*cflag=FALSE,i=0,klen--; i < klen;) {
   if (_lread(hFile,keyword+i,1) == 0) { 
    if (i == 0) return(-1);
    *(keyword+i) = '\0';              /* EOF and we got some chars */
    return(0);
   }
   if (*(keyword+i) == '\n' || *(keyword+i) == '\r') {
    *(keyword+i) = '\0';              /* terminate and return */
    return(0);
   }
   if (isspace(*(keyword+i))) {       /* whitespace? */
    if (i != 0) break;                /* end of keyword */
   }
   else {
    i++;                              /* advance the index */
   }
  }
  *(keyword+i) = '\0';                /* terminate the string */
  
  /* if this is configure, set configure flag and read keyword */
  if (strcmp("configure",keyword) == 0) {
   *cflag = TRUE;                     /* set configure flag */
   for(i=0,klen--; i < klen;) {
    if (_lread(hFile,keyword+i,1) == 0) { 
     if (i == 0) return(-1);
     *(keyword+i) = '\0';             /* EOF and we got some chars */
     return(0);
    }
    if (*(keyword+i) == '\n' || *(keyword+i) == '\r') {
     *(keyword+i) = '\0';             /* terminate and return */
     return(0);
    }
    if (isspace(*(keyword+i))) {      /* whitespace? */
     if (i != 0) break;               /* end of keyword */
    }
    else {
     i++;                             /* advance the index */
    }
   }
   *(keyword+i) = '\0';               /* terminate the string */
  }

  /* now get the rest of the command line */
  for(i=0,plen--; i < plen; i++) {
   if (_lread(hFile,params+i,1) == 0) break; 
   if (*(params+i) == '\n' || *(params+i) == '\r') break;
  }
  *(params+i) = '\0';                 /* terminate the string */
  
  /* all done */
  return(0);
}

/* openfile hook procedure */
UINT CALLBACK _export OpenFileHook(HWND hwnd, UINT message,
                                   WPARAM wParam, LPARAM lParam)
{
  int code;
    
  /* process the message, return TRUE if we handle the message */
  switch(message) {
   case WM_INITDIALOG:
        SetWindowText(hwnd,"Locate the program to launch");
        return(FALSE);
        
   case WM_COMMAND:
#ifdef WIN32
        code = LOWORD(wParam);
#else
        code = wParam;
#endif
        switch(code) {
         case pshHelp:
              WinHelp(hwnd,HELPFILE,HELP_CONTEXT,(DWORD) 1);
              return(TRUE);
        }
  }
  return(FALSE);
}
   