bixbite 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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;