|
|
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.