bixbite 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. data/LICENSE +20 -0
  2. data/README.markdown +49 -0
  3. data/VERSION +1 -0
  4. data/bin/bixbite +73 -0
  5. data/lib/bixbite.rb +13 -0
  6. data/lib/bixbite/command.rb +14 -0
  7. data/lib/bixbite/create.rb +76 -0
  8. data/template/Rakefile +25 -0
  9. data/template/assets/bixbite/Rakefile.rb +297 -0
  10. data/template/assets/naturaldocs/NaturalDocs/Config/Languages.txt +286 -0
  11. data/template/assets/naturaldocs/NaturalDocs/Config/Topics.txt +382 -0
  12. data/template/assets/naturaldocs/NaturalDocs/Help/customizinglanguages.html +52 -0
  13. data/template/assets/naturaldocs/NaturalDocs/Help/customizingtopics.html +74 -0
  14. data/template/assets/naturaldocs/NaturalDocs/Help/documenting.html +58 -0
  15. data/template/assets/naturaldocs/NaturalDocs/Help/documenting/reference.html +146 -0
  16. data/template/assets/naturaldocs/NaturalDocs/Help/documenting/walkthrough.html +180 -0
  17. data/template/assets/naturaldocs/NaturalDocs/Help/example/Default.css +528 -0
  18. data/template/assets/naturaldocs/NaturalDocs/Help/example/NaturalDocs.js +204 -0
  19. data/template/assets/naturaldocs/NaturalDocs/Help/examples.css +90 -0
  20. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/background.png +0 -0
  21. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/leftside.png +0 -0
  22. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/logo.png +0 -0
  23. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overbody.png +0 -0
  24. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overbodybg.png +0 -0
  25. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overleftmargin.png +0 -0
  26. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overmenu.png +0 -0
  27. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overmenubg.png +0 -0
  28. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/rightside.png +0 -0
  29. data/template/assets/naturaldocs/NaturalDocs/Help/images/logo.gif +0 -0
  30. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/about.png +0 -0
  31. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/background.png +0 -0
  32. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/bottomleft.png +0 -0
  33. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/bottomright.png +0 -0
  34. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/community.png +0 -0
  35. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/customizing.png +0 -0
  36. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/using.png +0 -0
  37. data/template/assets/naturaldocs/NaturalDocs/Help/index.html +9 -0
  38. data/template/assets/naturaldocs/NaturalDocs/Help/javascript/BrowserStyles.js +77 -0
  39. data/template/assets/naturaldocs/NaturalDocs/Help/javascript/PNGHandling.js +72 -0
  40. data/template/assets/naturaldocs/NaturalDocs/Help/keywords.html +38 -0
  41. data/template/assets/naturaldocs/NaturalDocs/Help/languages.html +32 -0
  42. data/template/assets/naturaldocs/NaturalDocs/Help/menu.html +79 -0
  43. data/template/assets/naturaldocs/NaturalDocs/Help/output.html +84 -0
  44. data/template/assets/naturaldocs/NaturalDocs/Help/running.html +40 -0
  45. data/template/assets/naturaldocs/NaturalDocs/Help/styles.css +290 -0
  46. data/template/assets/naturaldocs/NaturalDocs/Help/styles.html +52 -0
  47. data/template/assets/naturaldocs/NaturalDocs/Help/troubleshooting.html +18 -0
  48. data/template/assets/naturaldocs/NaturalDocs/Info/CSSGuide.txt +947 -0
  49. data/template/assets/naturaldocs/NaturalDocs/Info/File Parsing.txt +83 -0
  50. data/template/assets/naturaldocs/NaturalDocs/Info/HTMLTestCases.pm +269 -0
  51. data/template/assets/naturaldocs/NaturalDocs/Info/Languages.txt +107 -0
  52. data/template/assets/naturaldocs/NaturalDocs/Info/NDMarkup.txt +91 -0
  53. data/template/assets/naturaldocs/NaturalDocs/Info/Symbol Management.txt +59 -0
  54. data/template/assets/naturaldocs/NaturalDocs/Info/images/Logo.png +0 -0
  55. data/template/assets/naturaldocs/NaturalDocs/JavaScript/NaturalDocs.js +836 -0
  56. data/template/assets/naturaldocs/NaturalDocs/License-GPL.txt +341 -0
  57. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/BinaryFile.pm +294 -0
  58. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder.pm +280 -0
  59. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/Base.pm +348 -0
  60. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/FramedHTML.pm +345 -0
  61. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/HTML.pm +398 -0
  62. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/HTMLBase.pm +3693 -0
  63. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ClassHierarchy.pm +860 -0
  64. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ClassHierarchy/Class.pm +412 -0
  65. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ClassHierarchy/File.pm +157 -0
  66. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ConfigFile.pm +497 -0
  67. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Constants.pm +165 -0
  68. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/DefineMembers.pm +100 -0
  69. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Error.pm +305 -0
  70. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/File.pm +540 -0
  71. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ImageReferenceTable.pm +383 -0
  72. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ImageReferenceTable/Reference.pm +44 -0
  73. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ImageReferenceTable/String.pm +110 -0
  74. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages.pm +1475 -0
  75. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/ActionScript.pm +1473 -0
  76. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Ada.pm +38 -0
  77. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Advanced.pm +828 -0
  78. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Advanced/Scope.pm +95 -0
  79. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Advanced/ScopeChange.pm +70 -0
  80. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Base.pm +832 -0
  81. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/CSharp.pm +1484 -0
  82. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/PLSQL.pm +319 -0
  83. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Pascal.pm +143 -0
  84. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Perl.pm +1370 -0
  85. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Prototype.pm +92 -0
  86. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Prototype/Parameter.pm +87 -0
  87. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Simple.pm +503 -0
  88. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Tcl.pm +219 -0
  89. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Menu.pm +3406 -0
  90. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Menu/Entry.pm +201 -0
  91. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/NDMarkup.pm +76 -0
  92. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser.pm +1331 -0
  93. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser/JavaDoc.pm +464 -0
  94. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser/Native.pm +1060 -0
  95. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser/ParsedTopic.pm +253 -0
  96. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Project.pm +1402 -0
  97. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Project/ImageFile.pm +160 -0
  98. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Project/SourceFile.pm +113 -0
  99. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ReferenceString.pm +334 -0
  100. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Settings.pm +1418 -0
  101. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Settings/BuildTarget.pm +66 -0
  102. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB.pm +678 -0
  103. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/Extension.pm +84 -0
  104. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/File.pm +129 -0
  105. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/Item.pm +201 -0
  106. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/ItemDefinition.pm +45 -0
  107. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/WatchedFileDefinitions.pm +159 -0
  108. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/StatusMessage.pm +102 -0
  109. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolString.pm +212 -0
  110. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable.pm +1984 -0
  111. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/File.pm +186 -0
  112. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/IndexElement.pm +522 -0
  113. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/Reference.pm +273 -0
  114. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/ReferenceTarget.pm +97 -0
  115. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/Symbol.pm +428 -0
  116. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/SymbolDefinition.pm +96 -0
  117. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Topics.pm +1319 -0
  118. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Topics/Type.pm +151 -0
  119. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Version.pm +384 -0
  120. data/template/assets/naturaldocs/NaturalDocs/NaturalDocs +400 -0
  121. data/template/assets/naturaldocs/NaturalDocs/NaturalDocs.bat +17 -0
  122. data/template/assets/naturaldocs/NaturalDocs/Styles/Default.css +767 -0
  123. data/template/assets/naturaldocs/NaturalDocs/Styles/Roman.css +765 -0
  124. data/template/assets/naturaldocs/NaturalDocs/Styles/Small.css +763 -0
  125. data/template/assets/utilities/pngout +0 -0
  126. data/template/deploy/public_html/.htaccess +0 -0
  127. data/template/documentation/js/.htaccess +0 -0
  128. data/template/src/html/.htaccess +76 -0
  129. data/template/src/html/css/cmn/global.css +96 -0
  130. data/template/src/html/css/cmn/ie.css +15 -0
  131. data/template/src/html/css/cmn/ie6.css +15 -0
  132. data/template/src/html/images/cmn/.htaccess +0 -0
  133. data/template/src/html/images/tmp/.htaccess +0 -0
  134. data/template/src/html/includes/debug.inc +5 -0
  135. data/template/src/html/includes/footer.inc +52 -0
  136. data/template/src/html/includes/header.inc +61 -0
  137. data/template/src/html/includes/html.inc +3 -0
  138. data/template/src/html/includes/namespace.inc +19 -0
  139. data/template/src/html/includes/page.inc +151 -0
  140. data/template/src/html/index.html +35 -0
  141. data/template/src/html/js/cmn/bootstrap.js +74 -0
  142. data/template/src/html/js/cmn/global.js +142 -0
  143. data/template/src/html/js/cmn/lib/LAB.js +348 -0
  144. data/template/src/html/min/.htaccess +4 -0
  145. data/template/src/html/min/MinifyCLI.php +19 -0
  146. data/template/src/html/min/README.txt +132 -0
  147. data/template/src/html/min/builder/_index.js +242 -0
  148. data/template/src/html/min/builder/bm.js +36 -0
  149. data/template/src/html/min/builder/index.php +182 -0
  150. data/template/src/html/min/builder/ocCheck.php +36 -0
  151. data/template/src/html/min/builder/rewriteTest.js +1 -0
  152. data/template/src/html/min/config.php +187 -0
  153. data/template/src/html/min/groupsConfig.php +34 -0
  154. data/template/src/html/min/index.php +66 -0
  155. data/template/src/html/min/lib/FirePHP.php +1370 -0
  156. data/template/src/html/min/lib/HTTP/ConditionalGet.php +348 -0
  157. data/template/src/html/min/lib/HTTP/Encoder.php +326 -0
  158. data/template/src/html/min/lib/JSMin.php +314 -0
  159. data/template/src/html/min/lib/JSMinPlus.php +1872 -0
  160. data/template/src/html/min/lib/Minify.php +532 -0
  161. data/template/src/html/min/lib/Minify/Build.php +103 -0
  162. data/template/src/html/min/lib/Minify/CSS.php +83 -0
  163. data/template/src/html/min/lib/Minify/CSS/Compressor.php +250 -0
  164. data/template/src/html/min/lib/Minify/CSS/UriRewriter.php +270 -0
  165. data/template/src/html/min/lib/Minify/Cache/APC.php +130 -0
  166. data/template/src/html/min/lib/Minify/Cache/File.php +125 -0
  167. data/template/src/html/min/lib/Minify/Cache/Memcache.php +137 -0
  168. data/template/src/html/min/lib/Minify/ClosureCompiler.php +85 -0
  169. data/template/src/html/min/lib/Minify/CommentPreserver.php +90 -0
  170. data/template/src/html/min/lib/Minify/Controller/Base.php +202 -0
  171. data/template/src/html/min/lib/Minify/Controller/Files.php +78 -0
  172. data/template/src/html/min/lib/Minify/Controller/Groups.php +94 -0
  173. data/template/src/html/min/lib/Minify/Controller/MinApp.php +132 -0
  174. data/template/src/html/min/lib/Minify/Controller/Page.php +82 -0
  175. data/template/src/html/min/lib/Minify/Controller/Version1.php +118 -0
  176. data/template/src/html/min/lib/Minify/HTML.php +245 -0
  177. data/template/src/html/min/lib/Minify/ImportProcessor.php +157 -0
  178. data/template/src/html/min/lib/Minify/Lines.php +131 -0
  179. data/template/src/html/min/lib/Minify/Logger.php +45 -0
  180. data/template/src/html/min/lib/Minify/Packer.php +37 -0
  181. data/template/src/html/min/lib/Minify/Source.php +187 -0
  182. data/template/src/html/min/lib/Minify/YUICompressor.php +139 -0
  183. data/template/src/html/min/lib/Solar/Dir.php +199 -0
  184. data/template/src/html/min/lib/closure-compiler.jar +0 -0
  185. data/template/src/html/min/lib/yuicompressor-2.4.2.jar +0 -0
  186. data/template/src/html/min/utils.php +90 -0
  187. data/template/src/templates/css/template.css +7 -0
  188. data/template/src/templates/js/template.js +72 -0
  189. data/template/src/templates/template.html +18 -0
  190. data/template/src/yaml/config.yml +46 -0
  191. data/template/src/yaml/deploy.yml +35 -0
  192. data/test/bixbite_test.rb +7 -0
  193. data/test/test_helper.rb +10 -0
  194. metadata +278 -0
@@ -0,0 +1,253 @@
1
+ ###############################################################################
2
+ #
3
+ # Package: NaturalDocs::Parser::ParsedTopic
4
+ #
5
+ ###############################################################################
6
+ #
7
+ # A class for parsed topics of source files. Also encompasses some of the <TopicType>-specific behavior.
8
+ #
9
+ ###############################################################################
10
+
11
+ # This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
12
+ # Natural Docs is licensed under the GPL
13
+
14
+ use strict;
15
+ use integer;
16
+
17
+ package NaturalDocs::Parser::ParsedTopic;
18
+
19
+
20
+ ###############################################################################
21
+ # Group: Implementation
22
+
23
+ #
24
+ # Constants: Members
25
+ #
26
+ # The object is a blessed arrayref with the following indexes.
27
+ #
28
+ # TYPE - The <TopicType>.
29
+ # TITLE - The title of the topic.
30
+ # PACKAGE - The package <SymbolString> the topic appears in, or undef if none.
31
+ # USING - An arrayref of additional package <SymbolStrings> available to the topic via "using" statements, or undef if
32
+ # none.
33
+ # PROTOTYPE - The prototype, if it exists and is applicable.
34
+ # SUMMARY - The summary, if it exists.
35
+ # BODY - The body of the topic, formatted in <NDMarkup>. Some topics may not have bodies, and if not, this
36
+ # will be undef.
37
+ # LINE_NUMBER - The line number the topic appears at in the file.
38
+ # IS_LIST - Whether the topic is a list.
39
+ #
40
+ use NaturalDocs::DefineMembers 'TYPE', 'TITLE', 'PACKAGE', 'USING', 'PROTOTYPE', 'SUMMARY', 'BODY',
41
+ 'LINE_NUMBER', 'IS_LIST';
42
+ # DEPENDENCY: New() depends on the order of these constants, and that this class is not inheriting any members.
43
+
44
+
45
+ #
46
+ # Architecture: Title, Package, and Symbol Behavior
47
+ #
48
+ # Title, package, and symbol behavior is a little awkward so it deserves some explanation. Basically you set them according to
49
+ # certain rules, but you get computed values that try to hide all the different scoping situations.
50
+ #
51
+ # Normal Topics:
52
+ #
53
+ # Set them to the title and package as they appear. "Function" and "PkgA.PkgB" will return "Function" for the title,
54
+ # "PkgA.PkgB" for the package, and "PkgA.PkgB.Function" for the symbol.
55
+ #
56
+ # In the rare case that a title has a separator symbol it's treated as inadvertant, so "A vs. B" in "PkgA.PkgB" still returns just
57
+ # "PkgA.PkgB" for the package even though if you got it from the symbol it can be seen as "PkgA.PkgB.A vs".
58
+ #
59
+ # Scope Topics:
60
+ #
61
+ # Set the title normally and leave the package undef. So "PkgA.PkgB" and undef will return "PkgA.PkgB" for the title as well
62
+ # as for the package and symbol.
63
+ #
64
+ # The only time you should set the package is when you have full language support and they only documented the class with
65
+ # a partial title. So if you documented "PkgA.PkgB" with just "PkgB", you want to set the package to "PkgA". This
66
+ # will return "PkgB" as the title for presentation and will return "PkgA.PkgB" for the package and symbol, which is correct.
67
+ #
68
+ # Always Global Topics:
69
+ #
70
+ # Set the title and package normally, do not set the package to undef. So "Global" and "PkgA.PkgB" will return "Global" as
71
+ # the title, "PkgA.PkgB" as the package, and "Global" as the symbol.
72
+ #
73
+ # Um, yeah...:
74
+ #
75
+ # So does this suck? Yes, yes it does. But the suckiness is centralized here instead of having to be handled everywhere these
76
+ # issues come into play. Just realize there are a certain set of rules to follow when you *set* these variables, and the results
77
+ # you see when you *get* them are computed rather than literal.
78
+ #
79
+
80
+
81
+ ###############################################################################
82
+ # Group: Functions
83
+
84
+ #
85
+ # Function: New
86
+ #
87
+ # Creates a new object.
88
+ #
89
+ # Parameters:
90
+ #
91
+ # type - The <TopicType>.
92
+ # title - The title of the topic.
93
+ # package - The package <SymbolString> the topic appears in, or undef if none.
94
+ # using - An arrayref of additional package <SymbolStrings> available to the topic via "using" statements, or undef if
95
+ # none.
96
+ # prototype - The prototype, if it exists and is applicable. Otherwise set to undef.
97
+ # summary - The summary of the topic, if any.
98
+ # body - The body of the topic, formatted in <NDMarkup>. May be undef, as some topics may not have bodies.
99
+ # lineNumber - The line number the topic appears at in the file.
100
+ # isList - Whether the topic is a list topic or not.
101
+ #
102
+ # Returns:
103
+ #
104
+ # The new object.
105
+ #
106
+ sub New #(type, title, package, using, prototype, summary, body, lineNumber, isList)
107
+ {
108
+ # DEPENDENCY: This depends on the order of the parameter list being the same as the constants, and that there are no
109
+ # members inherited from a base class.
110
+
111
+ my $package = shift;
112
+
113
+ my $object = [ @_ ];
114
+ bless $object, $package;
115
+
116
+ if (defined $object->[USING])
117
+ { $object->[USING] = [ @{$object->[USING]} ]; };
118
+
119
+ return $object;
120
+ };
121
+
122
+
123
+ # Function: Type
124
+ # Returns the <TopicType>.
125
+ sub Type
126
+ { return $_[0]->[TYPE]; };
127
+
128
+ # Function: SetType
129
+ # Replaces the <TopicType>.
130
+ sub SetType #(type)
131
+ { $_[0]->[TYPE] = $_[1]; };
132
+
133
+ # Function: IsList
134
+ # Returns whether the topic is a list.
135
+ sub IsList
136
+ { return $_[0]->[IS_LIST]; };
137
+
138
+ # Function: SetIsList
139
+ # Sets whether the topic is a list.
140
+ sub SetIsList
141
+ { $_[0]->[IS_LIST] = $_[1]; };
142
+
143
+ # Function: Title
144
+ # Returns the title of the topic.
145
+ sub Title
146
+ { return $_[0]->[TITLE]; };
147
+
148
+ # Function: SetTitle
149
+ # Replaces the topic title.
150
+ sub SetTitle #(title)
151
+ { $_[0]->[TITLE] = $_[1]; };
152
+
153
+ #
154
+ # Function: Symbol
155
+ #
156
+ # Returns the <SymbolString> defined by the topic. It is fully resolved and does _not_ need to be joined with <Package()>.
157
+ #
158
+ # Type-Specific Behavior:
159
+ #
160
+ # - If the <TopicType> is always global, the symbol will be generated from the title only.
161
+ # - Everything else's symbols will be generated from the title and the package passed to <New()>.
162
+ #
163
+ sub Symbol
164
+ {
165
+ my ($self) = @_;
166
+
167
+ my $titleSymbol = NaturalDocs::SymbolString->FromText($self->[TITLE]);
168
+
169
+ if (NaturalDocs::Topics->TypeInfo($self->Type())->Scope() == ::SCOPE_ALWAYS_GLOBAL())
170
+ { return $titleSymbol; }
171
+ else
172
+ {
173
+ return NaturalDocs::SymbolString->Join( $self->[PACKAGE], $titleSymbol );
174
+ };
175
+ };
176
+
177
+
178
+ #
179
+ # Function: Package
180
+ #
181
+ # Returns the package <SymbolString> that the topic appears in.
182
+ #
183
+ # Type-Specific Behavior:
184
+ #
185
+ # - If the <TopicType> has scope, the package will be generated from both the title and the package passed to <New()>, not
186
+ # just the package.
187
+ # - If the <TopicType> is always global, the package will be the one passed to <New()>, even though it isn't part of it's
188
+ # <Symbol()>.
189
+ # - Everything else's package will be what was passed to <New()>, even if the title has separator symbols in it.
190
+ #
191
+ sub Package
192
+ {
193
+ my ($self) = @_;
194
+
195
+ # Headerless topics may not have a type yet.
196
+ if ($self->Type() && NaturalDocs::Topics->TypeInfo($self->Type())->Scope() == ::SCOPE_START())
197
+ { return $self->Symbol(); }
198
+ else
199
+ { return $self->[PACKAGE]; };
200
+ };
201
+
202
+
203
+ # Function: SetPackage
204
+ # Replaces the package the topic appears in. This will behave the same way as the package parameter in <New()>. Later calls
205
+ # to <Package()> will still be generated according to its type-specific behavior.
206
+ sub SetPackage #(package)
207
+ { $_[0]->[PACKAGE] = $_[1]; };
208
+
209
+ # Function: Using
210
+ # Returns an arrayref of additional scope <SymbolStrings> available to the topic via "using" statements, or undef if none.
211
+ sub Using
212
+ { return $_[0]->[USING]; };
213
+
214
+ # Function: SetUsing
215
+ # Replaces the using arrayref of sope <SymbolStrings>.
216
+ sub SetUsing #(using)
217
+ { $_[0]->[USING] = $_[1]; };
218
+
219
+ # Function: Prototype
220
+ # Returns the prototype if one is defined. Will be undef otherwise.
221
+ sub Prototype
222
+ { return $_[0]->[PROTOTYPE]; };
223
+
224
+ # Function: SetPrototype
225
+ # Replaces the function or variable prototype.
226
+ sub SetPrototype #(prototype)
227
+ { $_[0]->[PROTOTYPE] = $_[1]; };
228
+
229
+ # Function: Summary
230
+ # Returns the topic summary, if it exists, formatted in <NDMarkup>.
231
+ sub Summary
232
+ { return $_[0]->[SUMMARY]; };
233
+
234
+ # Function: Body
235
+ # Returns the topic's body, formatted in <NDMarkup>. May be undef.
236
+ sub Body
237
+ { return $_[0]->[BODY]; };
238
+
239
+ # Function: SetBody
240
+ # Replaces the topic's body, formatted in <NDMarkup>. May be undef.
241
+ sub SetBody #(body)
242
+ {
243
+ my ($self, $body) = @_;
244
+ $self->[BODY] = $body;
245
+ };
246
+
247
+ # Function: LineNumber
248
+ # Returns the line the topic appears at in the file.
249
+ sub LineNumber
250
+ { return $_[0]->[LINE_NUMBER]; };
251
+
252
+
253
+ 1;
@@ -0,0 +1,1402 @@
1
+ ###############################################################################
2
+ #
3
+ # Package: NaturalDocs::Project
4
+ #
5
+ ###############################################################################
6
+ #
7
+ # A package that manages information about the files in the source tree, as well as the list of files that have to be parsed
8
+ # and built.
9
+ #
10
+ # Usage and Dependencies:
11
+ #
12
+ # - All the <Config and Data File Functions> are available immediately, except for the status functions.
13
+ #
14
+ # - <ReparseEverything()> and <RebuildEverything()> are available immediately, because they may need to be called
15
+ # after <LoadConfigFileInfo()> but before <LoadSourceFileInfo()>.
16
+ #
17
+ # - Prior to <LoadConfigFileInfo()>, <NaturalDocs::Settings> must be initialized.
18
+ #
19
+ # - After <LoadConfigFileInfo()>, the status <Config and Data File Functions> are available as well.
20
+ #
21
+ # - Prior to <LoadSourceFileInfo()>, <NaturalDocs::Settings> and <NaturalDocs::Languages> must be initialized.
22
+ #
23
+ # - After <LoadSourceFileInfo()>, the rest of the <Source File Functions> are available.
24
+ #
25
+ ###############################################################################
26
+
27
+ # This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
28
+ # Natural Docs is licensed under the GPL
29
+
30
+ use NaturalDocs::Project::SourceFile;
31
+ use NaturalDocs::Project::ImageFile;
32
+
33
+ use strict;
34
+ use integer;
35
+
36
+ package NaturalDocs::Project;
37
+
38
+
39
+ ###############################################################################
40
+ # Group: File Handles
41
+
42
+ #
43
+ # handle: FH_FILEINFO
44
+ #
45
+ # The file handle for the file information file, <FileInfo.nd>.
46
+ #
47
+
48
+ #
49
+ # handle: FH_CONFIGFILEINFO
50
+ #
51
+ # The file handle for the config file information file, <ConfigFileInfo.nd>.
52
+ #
53
+
54
+ #
55
+ # handle: FH_IMAGEFILE
56
+ #
57
+ # The file handle for determining the dimensions of image files.
58
+ #
59
+
60
+
61
+
62
+ ###############################################################################
63
+ # Group: Source File Variables
64
+
65
+
66
+ #
67
+ # hash: supportedFiles
68
+ #
69
+ # A hash of all the supported files in the input directory. The keys are the <FileNames>, and the values are
70
+ # <NaturalDocs::Project::SourceFile> objects.
71
+ #
72
+ my %supportedFiles;
73
+
74
+ #
75
+ # hash: filesToParse
76
+ #
77
+ # An existence hash of all the <FileNames> that need to be parsed.
78
+ #
79
+ my %filesToParse;
80
+
81
+ #
82
+ # hash: filesToBuild
83
+ #
84
+ # An existence hash of all the <FileNames> that need to be built.
85
+ #
86
+ my %filesToBuild;
87
+
88
+ #
89
+ # hash: filesToPurge
90
+ #
91
+ # An existence hash of the <FileNames> that had Natural Docs content last time, but now either don't exist or no longer have
92
+ # content.
93
+ #
94
+ my %filesToPurge;
95
+
96
+ #
97
+ # hash: unbuiltFilesWithContent
98
+ #
99
+ # An existence hash of all the <FileNames> that have Natural Docs content but are not part of <filesToBuild>.
100
+ #
101
+ my %unbuiltFilesWithContent;
102
+
103
+
104
+ # bool: reparseEverything
105
+ # Whether all the source files need to be reparsed.
106
+ my $reparseEverything;
107
+
108
+ # bool: rebuildEverything
109
+ # Whether all the source files need to be rebuilt.
110
+ my $rebuildEverything;
111
+
112
+ # hash: mostUsedLanguage
113
+ # The name of the most used language. Doesn't include text files.
114
+ my $mostUsedLanguage;
115
+
116
+
117
+
118
+ ###############################################################################
119
+ # Group: Configuration File Variables
120
+
121
+
122
+ #
123
+ # hash: mainConfigFile
124
+ #
125
+ # A hash mapping all the main configuration file names without paths to their <FileStatus>. Prior to <LoadConfigFileInfo()>,
126
+ # it serves as an existence hashref of the file names.
127
+ #
128
+ my %mainConfigFiles = ( 'Topics.txt' => 1, 'Languages.txt' => 1 );
129
+
130
+ #
131
+ # hash: userConfigFiles
132
+ #
133
+ # A hash mapping all the user configuration file names without paths to their <FileStatus>. Prior to <LoadConfigFileInfo()>,
134
+ # it serves as an existence hashref of the file names.
135
+ #
136
+ my %userConfigFiles = ( 'Topics.txt' => 1, 'Languages.txt' => 1, 'Menu.txt' => 1 );
137
+
138
+
139
+
140
+
141
+ ###############################################################################
142
+ # Group: Image File Variables
143
+
144
+
145
+ #
146
+ # hash: imageFileExtensions
147
+ #
148
+ # An existence hash of all the file extensions for images. Extensions are in all lowercase.
149
+ #
150
+ my %imageFileExtensions = ( 'jpg' => 1, 'jpeg' => 1, 'gif' => 1, 'png' => 1, 'bmp' => 1 );
151
+
152
+
153
+ #
154
+ # hash: imageFiles
155
+ #
156
+ # A hash of all the image files in the project. The keys are the <FileNames> and the values are
157
+ # <NaturalDocs::Project::ImageFiles>.
158
+ #
159
+ my %imageFiles;
160
+
161
+
162
+ #
163
+ # hash: imageFilesToUpdate
164
+ #
165
+ # An existence hash of all the image <FileNames> that need to be updated, either because they changed or they're new to the
166
+ # project.
167
+ #
168
+ my %imageFilesToUpdate;
169
+
170
+
171
+ #
172
+ # hash: imageFilesToPurge
173
+ #
174
+ # An existence hash of all the image <FileNames> that need to be purged, either because the files no longer exist or because
175
+ # they are no longer used.
176
+ #
177
+ my %imageFilesToPurge;
178
+
179
+
180
+ #
181
+ # hash: insensitiveImageFiles
182
+ #
183
+ # A hash that maps all lowercase image <FileNames> to their proper case as it would appear in <imageFiles>. Used for
184
+ # case insensitivity, obviously.
185
+ #
186
+ # You can't just use all lowercase in <imageFiles> because both Linux and HTTP are case sensitive, so the original case must
187
+ # be preserved. We also want to allow separate entries for files that differ based only on case, so it goes to <imageFiles> first
188
+ # where they can be distinguished and here only if there's no match. Ties are broken by whichever is lower with cmp, because
189
+ # it has to resolve consistently on all runs of the program.
190
+ #
191
+ my %insensitiveImageFiles;
192
+
193
+
194
+
195
+ ###############################################################################
196
+ # Group: Files
197
+
198
+
199
+ #
200
+ # File: FileInfo.nd
201
+ #
202
+ # An index of the state of the files as of the last parse. Used to determine if files were added, deleted, or changed.
203
+ #
204
+ # Format:
205
+ #
206
+ # The format is a text file.
207
+ #
208
+ # > [VersionInt: app version]
209
+ #
210
+ # The beginning of the file is the <VersionInt> it was generated with.
211
+ #
212
+ # > [most used language name]
213
+ #
214
+ # Next is the name of the most used language in the source tree. Does not include text files.
215
+ #
216
+ # Each following line is
217
+ #
218
+ # > [file name] tab [last modification time] tab [has ND content (0 or 1)] tab [default menu title] \n
219
+ #
220
+ # Revisions:
221
+ #
222
+ # 1.3:
223
+ #
224
+ # - The line following the <VersionInt>, which was previously the last modification time of <Menu.txt>, was changed to
225
+ # the name of the most used language.
226
+ #
227
+ # 1.16:
228
+ #
229
+ # - File names are now absolute. Prior to 1.16, they were relative to the input directory since only one was allowed.
230
+ #
231
+ # 1.14:
232
+ #
233
+ # - The file was renamed from NaturalDocs.files to FileInfo.nd and moved into the Data subdirectory.
234
+ #
235
+ # 0.95:
236
+ #
237
+ # - The file version was changed to match the program version. Prior to 0.95, the version line was 1. Test for "1" instead
238
+ # of "1.0" to distinguish.
239
+ #
240
+
241
+
242
+ #
243
+ # File: ConfigFileInfo.nd
244
+ #
245
+ # An index of the state of the config files as of the last parse.
246
+ #
247
+ # Format:
248
+ #
249
+ # > [BINARY_FORMAT]
250
+ # > [VersionInt: app version]
251
+ #
252
+ # First is the standard <BINARY_FORMAT> <VersionInt> header.
253
+ #
254
+ # > [UInt32: last modification time of menu]
255
+ # > [UInt32: last modification of main topics file]
256
+ # > [UInt32: last modification of user topics file]
257
+ # > [UInt32: last modification of main languages file]
258
+ # > [UInt32: last modification of user languages file]
259
+ #
260
+ # Next are the last modification times of various configuration files as UInt32s in the standard Unix format.
261
+ #
262
+ #
263
+ # Revisions:
264
+ #
265
+ # 1.3:
266
+ #
267
+ # - The file was added to Natural Docs. Previously the last modification of <Menu.txt> was stored in <FileInfo.nd>, and
268
+ # <Topics.txt> and <Languages.txt> didn't exist.
269
+ #
270
+
271
+
272
+ #
273
+ # File: ImageFileInfo.nd
274
+ #
275
+ # An index of the state of the image files as of the last parse.
276
+ #
277
+ # Format:
278
+ #
279
+ # > [Standard Binary Header]
280
+ #
281
+ # First is the standard binary file header as defined by <NaturalDocs::BinaryFile>.
282
+ #
283
+ # > [AString16: file name or undef]
284
+ # > [UInt32: last modification time]
285
+ # > [UInt8: was used]
286
+ #
287
+ # This section is repeated until the file name is null. The last modification times are UInt32s in the standard Unix format.
288
+ #
289
+ #
290
+ # Revisions:
291
+ #
292
+ # 1.4:
293
+ #
294
+ # - The file was added to Natural Docs.
295
+ #
296
+
297
+
298
+
299
+ ###############################################################################
300
+ # Group: File Functions
301
+
302
+ #
303
+ # Function: LoadSourceFileInfo
304
+ #
305
+ # Loads the project file from disk and compares it against the files in the input directory. Project is loaded from
306
+ # <FileInfo.nd>. New and changed files will be added to <FilesToParse()>, and if they have content,
307
+ # <FilesToBuild()>.
308
+ #
309
+ # Will call <NaturalDocs::Languages->OnMostUsedLanguageKnown()> if <MostUsedLanguage()> changes.
310
+ #
311
+ # Returns:
312
+ #
313
+ # Returns whether the project was changed in any way.
314
+ #
315
+ sub LoadSourceFileInfo
316
+ {
317
+ my ($self) = @_;
318
+
319
+ $self->GetAllSupportedFiles();
320
+ NaturalDocs::Languages->OnMostUsedLanguageKnown();
321
+
322
+ my $fileIsOkay;
323
+ my $version;
324
+ my $hasChanged;
325
+
326
+ if (open(FH_FILEINFO, '<' . $self->DataFile('FileInfo.nd')))
327
+ {
328
+ # Check if the file is in the right format.
329
+ $version = NaturalDocs::Version->FromTextFile(\*FH_FILEINFO);
330
+
331
+ # The project file need to be rebuilt for 1.16. The source files need to be reparsed and the output files rebuilt for 1.4.
332
+ # We'll tolerate the difference between 1.16 and 1.3 in the loader.
333
+
334
+ if (NaturalDocs::Version->CheckFileFormat( $version, NaturalDocs::Version->FromString('1.16') ))
335
+ {
336
+ $fileIsOkay = 1;
337
+
338
+ if (!NaturalDocs::Version->CheckFileFormat( $version, NaturalDocs::Version->FromString('1.4') ))
339
+ {
340
+ $reparseEverything = 1;
341
+ $rebuildEverything = 1;
342
+ $hasChanged = 1;
343
+ };
344
+ }
345
+ else
346
+ {
347
+ close(FH_FILEINFO);
348
+ $hasChanged = 1;
349
+ };
350
+ };
351
+
352
+
353
+ if ($fileIsOkay)
354
+ {
355
+ my %indexedFiles;
356
+
357
+
358
+ my $line = <FH_FILEINFO>;
359
+ ::XChomp(\$line);
360
+
361
+ # Prior to 1.3 it was the last modification time of Menu.txt, which we ignore and treat as though the most used language
362
+ # changed. Prior to 1.32 the settings didn't transfer over correctly to Menu.txt so we need to behave that way again.
363
+ if ($version < NaturalDocs::Version->FromString('1.32') || lc($mostUsedLanguage) ne lc($line))
364
+ {
365
+ $reparseEverything = 1;
366
+ NaturalDocs::SymbolTable->RebuildAllIndexes();
367
+ };
368
+
369
+
370
+ # Parse the rest of the file.
371
+
372
+ while ($line = <FH_FILEINFO>)
373
+ {
374
+ ::XChomp(\$line);
375
+ my ($file, $modification, $hasContent, $menuTitle) = split(/\t/, $line, 4);
376
+
377
+ # If the file no longer exists...
378
+ if (!exists $supportedFiles{$file})
379
+ {
380
+ if ($hasContent)
381
+ { $filesToPurge{$file} = 1; };
382
+
383
+ $hasChanged = 1;
384
+ }
385
+
386
+ # If the file still exists...
387
+ else
388
+ {
389
+ $indexedFiles{$file} = 1;
390
+
391
+ # If the file changed...
392
+ if ($supportedFiles{$file}->LastModified() != $modification)
393
+ {
394
+ $supportedFiles{$file}->SetStatus(::FILE_CHANGED());
395
+ $filesToParse{$file} = 1;
396
+
397
+ # If the file loses its content, this will be removed by SetHasContent().
398
+ if ($hasContent)
399
+ { $filesToBuild{$file} = 1; };
400
+
401
+ $hasChanged = 1;
402
+ }
403
+
404
+ # If the file has not changed...
405
+ else
406
+ {
407
+ my $status;
408
+
409
+ if ($rebuildEverything && $hasContent)
410
+ {
411
+ $status = ::FILE_CHANGED();
412
+
413
+ # If the file loses its content, this will be removed by SetHasContent().
414
+ $filesToBuild{$file} = 1;
415
+ $hasChanged = 1;
416
+ }
417
+ else
418
+ {
419
+ $status = ::FILE_SAME();
420
+
421
+ if ($hasContent)
422
+ { $unbuiltFilesWithContent{$file} = 1; };
423
+ };
424
+
425
+ if ($reparseEverything)
426
+ {
427
+ $status = ::FILE_CHANGED();
428
+
429
+ $filesToParse{$file} = 1;
430
+ $hasChanged = 1;
431
+ };
432
+
433
+ $supportedFiles{$file}->SetStatus($status);
434
+ };
435
+
436
+ $supportedFiles{$file}->SetHasContent($hasContent);
437
+ $supportedFiles{$file}->SetDefaultMenuTitle($menuTitle);
438
+ };
439
+ };
440
+
441
+ close(FH_FILEINFO);
442
+
443
+
444
+ # Check for added files.
445
+
446
+ if (scalar keys %supportedFiles > scalar keys %indexedFiles)
447
+ {
448
+ foreach my $file (keys %supportedFiles)
449
+ {
450
+ if (!exists $indexedFiles{$file})
451
+ {
452
+ $supportedFiles{$file}->SetStatus(::FILE_NEW());
453
+ $supportedFiles{$file}->SetDefaultMenuTitle($file);
454
+ $supportedFiles{$file}->SetHasContent(undef);
455
+ $filesToParse{$file} = 1;
456
+ # It will be added to filesToBuild if HasContent gets set to true when it's parsed.
457
+ $hasChanged = 1;
458
+ };
459
+ };
460
+ };
461
+ }
462
+
463
+ # If something's wrong with FileInfo.nd, everything is new.
464
+ else
465
+ {
466
+ foreach my $file (keys %supportedFiles)
467
+ {
468
+ $supportedFiles{$file}->SetStatus(::FILE_NEW());
469
+ $supportedFiles{$file}->SetDefaultMenuTitle($file);
470
+ $supportedFiles{$file}->SetHasContent(undef);
471
+ $filesToParse{$file} = 1;
472
+ # It will be added to filesToBuild if HasContent gets set to true when it's parsed.
473
+ };
474
+
475
+ $hasChanged = 1;
476
+ };
477
+
478
+
479
+ # There are other side effects, so we need to call this.
480
+ if ($rebuildEverything)
481
+ { $self->RebuildEverything(); };
482
+
483
+
484
+ return $hasChanged;
485
+ };
486
+
487
+
488
+ #
489
+ # Function: SaveSourceFileInfo
490
+ #
491
+ # Saves the source file info to disk. Everything is saved in <FileInfo.nd>.
492
+ #
493
+ sub SaveSourceFileInfo
494
+ {
495
+ my ($self) = @_;
496
+
497
+ open(FH_FILEINFO, '>' . $self->DataFile('FileInfo.nd'))
498
+ or die "Couldn't save project file " . $self->DataFile('FileInfo.nd') . "\n";
499
+
500
+ NaturalDocs::Version->ToTextFile(\*FH_FILEINFO, NaturalDocs::Settings->AppVersion());
501
+
502
+ print FH_FILEINFO $mostUsedLanguage . "\n";
503
+
504
+ while (my ($fileName, $file) = each %supportedFiles)
505
+ {
506
+ print FH_FILEINFO $fileName . "\t"
507
+ . $file->LastModified() . "\t"
508
+ . ($file->HasContent() || '0') . "\t"
509
+ . $file->DefaultMenuTitle() . "\n";
510
+ };
511
+
512
+ close(FH_FILEINFO);
513
+ };
514
+
515
+
516
+ #
517
+ # Function: LoadConfigFileInfo
518
+ #
519
+ # Loads the config file info from disk.
520
+ #
521
+ sub LoadConfigFileInfo
522
+ {
523
+ my ($self) = @_;
524
+
525
+ my $fileIsOkay;
526
+ my $version;
527
+ my $fileName = NaturalDocs::Project->DataFile('ConfigFileInfo.nd');
528
+
529
+ if (open(FH_CONFIGFILEINFO, '<' . $fileName))
530
+ {
531
+ # See if it's binary.
532
+ binmode(FH_CONFIGFILEINFO);
533
+
534
+ my $firstChar;
535
+ read(FH_CONFIGFILEINFO, $firstChar, 1);
536
+
537
+ if ($firstChar == ::BINARY_FORMAT())
538
+ {
539
+ $version = NaturalDocs::Version->FromBinaryFile(\*FH_CONFIGFILEINFO);
540
+
541
+ # It hasn't changed since being introduced.
542
+
543
+ if (NaturalDocs::Version->CheckFileFormat($version))
544
+ { $fileIsOkay = 1; }
545
+ else
546
+ { close(FH_CONFIGFILEINFO); };
547
+ }
548
+
549
+ else # it's not in binary
550
+ { close(FH_CONFIGFILEINFO); };
551
+ };
552
+
553
+ my @configFiles = ( $self->UserConfigFile('Menu.txt'), \$userConfigFiles{'Menu.txt'},
554
+ $self->MainConfigFile('Topics.txt'), \$mainConfigFiles{'Topics.txt'},
555
+ $self->UserConfigFile('Topics.txt'), \$userConfigFiles{'Topics.txt'},
556
+ $self->MainConfigFile('Languages.txt'), \$mainConfigFiles{'Languages.txt'},
557
+ $self->UserConfigFile('Languages.txt'), \$userConfigFiles{'Languages.txt'} );
558
+
559
+ if ($fileIsOkay)
560
+ {
561
+ my $raw;
562
+
563
+ read(FH_CONFIGFILEINFO, $raw, 20);
564
+ my @configFileDates = unpack('NNNNN', $raw);
565
+
566
+ while (scalar @configFiles)
567
+ {
568
+ my $file = shift @configFiles;
569
+ my $fileStatus = shift @configFiles;
570
+ my $fileDate = shift @configFileDates;
571
+
572
+ if (-e $file)
573
+ {
574
+ if ($fileDate == (stat($file))[9])
575
+ { $$fileStatus = ::FILE_SAME(); }
576
+ else
577
+ { $$fileStatus = ::FILE_CHANGED(); };
578
+ }
579
+ else
580
+ { $$fileStatus = ::FILE_DOESNTEXIST(); };
581
+ };
582
+
583
+ close(FH_CONFIGFILEINFO);
584
+ }
585
+ else # !$fileIsOkay
586
+ {
587
+ while (scalar @configFiles)
588
+ {
589
+ my $file = shift @configFiles;
590
+ my $fileStatus = shift @configFiles;
591
+
592
+ if (-e $file)
593
+ { $$fileStatus = ::FILE_CHANGED(); }
594
+ else
595
+ { $$fileStatus = ::FILE_DOESNTEXIST(); };
596
+ };
597
+ };
598
+
599
+ if ($userConfigFiles{'Menu.txt'} == ::FILE_SAME() && $rebuildEverything)
600
+ { $userConfigFiles{'Menu.txt'} = ::FILE_CHANGED(); };
601
+ };
602
+
603
+
604
+ #
605
+ # Function: SaveConfigFileInfo
606
+ #
607
+ # Saves the config file info to disk. You *must* save all other config files first, such as <Menu.txt> and <Topics.txt>.
608
+ #
609
+ sub SaveConfigFileInfo
610
+ {
611
+ my ($self) = @_;
612
+
613
+ open (FH_CONFIGFILEINFO, '>' . NaturalDocs::Project->DataFile('ConfigFileInfo.nd'))
614
+ or die "Couldn't save " . NaturalDocs::Project->DataFile('ConfigFileInfo.nd') . ".\n";
615
+
616
+ binmode(FH_CONFIGFILEINFO);
617
+
618
+ print FH_CONFIGFILEINFO '' . ::BINARY_FORMAT();
619
+
620
+ NaturalDocs::Version->ToBinaryFile(\*FH_CONFIGFILEINFO, NaturalDocs::Settings->AppVersion());
621
+
622
+ print FH_CONFIGFILEINFO pack('NNNNN', (stat($self->UserConfigFile('Menu.txt')))[9],
623
+ (stat($self->MainConfigFile('Topics.txt')))[9],
624
+ (stat($self->UserConfigFile('Topics.txt')))[9],
625
+ (stat($self->MainConfigFile('Languages.txt')))[9],
626
+ (stat($self->UserConfigFile('Languages.txt')))[9] );
627
+
628
+ close(FH_CONFIGFILEINFO);
629
+ };
630
+
631
+
632
+ #
633
+ # Function: LoadImageFileInfo
634
+ #
635
+ # Loads the image file info from disk.
636
+ #
637
+ sub LoadImageFileInfo
638
+ {
639
+ my ($self) = @_;
640
+
641
+ my $version = NaturalDocs::BinaryFile->OpenForReading( NaturalDocs::Project->DataFile('ImageFileInfo.nd') );
642
+ my $fileIsOkay;
643
+
644
+ if (defined $version)
645
+ {
646
+ # It hasn't changed since being introduced.
647
+
648
+ if (NaturalDocs::Version->CheckFileFormat($version))
649
+ { $fileIsOkay = 1; }
650
+ else
651
+ { NaturalDocs::BinaryFile->Close(); };
652
+ };
653
+
654
+ if ($fileIsOkay)
655
+ {
656
+ # [AString16: file name or undef]
657
+
658
+ while (my $imageFile = NaturalDocs::BinaryFile->GetAString16())
659
+ {
660
+ # [UInt32: last modified]
661
+ # [UInt8: was used]
662
+
663
+ my $lastModified = NaturalDocs::BinaryFile->GetUInt32();
664
+ my $wasUsed = NaturalDocs::BinaryFile->GetUInt8();
665
+
666
+ my $imageFileObject = $imageFiles{$imageFile};
667
+
668
+ # If there's an image file in ImageFileInfo.nd that no longer exists...
669
+ if (!$imageFileObject)
670
+ {
671
+ $imageFileObject = NaturalDocs::Project::ImageFile->New($lastModified, ::FILE_DOESNTEXIST(), $wasUsed);
672
+ $imageFiles{$imageFile} = $imageFileObject;
673
+
674
+ if ($wasUsed)
675
+ { $imageFilesToPurge{$imageFile} = 1; };
676
+ }
677
+ else
678
+ {
679
+ $imageFileObject->SetWasUsed($wasUsed);
680
+
681
+ # This will be removed if it gets any references.
682
+ if ($wasUsed)
683
+ { $imageFilesToPurge{$imageFile} = 1; };
684
+
685
+ if ($imageFileObject->LastModified() == $lastModified && !$rebuildEverything)
686
+ { $imageFileObject->SetStatus(::FILE_SAME()); }
687
+ else
688
+ { $imageFileObject->SetStatus(::FILE_CHANGED()); };
689
+ };
690
+ };
691
+
692
+ NaturalDocs::BinaryFile->Close();
693
+ }
694
+
695
+ else # !$fileIsOkay
696
+ {
697
+ $self->RebuildEverything();
698
+ };
699
+ };
700
+
701
+
702
+ #
703
+ # Function: SaveImageFileInfo
704
+ #
705
+ # Saves the image file info to disk.
706
+ #
707
+ sub SaveImageFileInfo
708
+ {
709
+ my $self = shift;
710
+
711
+ NaturalDocs::BinaryFile->OpenForWriting( NaturalDocs::Project->DataFile('ImageFileInfo.nd') );
712
+
713
+ while (my ($imageFile, $imageFileInfo) = each %imageFiles)
714
+ {
715
+ if ($imageFileInfo->Status() != ::FILE_DOESNTEXIST())
716
+ {
717
+ # [AString16: file name or undef]
718
+ # [UInt32: last modification time]
719
+ # [UInt8: was used]
720
+
721
+ NaturalDocs::BinaryFile->WriteAString16($imageFile);
722
+ NaturalDocs::BinaryFile->WriteUInt32($imageFileInfo->LastModified());
723
+ NaturalDocs::BinaryFile->WriteUInt8( ($imageFileInfo->ReferenceCount() > 0 ? 1 : 0) );
724
+ };
725
+ };
726
+
727
+ NaturalDocs::BinaryFile->WriteAString16(undef);
728
+ NaturalDocs::BinaryFile->Close();
729
+ };
730
+
731
+
732
+ #
733
+ # Function: MigrateOldFiles
734
+ #
735
+ # If the project uses the old file names used prior to 1.14, it converts them to the new file names.
736
+ #
737
+ sub MigrateOldFiles
738
+ {
739
+ my ($self) = @_;
740
+
741
+ my $projectDirectory = NaturalDocs::Settings->ProjectDirectory();
742
+
743
+ # We use the menu file as a test to see if we're using the new format.
744
+ if (-e NaturalDocs::File->JoinPaths($projectDirectory, 'NaturalDocs_Menu.txt'))
745
+ {
746
+ # The Data subdirectory would have been created by NaturalDocs::Settings.
747
+
748
+ rename( NaturalDocs::File->JoinPaths($projectDirectory, 'NaturalDocs_Menu.txt'), $self->UserConfigFile('Menu.txt') );
749
+
750
+ if (-e NaturalDocs::File->JoinPaths($projectDirectory, 'NaturalDocs.sym'))
751
+ { rename( NaturalDocs::File->JoinPaths($projectDirectory, 'NaturalDocs.sym'), $self->DataFile('SymbolTable.nd') ); };
752
+
753
+ if (-e NaturalDocs::File->JoinPaths($projectDirectory, 'NaturalDocs.files'))
754
+ { rename( NaturalDocs::File->JoinPaths($projectDirectory, 'NaturalDocs.files'), $self->DataFile('FileInfo.nd') ); };
755
+
756
+ if (-e NaturalDocs::File->JoinPaths($projectDirectory, 'NaturalDocs.m'))
757
+ { rename( NaturalDocs::File->JoinPaths($projectDirectory, 'NaturalDocs.m'), $self->DataFile('PreviousMenuState.nd') ); };
758
+ };
759
+ };
760
+
761
+
762
+
763
+ ###############################################################################
764
+ # Group: Config and Data File Functions
765
+
766
+
767
+ #
768
+ # Function: MainConfigFile
769
+ #
770
+ # Returns the full path to the passed main configuration file. Pass the file name only.
771
+ #
772
+ sub MainConfigFile #(string file)
773
+ {
774
+ my ($self, $file) = @_;
775
+ return NaturalDocs::File->JoinPaths( NaturalDocs::Settings->ConfigDirectory(), $file );
776
+ };
777
+
778
+ #
779
+ # Function: MainConfigFileStatus
780
+ #
781
+ # Returns the <FileStatus> of the passed main configuration file. Pass the file name only.
782
+ #
783
+ sub MainConfigFileStatus #(string file)
784
+ {
785
+ my ($self, $file) = @_;
786
+ return $mainConfigFiles{$file};
787
+ };
788
+
789
+ #
790
+ # Function: UserConfigFile
791
+ #
792
+ # Returns the full path to the passed user configuration file. Pass the file name only.
793
+ #
794
+ sub UserConfigFile #(string file)
795
+ {
796
+ my ($self, $file) = @_;
797
+ return NaturalDocs::File->JoinPaths( NaturalDocs::Settings->ProjectDirectory(), $file );
798
+ };
799
+
800
+ #
801
+ # Function: UserConfigFileStatus
802
+ #
803
+ # Returns the <FileStatus> of the passed user configuration file. Pass the file name only.
804
+ #
805
+ sub UserConfigFileStatus #(string file)
806
+ {
807
+ my ($self, $file) = @_;
808
+ return $userConfigFiles{$file};
809
+ };
810
+
811
+ #
812
+ # Function: DataFile
813
+ #
814
+ # Returns the full path to the passed data file. Pass the file name only.
815
+ #
816
+ sub DataFile #(string file)
817
+ {
818
+ my ($self, $file) = @_;
819
+ return NaturalDocs::File->JoinPaths( NaturalDocs::Settings->ProjectDataDirectory(), $file );
820
+ };
821
+
822
+
823
+
824
+
825
+ ###############################################################################
826
+ # Group: Source File Functions
827
+
828
+
829
+ # Function: FilesToParse
830
+ # Returns an existence hashref of the <FileNames> to parse. This is not a copy of the data, so don't change it.
831
+ sub FilesToParse
832
+ { return \%filesToParse; };
833
+
834
+ # Function: FilesToBuild
835
+ # Returns an existence hashref of the <FileNames> to build. This is not a copy of the data, so don't change it.
836
+ sub FilesToBuild
837
+ { return \%filesToBuild; };
838
+
839
+ # Function: FilesToPurge
840
+ # Returns an existence hashref of the <FileNames> that had content last time, but now either don't anymore or were deleted.
841
+ # This is not a copy of the data, so don't change it.
842
+ sub FilesToPurge
843
+ { return \%filesToPurge; };
844
+
845
+ #
846
+ # Function: RebuildFile
847
+ #
848
+ # Adds the file to the list of files to build. This function will automatically filter out files that don't have Natural Docs content and
849
+ # files that are part of <FilesToPurge()>. If this gets called on a file and that file later gets Natural Docs content, it will be added.
850
+ #
851
+ # Parameters:
852
+ #
853
+ # file - The <FileName> to build or rebuild.
854
+ #
855
+ sub RebuildFile #(file)
856
+ {
857
+ my ($self, $file) = @_;
858
+
859
+ # We don't want to add it to the build list if it doesn't exist, doesn't have Natural Docs content, or it's going to be purged.
860
+ # If it wasn't parsed yet and will later be found to have ND content, it will be added by SetHasContent().
861
+ if (exists $supportedFiles{$file} && !exists $filesToPurge{$file} && $supportedFiles{$file}->HasContent())
862
+ {
863
+ $filesToBuild{$file} = 1;
864
+
865
+ if (exists $unbuiltFilesWithContent{$file})
866
+ { delete $unbuiltFilesWithContent{$file}; };
867
+ };
868
+ };
869
+
870
+
871
+ #
872
+ # Function: ReparseEverything
873
+ #
874
+ # Adds all supported files to the list of files to parse. This does not necessarily mean these files are going to be rebuilt.
875
+ #
876
+ sub ReparseEverything
877
+ {
878
+ my ($self) = @_;
879
+
880
+ if (!$reparseEverything)
881
+ {
882
+ foreach my $file (keys %supportedFiles)
883
+ {
884
+ $filesToParse{$file} = 1;
885
+ };
886
+
887
+ $reparseEverything = 1;
888
+ };
889
+ };
890
+
891
+
892
+ #
893
+ # Function: RebuildEverything
894
+ #
895
+ # Adds all supported files to the list of files to build. This does not necessarily mean these files are going to be reparsed.
896
+ #
897
+ sub RebuildEverything
898
+ {
899
+ my ($self) = @_;
900
+
901
+ foreach my $file (keys %unbuiltFilesWithContent)
902
+ {
903
+ $filesToBuild{$file} = 1;
904
+ };
905
+
906
+ %unbuiltFilesWithContent = ( );
907
+ $rebuildEverything = 1;
908
+
909
+ NaturalDocs::SymbolTable->RebuildAllIndexes();
910
+
911
+ if ($userConfigFiles{'Menu.txt'} == ::FILE_SAME())
912
+ { $userConfigFiles{'Menu.txt'} = ::FILE_CHANGED(); };
913
+
914
+ while (my ($imageFile, $imageObject) = each %imageFiles)
915
+ {
916
+ if ($imageObject->ReferenceCount())
917
+ { $imageFilesToUpdate{$imageFile} = 1; };
918
+ };
919
+ };
920
+
921
+
922
+ # Function: UnbuiltFilesWithContent
923
+ # Returns an existence hashref of the <FileNames> that have Natural Docs content but are not part of <FilesToBuild()>. This is
924
+ # not a copy of the data so don't change it.
925
+ sub UnbuiltFilesWithContent
926
+ { return \%unbuiltFilesWithContent; };
927
+
928
+ # Function: FilesWithContent
929
+ # Returns and existence hashref of the <FileNames> that have Natural Docs content.
930
+ sub FilesWithContent
931
+ {
932
+ # Don't keep this one internally, but there's an easy way to make it.
933
+ return { %filesToBuild, %unbuiltFilesWithContent };
934
+ };
935
+
936
+
937
+ #
938
+ # Function: HasContent
939
+ #
940
+ # Returns whether the <FileName> contains Natural Docs content.
941
+ #
942
+ sub HasContent #(file)
943
+ {
944
+ my ($self, $file) = @_;
945
+
946
+ if (exists $supportedFiles{$file})
947
+ { return $supportedFiles{$file}->HasContent(); }
948
+ else
949
+ { return undef; };
950
+ };
951
+
952
+
953
+ #
954
+ # Function: SetHasContent
955
+ #
956
+ # Sets whether the <FileName> has Natural Docs content or not.
957
+ #
958
+ sub SetHasContent #(file, hasContent)
959
+ {
960
+ my ($self, $file, $hasContent) = @_;
961
+
962
+ if (exists $supportedFiles{$file} && $supportedFiles{$file}->HasContent() != $hasContent)
963
+ {
964
+ # If the file now has content...
965
+ if ($hasContent)
966
+ {
967
+ $filesToBuild{$file} = 1;
968
+ }
969
+
970
+ # If the file's content has been removed...
971
+ else
972
+ {
973
+ delete $filesToBuild{$file}; # may not be there
974
+ $filesToPurge{$file} = 1;
975
+ };
976
+
977
+ $supportedFiles{$file}->SetHasContent($hasContent);
978
+ };
979
+ };
980
+
981
+
982
+ #
983
+ # Function: StatusOf
984
+ #
985
+ # Returns the <FileStatus> of the passed <FileName>.
986
+ #
987
+ sub StatusOf #(file)
988
+ {
989
+ my ($self, $file) = @_;
990
+
991
+ if (exists $supportedFiles{$file})
992
+ { return $supportedFiles{$file}->Status(); }
993
+ else
994
+ { return ::FILE_DOESNTEXIST(); };
995
+ };
996
+
997
+
998
+ #
999
+ # Function: DefaultMenuTitleOf
1000
+ #
1001
+ # Returns the default menu title of the <FileName>. If one isn't specified, it returns the <FileName>.
1002
+ #
1003
+ sub DefaultMenuTitleOf #(file)
1004
+ {
1005
+ my ($self, $file) = @_;
1006
+
1007
+ if (exists $supportedFiles{$file})
1008
+ { return $supportedFiles{$file}->DefaultMenuTitle(); }
1009
+ else
1010
+ { return $file; };
1011
+ };
1012
+
1013
+
1014
+ #
1015
+ # Function: SetDefaultMenuTitle
1016
+ #
1017
+ # Sets the <FileName's> default menu title.
1018
+ #
1019
+ sub SetDefaultMenuTitle #(file, menuTitle)
1020
+ {
1021
+ my ($self, $file, $menuTitle) = @_;
1022
+
1023
+ if (exists $supportedFiles{$file} && $supportedFiles{$file}->DefaultMenuTitle() ne $menuTitle)
1024
+ {
1025
+ $supportedFiles{$file}->SetDefaultMenuTitle($menuTitle);
1026
+ NaturalDocs::Menu->OnDefaultTitleChange($file);
1027
+ };
1028
+ };
1029
+
1030
+
1031
+ #
1032
+ # Function: MostUsedLanguage
1033
+ #
1034
+ # Returns the name of the most used language in the source trees. Does not include text files.
1035
+ #
1036
+ sub MostUsedLanguage
1037
+ { return $mostUsedLanguage; };
1038
+
1039
+
1040
+
1041
+
1042
+ ###############################################################################
1043
+ # Group: Image File Functions
1044
+
1045
+
1046
+ #
1047
+ # Function: ImageFileExists
1048
+ # Returns whether the passed image file exists.
1049
+ #
1050
+ sub ImageFileExists #(FileName file) => bool
1051
+ {
1052
+ my ($self, $file) = @_;
1053
+
1054
+ if (!exists $imageFiles{$file})
1055
+ { $file = $insensitiveImageFiles{lc($file)}; };
1056
+
1057
+ return (exists $imageFiles{$file} && $imageFiles{$file}->Status() != ::FILE_DOESNTEXIST());
1058
+ };
1059
+
1060
+
1061
+ #
1062
+ # Function: ImageFileDimensions
1063
+ # Returns the dimensions of the passed image file as the array ( width, height ). Returns them both as undef if it cannot be
1064
+ # determined.
1065
+ #
1066
+ sub ImageFileDimensions #(FileName file) => (int, int)
1067
+ {
1068
+ my ($self, $file) = @_;
1069
+
1070
+ if (!exists $imageFiles{$file})
1071
+ { $file = $insensitiveImageFiles{lc($file)}; };
1072
+
1073
+ my $object = $imageFiles{$file};
1074
+ if (!$object)
1075
+ { die "Tried to get the dimensions of an image that doesn't exist."; };
1076
+
1077
+ if ($object->Width() == -1)
1078
+ { $self->DetermineImageDimensions($file); };
1079
+
1080
+ return ($object->Width(), $object->Height());
1081
+ };
1082
+
1083
+
1084
+ #
1085
+ # Function: ImageFileCapitalization
1086
+ # Returns the properly capitalized version of the passed image <FileName>. Image file paths are treated as case insensitive
1087
+ # regardless of whether the underlying operating system is or not, so we have to make sure the final version matches the
1088
+ # capitalization of the actual file.
1089
+ #
1090
+ sub ImageFileCapitalization #(FileName file) => FileName
1091
+ {
1092
+ my ($self, $file) = @_;
1093
+
1094
+ if (exists $imageFiles{$file})
1095
+ { return $file; }
1096
+ elsif (exists $insensitiveImageFiles{lc($file)})
1097
+ { return $insensitiveImageFiles{lc($file)}; }
1098
+ else
1099
+ { die "Tried to get the capitalization of an image file that doesn't exist."; };
1100
+ };
1101
+
1102
+
1103
+ #
1104
+ # Function: AddImageFileReference
1105
+ # Adds a reference to the passed image <FileName>.
1106
+ #
1107
+ sub AddImageFileReference #(FileName imageFile)
1108
+ {
1109
+ my ($self, $imageFile) = @_;
1110
+
1111
+ if (!exists $imageFiles{$imageFile})
1112
+ { $imageFile = $insensitiveImageFiles{lc($imageFile)}; };
1113
+
1114
+ my $imageFileInfo = $imageFiles{$imageFile};
1115
+
1116
+ if ($imageFileInfo == undef || $imageFileInfo->Status() == ::FILE_DOESNTEXIST())
1117
+ { die "Tried to add a reference to a non-existant image file."; };
1118
+
1119
+ if ($imageFileInfo->AddReference() == 1)
1120
+ {
1121
+ delete $imageFilesToPurge{$imageFile};
1122
+
1123
+ if (!$imageFileInfo->WasUsed() ||
1124
+ $imageFileInfo->Status() == ::FILE_NEW() ||
1125
+ $imageFileInfo->Status() == ::FILE_CHANGED())
1126
+ { $imageFilesToUpdate{$imageFile} = 1; };
1127
+ };
1128
+ };
1129
+
1130
+
1131
+ #
1132
+ # Function: DeleteImageFileReference
1133
+ # Deletes a reference from the passed image <FileName>.
1134
+ #
1135
+ sub DeleteImageFileReference #(FileName imageFile)
1136
+ {
1137
+ my ($self, $imageFile) = @_;
1138
+
1139
+ if (!exists $imageFiles{$imageFile})
1140
+ { $imageFile = $insensitiveImageFiles{lc($imageFile)}; };
1141
+
1142
+ if (!exists $imageFiles{$imageFile})
1143
+ { die "Tried to delete a reference to a non-existant image file."; };
1144
+
1145
+ if ($imageFiles{$imageFile}->DeleteReference() == 0)
1146
+ {
1147
+ delete $imageFilesToUpdate{$imageFile};
1148
+
1149
+ if ($imageFiles{$imageFile}->WasUsed())
1150
+ { $imageFilesToPurge{$imageFile} = 1; };
1151
+ };
1152
+ };
1153
+
1154
+
1155
+ #
1156
+ # Function: ImageFilesToUpdate
1157
+ # Returns an existence hashref of image <FileNames> that need to be updated. *Do not change.*
1158
+ #
1159
+ sub ImageFilesToUpdate
1160
+ { return \%imageFilesToUpdate; };
1161
+
1162
+
1163
+ #
1164
+ # Function: ImageFilesToPurge
1165
+ # Returns an existence hashref of image <FileNames> that need to be updated. *Do not change.*
1166
+ #
1167
+ sub ImageFilesToPurge
1168
+ { return \%imageFilesToPurge; };
1169
+
1170
+
1171
+
1172
+ ###############################################################################
1173
+ # Group: Support Functions
1174
+
1175
+ #
1176
+ # Function: GetAllSupportedFiles
1177
+ #
1178
+ # Gets all the supported files in the passed directory and its subdirectories and puts them into <supportedFiles>. The only
1179
+ # attribute that will be set is <NaturalDocs::Project::SourceFile->LastModified()>. Also sets <mostUsedLanguage>.
1180
+ #
1181
+ sub GetAllSupportedFiles
1182
+ {
1183
+ my ($self) = @_;
1184
+
1185
+ my @directories = @{NaturalDocs::Settings->InputDirectories()};
1186
+ my $isCaseSensitive = NaturalDocs::File->IsCaseSensitive();
1187
+
1188
+ # Keys are language names, values are counts.
1189
+ my %languageCounts;
1190
+
1191
+
1192
+ # Make an existence hash of excluded directories.
1193
+
1194
+ my %excludedDirectories;
1195
+ my $excludedDirectoryArrayRef = NaturalDocs::Settings->ExcludedInputDirectories();
1196
+
1197
+ foreach my $excludedDirectory (@$excludedDirectoryArrayRef)
1198
+ {
1199
+ if ($isCaseSensitive)
1200
+ { $excludedDirectories{$excludedDirectory} = 1; }
1201
+ else
1202
+ { $excludedDirectories{lc($excludedDirectory)} = 1; };
1203
+ };
1204
+
1205
+
1206
+ my $imagesOnly;
1207
+ my $language;
1208
+
1209
+ while (scalar @directories)
1210
+ {
1211
+ my $directory = pop @directories;
1212
+
1213
+ opendir DIRECTORYHANDLE, $directory;
1214
+ my @entries = readdir DIRECTORYHANDLE;
1215
+ closedir DIRECTORYHANDLE;
1216
+
1217
+ @entries = NaturalDocs::File->NoUpwards(@entries);
1218
+
1219
+ foreach my $entry (@entries)
1220
+ {
1221
+ my $fullEntry = NaturalDocs::File->JoinPaths($directory, $entry);
1222
+
1223
+ # If an entry is a directory, recurse.
1224
+ if (-d $fullEntry)
1225
+ {
1226
+ # Join again with the noFile flag set in case the platform handles them differently.
1227
+ $fullEntry = NaturalDocs::File->JoinPaths($directory, $entry, 1);
1228
+
1229
+ if ($isCaseSensitive)
1230
+ {
1231
+ if (!exists $excludedDirectories{$fullEntry})
1232
+ { push @directories, $fullEntry; };
1233
+ }
1234
+ else
1235
+ {
1236
+ if (!exists $excludedDirectories{lc($fullEntry)})
1237
+ { push @directories, $fullEntry; };
1238
+ };
1239
+ }
1240
+
1241
+ # Otherwise add it if it's a supported extension.
1242
+ else
1243
+ {
1244
+ my $extension = NaturalDocs::File->ExtensionOf($entry);
1245
+
1246
+ if (exists $imageFileExtensions{lc($extension)})
1247
+ {
1248
+ my $fileObject = NaturalDocs::Project::ImageFile->New( (stat($fullEntry))[9], ::FILE_NEW(), 0 );
1249
+ $imageFiles{$fullEntry} = $fileObject;
1250
+
1251
+ my $lcFullEntry = lc($fullEntry);
1252
+
1253
+ if (!exists $insensitiveImageFiles{$lcFullEntry} ||
1254
+ ($fullEntry cmp $insensitiveImageFiles{$lcFullEntry}) < 0)
1255
+ {
1256
+ $insensitiveImageFiles{$lcFullEntry} = $fullEntry;
1257
+ };
1258
+ }
1259
+ elsif (!$imagesOnly && ($language = NaturalDocs::Languages->LanguageOf($fullEntry)) )
1260
+ {
1261
+ my $fileObject = NaturalDocs::Project::SourceFile->New();
1262
+ $fileObject->SetLastModified(( stat($fullEntry))[9] );
1263
+ $supportedFiles{$fullEntry} = $fileObject;
1264
+
1265
+ $languageCounts{$language->Name()}++;
1266
+ };
1267
+ };
1268
+ };
1269
+
1270
+
1271
+ # After we run out of source directories, add the image directories.
1272
+
1273
+ if (scalar @directories == 0 && !$imagesOnly)
1274
+ {
1275
+ $imagesOnly = 1;
1276
+ @directories = @{NaturalDocs::Settings->ImageDirectories()};
1277
+ };
1278
+ };
1279
+
1280
+
1281
+ my $topCount = 0;
1282
+
1283
+ while (my ($language, $count) = each %languageCounts)
1284
+ {
1285
+ if ($count > $topCount && $language ne 'Text File')
1286
+ {
1287
+ $topCount = $count;
1288
+ $mostUsedLanguage = $language;
1289
+ };
1290
+ };
1291
+ };
1292
+
1293
+
1294
+ #
1295
+ # Function: DetermineImageDimensions
1296
+ #
1297
+ # Attempts to determine the dimensions of the passed image and apply them to their object in <imageFiles>. Will set them to
1298
+ # undef if they can't be determined.
1299
+ #
1300
+ sub DetermineImageDimensions #(FileName imageFile)
1301
+ {
1302
+ my ($self, $imageFile) = @_;
1303
+
1304
+ my $imageFileObject = $imageFiles{$imageFile};
1305
+ if (!defined $imageFileObject)
1306
+ { die "Tried to determine image dimensions of a file with no object."; };
1307
+
1308
+ my $extension = lc( NaturalDocs::File->ExtensionOf($imageFile) );
1309
+ my ($width, $height);
1310
+
1311
+ if ($imageFileExtensions{$extension})
1312
+ {
1313
+ open(FH_IMAGEFILE, '<' . $imageFile)
1314
+ or die 'Could not open ' . $imageFile . "\n";
1315
+ binmode(FH_IMAGEFILE);
1316
+
1317
+ my $raw;
1318
+
1319
+ if ($extension eq 'gif')
1320
+ {
1321
+ read(FH_IMAGEFILE, $raw, 6);
1322
+
1323
+ if ($raw eq 'GIF87a' || $raw eq 'GIF89a')
1324
+ {
1325
+ read(FH_IMAGEFILE, $raw, 4);
1326
+ ($width, $height) = unpack('vv', $raw);
1327
+ };
1328
+ }
1329
+
1330
+ elsif ($extension eq 'png')
1331
+ {
1332
+ read(FH_IMAGEFILE, $raw, 8);
1333
+
1334
+ if ($raw eq "\x89PNG\x0D\x0A\x1A\x0A")
1335
+ {
1336
+ seek(FH_IMAGEFILE, 4, 1);
1337
+ read(FH_IMAGEFILE, $raw, 4);
1338
+
1339
+ if ($raw eq 'IHDR')
1340
+ {
1341
+ read(FH_IMAGEFILE, $raw, 8);
1342
+ ($width, $height) = unpack('NN', $raw);
1343
+ };
1344
+ };
1345
+ }
1346
+
1347
+ elsif ($extension eq 'bmp')
1348
+ {
1349
+ read(FH_IMAGEFILE, $raw, 2);
1350
+
1351
+ if ($raw eq 'BM')
1352
+ {
1353
+ seek(FH_IMAGEFILE, 16, 1);
1354
+ read(FH_IMAGEFILE, $raw, 8);
1355
+
1356
+ ($width, $height) = unpack('VV', $raw);
1357
+ };
1358
+ }
1359
+
1360
+ elsif ($extension eq 'jpg' || $extension eq 'jpeg')
1361
+ {
1362
+ read(FH_IMAGEFILE, $raw, 2);
1363
+ my $isOkay = ($raw eq "\xFF\xD8");
1364
+
1365
+ while ($isOkay)
1366
+ {
1367
+ read(FH_IMAGEFILE, $raw, 4);
1368
+ my ($marker, $code, $length) = unpack('CCn', $raw);
1369
+
1370
+ $isOkay = ($marker eq 0xFF);
1371
+
1372
+ if ($isOkay)
1373
+ {
1374
+ if ($code >= 0xC0 && $code <= 0xC3)
1375
+ {
1376
+ read(FH_IMAGEFILE, $raw, 5);
1377
+ ($height, $width) = unpack('xnn', $raw);
1378
+ last;
1379
+ }
1380
+
1381
+ else
1382
+ {
1383
+ $isOkay = seek(FH_IMAGEFILE, $length - 2, 1);
1384
+ };
1385
+ };
1386
+ };
1387
+ };
1388
+
1389
+ close(FH_IMAGEFILE);
1390
+ };
1391
+
1392
+
1393
+ # Sanity check the values. Although images can theoretically be bigger than 5000, most won't. The worst that happens in this
1394
+ # case is just that they don't get length and width values in the output anyway.
1395
+ if ($width > 0 && $width < 5000 && $height > 0 && $height < 5000)
1396
+ { $imageFileObject->SetDimensions($width, $height); }
1397
+ else
1398
+ { $imageFileObject->SetDimensions(undef, undef); };
1399
+ };
1400
+
1401
+
1402
+ 1;