Annotation of mstools/samples/sdktools/windiff/utils.c, revision 1.1.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.