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

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