home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic 4 Unleashed / Visual_Basic_4_Unleashed_SAMS_Publishing_1995.iso / repease / rep_misc.c < prev    next >
C/C++ Source or Header  |  1995-02-17  |  22KB  |  649 lines

  1. /*==============================================================================
  2.    REP_MISC.C
  3.    Report Ease miscellaneous functions.
  4.  
  5.    ReportEase Plus
  6.    Sub Systems, Inc.
  7.    ReportEase Plus, Copyright (c) 1993, Sub Systems, Inc. All Rights Reserved.
  8.    159 Main Street, #8C, Stoneham,  MA 02180 
  9.    (617) 438-8901.
  10.  
  11.    Software License Agreement  (1993)              
  12.    ----------------------------------
  13.    This license agreement allows the purchaser the right to modify the 
  14.    source code to incorporate in their application.
  15.    The target application must not be distributed as a standalone report writer
  16.    or a mail merge product.
  17.    Sub Systems, Inc. reserves the right to prosecute anybody found to be 
  18.    making illegal copies of the executable software or compiling the source
  19.    code for the purpose of selling there after.
  20.  
  21. ===============================================================================*/
  22. #include "windows.h"
  23.  
  24. #if defined (_WIN32)
  25.    #if !defined(WIN32)
  26.      #define WIN32
  27.    #endif
  28. #endif
  29. #if !defined(WIN32) 
  30.   #include "print.h"
  31. #endif
  32.  
  33. #include "stdio.h"
  34. #include "stdlib.h"
  35. #include "ctype.h"
  36. #include "fcntl.h"
  37. #include "io.h"
  38. #include "sys\types.h"
  39. #include "sys\stat.h"
  40. #include "string.h"
  41. #include "dos.h"
  42. #include "setjmp.h"
  43.  
  44. #include "rep.h"
  45.  
  46. #define  PREFIX extern
  47. #include "rep1.h"
  48.  
  49. /*****************************************************************************
  50.     RepGetParent:
  51.     Get the parent window handle.  Needed by RVB.VBX
  52. ******************************************************************************/
  53. HWND WINAPI _export RepGetParent()
  54. {
  55.     if (SessionType=='F') return FormArg.hParentWnd;
  56.     else                  return RepArg.hParentWnd;
  57. }
  58.  
  59. /******************************************************************************
  60.     GetFileLength:
  61.     Get the size of the given file in number of bytes.  This function returns
  62.     -1 if an error occurs
  63. *******************************************************************************/
  64. long GetFileLength(LPSTR FileName)
  65. {
  66.     HFILE iFile;
  67.     long len=-1L;
  68.  
  69.     if ((iFile=_lopen(FileName,OF_READ))==HFILE_ERROR) return len;
  70.  
  71.     if (HFILE_ERROR==(len=_llseek(iFile,0,2))) return (long)-1; // position at the end of the file
  72.  
  73.     _lclose(iFile);
  74.  
  75.     return len;
  76. }
  77.  
  78. /*****************************************************************************
  79.     GetSystemDateTime:
  80.     Get the system date and time
  81. ******************************************************************************/
  82. void GetSystemDateTime()  
  83. {
  84.    #if defined (WIN32)
  85.       SYSTEMTIME DateTime;
  86.  
  87.       GetSystemTime(&DateTime);
  88.       SystemDate=(long)DateTime.wYear*10000L+(long)DateTime.wMonth*100L+(long)DateTime.wDay;
  89.       wsprintf(SystemTime,"%02d:%02d:%02d",DateTime.wHour,DateTime.wMinute,DateTime.wSecond);
  90.  
  91.    #else
  92.       union  REGS reg;
  93.       union  REGS oreg;
  94.       struct SREGS sreg;
  95.  
  96.       //***************** get system date time **********************************
  97.       // get date 
  98.       reg.h.ah=0x2a;
  99.       segread(&sreg);
  100.       sreg.es=sreg.ds;               // a valid value for ES 
  101.       int86x(0x21,®,&oreg,&sreg);
  102.  
  103.       SystemDate=(long)oreg.x.cx*10000L+(long)oreg.h.dh*100L+(long)oreg.h.dl;
  104.       
  105.       // get time 
  106.       reg.h.ah=0x2c;
  107.       segread(&sreg);
  108.       sreg.es=sreg.ds;               // a valid value for ES 
  109.       int86x(0x21,®,&oreg,&sreg);
  110.       wsprintf(SystemTime,"%02d:%02d:%02d",oreg.h.ch,oreg.h.cl,oreg.h.dh);
  111.    #endif
  112.  
  113. }
  114.  
  115. /*****************************************************************************
  116.     StrTrim:
  117.     Remove spaces from the left and right of a NULL terminated string.
  118. ******************************************************************************/
  119. void StrTrim(LPSTR string)  
  120. {
  121.     rTrim(string);lTrim(string);
  122. }
  123.  
  124. /******************************************************************************
  125.     rTrim:
  126.     Remove spaces on the right of a string.
  127. *****************************************************************************/
  128. void rTrim(LPSTR string)  
  129. {
  130.     int i,TempLen;
  131.  
  132.     TempLen=lstrlen(string);
  133.     for (i=TempLen-1;i>=0 && string[i] == ' ';i--);
  134.     string[i+1] = '\0';
  135. }
  136.  
  137. /******************************************************************************
  138.     lTrim:
  139.     Trim initial spaces from the string.
  140. *******************************************************************************/
  141. void lTrim(LPSTR string)    
  142. {
  143.     int i,TempLen,BeginPoint;char TempStr[LINE_WIDTH+2];
  144.  
  145.     TempLen=lstrlen(string);
  146.     for (i=0;i < TempLen && string[i] == ' ';i++);
  147.     BeginPoint=i;
  148.     for (i=BeginPoint;i<TempLen;i++) TempStr[i-BeginPoint]=string[i];
  149.     TempStr[TempLen-BeginPoint] = '\0';
  150.     lstrcpy(string,TempStr);
  151. }
  152.  
  153. /*******************************************************************************
  154.    lPad:
  155.    Insert spaces before the string such that the string length becomes
  156.    as specified.
  157.    length=Final length;
  158. *******************************************************************************/
  159. lPad(LPSTR string,int length)
  160. {
  161.     int i,len,spaces;
  162.     
  163.     len=lstrlen(string);
  164.     if (len>=length) return TRUE;
  165.     
  166.     spaces=length-len;
  167.  
  168.     FarMoveOl(string,&string[spaces],len+1);
  169.     for (i=0;i<spaces;i++) string[i]=' ';
  170.  
  171.     return TRUE;
  172. }
  173.  
  174. /*******************************************************************************
  175.    rPad:
  176.    Insert spaces after the string such that the string length becomes
  177.    as specified.
  178.    length=Final length;
  179. *******************************************************************************/
  180. rPad(LPSTR string,int length)
  181. {
  182.     int i,len,spaces;
  183.     
  184.     len=lstrlen(string);
  185.     if (len>=length) return TRUE;
  186.     
  187.     spaces=length-len;
  188.  
  189.     for (i=0;i<spaces;i++) string[len+i]=' ';
  190.     string[len+i]=0;
  191.     return TRUE;
  192. }
  193. /******************************************************************************
  194.     lstrupr:
  195.     Converts a far string to upper case.
  196. *******************************************************************************/
  197. LPSTR lstrupr(LPSTR string)    
  198. {
  199.     int i,len;
  200.  
  201.     len=lstrlen(string);
  202.     
  203.     for (i=0;i<len;i++) {
  204.        string[i]=toupper(string[i]);
  205.     }
  206.     return string;
  207. }
  208.  
  209. /******************************************************************************
  210.     lstrlwr:
  211.     Converts a far string to lower case.
  212. *******************************************************************************/
  213. LPSTR lstrlwr(LPSTR string)    
  214. {
  215.     int i,len;
  216.  
  217.     len=lstrlen(string);
  218.     
  219.     for (i=0;i<len;i++) {
  220.        string[i]=tolower(string[i]);
  221.     }
  222.     return string;
  223. }
  224.  
  225. /******************************************************************************
  226.     lstrstr:
  227.     This routine  returns the location of the second string within the 
  228.     first string.
  229. *******************************************************************************/
  230. LPSTR lstrstr(LPSTR string1,LPSTR string2)    
  231. {
  232.     int len1,len2,ScanLen,i;
  233.  
  234.     len1=lstrlen(string1);
  235.     len2=lstrlen(string2);
  236.  
  237.     if (len1<len2) return NULL;  // first string too small to contain the second string 
  238.  
  239.     ScanLen=len1-len2;
  240.  
  241.     for (i=0;i<=ScanLen;i++) if (StringBegins(&string1[i],string2)) return &string1[i];
  242.  
  243.     return NULL;
  244. }
  245.  
  246. /******************************************************************************
  247.     StringBegin:
  248.     This routine  returns a TRUE value of the first string begins with
  249.     the second string.
  250. *******************************************************************************/
  251. BOOL StringBegins(LPSTR string1,LPSTR string2)    
  252. {
  253.     int len1,len2,i;
  254.  
  255.     len1=lstrlen(string1);
  256.     len2=lstrlen(string2);
  257.  
  258.     if (len1<len2) return FALSE;  // first string too small to contain the second string 
  259.  
  260.     for (i=0;i<len2;i++) if (string1[i]!=string2[i]) return FALSE;
  261.     
  262.     return TRUE;
  263. }
  264.  
  265. /******************************************************************************
  266.      AssignNumVal:
  267.      Extract a numeric value from the dialog item.  Display error if a non-
  268.      numeric value is encountered and return a false result.
  269. *******************************************************************************/
  270. BOOL AssignNumVal(HWND hWin,int ControlId,int *pInt)
  271. {
  272.     BOOL ErrorFlag;
  273.  
  274.     *pInt=GetDlgItemInt(hWin,ControlId,&ErrorFlag,(BOOL) 0);
  275.     if (!ErrorFlag) {
  276.        MessageBox(hWin,"Must Enter a Valid Number",NULL,MB_OK);
  277.        SetFocus(GetDlgItem(hWin,ControlId));
  278.        return (FALSE);
  279.     }
  280.     return TRUE;
  281. }
  282.  
  283. /******************************************************************************
  284.     CheckDlgValue:
  285.     This routine checks if the user entered a numeric value within the given
  286.     range.  If a value is found outside the range,  the routine displays
  287.     an error message, sets the focus on the item, and returns a false value.
  288. *******************************************************************************/
  289. BOOL CheckDlgValue(HWND hDlg,char type,int id,double BeginRange,double EndRange) 
  290. {
  291.     double value;
  292.     BOOL flag=TRUE;
  293.     char string[100];
  294.  
  295.     if (type=='I') {
  296.        value=(double)GetDlgItemInt(hDlg,id,&flag,0);
  297.        if (!flag) goto ERROR_FOUND;
  298.     }
  299.     else {
  300.        GetDlgItemText(hDlg,id,string,100);
  301.        value=atof(string);
  302.     }
  303.  
  304.     if (value<BeginRange || value>EndRange) goto ERROR_FOUND;
  305.  
  306.     return TRUE;
  307.  
  308.     ERROR_FOUND:
  309.     MessageBox(hDlg,"Invalid Value, Please Re-enter","Value Out of Range",MB_OK);
  310.     SetFocus(GetDlgItem(hDlg,id));
  311.     return FALSE;
  312. }
  313.  
  314. /******************************************************************************
  315.     CurrentPrinter:
  316.     Get information (name,driver,port) for the currently selected printer.
  317.     The function returns FALSE if the current printer not set.
  318. ******************************************************************************/
  319. BOOL CurrentPrinter(LPSTR name,LPSTR driver,LPSTR port)
  320. {
  321.     int len;
  322.     char ext[5];
  323.  
  324.     if (!ParseProfileString("windows","device", name,driver,port)) {
  325.        MessageBox(hFrParentWnd,"Unable to Access the Current Printer!",NULL,MB_OK);
  326.        return FALSE;
  327.     }
  328.  
  329.     // add .drv extension to the driver name, if necessary 
  330.     len=lstrlen(driver);
  331.     if (len<=4) lstrcat(driver,".drv");
  332.     else {
  333.        lstrcpy(ext,&driver[len-4]);
  334.        strupr(ext);
  335.        if (strcmp(ext,".DRV")!=0) lstrcat(driver,".DRV");
  336.     }
  337.     
  338.     return TRUE;
  339. }
  340.  
  341. /******************************************************************************
  342.     ParseProfileString:
  343.     This routine retrieves the profile string for the given application
  344.     and key value.  It then parses the string and returns first 3 strings
  345.     delimited by comma characters.
  346. ******************************************************************************/
  347. BOOL ParseProfileString(LPSTR appl,LPSTR key, LPSTR string1, LPSTR string2, LPSTR string3)
  348. {
  349.     LPSTR temp,str1=0,str2=0,str3=0;
  350.     char string[100];
  351.     
  352.     string1[0]=string2[0]=string3[0]=0;  // initialize the output strings 
  353.  
  354.     if (!GetProfileString(appl,key,(LPSTR) "",string,99)) return FALSE;
  355.  
  356.     temp=str1=string;                  // beginning pointer for the scan 
  357.  
  358.     while(*temp) {                     // scan until a NULL is found 
  359.        if (*temp==',') {               // a delimited found 
  360.           *temp=0;                     // NULL terminate the previous string, and advance the pointer 
  361.           temp++;
  362.           while (*temp==' ') temp=AnsiNext(temp);   // skip leading spaces 
  363.           if (!str2) str2=temp;        // Initiate the driver string if not found yet 
  364.           else if (!str3) str3=temp;   // else it is the last string, i.e. the port string 
  365.           else break;
  366.        }
  367.        else temp=AnsiNext(temp);       // advance the pointer 
  368.     }
  369.     
  370.     if (str1) lstrcpy(string1,str1);   // copy the strings to the user specified area 
  371.     if (str2) lstrcpy(string2,str2);
  372.     if (str3) lstrcpy(string3,str3);
  373.     
  374.     return TRUE;
  375. }
  376.  
  377. /******************************************************************************
  378.     ValidateDate:
  379.     Validate a date in a string and convert to its numeric value (YYYYMMDD).
  380.     The input date is in a quoted string.
  381. ******************************************************************************/
  382. int ValidateDate(LPSTR InDate,long far *NumValue)
  383. {
  384.     char string[20],delim=0,CurChar;
  385.     int  i,j,len,mm,dd,yy,TotalDelims;
  386.     long temp;
  387.  
  388.     len=lstrlen(InDate);
  389.     if (len<8 || len>12) return FALSE;   // invalid date 
  390.  
  391.     TotalDelims=0;
  392.  
  393.     j=0;
  394.     mm=dd=yy=0;
  395.     for(i=1;i<(len-1);i++) {             // omit beginnning and ending quotes 
  396.        CurChar=InDate[i];
  397.        if (CurChar>='0' && CurChar<='9') {
  398.           string[j]=CurChar;
  399.           j++;
  400.        }
  401.        else if (strchr("-/,",CurChar)) {
  402.           if (j==0 || j>2)   return FALSE; // not a valid date format 
  403.           if (TotalDelims>2) return FALSE; // not a valid date format 
  404.           if (TotalDelims==1 && delim!=CurChar) return FALSE;
  405.           string[j]=0;
  406.           if (TotalDelims==0) {
  407.              if (FormHdr.DateFormat==0) mm=atoi(string);
  408.              else                       dd=atoi(string);
  409.           }
  410.           else {
  411.              if (FormHdr.DateFormat==0) dd=atoi(string);
  412.              else                       mm=atoi(string);
  413.           }
  414.           j=0;
  415.           delim=CurChar;
  416.           TotalDelims++;
  417.        }
  418.        else return FALSE;                  // invalid character 
  419.     }
  420.     if (j==0 || j>4)   return FALSE; // not a valid date format 
  421.     string[j]=0;
  422.     yy=atoi(string);
  423.  
  424.     // validate the date 
  425.     (*NumValue)=-1;                  // marks an invalid date 
  426.     if (mm<1 || mm>12) return TRUE;
  427.     if (dd<1 || dd>31) return TRUE;
  428.     if ((mm==4 || mm==6 || mm==9 || mm==11) && dd>30) return TRUE;
  429.     if (mm==2) {                     // check leap year 
  430.        if (yy==(yy/4)*4) {
  431.           if (dd>29) return TRUE;
  432.        }
  433.        else if (dd>28) return TRUE;
  434.     }
  435.  
  436.     //********** convert to the YYYYMMDD numeric value **********
  437.     if (yy<=99) yy+=1900;
  438.     temp=yy;
  439.     temp=(temp*10000L)+mm*100+dd;
  440.     (*NumValue)=temp;
  441.  
  442.     return TRUE;
  443. }
  444.  
  445. /******************************************************************************
  446.     DoubleToStr:
  447.     This routine converts a double value to a string.  The second argument
  448.     provides the digits after the decimal point.  
  449.     The function returns the pointer to the third argument after storing
  450.     the result in the third argument.
  451. *******************************************************************************/
  452. LPSTR DoubleToStr(double nbr,int dec,LPSTR out)
  453. {
  454.     long i,len,BeforeDec,AfterDec,multiply;
  455.     char string[20];
  456.     double dAfterDec;
  457.     
  458.     out[0]=0;
  459.  
  460.     //************* apply sign *******
  461.     if (nbr<0) {
  462.        lstrcat(out,"-");
  463.        nbr=-nbr;
  464.     }
  465.  
  466.     BeforeDec = (long) nbr;           // number before the decimal point 
  467.  
  468.     //****** append the digits after the decimal point ****
  469.     if (dec>0) {
  470.        nbr=nbr-(double)BeforeDec;
  471.        multiply=1;                   
  472.        for (i=0;i<dec;i++) multiply=multiply*10;
  473.        dAfterDec=nbr*(double)multiply;
  474.        AfterDec=(long)dAfterDec;
  475.        nbr=dAfterDec-(double)AfterDec;
  476.        if (nbr>=.5) AfterDec++;
  477.        if (AfterDec>=multiply) {    // overflow 
  478.           BeforeDec++;
  479.           AfterDec=0;
  480.        }
  481.        
  482.        //************* make the out *****************
  483.        if (BeforeDec>0) {
  484.           ltoa(BeforeDec,string,10);
  485.           lstrcat(out,string);
  486.        }
  487.        lstrcat(out,".");
  488.        
  489.        ltoa(AfterDec,string,10);
  490.        len=strlen(string);
  491.        for (i=len;i<dec;i++) lstrcat(out,"0");  // first pad with necessary space
  492.        lstrcat(out,string);                     // then append the digits
  493.     }
  494.     else if (BeforeDec>0) {
  495.        ltoa(BeforeDec,string,10);
  496.        lstrcat(out,string);
  497.     }
  498.     
  499.     return out;
  500. }
  501.  
  502. /******************************************************************************
  503.     Copy a specified number of bytes from the source to the destination location.
  504.     Both the source and destination locations are specified by using far pointers.
  505.     
  506.     When source and destination memory overlaps,  use FarMoveOl function for
  507.     a proper trasfer.
  508.  
  509.     Small/Medium Model Note:  This function will not work if compiled 
  510.     as an EXECUTABLE under small/medium model using the Borland compiler.
  511.     This is because Borland 'C' does not have a fmemmove library function.
  512. *******************************************************************************/
  513. void FarMove(void far * src,void far * dest, UINT count)
  514. {
  515.     #if defined(WIN32)
  516.        memmove(dest,src,count);
  517.     #else
  518.        WORD i,SrcOff,DestOff,SrcSeg,DestSeg;
  519.        char huge *SrcPtr,huge *DestPtr;
  520.  
  521.        if (count==0) return;             // nothing to move
  522.  
  523.        SrcSeg=HIWORD((DWORD)(src));     // source segment
  524.        DestSeg=HIWORD((DWORD)(dest));   // destination segment
  525.        SrcOff=LOWORD((DWORD)(src));     // source offset
  526.        DestOff=LOWORD((DWORD)(dest));   // destination offset
  527.  
  528.        // use _fmemmove function if source and destination do not wrap
  529.        if ((SrcOff+count)>SrcOff && (DestOff+count)>DestOff) _fmemmove(dest,src,count);
  530.        else {                            // move one by one if source of destination wrap
  531.            SrcPtr=(char huge *)src;
  532.            DestPtr=(char huge *)dest;
  533.  
  534.            if ( (GetSelectorBase(SrcSeg)+SrcOff)
  535.               > (GetSelectorBase(DestSeg)+DestOff) ){  // source at higher address
  536.               for (i=0;i<count;i++) DestPtr[i]=SrcPtr[i];
  537.            }
  538.            else {  // src at lower address, move in reverse order
  539.               for (i=count-1;i!=0xFFFF;i--) DestPtr[i]=SrcPtr[i];
  540.            }
  541.        }
  542.  
  543.     #endif
  544.        
  545.     return;
  546.  
  547. }
  548.  
  549. /******************************************************************************
  550.     Copy a specified number of bytes from the source to the destination location.
  551.     Both the source and destination locations are specified by using far pointers.
  552. *******************************************************************************/
  553. void FarMoveOl(void far * src,void far * dest, UINT count)
  554. {
  555.     FarMove(src,dest,count);  // current version of FarMove takes care of overlapping
  556.     return;
  557. }
  558.  
  559. /******************************************************************************
  560.     FarStringIndex:
  561.     This function returns the position of the second string within the first
  562.     string.  The position is an index from the beginning of the first string.
  563.     If the string is located, the return value will range from 0 to length of
  564.     first string minus the length of the second string.
  565.     If the second string could not be located,  the return value is equal to
  566.     the length of the first string.
  567. ******************************************************************************/
  568. UINT FarStringIndex(LPSTR string1,LPSTR string2)
  569. {
  570.     UINT i,j,k,len1,len2,SearchLen;
  571.     char FirstChar;
  572.  
  573.     len1=lstrlen(string1);
  574.     len2=lstrlen(string2);
  575.     if (len2>len1) return len1;          // the second string too big to fit within the first string 
  576.  
  577.     FirstChar=string2[0];                // first character of the second string 
  578.  
  579.     i=0;
  580.     do {
  581.         SearchLen=len1-len2-i+1;         // length of the string to search 
  582.         j=FarCharIndex(&string1[i],FirstChar,SearchLen);
  583.         if (j==SearchLen) return len1;   // first character of the second string in the first string not found 
  584.         
  585.         for (k=1;k<len2;k++) if (string1[i+j+k]!=string2[k]) goto CONTINUE_LOOP;
  586.         return i+j;
  587.  
  588.         CONTINUE_LOOP:
  589.         i=i+j+1;                         // repeat after the first character match location 
  590.     } while (i<=(len1-len2));
  591.  
  592.     return len1;                         // the string was not located 
  593. }
  594.  
  595. /******************************************************************************
  596.     FarCharIndex:
  597.     This function returns the position of the specified character within the 
  598.     given string.  The position is an index from the beginning of the string.
  599.     If the character is found, the return value will range from 0 to SearchLen
  600.     minus 1 (index of the character).
  601.     If the character could not be located,  the return value is equal to
  602.     SearchLen.
  603. ******************************************************************************/
  604. UINT FarCharIndex(LPSTR string,char chr, UINT SearchLen)
  605. {
  606.     UINT i;
  607.     
  608.     for (i=0;i<SearchLen;i++) if (string[i]==chr) return i;
  609.     return i;
  610. }
  611.  
  612. /******************************************************************************
  613.     FarMemSet:
  614.     This function every byte of the given far buffer to the specified character.
  615. ******************************************************************************/
  616. void FarMemSet(void far *ptr,char chr, UINT count)
  617. {
  618.     UINT i;
  619.     LPSTR lptr;
  620.  
  621.     lptr=(LPSTR)ptr;
  622.  
  623.     for (i=0;i<count;i++) lptr[i]=chr;
  624. }
  625.  
  626. /******************************************************************************
  627.     OurPrintf:
  628.     This routine formats and display a given set of arguments.  The format
  629.     is given by the first argument.  The argument 2 to n contain the
  630.     arguments for the specified format.  The function uses MessageBox to
  631.     display the formatted string.
  632. ******************************************************************************/
  633. OurPrintf(LPSTR fmt,...)
  634. {
  635.     LPSTR ArgStart;
  636.     char string[256];
  637.  
  638.     ArgStart=(LPSTR) &fmt;  // pointer to first argument 
  639.     ArgStart=&ArgStart[4];  // go past the first argument 
  640.     wvsprintf(string,fmt,ArgStart);
  641.     if (FindWindow("DBWin",NULL)) { // debug window open
  642.         lstrcat(string,"\n");
  643.         OutputDebugString(string);  // send to the debug terminal
  644.     }
  645.     else MessageBox(NULL,string,NULL,MB_OK);
  646.     return TRUE;
  647. }
  648.  
  649.