|
|
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: LINE.C ! 14: * ! 15: * Functions that handle lines of text to be output. ! 16: * ! 17: * Functions: ! 18: * ! 19: * line_new() ! 20: * line_delete() ! 21: * line_reset() ! 22: * line_gettext() ! 23: * line_gettabbedlength() ! 24: * line_getlink() ! 25: * line_getlinenr() ! 26: * line_compare() ! 27: * line_link() ! 28: * line_isblank() ! 29: * ! 30: * Comments: ! 31: * ! 32: * LINE is a data type representing a string of ascii text along with ! 33: * a line number. ! 34: * ! 35: * A LINE can compare itself to another line, and maintain a link if the ! 36: * lines are similar. ! 37: * ! 38: * Comparisons between lines take note of the global option flag ! 39: * ignore_blanks, defined elsewhere. If this is true, we ignore ! 40: * differences in spaces and tabs when comparing lines, and when ! 41: * generating hashcodes. ! 42: * ! 43: * Links and are only generated once. To clear the link call line_reset. ! 44: * ! 45: * Lines can be allocated on a list. If a null list handle is passed, the ! 46: * line will be allocated using gmem_get() from the hHeap defined and ! 47: * initialised elsewhere. ! 48: * ! 49: ****************************************************************************/ ! 50: ! 51: #include <windows.h> ! 52: #include <stdlib.h> ! 53: #include <string.h> ! 54: ! 55: #include "gutils.h" ! 56: #include "windiff.h" /* defines hHeap and ignore_blanks */ ! 57: #include "list.h" ! 58: #include "line.h" ! 59: ! 60: struct fileline { ! 61: ! 62: UINT flags; /* see below */ ! 63: ! 64: LPSTR text; /* null-terminated copy of line text */ ! 65: DWORD hash; /* hashcode for line */ ! 66: LINE link; /* handle for linked line */ ! 67: UINT linenr; /* line number (any arbitrary value) */ ! 68: }; ! 69: ! 70: /* flag values (or-ed) */ ! 71: #define LF_DISCARD 1 /* if true, alloced from gmem heap */ ! 72: #define LF_HASHVALID 2 /* if true, hashcode need not be recalced */ ! 73: ! 74: ! 75: /*************************************************************************** ! 76: * Function: line_new ! 77: * ! 78: * Purpose: ! 79: * ! 80: * Creates a new line and makes a copy of the text. ! 81: * ! 82: * If the list is non-null, allocate on the list. If null, alloc from ! 83: * gmem_get. ! 84: * ! 85: ***************************************************************************/ ! 86: LINE ! 87: line_new(LPSTR text, int linelength, UINT linenr, LIST list) ! 88: { ! 89: LINE line; ! 90: ! 91: /* alloc a line. from the list if there is a list */ ! 92: if (list) { ! 93: line = List_NewLast(list, sizeof(struct fileline)); ! 94: if (line == NULL) { ! 95: return(NULL); ! 96: } ! 97: line->flags = 0; ! 98: } else { ! 99: line = (LINE) gmem_get(hHeap, sizeof(struct fileline)); ! 100: if (line == NULL) { ! 101: return(NULL); ! 102: } ! 103: line->flags = LF_DISCARD; ! 104: } ! 105: ! 106: /* alloc space for the text. remember the null character */ ! 107: line->text = gmem_get(hHeap, linelength + 1); ! 108: strncpy(line->text, text, linelength); ! 109: line->text[linelength] = '\0'; ! 110: ! 111: line->link = NULL; ! 112: line->linenr = linenr; ! 113: ! 114: return(line); ! 115: } ! 116: ! 117: /*************************************************************************** ! 118: * Function: line_delete ! 119: * ! 120: * Purpose: ! 121: * ! 122: * Deletes a line and frees up all associated memory and if the line ! 123: * was not alloc-ed from a list, frees up the line struct itself ! 124: * ! 125: ***************************************************************************/ ! 126: void ! 127: line_delete(LINE line) ! 128: { ! 129: if (line == NULL) { ! 130: return; ! 131: } ! 132: ! 133: /* free up text space */ ! 134: gmem_free(hHeap, line->text, lstrlen(line->text)+1); ! 135: ! 136: /* free up line itself only if not on list */ ! 137: if (line->flags & LF_DISCARD) { ! 138: gmem_free(hHeap, (LPSTR) line, sizeof(struct fileline)); ! 139: } ! 140: } ! 141: ! 142: /*************************************************************************** ! 143: * Function: line_reset ! 144: * ! 145: * Purpose: ! 146: * ! 147: * Clears the link and force recalc of the hash code. ! 148: * ! 149: ***************************************************************************/ ! 150: void ! 151: line_reset(LINE line) ! 152: { ! 153: if (line == NULL) { ! 154: return; ! 155: } ! 156: ! 157: line->link = NULL; ! 158: ! 159: line->flags &= ~LF_HASHVALID; ! 160: } ! 161: ! 162: ! 163: /*************************************************************************** ! 164: * Function: line_gettext ! 165: * ! 166: * Purpose: ! 167: * ! 168: * Returns a pointer to the line text ! 169: * ! 170: ***************************************************************************/ ! 171: LPSTR ! 172: line_gettext(LINE line) ! 173: { ! 174: if (line == NULL) { ! 175: return(NULL); ! 176: } ! 177: ! 178: return (line->text); ! 179: } ! 180: ! 181: /*************************************************************************** ! 182: * Function: line_gettabbedlength ! 183: * ! 184: * Purpose: ! 185: * ! 186: * Returns the length of line in characters, expanding tabs. ! 187: * ! 188: ***************************************************************************/ ! 189: int ! 190: line_gettabbedlength(LINE line, int tabstops) ! 191: { ! 192: int length; ! 193: LPSTR chp; ! 194: ! 195: if (line == NULL) { ! 196: return(0); ! 197: } ! 198: ! 199: for (length = 0, chp = line->text; *chp != '\0'; chp++) { ! 200: if (*chp == '\t') { ! 201: length = (length + tabstops) / tabstops * tabstops; ! 202: } else { ! 203: length++; ! 204: } ! 205: } ! 206: return(length); ! 207: } ! 208: ! 209: ! 210: /*************************************************************************** ! 211: * Function: line_gethashcode ! 212: * ! 213: * Purpose: ! 214: * ! 215: * Returns the hashcode for this line ! 216: * ! 217: ***************************************************************************/ ! 218: DWORD ! 219: line_gethashcode(LINE line) ! 220: { ! 221: if (line == NULL) { ! 222: return(0); ! 223: } ! 224: ! 225: if (! (line->flags & LF_HASHVALID)) { ! 226: ! 227: ! 228: /* hashcode needs to be recalced */ ! 229: line->hash = hash_string(line->text, ignore_blanks); ! 230: line->flags |= LF_HASHVALID; ! 231: } ! 232: return (line->hash); ! 233: } ! 234: ! 235: /*************************************************************************** ! 236: * Function: line_getlink ! 237: * ! 238: * Purpose: ! 239: * ! 240: * Returns the handle for the line that is linked to this line (the ! 241: * result of a successful line_link() operation). This line is ! 242: * identical in text to the linked line (allowing for ignore_blanks). ! 243: * ! 244: ***************************************************************************/ ! 245: LINE ! 246: line_getlink(LINE line) ! 247: { ! 248: if (line == NULL) { ! 249: return(NULL); ! 250: } ! 251: ! 252: return(line->link); ! 253: } ! 254: ! 255: /*************************************************************************** ! 256: * Function: line_getlinenr ! 257: * ! 258: * Purpose: ! 259: * ! 260: * Returns the line number associated with this line ! 261: * ! 262: ***************************************************************************/ ! 263: UINT ! 264: line_getlinenr(LINE line) ! 265: { ! 266: if (line == NULL) { ! 267: return(0); ! 268: } ! 269: ! 270: return(line->linenr); ! 271: } ! 272: ! 273: /*************************************************************************** ! 274: * Function: line_compare ! 275: * ! 276: * Purpose: ! 277: * ! 278: * Compares two lines and returns TRUE if they are the same. ! 279: * ! 280: ***************************************************************************/ ! 281: BOOL ! 282: line_compare(LINE line1, LINE line2) ! 283: { ! 284: LPSTR p1, p2; ! 285: ! 286: /* Assert: At least one of them is not null ??? */ ! 287: ! 288: if ((line1 == NULL) || (line2 == NULL)) { ! 289: /* null line handles do not compare */ ! 290: return(FALSE); ! 291: } ! 292: ! 293: /* check that the hashcodes match */ ! 294: if (line_gethashcode(line1) != line_gethashcode(line2)) { ! 295: return(FALSE); ! 296: } ! 297: ! 298: /* hashcodes match - are the lines really the same ? */ ! 299: /* note that this is coupled to gutils\utils.c in definition of blank */ ! 300: p1 = line_gettext(line1); ! 301: p2 = line_gettext(line2); ! 302: do { ! 303: if (ignore_blanks) { ! 304: while ( (*p1 == ' ') || (*p1 == '\t')) { ! 305: p1++; ! 306: } ! 307: while ( (*p2 == ' ') || (*p2 == '\t')) { ! 308: p2++; ! 309: } ! 310: } ! 311: if (*p1 != *p2) { ! 312: return(FALSE); ! 313: } ! 314: } while ( (*p1++ != '\0') && (*p2++ != '\0')); ! 315: ! 316: return(TRUE); ! 317: } ! 318: ! 319: /*************************************************************************** ! 320: * Function: line_link ! 321: * ! 322: * Purpose: ! 323: * ! 324: * Attempts to link two lines and returns TRUE if succesful. ! 325: * ! 326: * This will fail if either line is NULL, or already linked, or if ! 327: * they differ. ! 328: * ! 329: ***************************************************************************/ ! 330: BOOL ! 331: line_link(LINE line1, LINE line2) ! 332: { ! 333: if ( (line1 == NULL) || (line2 == NULL)) { ! 334: return(FALSE); ! 335: } ! 336: ! 337: if ( (line1->link != NULL) || (line2->link != NULL)) { ! 338: return(FALSE); ! 339: } ! 340: ! 341: if (line_compare(line1, line2)) { ! 342: line1->link = line2; ! 343: line2->link = line1; ! 344: return(TRUE); ! 345: } else { ! 346: return(FALSE); ! 347: } ! 348: } ! 349: ! 350: ! 351: /*************************************************************************** ! 352: * Function: line_isblank ! 353: * ! 354: * Purpose: ! 355: * ! 356: * Returns TRUE iff line is blank. NULL => return FALSE ! 357: * ! 358: ***************************************************************************/ ! 359: BOOL line_isblank(LINE line) ! 360: { ! 361: return line!=NULL && utils_isblank(line->text); ! 362: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.