Annotation of mstools/samples/sdktools/windiff/utils.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.