UTILS.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:14k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /******************************************************************************
  2. *       This is a part of the Microsoft Source Code Samples. 
  3. *       Copyright (C) 1993-1997 Microsoft Corporation.
  4. *       All rights reserved. 
  5. *       This source code is only intended as a supplement to 
  6. *       Microsoft Development Tools and/or WinHelp documentation.
  7. *       See these sources for detailed information regarding the 
  8. *       Microsoft samples programs.
  9. ******************************************************************************/
  10. /****************************** Module Header *******************************
  11. * Module Name: UTILS.C
  12. *
  13. * standard file-reading utilities.
  14. *
  15. * Functions:
  16. *
  17. * readfile_new()
  18. * readfile_next()
  19. * readfile_delete()
  20. * utils_CompPath()
  21. * has_string()
  22. * utils_isblank()
  23. * StringInput()
  24. * dodlg_stringin()
  25. *
  26. * Comments:
  27. *
  28. ****************************************************************************/
  29. #include <windows.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include "gutils.h"
  33. #include "gutilsrc.h"
  34. /*
  35.  * we need an instance handle. this should be the dll instance
  36.  */
  37. extern HANDLE hLibInst;
  38. /*
  39.  * -- forward declaration of procedures -----------------------------------
  40.  */
  41. int FAR PASCAL dodlg_stringin(HWND hDlg, UINT message, UINT wParam, LONG lParam);
  42. /*-- readfile: buffered line input ------------------------------*/
  43. /*
  44.  * set of functions to read a line at a time from a file, using
  45.  * a buffer to read a block at a time from the file
  46.  *
  47.  */
  48. /*
  49.  * a FILEBUFFER handle is a pointer to a struct filebuffer
  50.  */
  51. struct filebuffer {
  52.         int fh;         /* open file handle */
  53.         PSTR start;     /* offset within buffer of next character */
  54.         PSTR last;      /* offset within buffer of last valid char read in */
  55.         char buffer[512];
  56. };
  57. /***************************************************************************
  58.  * Function: readfile_new
  59.  *
  60.  * Purpose:
  61.  *
  62.  * Initialise a filebuffer and return a handle to it
  63.  */
  64. FILEBUFFER APIENTRY
  65. readfile_new(int fh)
  66. {
  67.         FILEBUFFER fbuf;
  68.         fbuf = (FILEBUFFER) LocalLock(LocalAlloc(LHND, sizeof(struct filebuffer)));
  69.         if (fbuf == NULL) {
  70.                 return(NULL);
  71.         }
  72.         fbuf->fh = fh;
  73.         fbuf->start = fbuf->buffer;
  74.         fbuf->last = fbuf->buffer;
  75.         /* return file pointer to beginning of file */
  76.         _llseek(fh, 0, 0);
  77.         return(fbuf);
  78. }
  79. /***************************************************************************
  80.  * Function: readfile_next
  81.  *
  82.  * Purpose:
  83.  *
  84.  * Get the next line from a file. Returns a pointer to the line
  85.  * in the buffer - so copy it before changing it.
  86.  *
  87.  * The line is *not* null-terminated. *plen is set to the length of the
  88.  * line.
  89.  */
  90. LPSTR APIENTRY
  91. readfile_next(FILEBUFFER fbuf, int FAR * plen)
  92. {
  93.         PSTR cstart;
  94.         /* look for an end of line in the buffer we have*/
  95.         for (cstart = fbuf->start; cstart < fbuf->last; cstart++) {
  96.                 if (*cstart == 'n') {
  97.                         *plen = (cstart - fbuf->start) + 1;
  98.                         cstart = fbuf->start;
  99.                         fbuf->start += *plen;
  100.                         return(cstart);
  101.                 }
  102.         }
  103.         /* no cr in this buffer - this buffer contains a partial line.
  104.          * copy the partial up to the beginning of the buffer, and
  105.          * adjust the pointers to reflect this move
  106.          */
  107.         Old_strncpy(fbuf->buffer, fbuf->start, fbuf->last - fbuf->start);
  108.         fbuf->last = &fbuf->buffer[fbuf->last - fbuf->start];
  109.         fbuf->start = fbuf->buffer;
  110.         /* read in to fill the block */
  111.         fbuf->last += _lread(fbuf->fh, fbuf->last,
  112.                         &fbuf->buffer[sizeof(fbuf->buffer)] - fbuf->last);
  113.         /* look for an end of line in the newly filled buffer */
  114.         for (cstart = fbuf->start; cstart < fbuf->last; cstart++) {
  115.                 if (*cstart == 'n') {
  116.                         *plen = (cstart - fbuf->start) + 1;
  117.                         cstart = fbuf->start;
  118.                         fbuf->start += *plen;
  119.                         return(cstart);
  120.                 }
  121.         }
  122.         /* still no end of line. either the buffer is empty -
  123.          * because of end of file - or the line is longer than
  124.          * the buffer. in either case, return all that we have
  125.          */
  126.         *plen = fbuf->last - fbuf->start;
  127.         { // for JAPAN (nChars != nBytes)
  128.             PSTR ptr;
  129.             for(ptr=fbuf->start;ptr<fbuf->last;ptr++) ;
  130.             if(ptr!=fbuf->last && *plen) {
  131.                 --(*plen);
  132.                 --(fbuf->last);
  133.                 _llseek(fbuf->fh,-1,1);
  134.             }
  135.         }
  136.         cstart = fbuf->start;
  137.         fbuf->start += *plen;
  138.         if (*plen == 0) {
  139.                 return(NULL);
  140.         } else {
  141.                 return(cstart);
  142.         }
  143. }
  144. /***************************************************************************
  145.  * Function: readfile_delete
  146.  *
  147.  * Purpose:
  148.  *
  149.  * Delete a FILEBUFFER - close the file handle and free the buffer
  150.  */
  151. void APIENTRY
  152. readfile_delete(FILEBUFFER fbuf)
  153. {
  154.         _lclose(fbuf->fh);
  155.         LocalUnlock(LocalHandle( (PSTR) fbuf));
  156.         LocalFree(LocalHandle( (PSTR) fbuf));
  157. }
  158. /* ----------- things for strings-------------------------------------*/
  159. /*
  160.  * Compare two pathnames, and if not equal, decide which should come first.
  161.  * Both path names should be lower cased by AnsiLowerBuff before calling.
  162.  *
  163.  * Returns 0 if the same, -1 if left is first, and +1 if right is first.
  164.  *
  165.  * The comparison is such that all filenames in a directory come before any
  166.  * file in a subdirectory of that directory.
  167.  *
  168.  * Given directthisfile v. directsubdirthatfile, we take
  169.  * thisfile < thatfile   even though it is second alphabetically.
  170.  * We do this by picking out the shorter path
  171.  * (fewer path elements), and comparing them up till the last element of that
  172.  * path (in the example: compare the 'dir' in both cases.)
  173.  * If they are the same, then the name with more path elements is
  174.  * in a subdirectory, and should come second.
  175.  *
  176.  * We have had trouble with apparently multiple collating sequences and
  177.  * the position of  in the sequence.  To eliminate this trouble
  178.  * a. EVERYTHING is mapped to lower case first (actually this is done
  179.  *    before calling this routine).
  180.  * b. All comparison is done by using lstrcmpi with two special cases.
  181.  *    1. Subdirs come after parents as noted above
  182.  *    2.  must compare low so that fred2x > fredx in the same way
  183.  *       that fred2 < fred.  Unfortunately in ANSI '2' < '\'
  184.  *
  185.  */
  186. int APIENTRY
  187. utils_CompPath(LPSTR left, LPSTR right)
  188. {
  189.         int compval;            // provisional value of comparison
  190.         if (left==NULL) return -1;        // empty is less than anything else
  191.         else if (right==NULL) return 1;  // anything is greater than empty
  192.         for (; ; ) {
  193.                 if (*left=='' && *right=='') return 0;
  194.                 if (*left=='')  return -1;
  195.                 if (*right=='')  return 1;
  196.                 if (IsDBCSLeadByte(*left) || IsDBCSLeadByte(*right)) {
  197.                         if (*right != *left) {
  198.                                 compval = (*left - *right);
  199.                                 break;
  200.                         }
  201.                         ++left;
  202.                         ++right;
  203.                         if (*right != *left) {
  204.                                 compval = (*left - *right);
  205.                                 break;
  206.                         }
  207.                         ++left;
  208.                         ++right;
  209.                 } else {
  210.                 if (*right==*left)  {++left; ++right; continue;}
  211.                 if (*left=='\') {compval = -1; break;}
  212.                 if (*right=='\') {compval = 1; break;}
  213.                 compval = (*left - *right);
  214.                 break;
  215.                 }
  216.         }
  217.         /* We have detected a difference.  If the rest of one
  218.            of the strings (including the current character) contains
  219.            some  characters, but the other one does not, then all
  220.            elements up to the last element of the one with the fewer
  221.            elements are equal and so the other one lies in a subdir
  222.            and so compares greater i.e. xyf > xf
  223.            Otherwise compval tells the truth.
  224.         */
  225.         left = strchr(left, '\');
  226.         right = strchr(right, '\');
  227.         if (left && !right) return 1;
  228.         if (right && !left) return -1;
  229.         return compval;
  230. } /* utils_CompPath */
  231. /***************************************************************************
  232.  * Function: hash_string
  233.  *
  234.  * Purpose:
  235.  *
  236.  * Generate a hashcode for a null-terminated ascii string.
  237.  *
  238.  * If bIgnoreBlanks is set, then ignore all spaces and tabs in calculating
  239.  * the hashcode.
  240.  *
  241.  * Multiply each character by a function of its position and sum these.
  242.  * The function chosen is to multiply the position by successive
  243.  * powers of a large number.
  244.  * The large multiple ensures that anagrams generate different hash
  245.  * codes.
  246.  */
  247. DWORD APIENTRY
  248. hash_string(LPSTR string, BOOL bIgnoreBlanks)
  249. {
  250. #define LARGENUMBER     6293815
  251.         DWORD sum = 0;
  252.         DWORD multiple = LARGENUMBER;
  253.         int index = 1;
  254.         while (*string != '') {
  255.                 if (bIgnoreBlanks) {
  256.                         while ( (*string == ' ') || (*string == 't')) {
  257.                                 string = CharNext(string);
  258.                         }
  259.                 }
  260.                 sum += multiple * index++ * (*string++);
  261.                 multiple *= LARGENUMBER;
  262.         }
  263.         return(sum);
  264. }
  265. /***************************************************************************
  266.  * Function: utils_isblank
  267.  *
  268.  * Purpose:
  269.  *
  270.  * Return TRUE iff the string is blank.  Blank means the same as
  271.  * the characters which are ignored in hash_string when ignore_blanks is set
  272.  */
  273. BOOL APIENTRY
  274. utils_isblank(LPSTR string)
  275. {
  276.         while ( (*string == ' ') || (*string == 't')) {
  277.                 string = CharNext(string);
  278.         }
  279.         /* having skipped all the blanks, do we see the end delimiter? */
  280.         return (*string == '' || *string == 'r' || *string == 'n');
  281. }
  282. /* --- simple string input -------------------------------------- */
  283. /*
  284.  * static variables for communication between function and dialog
  285.  */
  286. LPSTR dlg_result;
  287. int dlg_size;
  288. LPSTR dlg_prompt, dlg_default, dlg_caption;
  289. /***************************************************************************
  290.  * Function: StringInput
  291.  *
  292.  * Purpose:
  293.  *
  294.  * Input of a single text string, using a simple dialog.
  295.  *
  296.  * Returns TRUE if ok, or FALSE if error or user canceled. If TRUE,
  297.  * puts the string entered into result (up to resultsize characters).
  298.  *
  299.  * Prompt is used as the prompt string, caption as the dialog caption and
  300.  * default as the default input. All of these can be null.
  301.  */
  302. int APIENTRY
  303. StringInput(LPSTR result, int resultsize, LPSTR prompt, LPSTR caption,
  304.                 LPSTR def_input)
  305. {
  306.         DLGPROC lpProc;
  307.         BOOL fOK;
  308.         /* copy args to static variable so that winproc can see them */
  309.         dlg_result = result;
  310.         dlg_size = resultsize;
  311.         dlg_prompt = prompt;
  312.         dlg_caption = caption;
  313.         dlg_default = def_input;
  314.         lpProc = (DLGPROC)MakeProcInstance((WNDPROC)dodlg_stringin, hLibInst);
  315.         fOK = DialogBox(hLibInst, "StringInput", GetFocus(), lpProc);
  316.         FreeProcInstance((WNDPROC)lpProc);
  317.         return(fOK);
  318. }
  319. /***************************************************************************
  320.  * Function: dodlg_stringin
  321.  *
  322.  */
  323. int FAR PASCAL
  324. dodlg_stringin(HWND hDlg, UINT message, UINT wParam, LONG lParam)
  325. {
  326.         switch(message) {
  327.         case WM_INITDIALOG:
  328.                 if (dlg_caption != NULL) {
  329.                         SendMessage(hDlg, WM_SETTEXT, 0, (LONG) dlg_caption);
  330.                 }
  331.                 if (dlg_prompt != NULL) {
  332.                         SetDlgItemText(hDlg, IDD_LABEL, dlg_prompt);
  333.                 }
  334.                 if (dlg_default) {
  335.                         SetDlgItemText(hDlg, IDD_FILE, dlg_default);
  336.                 }
  337.                 return(TRUE);
  338.         case WM_COMMAND:
  339.                 switch(GET_WM_COMMAND_ID(wParam, lParam)) {
  340.                 case IDCANCEL:
  341.                         EndDialog(hDlg, FALSE);
  342.                         return(TRUE);
  343.                 case IDOK:
  344.                         GetDlgItemText(hDlg, IDD_FILE, dlg_result, dlg_size);
  345.                         EndDialog(hDlg, TRUE);
  346.                         return(TRUE);
  347.                 }
  348.         }
  349.         return (FALSE);
  350. }
  351. /***************************************************************************
  352.  * Function: My_mbschr
  353.  *
  354.  * Purpose:
  355.  *
  356.  * DBCS version of strchr
  357.  *
  358.  */
  359. unsigned char * _CRTAPI1 My_mbschr(
  360.     unsigned char *psz, unsigned short uiSep)
  361. {
  362.     while (*psz != '' && *psz != uiSep) {
  363.         psz = CharNext(psz);
  364.     }
  365.     return *psz == uiSep ? psz : NULL;
  366. }
  367. /***************************************************************************
  368.  * Function: My_mbsncpy
  369.  *
  370.  * Purpose:
  371.  *
  372.  * DBCS version of strncpy
  373.  *
  374.  */
  375. unsigned char * _CRTAPI1 My_mbsncpy(
  376. unsigned char *psz1, const unsigned char *psz2, size_t Length)
  377. {
  378.         int nLen = (int)Length;
  379. unsigned char *pszSv = psz1;
  380. while (0 < nLen) {
  381. if (*psz2 == '') {
  382. *psz1++ = '';
  383. nLen--;
  384. } else if (IsDBCSLeadByte(*psz2)) {
  385. if (nLen == 1) {
  386. *psz1 = '';
  387. } else {
  388. *psz1++ = *psz2++;
  389. *psz1++ = *psz2++;
  390. }
  391. nLen -= 2;
  392. } else {
  393. *psz1++ = *psz2++;
  394. nLen--;
  395. }
  396. }
  397. return pszSv;
  398. }
  399. /***************************************************************************
  400.  * Function: LoadRcString
  401.  *
  402.  * Purpose: Loads a resource string from string table and returns a pointer
  403.  *          to the string.
  404.  *
  405.  * Parameters: wID - resource string id
  406.  *
  407.  */
  408. LPTSTR APIENTRY LoadRcString(UINT wID)
  409. {
  410.     static TCHAR szBuf[512];
  411.     LoadString((HANDLE)GetModuleHandle(NULL),wID,szBuf,sizeof(szBuf));
  412.     return szBuf;
  413. }
  414. LPTSTR APIENTRY LoadRcString2(UINT wID)
  415. {
  416.     static TCHAR szBuf[512];
  417.     LoadString((HANDLE)GetModuleHandle(NULL),wID,szBuf,sizeof(szBuf));
  418.     return szBuf;
  419. }