Merge branch 'master' of git://github.com/teeworlds/teeworlds

Conflicts:
	src/game/client/components/menus_ingame.cpp
This commit is contained in:
SushiTee 2012-10-09 13:08:01 +02:00
commit 20cfbfe3a7
181 changed files with 1488 additions and 46220 deletions

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "data/languages"]
path = data/languages
url = git://github.com/teeworlds/teeworlds-translation.git

59
bam.lua
View file

@ -9,6 +9,7 @@ config = NewConfig()
config:Add(OptCCompiler("compiler"))
config:Add(OptTestCompileC("stackprotector", "int main(){return 0;}", "-fstack-protector -fstack-protector-all"))
config:Add(OptTestCompileC("minmacosxsdk", "int main(){return 0;}", "-mmacosx-version-min=10.5 -isysroot /Developer/SDKs/MacOSX10.5.sdk"))
config:Add(OptTestCompileC("macosxppc", "int main(){return 0;}", "-arch ppc"))
config:Add(OptLibrary("zlib", "zlib.h", false))
config:Add(SDL.OptFind("sdl", true))
config:Add(FreeType.OptFind("freetype", true))
@ -363,27 +364,45 @@ if platform == "macosx" then
DefaultTarget("game_debug_x86")
if arch == "ia32" then
PseudoTarget("release", ppc_r, x86_r)
PseudoTarget("debug", ppc_d, x86_d)
PseudoTarget("server_release", "server_release_x86", "server_release_ppc")
PseudoTarget("server_debug", "server_debug_x86", "server_debug_ppc")
PseudoTarget("client_release", "client_release_x86", "client_release_ppc")
PseudoTarget("client_debug", "client_debug_x86", "client_debug_ppc")
elseif arch == "amd64" then
PseudoTarget("release", ppc_r, x86_r, x86_64_r)
PseudoTarget("debug", ppc_d, x86_d, x86_64_d)
PseudoTarget("server_release", "server_release_x86", "server_release_x86_64", "server_release_ppc")
PseudoTarget("server_debug", "server_debug_x86", "server_debug_x86_64", "server_debug_ppc")
PseudoTarget("client_release", "client_release_x86", "client_release_x86_64", "client_release_ppc")
PseudoTarget("client_debug", "client_debug_x86", "client_debug_x86_64", "client_debug_ppc")
if config.macosxppc.value == 1 then
if arch == "ia32" then
PseudoTarget("release", ppc_r, x86_r)
PseudoTarget("debug", ppc_d, x86_d)
PseudoTarget("server_release", "server_release_ppc", "server_release_x86")
PseudoTarget("server_debug", "server_debug_ppc", "server_debug_x86")
PseudoTarget("client_release", "client_release_ppc", "client_release_x86")
PseudoTarget("client_debug", "client_debug_ppc", "client_debug_x86")
elseif arch == "amd64" then
PseudoTarget("release", ppc_r, x86_r, x86_64_r)
PseudoTarget("debug", ppc_d, x86_d, x86_64_d)
PseudoTarget("server_release", "server_release_ppc", "server_release_x86", "server_release_x86_64")
PseudoTarget("server_debug", "server_debug_ppc", "server_debug_x86", "server_debug_x86_64")
PseudoTarget("client_release", "client_release_ppc", "client_release_x86", "client_release_x86_64")
PseudoTarget("client_debug", "client_debug_ppc", "client_debug_x86", "client_debug_x86_64")
else
PseudoTarget("release", ppc_r)
PseudoTarget("debug", ppc_d)
PseudoTarget("server_release", "server_release_ppc")
PseudoTarget("server_debug", "server_debug_ppc")
PseudoTarget("client_release", "client_release_ppc")
PseudoTarget("client_debug", "client_debug_ppc")
end
else
PseudoTarget("release", ppc_r)
PseudoTarget("debug", ppc_d)
PseudoTarget("server_release", "server_release_ppc")
PseudoTarget("server_debug", "server_debug_ppc")
PseudoTarget("client_release", "client_release_ppc")
PseudoTarget("client_debug", "client_debug_ppc")
if arch == "ia32" then
PseudoTarget("release", x86_r)
PseudoTarget("debug", x86_d)
PseudoTarget("server_release", "server_release_x86")
PseudoTarget("server_debug", "server_debug_x86")
PseudoTarget("client_release", "client_release_x86")
PseudoTarget("client_debug", "client_debug_x86")
elseif arch == "amd64" then
PseudoTarget("release", x86_r, x86_64_r)
PseudoTarget("debug", x86_d, x86_64_d)
PseudoTarget("server_release", "server_release_x86", "server_release_x86_64")
PseudoTarget("server_debug", "server_debug_x86", "server_debug_x86_64")
PseudoTarget("client_release", "client_release_x86", "client_release_x86_64")
PseudoTarget("client_debug", "client_debug_x86", "client_debug_x86_64")
end
end
else
build(debug_settings)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 634 B

After

Width:  |  Height:  |  Size: 1.5 KiB

1
data/languages Submodule

@ -0,0 +1 @@
Subproject commit 0ed1dd2ca9c3d3cae9863a3618202872da10d31b

View file

@ -3,10 +3,19 @@ from datatypes import *
Pickups = Enum("PICKUP", ["HEALTH", "ARMOR", "GRENADE", "SHOTGUN", "LASER", "NINJA"])
Emotes = Enum("EMOTE", ["NORMAL", "PAIN", "HAPPY", "SURPRISE", "ANGRY", "BLINK"])
Emoticons = Enum("EMOTICON", ["OOP", "EXCLAMATION", "HEARTS", "DROP", "DOTDOT", "MUSIC", "SORRY", "GHOST", "SUSHI", "SPLATTEE", "DEVILTEE", "ZOMG", "ZZZ", "WTF", "EYES", "QUESTION"])
Votes = Enum("VOTE", ["UNKNOWN", "START_OP", "START_KICK", "START_SPEC", "END_ABORT", "END_PASS", "END_FAIL"])
PlayerFlags = Flags("PLAYERFLAG", ["CHATTING", "SCOREBOARD", "READY", "DEAD", "WATCHING"])
PlayerFlags = Flags("PLAYERFLAG", ["ADMIN", "CHATTING", "SCOREBOARD", "READY", "DEAD", "WATCHING"])
GameFlags = Flags("GAMEFLAG", ["TEAMS", "FLAGS", "SURVIVAL"])
GameStateFlags = Flags("GAMESTATEFLAG", ["WARMUP", "SUDDENDEATH", "ROUNDOVER", "GAMEOVER", "PAUSED", "STARTCOUNTDOWN"])
CoreEventFlags = Flags("COREEVENTFLAG", ["GROUND_JUMP", "AIR_JUMP", "HOOK_ATTACH_PLAYER", "HOOK_ATTACH_GROUND", "HOOK_HIT_NOHOOK"])
GameMsgIDs = Enum("GAMEMSG", ["TEAM_SWAP", "SPEC_INVALIDID", "TEAM_SHUFFLE", "TEAM_BALANCE", "CTF_DROP", "CTF_RETURN",
"TEAM_ALL", "TEAM_BALANCE_VICTIM", "CTF_GRAB",
"CTF_CAPTURE"])
RawHeader = '''
@ -40,13 +49,16 @@ RawSource = '''
Enums = [
Pickups,
Emotes,
Emoticons
Emoticons,
Votes,
GameMsgIDs,
]
Flags = [
PlayerFlags,
GameFlags,
GameStateFlags
GameStateFlags,
CoreEventFlags,
]
Objects = [
@ -146,6 +158,7 @@ Objects = [
NetIntRange("m_Weapon", 0, 'NUM_WEAPONS-1'),
NetEnum("m_Emote", Emotes),
NetTick("m_AttackTick"),
NetFlag("m_TriggeredEvents", CoreEventFlags),
]),
NetObject("PlayerInfo", [
@ -223,10 +236,6 @@ Messages = [
NetString("m_pMessage"),
]),
NetMessage("Sv_Broadcast", [
NetString("m_pMessage"),
]),
NetMessage("Sv_Chat", [
NetIntRange("m_Team", 'TEAM_SPECTATORS', 'TEAM_BLUE'),
NetIntRange("m_ClientID", -1, 'MAX_CLIENTS-1'),
@ -237,6 +246,7 @@ Messages = [
NetIntRange("m_ClientID", -1, 'MAX_CLIENTS-1'),
NetIntRange("m_Team", 'TEAM_SPECTATORS', 'TEAM_BLUE'),
NetBool("m_Silent"),
NetTick("m_CooldownTick"),
]),
NetMessage("Sv_KillMsg", [
@ -246,10 +256,6 @@ Messages = [
NetIntAny("m_ModeSpecial"),
]),
NetMessage("Sv_SoundGlobal", [
NetIntRange("m_SoundID", 0, 'NUM_SOUNDS-1'),
]),
NetMessage("Sv_TuneParams", []),
NetMessage("Sv_ExtraProjectile", []),
NetMessage("Sv_ReadyToEnter", []),
@ -263,17 +269,9 @@ Messages = [
NetEnum("m_Emoticon", Emoticons),
]),
NetMessage("Sv_VoteClearOptions", [
]),
NetMessage("Sv_VoteClearOptions", []),
NetMessage("Sv_VoteOptionListAdd", [
NetIntRange("m_NumOptions", 1, 15),
NetStringStrict("m_pDescription0"), NetStringStrict("m_pDescription1"), NetStringStrict("m_pDescription2"),
NetStringStrict("m_pDescription3"), NetStringStrict("m_pDescription4"), NetStringStrict("m_pDescription5"),
NetStringStrict("m_pDescription6"), NetStringStrict("m_pDescription7"), NetStringStrict("m_pDescription8"),
NetStringStrict("m_pDescription9"), NetStringStrict("m_pDescription10"), NetStringStrict("m_pDescription11"),
NetStringStrict("m_pDescription12"), NetStringStrict("m_pDescription13"), NetStringStrict("m_pDescription14"),
]),
NetMessage("Sv_VoteOptionListAdd", []),
NetMessage("Sv_VoteOptionAdd", [
NetStringStrict("m_pDescription"),
@ -284,6 +282,8 @@ Messages = [
]),
NetMessage("Sv_VoteSet", [
NetIntRange("m_ClientID", -1, 'MAX_CLIENTS-1'),
NetEnum("m_Type", Votes),
NetIntRange("m_Timeout", 0, 60),
NetStringStrict("m_pDescription"),
NetStringStrict("m_pReason"),
@ -296,6 +296,15 @@ Messages = [
NetIntRange("m_Total", 0, 'MAX_CLIENTS'),
]),
NetMessage("Sv_ServerSettings", [
NetBool("m_KickVote"),
NetIntRange("m_KickMin", 0, 'MAX_CLIENTS'),
NetBool("m_SpecVote"),
NetBool("m_TeamLock"),
NetBool("m_TeamBalance"),
NetIntRange("m_PlayerSlots", 0, 'MAX_CLIENTS'),
]),
NetMessage("Sv_ClientInfo", [
NetIntRange("m_ClientID", 0, 'MAX_CLIENTS-1'),
NetBool("m_Local"),
@ -323,6 +332,8 @@ Messages = [
NetStringStrict("m_pReason"),
]),
NetMessage("Sv_GameMsg", []),
## Demo messages
NetMessage("De_ClientEnter", [
NetStringStrict("m_pName"),
@ -373,5 +384,6 @@ Messages = [
NetStringStrict("m_Type"),
NetStringStrict("m_Value"),
NetStringStrict("m_Reason"),
NetBool("m_Force"),
]),
]

Binary file not shown.

Binary file not shown.

View file

@ -1,180 +0,0 @@
1.4
C/C++
/home/kma/code/teeworlds/trunk/src/engine/e_huffman.h 1222170110 1 /home/kma/code/teeworlds/trunk/src/engine/e_huffman.h
/home/kma/code/teeworlds/trunk/src/game/generated/gs_data.hpp 1222683446 0 /home/kma/code/teeworlds/trunk/src/game/generated/gs_data.hpp
/home/kma/code/teeworlds/trunk/src/game/client/ui.hpp 1220136086 0 /home/kma/code/teeworlds/trunk/src/game/client/ui.hpp
/home/kma/code/teeworlds/trunk/src/engine/client/ec_srvbrowse.c 1222683496 0 /home/kma/code/teeworlds/trunk/src/engine/client/ec_srvbrowse.c
/home/kma/code/teeworlds/trunk/src/game/editor/ed_editor.hpp 1220477125 0 /home/kma/code/teeworlds/trunk/src/game/editor/ed_editor.hpp
/home/kma/code/teeworlds/trunk/src/engine/e_compression.c 1218717193 0 /home/kma/code/teeworlds/trunk/src/engine/e_compression.c
/home/kma/code/teeworlds/trunk/src/game/client/components/effects.hpp 1219856603 0 /home/kma/code/teeworlds/trunk/src/game/client/components/effects.hpp
/home/kma/code/teeworlds/trunk/src/game/editor/array.hpp 1213274598 0 /home/kma/code/teeworlds/trunk/src/game/editor/array.hpp
/home/kma/code/teeworlds/trunk/src/engine/e_if_msg.h 1209633421 1 Messaging
/home/kma/code/teeworlds/trunk/src/game/server/gamemodes/dm.cpp 1220222024 0 /home/kma/code/teeworlds/trunk/src/game/server/gamemodes/dm.cpp
/home/kma/code/teeworlds/trunk/src/game/server/gamecontext.cpp 1222365211 0 /home/kma/code/teeworlds/trunk/src/game/server/gamecontext.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/hud.hpp 1222354048 0 /home/kma/code/teeworlds/trunk/src/game/client/components/hud.hpp
/home/kma/code/teeworlds/trunk/src/engine/e_packer.h 1209633421 0 /home/kma/code/teeworlds/trunk/src/engine/e_packer.h
/home/kma/code/teeworlds/trunk/src/game/client/components/items.cpp 1220136174 0 /home/kma/code/teeworlds/trunk/src/game/client/components/items.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/camera.hpp 1219845973 0 /home/kma/code/teeworlds/trunk/src/game/client/components/camera.hpp
/home/kma/code/teeworlds/trunk/src/game/editor/ed_io.cpp 1212341007 0 /home/kma/code/teeworlds/trunk/src/game/editor/ed_io.cpp
/home/kma/code/teeworlds/trunk/src/engine/client/ec_font.h 1209633421 0 /home/kma/code/teeworlds/trunk/src/engine/client/ec_font.h
/home/kma/code/teeworlds/trunk/src/engine/e_msg.c 1212964729 0 /home/kma/code/teeworlds/trunk/src/engine/e_msg.c
/home/kma/code/teeworlds/trunk/src/game/client/components/menus_ingame.cpp 1222692848 0 /home/kma/code/teeworlds/trunk/src/game/client/components/menus_ingame.cpp
/home/kma/code/teeworlds/trunk/src/engine/e_compression.h 1209633421 0 /home/kma/code/teeworlds/trunk/src/engine/e_compression.h
/home/kma/code/teeworlds/trunk/src/game/client/components/flow.cpp 1219782150 0 /home/kma/code/teeworlds/trunk/src/game/client/components/flow.cpp
/home/kma/code/teeworlds/trunk/src/engine/e_engine.h 1220813504 0 /home/kma/code/teeworlds/trunk/src/engine/e_engine.h
/home/kma/code/teeworlds/trunk/src/game/generated/gc_data.cpp 1222683449 0 /home/kma/code/teeworlds/trunk/src/game/generated/gc_data.cpp
/home/kma/code/teeworlds/trunk/src/engine/docs/client_time.txt 1209633420 1 Time on the client
/home/kma/code/teeworlds/trunk/src/game/client/animstate.cpp 1219785741 0 /home/kma/code/teeworlds/trunk/src/game/client/animstate.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/damageind.hpp 1219841173 0 /home/kma/code/teeworlds/trunk/src/game/client/components/damageind.hpp
/home/kma/code/teeworlds/trunk/src/game/server/entities/laser.hpp 1218740976 0 /home/kma/code/teeworlds/trunk/src/game/server/entities/laser.hpp
/home/kma/code/teeworlds/trunk/src/game/client/components/nameplates.hpp 1220569205 0 /home/kma/code/teeworlds/trunk/src/game/client/components/nameplates.hpp
/home/kma/code/teeworlds/trunk/src/game/server/gamemodes/tdm.cpp 1220222010 0 /home/kma/code/teeworlds/trunk/src/game/server/gamemodes/tdm.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/broadcast.hpp 1219841173 0 /home/kma/code/teeworlds/trunk/src/game/client/components/broadcast.hpp
/home/kma/code/teeworlds/trunk/src/engine/e_if_snd.h 1221327616 1 Sound
/home/kma/code/teeworlds/trunk/src/game/client/components/menus.cpp 1222640846 0 /home/kma/code/teeworlds/trunk/src/game/client/components/menus.cpp
/home/kma/code/teeworlds/trunk/src/game/server/gamemodes/ctf.hpp 1219777811 0 /home/kma/code/teeworlds/trunk/src/game/server/gamemodes/ctf.hpp
/home/kma/code/teeworlds/trunk/src/game/generated/gs_data.cpp 1222683446 0 /home/kma/code/teeworlds/trunk/src/game/generated/gs_data.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/motd.hpp 1220137292 0 /home/kma/code/teeworlds/trunk/src/game/client/components/motd.hpp
/home/kma/code/teeworlds/trunk/src/engine/e_if_other.h 1222181143 1 Engine Interface
/home/kma/code/teeworlds/trunk/src/game/editor/ed_layer_game.cpp 1209633421 0 /home/kma/code/teeworlds/trunk/src/game/editor/ed_layer_game.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/mapimages.cpp 1220253155 0 /home/kma/code/teeworlds/trunk/src/game/client/components/mapimages.cpp
/home/kma/code/teeworlds/trunk/src/engine/e_keynames.c 1222353741 0 /home/kma/code/teeworlds/trunk/src/engine/e_keynames.c
/home/kma/code/teeworlds/trunk/src/game/server/gamecontroller.cpp 1222194081 0 /home/kma/code/teeworlds/trunk/src/game/server/gamecontroller.cpp
/home/kma/code/teeworlds/trunk/src/game/client/ui.cpp 1220136096 0 /home/kma/code/teeworlds/trunk/src/game/client/ui.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/nameplates.cpp 1222164899 0 /home/kma/code/teeworlds/trunk/src/game/client/components/nameplates.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/broadcast.cpp 1220135264 0 /home/kma/code/teeworlds/trunk/src/game/client/components/broadcast.cpp
/home/kma/code/teeworlds/trunk/src/engine/e_map.c 1218717325 0 /home/kma/code/teeworlds/trunk/src/engine/e_map.c
/home/kma/code/teeworlds/trunk/src/game/mapitems.hpp 1222183329 0 /home/kma/code/teeworlds/trunk/src/game/mapitems.hpp
/home/kma/code/teeworlds/trunk/src/game/gamecore.cpp 1222186019 0 /home/kma/code/teeworlds/trunk/src/game/gamecore.cpp
/home/kma/code/teeworlds/trunk/src/game/server/hooks.cpp 1222682379 0 /home/kma/code/teeworlds/trunk/src/game/server/hooks.cpp
/home/kma/code/teeworlds/trunk/src/game/layers.hpp 1218967138 0 /home/kma/code/teeworlds/trunk/src/game/layers.hpp
/home/kma/code/teeworlds/trunk/src/game/client/components/killmessages.hpp 1219841185 0 /home/kma/code/teeworlds/trunk/src/game/client/components/killmessages.hpp
/home/kma/code/teeworlds/trunk/src/engine/e_console.c 1222181217 0 /home/kma/code/teeworlds/trunk/src/engine/e_console.c
/home/kma/code/teeworlds/trunk/src/game/client/components/sounds.cpp 1222029308 0 /home/kma/code/teeworlds/trunk/src/game/client/components/sounds.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/emoticon.cpp 1220569076 0 /home/kma/code/teeworlds/trunk/src/game/client/components/emoticon.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/skins.cpp 1219618613 0 /home/kma/code/teeworlds/trunk/src/game/client/components/skins.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/effects.cpp 1220135224 0 /home/kma/code/teeworlds/trunk/src/game/client/components/effects.cpp
/home/kma/code/teeworlds/trunk/src/game/server/player.hpp 1222356463 0 /home/kma/code/teeworlds/trunk/src/game/server/player.hpp
/home/kma/code/teeworlds/trunk/src/game/client/lineinput.hpp 1220087940 0 /home/kma/code/teeworlds/trunk/src/game/client/lineinput.hpp
/home/kma/code/teeworlds/trunk/src/engine/server/es_server.c 1222638818 0 /home/kma/code/teeworlds/trunk/src/engine/server/es_server.c
/home/kma/code/teeworlds/trunk/src/game/server/entities/projectile.hpp 1218741010 0 /home/kma/code/teeworlds/trunk/src/game/server/entities/projectile.hpp
/home/kma/code/teeworlds/trunk/src/game/client/components/debughud.cpp 1220135200 0 /home/kma/code/teeworlds/trunk/src/game/client/components/debughud.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/items.hpp 1219841173 0 /home/kma/code/teeworlds/trunk/src/game/client/components/items.hpp
/home/kma/code/teeworlds/trunk/src/game/server/player.cpp 1222273690 0 /home/kma/code/teeworlds/trunk/src/game/server/player.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/sounds.hpp 1221328048 0 /home/kma/code/teeworlds/trunk/src/game/client/components/sounds.hpp
/home/kma/code/teeworlds/trunk/src/game/client/components/maplist.hpp 1222691020 0 /home/kma/code/teeworlds/trunk/src/game/client/components/maplist.hpp
/home/kma/code/teeworlds/trunk/src/engine/e_snapshot.c 1214463651 0 /home/kma/code/teeworlds/trunk/src/engine/e_snapshot.c
/home/kma/code/teeworlds/trunk/src/game/client/components/binds.hpp 1222354232 0 /home/kma/code/teeworlds/trunk/src/game/client/components/binds.hpp
/home/kma/code/teeworlds/trunk/src/game/server/entities/character.cpp 1222356921 0 /home/kma/code/teeworlds/trunk/src/game/server/entities/character.cpp
/home/kma/code/teeworlds/trunk/src/game/server/entities/laser.cpp 1222190271 0 /home/kma/code/teeworlds/trunk/src/game/server/entities/laser.cpp
/home/kma/code/teeworlds/trunk/src/engine/docs/snapshots.txt 1218450372 1 Snapshots
/home/kma/code/teeworlds/trunk/src/game/generated/gc_data.hpp 1222683447 0 /home/kma/code/teeworlds/trunk/src/game/generated/gc_data.hpp
/home/kma/code/teeworlds/trunk/src/game/generated/nethash.c 1222161195 0 /home/kma/code/teeworlds/trunk/src/game/generated/nethash.c
/home/kma/code/teeworlds/trunk/src/engine/e_ringbuffer.h 1219871251 0 /home/kma/code/teeworlds/trunk/src/engine/e_ringbuffer.h
/home/kma/code/teeworlds/trunk/src/game/client/gameclient.cpp 1222692136 0 /home/kma/code/teeworlds/trunk/src/game/client/gameclient.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/killmessages.cpp 1220198084 0 /home/kma/code/teeworlds/trunk/src/game/client/components/killmessages.cpp
/home/kma/code/teeworlds/trunk/src/game/server/entity.cpp 1218743197 0 /home/kma/code/teeworlds/trunk/src/game/server/entity.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/controls.cpp 1221290669 0 /home/kma/code/teeworlds/trunk/src/game/client/components/controls.cpp
/home/kma/code/teeworlds/trunk/src/engine/e_if_gfx.h 1220477125 1 Graphics
/home/kma/code/teeworlds/trunk/src/game/client/components/motd.cpp 1220135205 0 /home/kma/code/teeworlds/trunk/src/game/client/components/motd.cpp
/home/kma/code/teeworlds/trunk/src/engine/e_protocol.h 1220799767 0 /home/kma/code/teeworlds/trunk/src/engine/e_protocol.h
/home/kma/code/teeworlds/trunk/src/game/client/gameclient.hpp 1222691935 0 /home/kma/code/teeworlds/trunk/src/game/client/gameclient.hpp
/home/kma/code/teeworlds/trunk/src/engine/e_datafile.c 1218717112 0 /home/kma/code/teeworlds/trunk/src/engine/e_datafile.c
/home/kma/code/teeworlds/trunk/src/engine/e_huffman.c 1222170780 0 /home/kma/code/teeworlds/trunk/src/engine/e_huffman.c
/home/kma/code/teeworlds/trunk/src/engine/docs/server_op.txt 1218450372 1 Server Operation
/home/kma/code/teeworlds/trunk/src/game/editor/ed_editor.cpp 1222182161 0 /home/kma/code/teeworlds/trunk/src/game/editor/ed_editor.cpp
/home/kma/code/teeworlds/trunk/src/game/client/gc_render.cpp 1220295093 0 /home/kma/code/teeworlds/trunk/src/game/client/gc_render.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/maplayers.hpp 1219841173 0 /home/kma/code/teeworlds/trunk/src/game/client/components/maplayers.hpp
/home/kma/code/teeworlds/trunk/src/engine/e_if_client.h 1222031069 1 Client Interface
/home/kma/code/teeworlds/trunk/src/engine/e_keys.h 1222353741 0 /home/kma/code/teeworlds/trunk/src/engine/e_keys.h
/home/kma/code/teeworlds/trunk/src/game/client/components/console.hpp 1220569113 0 /home/kma/code/teeworlds/trunk/src/game/client/components/console.hpp
/home/kma/code/teeworlds/trunk/src/engine/e_engine.c 1220822064 0 /home/kma/code/teeworlds/trunk/src/engine/e_engine.c
/home/kma/code/teeworlds/trunk/src/engine/e_if_modc.h 1209633421 1 Client Hooks
/home/kma/code/teeworlds/trunk/src/game/client/components/particles.cpp 1220138535 0 /home/kma/code/teeworlds/trunk/src/game/client/components/particles.cpp
/home/kma/code/teeworlds/trunk/src/engine/e_ringbuffer.c 1218717337 0 /home/kma/code/teeworlds/trunk/src/engine/e_ringbuffer.c
/home/kma/code/teeworlds/trunk/src/game/server/gamemodes/dm.hpp 1220222050 0 /home/kma/code/teeworlds/trunk/src/game/server/gamemodes/dm.hpp
/home/kma/code/teeworlds/trunk/src/engine/e_server_interface.h 1209633421 0 /home/kma/code/teeworlds/trunk/src/engine/e_server_interface.h
/home/kma/code/teeworlds/trunk/src/game/client/components/binds.cpp 1222354494 0 /home/kma/code/teeworlds/trunk/src/game/client/components/binds.cpp
/home/kma/code/teeworlds/trunk/src/engine/e_packer.c 1218717159 0 /home/kma/code/teeworlds/trunk/src/engine/e_packer.c
/home/kma/code/teeworlds/trunk/src/game/client/components/particles.hpp 1219845940 0 /home/kma/code/teeworlds/trunk/src/game/client/components/particles.hpp
/home/kma/code/teeworlds/trunk/src/engine/e_config.h 1209633421 0 /home/kma/code/teeworlds/trunk/src/engine/e_config.h
/home/kma/code/teeworlds/trunk/src/game/tuning.hpp 1218966967 0 /home/kma/code/teeworlds/trunk/src/game/tuning.hpp
/home/kma/code/teeworlds/trunk/src/game/server/gamecontext.hpp 1222356971 0 /home/kma/code/teeworlds/trunk/src/game/server/gamecontext.hpp
/home/kma/code/teeworlds/trunk/src/game/client/components/players.cpp 1222347355 0 /home/kma/code/teeworlds/trunk/src/game/client/components/players.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/controls.hpp 1221290643 0 /home/kma/code/teeworlds/trunk/src/game/client/components/controls.hpp
/home/kma/code/teeworlds/trunk/src/engine/e_jobs.h 1220813546 0 /home/kma/code/teeworlds/trunk/src/engine/e_jobs.h
/home/kma/code/teeworlds/trunk/src/engine/e_memheap.c 1218717128 0 /home/kma/code/teeworlds/trunk/src/engine/e_memheap.c
/home/kma/code/teeworlds/trunk/src/game/client/lineinput.cpp 1219040530 0 /home/kma/code/teeworlds/trunk/src/game/client/lineinput.cpp
/home/kma/code/teeworlds/trunk/src/game/generated/createdir.txt 1209633421 0 /home/kma/code/teeworlds/trunk/src/game/generated/createdir.txt
/home/kma/code/teeworlds/trunk/src/game/client/components/maplist.cpp 1222692119 0 /home/kma/code/teeworlds/trunk/src/game/client/components/maplist.cpp
/home/kma/code/teeworlds/trunk/src/game/version.hpp 1218966879 0 /home/kma/code/teeworlds/trunk/src/game/version.hpp
/home/kma/code/teeworlds/trunk/src/game/collision.hpp 1222185632 0 /home/kma/code/teeworlds/trunk/src/game/collision.hpp
/home/kma/code/teeworlds/trunk/src/engine/client/ec_client.c 1222683366 0 /home/kma/code/teeworlds/trunk/src/engine/client/ec_client.c
/home/kma/code/teeworlds/trunk/src/game/generated/g_protocol.cpp 1222683446 0 /home/kma/code/teeworlds/trunk/src/game/generated/g_protocol.cpp
/home/kma/code/teeworlds/trunk/src/engine/e_datafile.h 1209633421 0 /home/kma/code/teeworlds/trunk/src/engine/e_datafile.h
/home/kma/code/teeworlds/trunk/src/engine/e_linereader.h 1218717511 0 /home/kma/code/teeworlds/trunk/src/engine/e_linereader.h
/home/kma/code/teeworlds/trunk/src/game/server/entities/pickup.cpp 1220570254 0 /home/kma/code/teeworlds/trunk/src/game/server/entities/pickup.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/maplayers.cpp 1220253273 0 /home/kma/code/teeworlds/trunk/src/game/client/components/maplayers.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/hud.cpp 1222355982 0 /home/kma/code/teeworlds/trunk/src/game/client/components/hud.cpp
/home/kma/code/teeworlds/trunk/src/game/server/gamemodes/tdm.hpp 1218741462 0 /home/kma/code/teeworlds/trunk/src/game/server/gamemodes/tdm.hpp
/home/kma/code/teeworlds/trunk/src/game/client/components/menus_browser.cpp 1222640967 0 /home/kma/code/teeworlds/trunk/src/game/client/components/menus_browser.cpp
/home/kma/code/teeworlds/trunk/src/game/collision.cpp 1222185936 0 /home/kma/code/teeworlds/trunk/src/game/collision.cpp
/home/kma/code/teeworlds/trunk/src/engine/e_snapshot.h 1218717534 0 /home/kma/code/teeworlds/trunk/src/engine/e_snapshot.h
/home/kma/code/teeworlds/trunk/src/engine/e_client_interface.h 1220135564 0 /home/kma/code/teeworlds/trunk/src/engine/e_client_interface.h
/home/kma/code/teeworlds/trunk/src/game/editor/ed_layer_tiles.cpp 1220827108 0 /home/kma/code/teeworlds/trunk/src/game/editor/ed_layer_tiles.cpp
/home/kma/code/teeworlds/trunk/src/engine/e_network.h 1220214060 0 /home/kma/code/teeworlds/trunk/src/engine/e_network.h
/home/kma/code/teeworlds/trunk/src/game/client/components/emoticon.hpp 1220569077 0 /home/kma/code/teeworlds/trunk/src/game/client/components/emoticon.hpp
/home/kma/code/teeworlds/trunk/src/engine/e_config.c 1222181231 0 /home/kma/code/teeworlds/trunk/src/engine/e_config.c
/home/kma/code/teeworlds/trunk/src/game/client/components/menus.hpp 1222681494 0 /home/kma/code/teeworlds/trunk/src/game/client/components/menus.hpp
/home/kma/code/teeworlds/trunk/src/game/server/gamemodes/ctf.cpp 1222190258 0 /home/kma/code/teeworlds/trunk/src/game/server/gamemodes/ctf.cpp
/home/kma/code/teeworlds/trunk/src/engine/e_config_variables.h 1222181173 0 /home/kma/code/teeworlds/trunk/src/engine/e_config_variables.h
/home/kma/code/teeworlds/trunk/src/engine/docs/prediction.txt 1209633420 1 Prediction
/home/kma/code/teeworlds/trunk/src/game/client/components/voting.hpp 1222692628 0 /home/kma/code/teeworlds/trunk/src/game/client/components/voting.hpp
/home/kma/code/teeworlds/trunk/src/game/client/components/camera.cpp 1221209283 0 /home/kma/code/teeworlds/trunk/src/game/client/components/camera.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/damageind.cpp 1220136328 0 /home/kma/code/teeworlds/trunk/src/game/client/components/damageind.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/chat.hpp 1220569130 0 /home/kma/code/teeworlds/trunk/src/game/client/components/chat.hpp
/home/kma/code/teeworlds/trunk/src/game/editor/ed_popups.cpp 1209633421 0 /home/kma/code/teeworlds/trunk/src/game/editor/ed_popups.cpp
/home/kma/code/teeworlds/trunk/src/engine/client/ec_font.c 1218724640 0 /home/kma/code/teeworlds/trunk/src/engine/client/ec_font.c
/home/kma/code/teeworlds/trunk/src/game/client/component.hpp 1220568968 0 /home/kma/code/teeworlds/trunk/src/game/client/component.hpp
/home/kma/code/teeworlds/trunk/src/game/client/components/voting.cpp 1222692648 0 /home/kma/code/teeworlds/trunk/src/game/client/components/voting.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/debughud.hpp 1219855509 0 /home/kma/code/teeworlds/trunk/src/game/client/components/debughud.hpp
/home/kma/code/teeworlds/trunk/src/game/client/components/skins.hpp 1219841173 0 /home/kma/code/teeworlds/trunk/src/game/client/components/skins.hpp
/home/kma/code/teeworlds/trunk/src/game/client/components/scoreboard.hpp 1220569089 0 /home/kma/code/teeworlds/trunk/src/game/client/components/scoreboard.hpp
/home/kma/code/teeworlds/trunk/src/engine/e_common_interface.h 1209633421 0 /home/kma/code/teeworlds/trunk/src/engine/e_common_interface.h
/home/kma/code/teeworlds/trunk/src/engine/e_if_mods.h 1209633421 1 Server Hooks
/home/kma/code/teeworlds/trunk/src/game/client/components/scoreboard.cpp 1220827108 0 /home/kma/code/teeworlds/trunk/src/game/client/components/scoreboard.cpp
/home/kma/code/teeworlds/trunk/src/game/server/gameworld.cpp 1220827108 0 /home/kma/code/teeworlds/trunk/src/game/server/gameworld.cpp
/home/kma/code/teeworlds/trunk/src/game/server/eventhandler.cpp 1222190459 0 /home/kma/code/teeworlds/trunk/src/game/server/eventhandler.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/chat.cpp 1220827108 0 /home/kma/code/teeworlds/trunk/src/game/client/components/chat.cpp
/home/kma/code/teeworlds/trunk/src/game/client/gc_render_map.cpp 1220135308 0 /home/kma/code/teeworlds/trunk/src/game/client/gc_render_map.cpp
/home/kma/code/teeworlds/trunk/src/game/server/gameworld.hpp 1218967107 1 Game World
/home/kma/code/teeworlds/trunk/src/game/gamecore.hpp 1222185988 0 /home/kma/code/teeworlds/trunk/src/game/gamecore.hpp
/home/kma/code/teeworlds/trunk/src/engine/client/ec_inp.c 1218724618 0 /home/kma/code/teeworlds/trunk/src/engine/client/ec_inp.c
/home/kma/code/teeworlds/trunk/src/engine/client/ec_snd.c 1222029620 0 /home/kma/code/teeworlds/trunk/src/engine/client/ec_snd.c
/home/kma/code/teeworlds/trunk/src/engine/e_if_inp.h 1209633421 1 Input
/home/kma/code/teeworlds/trunk/src/engine/e_jobs.c 1220818102 0 /home/kma/code/teeworlds/trunk/src/engine/e_jobs.c
/home/kma/code/teeworlds/trunk/src/game/client/components/menus_settings.cpp 1222353486 0 /home/kma/code/teeworlds/trunk/src/game/client/components/menus_settings.cpp
/home/kma/code/teeworlds/trunk/src/engine/client/ec_gfx.c 1220477125 0 /home/kma/code/teeworlds/trunk/src/engine/client/ec_gfx.c
/home/kma/code/teeworlds/trunk/src/game/server/entities/character.hpp 1222203546 0 /home/kma/code/teeworlds/trunk/src/game/server/entities/character.hpp
/home/kma/code/teeworlds/trunk/src/game/server/eventhandler.hpp 1218742466 0 /home/kma/code/teeworlds/trunk/src/game/server/eventhandler.hpp
/home/kma/code/teeworlds/trunk/src/game/client/clienthooks.cpp 1220568950 0 /home/kma/code/teeworlds/trunk/src/game/client/clienthooks.cpp
/home/kma/code/teeworlds/trunk/src/game/client/components/console.cpp 1220569111 0 /home/kma/code/teeworlds/trunk/src/game/client/components/console.cpp
/home/kma/code/teeworlds/trunk/src/game/variables.hpp 1222682334 0 /home/kma/code/teeworlds/trunk/src/game/variables.hpp
/home/kma/code/teeworlds/trunk/src/engine/e_linereader.c 1209633421 0 /home/kma/code/teeworlds/trunk/src/engine/e_linereader.c
/home/kma/code/teeworlds/trunk/src/engine/e_memheap.h 1209633421 0 /home/kma/code/teeworlds/trunk/src/engine/e_memheap.h
/home/kma/code/teeworlds/trunk/src/engine/e_console.h 1219858821 0 /home/kma/code/teeworlds/trunk/src/engine/e_console.h
/home/kma/code/teeworlds/trunk/src/engine/e_network.c 1222251355 0 /home/kma/code/teeworlds/trunk/src/engine/e_network.c
/home/kma/code/teeworlds/trunk/src/game/server/gamecontroller.hpp 1220827108 1 Game Controller
/home/kma/code/teeworlds/trunk/src/game/layers.cpp 1218967120 0 /home/kma/code/teeworlds/trunk/src/game/layers.cpp
/home/kma/code/teeworlds/trunk/src/engine/e_if_server.h 1220195032 1 Server Interface
/home/kma/code/teeworlds/trunk/src/game/client/animstate.hpp 1219785206 0 /home/kma/code/teeworlds/trunk/src/game/client/animstate.hpp
/home/kma/code/teeworlds/trunk/src/game/server/entities/projectile.cpp 1222190276 0 /home/kma/code/teeworlds/trunk/src/game/server/entities/projectile.cpp
/home/kma/code/teeworlds/trunk/src/game/editor/ed_layer_quads.cpp 1218738227 0 /home/kma/code/teeworlds/trunk/src/game/editor/ed_layer_quads.cpp
/home/kma/code/teeworlds/trunk/src/game/server/entities/pickup.hpp 1218740990 0 /home/kma/code/teeworlds/trunk/src/game/server/entities/pickup.hpp
/home/kma/code/teeworlds/trunk/src/game/server/entity.hpp 1222252624 1 Entity
/home/kma/code/teeworlds/trunk/src/game/generated/g_protocol.hpp 1222683446 0 /home/kma/code/teeworlds/trunk/src/game/generated/g_protocol.hpp
/home/kma/code/teeworlds/trunk/src/game/client/gc_render.hpp 1222182049 0 /home/kma/code/teeworlds/trunk/src/game/client/gc_render.hpp
/home/kma/code/teeworlds/trunk/src/engine/server/es_register.c 1218717909 0 /home/kma/code/teeworlds/trunk/src/engine/server/es_register.c
/home/kma/code/teeworlds/trunk/src/game/client/components/flow.hpp 1219841173 0 /home/kma/code/teeworlds/trunk/src/game/client/components/flow.hpp
/home/kma/code/teeworlds/trunk/src/game/client/components/mapimages.hpp 1220253106 0 /home/kma/code/teeworlds/trunk/src/game/client/components/mapimages.hpp
/home/kma/code/teeworlds/trunk/src/game/client/components/players.hpp 1219841173 0 /home/kma/code/teeworlds/trunk/src/game/client/components/players.hpp

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,113 +0,0 @@
Format: 1.4
# This is the Natural Docs languages file for this project. If you change
# anything here, it will apply to THIS PROJECT ONLY. If you'd like to change
# something for all your projects, edit the Languages.txt in Natural Docs'
# Config directory instead.
# You can prevent certain file extensions from being scanned like this:
# Ignore Extensions: [extension] [extension] ...
#-------------------------------------------------------------------------------
# SYNTAX:
#
# Unlike other Natural Docs configuration files, in this file all comments
# MUST be alone on a line. Some languages deal with the # character, so you
# cannot put comments on the same line as content.
#
# Also, all lists are separated with spaces, not commas, again because some
# languages may need to use them.
#
# Language: [name]
# Alter Language: [name]
# Defines a new language or alters an existing one. Its name can use any
# characters. If any of the properties below have an add/replace form, you
# must use that when using Alter Language.
#
# The language Shebang Script is special. It's entry is only used for
# extensions, and files with those extensions have their shebang (#!) lines
# read to determine the real language of the file. Extensionless files are
# always treated this way.
#
# The language Text File is also special. It's treated as one big comment
# so you can put Natural Docs content in them without special symbols. Also,
# if you don't specify a package separator, ignored prefixes, or enum value
# behavior, it will copy those settings from the language that is used most
# in the source tree.
#
# Extensions: [extension] [extension] ...
# [Add/Replace] Extensions: [extension] [extension] ...
# Defines the file extensions of the language's source files. You can
# redefine extensions found in the main languages file. You can use * to
# mean any undefined extension.
#
# Shebang Strings: [string] [string] ...
# [Add/Replace] Shebang Strings: [string] [string] ...
# Defines a list of strings that can appear in the shebang (#!) line to
# designate that it's part of the language. You can redefine strings found
# in the main languages file.
#
# Ignore Prefixes in Index: [prefix] [prefix] ...
# [Add/Replace] Ignored Prefixes in Index: [prefix] [prefix] ...
#
# Ignore [Topic Type] Prefixes in Index: [prefix] [prefix] ...
# [Add/Replace] Ignored [Topic Type] Prefixes in Index: [prefix] [prefix] ...
# Specifies prefixes that should be ignored when sorting symbols in an
# index. Can be specified in general or for a specific topic type.
#
#------------------------------------------------------------------------------
# For basic language support only:
#
# Line Comments: [symbol] [symbol] ...
# Defines a space-separated list of symbols that are used for line comments,
# if any.
#
# Block Comments: [opening sym] [closing sym] [opening sym] [closing sym] ...
# Defines a space-separated list of symbol pairs that are used for block
# comments, if any.
#
# Package Separator: [symbol]
# Defines the default package separator symbol. The default is a dot.
#
# [Topic Type] Prototype Enders: [symbol] [symbol] ...
# When defined, Natural Docs will attempt to get a prototype from the code
# immediately following the topic type. It stops when it reaches one of
# these symbols. Use \n for line breaks.
#
# Line Extender: [symbol]
# Defines the symbol that allows a prototype to span multiple lines if
# normally a line break would end it.
#
# Enum Values: [global|under type|under parent]
# Defines how enum values are referenced. The default is global.
# global - Values are always global, referenced as 'value'.
# under type - Values are under the enum type, referenced as
# 'package.enum.value'.
# under parent - Values are under the enum's parent, referenced as
# 'package.value'.
#
# Perl Package: [perl package]
# Specifies the Perl package used to fine-tune the language behavior in ways
# too complex to do in this file.
#
#------------------------------------------------------------------------------
# For full language support only:
#
# Full Language Support: [perl package]
# Specifies the Perl package that has the parsing routines necessary for full
# language support.
#
#-------------------------------------------------------------------------------
# The following languages are defined in the main file, if you'd like to alter
# them:
#
# Text File, Shebang Script, C/C++, C#, Java, JavaScript, Perl, Python,
# PHP, SQL, Visual Basic, Pascal, Assembly, Ada, Tcl, Ruby, Makefile,
# ActionScript, ColdFusion, R, Fortran
# If you add a language that you think would be useful to other developers
# and should be included in Natural Docs by default, please e-mail it to
# languages [at] naturaldocs [dot] org.

View file

@ -1,113 +0,0 @@
Format: 1.4
# You can add a title and sub-title to your menu like this:
# Title: [project name]
# SubTitle: [subtitle]
# You can add a footer to your documentation like this:
# Footer: [text]
# If you want to add a copyright notice, this would be the place to do it.
# You can add a timestamp to your documentation like one of these:
# Timestamp: Generated on month day, year
# Timestamp: Updated mm/dd/yyyy
# Timestamp: Last updated mon day
#
# m - One or two digit month. January is "1"
# mm - Always two digit month. January is "01"
# mon - Short month word. January is "Jan"
# month - Long month word. January is "January"
# d - One or two digit day. 1 is "1"
# dd - Always two digit day. 1 is "01"
# day - Day with letter extension. 1 is "1st"
# yy - Two digit year. 2006 is "06"
# yyyy - Four digit year. 2006 is "2006"
# year - Four digit year. 2006 is "2006"
# --------------------------------------------------------------------------
#
# Cut and paste the lines below to change the order in which your files
# appear on the menu. Don't worry about adding or removing files, Natural
# Docs will take care of that.
#
# You can further organize the menu by grouping the entries. Add a
# "Group: [name] {" line to start a group, and add a "}" to end it.
#
# You can add text and web links to the menu by adding "Text: [text]" and
# "Link: [name] ([URL])" lines, respectively.
#
# The formatting and comments are auto-generated, so don't worry about
# neatness when editing the file. Natural Docs will clean it up the next
# time it is run. When working with groups, just deal with the braces and
# forget about the indentation and comments.
#
# You can use this file on other computers even if they use different
# directories. As long as the command line points to the same source files,
# Natural Docs will be able to correct the locations automatically.
#
# --------------------------------------------------------------------------
Group: Engine {
File: Messaging (/home/kma/code/teeworlds/trunk/src/engine/e_if_msg.h)
Group: Client {
Group: Overview {
File: Time on the client (/home/kma/code/teeworlds/trunk/src/engine/docs/client_time.txt)
File: Prediction (/home/kma/code/teeworlds/trunk/src/engine/docs/prediction.txt)
File: Snapshots (/home/kma/code/teeworlds/trunk/src/engine/docs/snapshots.txt)
File: Server Operation (/home/kma/code/teeworlds/trunk/src/engine/docs/server_op.txt)
} # Group: Overview
Group: Reference {
File: Client Hooks (/home/kma/code/teeworlds/trunk/src/engine/e_if_modc.h)
File: Client Interface (/home/kma/code/teeworlds/trunk/src/engine/e_if_client.h)
File: e_huffman.h (/home/kma/code/teeworlds/trunk/src/engine/e_huffman.h)
File: Engine Interface (/home/kma/code/teeworlds/trunk/src/engine/e_if_other.h)
File: Graphics (/home/kma/code/teeworlds/trunk/src/engine/e_if_gfx.h)
File: Input (/home/kma/code/teeworlds/trunk/src/engine/e_if_inp.h)
File: Sound (/home/kma/code/teeworlds/trunk/src/engine/e_if_snd.h)
} # Group: Reference
} # Group: Client
Group: Server {
Group: Reference {
File: Server Hooks (/home/kma/code/teeworlds/trunk/src/engine/e_if_mods.h)
File: Server Interface (/home/kma/code/teeworlds/trunk/src/engine/e_if_server.h)
} # Group: Reference
} # Group: Server
} # Group: Engine
Group: Game {
File: Entity (/home/kma/code/teeworlds/trunk/src/game/server/entity.hpp)
File: Game Controller (/home/kma/code/teeworlds/trunk/src/game/server/gamecontroller.hpp)
File: Game World (/home/kma/code/teeworlds/trunk/src/game/server/gameworld.hpp)
} # Group: Game
Group: Index {
Index: Everything
Class Index: Classes
Constant Index: Constants
Function Index: Functions
Variable Index: Variables
File Index: Files
} # Group: Index
##### Do not change or remove these lines. #####
Data: 1(D3333RuEG3AEp39ufG3tGG7uHof63tHN\A36H93`pEG)
Data: 1(h3333RuEG3AEp39ufG3tGG7uHof63tHN\A36H93G\`8\G)

View file

@ -1,81 +0,0 @@
Format: 1.4
# This is the Natural Docs topics file for this project. If you change anything
# here, it will apply to THIS PROJECT ONLY. If you'd like to change something
# for all your projects, edit the Topics.txt in Natural Docs' Config directory
# instead.
# If you'd like to prevent keywords from being recognized by Natural Docs, you
# can do it like this:
# Ignore Keywords: [keyword], [keyword], ...
#
# Or you can use the list syntax like how they are defined:
# Ignore Keywords:
# [keyword]
# [keyword], [plural keyword]
# ...
#-------------------------------------------------------------------------------
# SYNTAX:
#
# Topic Type: [name]
# Alter Topic Type: [name]
# Creates a new topic type or alters one from the main file. Each type gets
# its own index and behavior settings. Its name can have letters, numbers,
# spaces, and these charaters: - / . '
#
# Plural: [name]
# Sets the plural name of the topic type, if different.
#
# Keywords:
# [keyword]
# [keyword], [plural keyword]
# ...
# Defines or adds to the list of keywords for the topic type. They may only
# contain letters, numbers, and spaces and are not case sensitive. Plural
# keywords are used for list topics. You can redefine keywords found in the
# main topics file.
#
# Index: [yes|no]
# Whether the topics get their own index. Defaults to yes. Everything is
# included in the general index regardless of this setting.
#
# Scope: [normal|start|end|always global]
# How the topics affects scope. Defaults to normal.
# normal - Topics stay within the current scope.
# start - Topics start a new scope for all the topics beneath it,
# like class topics.
# end - Topics reset the scope back to global for all the topics
# beneath it.
# always global - Topics are defined as global, but do not change the scope
# for any other topics.
#
# Class Hierarchy: [yes|no]
# Whether the topics are part of the class hierarchy. Defaults to no.
#
# Page Title If First: [yes|no]
# Whether the topic's title becomes the page title if it's the first one in
# a file. Defaults to no.
#
# Break Lists: [yes|no]
# Whether list topics should be broken into individual topics in the output.
# Defaults to no.
#
# Can Group With: [type], [type], ...
# Defines a list of topic types that this one can possibly be grouped with.
# Defaults to none.
#-------------------------------------------------------------------------------
# The following topics are defined in the main file, if you'd like to alter
# their behavior or add keywords:
#
# Generic, Class, Interface, Section, File, Group, Function, Variable,
# Property, Type, Constant, Enumeration, Event, Delegate, Macro,
# Database, Database Table, Database View, Database Index, Database
# Cursor, Database Trigger, Cookie, Build Target
# If you add something that you think would be useful to other developers
# and should be included in Natural Docs by default, please e-mail it to
# topics [at] naturaldocs [dot] org.

View file

@ -1,286 +0,0 @@
Format: 1.4
# This is the main Natural Docs languages file. If you change anything here,
# it will apply to EVERY PROJECT you use Natural Docs on. If you'd like to
# change something for just one project, edit the Languages.txt in its project
# directory instead.
#-------------------------------------------------------------------------------
# SYNTAX:
#
# Unlike other Natural Docs configuration files, in this file all comments
# MUST be alone on a line. Some languages deal with the # character, so you
# cannot put comments on the same line as content.
#
# Also, all lists are separated with spaces, not commas, again because some
# languages may need to use them.
#
# Language: [name]
# Defines a new language. Its name can use any characters.
#
# The language Shebang Script is special. It's entry is only used for
# extensions, and files with those extensions have their shebang (#!) lines
# read to determine the real language of the file. Extensionless files are
# always treated this way.
#
# The language Text File is also special. It's treated as one big comment
# so you can put Natural Docs content in them without special symbols. Also,
# if you don't specify a package separator, ignored prefixes, or enum value
# behavior, it will copy those settings from the language that is used most
# in the source tree.
#
# Extensions: [extension] [extension] ...
# Defines the file extensions of the language's source files. You can use *
# to mean any undefined extension.
#
# Shebang Strings: [string] [string] ...
# Defines a list of strings that can appear in the shebang (#!) line to
# designate that it's part of the language.
#
# Ignore Prefixes in Index: [prefix] [prefix] ...
# Ignore [Topic Type] Prefixes in Index: [prefix] [prefix] ...
# Specifies prefixes that should be ignored when sorting symbols in an
# index. Can be specified in general or for a specific topic type.
#
#------------------------------------------------------------------------------
# For basic language support only:
#
# Line Comments: [symbol] [symbol] ...
# Defines a space-separated list of symbols that are used for line comments,
# if any.
#
# Block Comments: [opening sym] [closing sym] [opening sym] [closing sym] ...
# Defines a space-separated list of symbol pairs that are used for block
# comments, if any.
#
# Package Separator: [symbol]
# Defines the default package separator symbol. The default is a dot.
#
# [Topic Type] Prototype Enders: [symbol] [symbol] ...
# When defined, Natural Docs will attempt to get a prototype from the code
# immediately following the topic type. It stops when it reaches one of
# these symbols. Use \n for line breaks.
#
# Line Extender: [symbol]
# Defines the symbol that allows a prototype to span multiple lines if
# normally a line break would end it.
#
# Enum Values: [global|under type|under parent]
# Defines how enum values are referenced. The default is global.
# global - Values are always global, referenced as 'value'.
# under type - Values are under the enum type, referenced as
# 'package.enum.value'.
# under parent - Values are under the enum's parent, referenced as
# 'package.value'.
#
# Perl Package: [perl package]
# Specifies the Perl package used to fine-tune the language behavior in ways
# too complex to do in this file.
#
#------------------------------------------------------------------------------
# For full language support only:
#
# Full Language Support: [perl package]
# Specifies the Perl package that has the parsing routines necessary for full
# language support.
#
#-------------------------------------------------------------------------------
# The following languages MUST be defined in this file:
#
# Text File, Shebang Script
# If you add a language that you think would be useful to other developers
# and should be included in Natural Docs by default, please e-mail it to
# languages [at] naturaldocs [dot] org.
Language: Text File
Extension: txt
Language: Shebang Script
Extension: cgi
Language: C/C++
Extensions: c cpp h hpp cxx hxx
Ignore Function Prefix in Index: ~
Line Comment: //
Block Comment: /* */
Package Separator: ::
Enum Values: Under parent
Class Prototype Enders: ; {
Function Prototype Enders: ; {
Variable Prototype Enders: ; =
Language: C#
Extension: cs
Ignore Prefix in Index: @
Full Language Support: NaturalDocs::Languages::CSharp
Language: Java
Extension: java
Line Comment: //
Block Comment: /* */
Enum Values: Under type
Function Prototype Ender: {
Variable Prototype Enders: ; =
Language: JavaScript
Extension: js
Line Comment: //
Block Comment: /* */
Enum Values: Under type
Function Prototype Ender: {
Variable Prototype Enders: ; =
Language: Perl
Extensions: pl pm
Shebang String: perl
Ignore Variable Prefixes in Index: $ @ % *
Full Language Support: NaturalDocs::Languages::Perl
Language: Python
Extension: py
Shebang String: python
Line Comment: #
Function Prototype Ender: :
Variable Prototype Ender: =
Line Extender: \
Language: PHP
Extensions: inc php php3 php4 phtml
Shebang String: php
Ignore Variable Prefix in Index: $
Line Comments: // #
Block Comment: /* */
Function Prototype Enders: ; {
Variable Prototype Enders: ; =
Language: SQL
Extension: sql
Line Comment: --
Block Comment: /* */
Enum Values: Global
Function Prototype Enders: , ; ) as As AS is Is IS
Variable Prototype Enders: , ; ) := default Default DEFAULT
Database Index Prototype Enders: , ; )
Database Trigger Prototype Enders: begin Begin BEGIN as As AS
Perl Package: NaturalDocs::Languages::PLSQL
Language: Visual Basic
Extensions: vb vbs bas cls frm
Line Comment: '
Enum Values: Under type
Function Prototype Ender: \n
Variable Prototype Enders: \n =
Line Extender: _
Language: Pascal
Extension: pas
Line Comment: //
Block Comments: { } (* *)
Function Prototype Ender: ;
Variable Prototype Enders: ; =
Perl Package: NaturalDocs::Languages::Pascal
Language: Assembly
Extension: asm
Line Comment: ;
Variable Prototype Ender: \n
Line Extender: \
Language: Ada
Extensions: ada ads adb
Line Comment: --
Function Prototype Enders: ; is Is IS
Variable Prototype Enders: ; :=
Perl Package: NaturalDocs::Languages::Ada
Language: Tcl
Extensions: tcl exp
Shebang Strings: tclsh wish expect
Line Comment: #
Package Separator: ::
Function Prototype Enders: ; {
Variable Prototype Enders: ; \n
Line Extender: \
Perl Package: NaturalDocs::Languages::Tcl
Language: Ruby
Extension: rb
Shebang String: ruby
Ignore Variable Prefixes in Index: $ @ @@
Line Comment: #
Enum Values: Under parent
Function Prototype Enders: ; \n
Variable Prototype Enders: ; \n =
Line Extender: \
Language: Makefile
Extensions: mk mak make
Line Comment: #
Language: ActionScript
Extensions: as mxml
Full Language Support: NaturalDocs::Languages::ActionScript
Language: ColdFusion
Extensions: cfm cfml cfc
Line Comment: //
Block Comments: <!--- ---> /* */
Function Prototype Enders: { <
Language: R
Extension: r
Line Comment: #
Function Prototype Enders: { ;
Variable Prototype Enders: <- = ; \n
Language: Fortran
Extensions: f90 f95 f03
Line Comment: !
Function Prototype Ender: \n
Variable Prototype Enders: \n = =>
Line Extender: &

View file

@ -1,382 +0,0 @@
Format: 1.4
# This is the main Natural Docs topics file. If you change anything here, it
# will apply to EVERY PROJECT you use Natural Docs on. If you'd like to
# change something for just one project, edit the Topics.txt in its project
# directory instead.
#-------------------------------------------------------------------------------
# SYNTAX:
#
# Topic Type: [name]
# Creates a new topic type. Each type gets its own index and behavior
# settings. Its name can have letters, numbers, spaces, and these
# charaters: - / . '
#
# The Enumeration type is special. It's indexed with Types but its members
# are indexed with Constants according to the rules in Languages.txt.
#
# Plural: [name]
# Sets the plural name of the topic type, if different.
#
# Keywords:
# [keyword]
# [keyword], [plural keyword]
# ...
# Defines a list of keywords for the topic type. They may only contain
# letters, numbers, and spaces and are not case sensitive. Plural keywords
# are used for list topics.
#
# Index: [yes|no]
# Whether the topics get their own index. Defaults to yes. Everything is
# included in the general index regardless of this setting.
#
# Scope: [normal|start|end|always global]
# How the topics affects scope. Defaults to normal.
# normal - Topics stay within the current scope.
# start - Topics start a new scope for all the topics beneath it,
# like class topics.
# end - Topics reset the scope back to global for all the topics
# beneath it.
# always global - Topics are defined as global, but do not change the scope
# for any other topics.
#
# Class Hierarchy: [yes|no]
# Whether the topics are part of the class hierarchy. Defaults to no.
#
# Page Title If First: [yes|no]
# Whether the topic's title becomes the page title if it's the first one in
# a file. Defaults to no.
#
# Break Lists: [yes|no]
# Whether list topics should be broken into individual topics in the output.
# Defaults to no.
#
# Can Group With: [type], [type], ...
# Defines a list of topic types that this one can possibly be grouped with.
# Defaults to none.
#-------------------------------------------------------------------------------
# The following topics MUST be defined in this file:
#
# Generic, Class, Interface, Section, File, Group, Function, Variable,
# Property, Type, Constant, Enumeration, Event, Delegate
# If you add something that you think would be useful to other developers
# and should be included in Natural Docs by default, please e-mail it to
# topics [at] naturaldocs [dot] org.
Topic Type: Generic
Index: No
Keywords:
topic, topics
about, list
Topic Type: Class
Plural: Classes
Scope: Start
Class Hierarchy: Yes
Page Title If First: Yes
Can Group With: Interfaces
Keywords:
class, classes
structure, structures
struct, structs
package, packages
namespace, namespaces
Topic Type: Interface
Plural: Interfaces
Scope: Start
Class Hierarchy: Yes
Page Title If First: Yes
Can Group With: Classes
Keywords:
interface, interfaces
Topic Type: Section
Plural: Sections
Index: No
Scope: End
Page Title If First: Yes
Keywords:
section
title
Topic Type: File
Plural: Files
Scope: Always global
Page Title If First: Yes
Keywords:
file, files
program, programs
script, scripts
document, documents
doc, docs
header, headers
Topic Type: Group
Plural: Groups
Index: No
Keywords:
group
Topic Type: Function
Plural: Functions
Break Lists: Yes
Can Group With: Properties
Keywords:
function, functions
func, funcs
procedure, procedures
proc, procs
routine, routines
subroutine, subroutines
sub, subs
method, methods
callback, callbacks
constructor, constructors
destructor, destructors
operator, operators
Topic Type: Variable
Plural: Variables
Can Group With: Types, Constants, Macros, Enumerations
Keywords:
variable, variables
var, vars
integer, integers
int, ints
uint, uints
long, longs
ulong, ulongs
short, shorts
ushort, ushorts
byte, bytes
ubyte, ubytes
sbyte, sbytes
float, floats
double, doubles
real, reals
decimal, decimals
scalar, scalars
array, arrays
arrayref, arrayrefs
hash, hashes
hashref, hashrefs
bool, bools
boolean, booleans
flag, flags
bit, bits
bitfield, bitfields
field, fields
pointer, pointers
ptr, ptrs
reference, references
ref, refs
object, objects
obj, objs
character, characters
wcharacter, wcharacters
char, chars
wchar, wchars
string, strings
wstring, wstrings
str, strs
wstr, wstrs
handle, handles
Topic Type: Property
Plural: Properties
Can Group With: Functions
Keywords:
property, properties
prop, props
Topic Type: Type
Plural: Types
Can Group With: Variables, Constants, Macros, Enumerations
Keywords:
type, types
typedef, typedefs
Topic Type: Constant
Plural: Constants
Can Group With: Variables, Types, Macros, Enumerations
Keywords:
constant, constants
const, consts
Topic Type: Enumeration
Plural: Enumerations
Index: No
Can Group With: Variables, Types, Macros, Constants
Keywords:
enum, enums
enumeration, enumerations
Topic Type: Event
Plural: Events
Keywords:
event, events
Topic Type: Delegate
Plural: Delegates
Keywords:
delegate, delegates
Topic Type: Macro
Plural: Macros
Can Group With: Variables, Types, Constants
Keywords:
define, defines
def, defs
macro, macros
Topic Type: Database
Plural: Databases
Page Title If First: Yes
Keywords:
database, databases
db, dbs
Topic Type: Database Table
Plural: Database Tables
Scope: Start
Page Title If First: Yes
Keywords:
table, tables
database table, database tables
databasetable, databasetables
db table, db tables
dbtable, dbtables
Topic Type: Database View
Plural: Database Views
Scope: Start
Page Title If First: Yes
Keywords:
view, views
database view, database views
databaseview, databaseviews
db view, db views
dbview, dbviews
Topic Type: Database Index
Plural: Database Indexes
Keywords:
index, indexes
index, indices
database index, database indexes
database index, database indices
databaseindex, databaseindexes
databaseindex, databaseindices
db index, db indexes
db index, db indices
dbindex, dbindexes
dbindex, dbindices
key, keys
database key, database keys
databasekey, databasekeys
db key, db keys
dbkey, dbkeys
primary key, primary keys
primarykey, primarykeys
database primary key, database primary keys
databaseprimarykey, databaseprimarykeys
db primary key, db primary keys
dbprimarykey, dbprimarykeys
Topic Type: Database Cursor
Plural: Database Cursors
Keywords:
cursor, cursors
database cursor, database cursors
databasecursor, databasecursors
db cursor, db cursors
dbcursor, dbcursors
Topic Type: Database Trigger
Plural: Database Triggers
Keywords:
trigger, triggers
database trigger, database triggers
databasetrigger, databasetriggers
db trigger, db triggers
dbtrigger, dbtriggers
Topic Type: Cookie
Plural: Cookies
Scope: Always global
Keywords:
cookie, cookies
Topic Type: Build Target
Plural: Build Targets
Keywords:
target, targets
build target, build targets
buildtarget, buildtargets

View file

@ -1,52 +0,0 @@
<html><head><title>Customizing Natural Docs Languages</title><link rel=stylesheet type="text/css" href="styles.css"><link rel=stylesheet type="text/css" href="examples.css"><style type="text/css"><!--
.InMainFile {
padding: 1ex 2ex;
margin: 1em 0;
font: italic 9pt Verdana, sans-serif;
line-height: 150%;
background-color: #F8F8F8;
}
.InMainFile code {
font-size: 9pt;
}
.EnumTable {
margin: .5em 5ex;
}
.EnumOption {
font-weight: bold;
padding-right: 2ex;
}
--></style><script language=JavaScript src="javascript/PNGHandling.js"></script><script language=JavaScript src="javascript/BrowserStyles.js"></script></head><body marginwidth=0 marginheight=0 leftmargin=0 topmargin=0><script language=JavaScript><!--
OpeningBrowserTags();// --></script>
<!-- saved from url=(0026)http://www.naturaldocs.org -->
<table width=100% border=0 cellspacing=0 cellpadding=0><tr><td colspan=3 class=Header><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td><img src="images/header/leftside.png" width=30 height=75><a href="index.html"><img src="images/header/logo.png" width=524 height=75 alt="Natural Docs"></a></td><td align=right><img src="images/header/rightside.png" width=30 height=75></td></tr></table></td></tr><tr><td><img src="images/header/overleftmargin.png" width=10 height=6></td><td class=SideMenuTop><img src="images/header/overmenu.png" width=14 height=6></td><td class=BodyTop><img src="images/header/overbody.png" width=24 height=6></td></tr><tr><td></td><td class=SideMenu nowrap><div class=SideMenuSection><div class=SideMenuTitle><img src="images/menu/about.png" width=52 height=13 alt="About"></div><div class=SideMenuBody><a href="languages.html" class=SideMenuEntry>Language Support</a><a href="output.html" class=SideMenuEntry>Output Formats</a></div></div><div class=SideMenuSection><div class=SideMenuTitle><img src="images/menu/using.png" width=45 height=13 alt="Using"></div><div class=SideMenuBody><a href="documenting.html" class=SideMenuEntry>Documenting<br>Your Code</a><a href="keywords.html" class=SideMenuEntry>Keywords</a><a href="running.html" class=SideMenuEntry>Running</a><a href="troubleshooting.html" class=SideMenuEntry>Troubleshooting</a></div></div><div class=SideMenuSection><div class=SideMenuTitle><img src="images/menu/customizing.png" width=96 height=13 alt="Customizing"></div><div class=SideMenuBody><a href="menu.html" class=SideMenuEntry>Organizing the Menu</a><a href="styles.html" class=SideMenuEntry>CSS Styles</a><a href="customizingtopics.html" class=SideMenuEntry>Topics and Keywords</a><span class=SideMenuEntry id=SelectedSideMenuEntry>Languages, Indexes,<br>and Prototypes</span></div></div><div class=SideMenuSection><div class=SideMenuTitle><img src="images/menu/community.png" width=86 height=13 alt="Community"></div><div class=SideMenuBody><a href="http://www.naturaldocs.org/" class=SideMenuEntry>Web Site</a><a href="http://www.naturaldocs.org/mailinglist.html" class=SideMenuEntry>Mailing Lists</a><a href="http://www.naturaldocs.org/messageboards.html" class=SideMenuEntry>Message Boards</a><a href="http://www.naturaldocs.org/bugs.html" class=SideMenuEntry>Bugs and<br>Feature Requests</a></div></div></td><td class=Body width=100%><div class=PageTitle>Customizing Languages</div><div class=TOC><a href="#LanguagesTxt">Languages.txt</a> &middot; <a href="#FileExtensions">File Extensions</a> &middot; <a href="#AddingLanguages">Adding Languages</a> &middot; <a href="#Prototypes">Prototypes</a><br><a href="#IndexPrefixes">Index Prefixes</a> &middot; <a href="#SpecialLanguages">Special Languages</a> &middot; <a href="#SyntaxReference">Syntax Reference</a></div><div class=Topic><a name="LanguagesTxt"></a><div class=TopicTitle>Languages.txt</div><p>Natural Docs has two files called <code>Languages.txt</code>: one in its Config directory, and one in <a href="running.html#CommandLine">your project directory.</a>&nbsp; These control the language, index prefix, and prototype features of Natural Docs.</p><p>You should edit the one in your project directory whenever possible.&nbsp; It keeps your changes separate and easier to manage, plus you don&rsquo;t have to reapply them whenever you upgrade.&nbsp; Editing the one in Natural Docs&rsquo; Config directory would be better only if you&rsquo;re using Natural Docs with a lot of projects and would like the changes to apply everywhere.</p><p>Note that unlike other Natural Docs configuration files, comments can only appear on their own lines.&nbsp; They cannot appear after something else on a line because settings may need to use the <code>#</code> symbol.&nbsp; Also, all lists are space-separated instead of comma-separated, again because some settings may need to use the comma symbol.</p></div><div class=Topic><a name=FileExtensions></a><div class=TopicTitle>File Extensions</div><p>If Natural Docs doesn&rsquo;t recognize a file extension you use for your code, it&rsquo;s not a problem.&nbsp; You can alter the language definition from your project file to add them.</p><pre class=Example>Alter Language: <i>[your language]</i>
Add Extensions: cxx hxx</pre><p>On the other hand, if it&rsquo;s scanning some files you don&rsquo;t want it to scan, you can exclude extensions as well.&nbsp; Just add this to the top of your file:</p><pre class=Example>Ignore Extensions: c cpp</pre><p>In this example, Natural Docs will ignore C++ source files, thus only scanning the headers.</p></div><div class=Topic><a name=AddingLanguages></a><div class=TopicTitle>Adding Languages</div><p>You can add <a href="languages.html">basic language support</a> for any programming language just by editing these configuration files.&nbsp; Here are the most important settings:</p><pre class=Example>Language: Fictional
Extensions: fsrc fhdr
Shebang Strings: fictional
Line Comment: //
Block Comment: /* */
Package Separator: ::</pre><p>This tells Natural Docs that any files with the .fsrc or .fhdr extensions are part of our fictional programming language.&nbsp; Also, any .cgi or extensionless files that have &ldquo;fictional&rdquo; in the shebang (<code>#!</code>) line are part of it as well.&nbsp; Line comments start with <code>//</code> and block comments appear between <code>/*</code> and <code>*/</code>.&nbsp; The default package separator is <code>::</code>.&nbsp; Not too hard, huh?</p><p>You can also add settings to <a href="#IndexPrefixes">ignore prefixes in the index</a> and <a href="#Prototypes">detect prototypes</a>, but those are dealt with in their own sections on this page.</p></div><div class=Topic><a name=Prototypes></a><div class=TopicTitle>Prototypes</div><p>So you&rsquo;ve <a href="#AddingLanguages">added a new language</a> and want to detect prototypes.&nbsp; Or perhaps you <a href="customizingtopics.html#AddingTopicTypes">added a custom topic type</a> and want to detect prototypes for that as well.&nbsp; Here&rsquo;s an example of the properties you need:</p><pre class=Example>Function Prototype Enders: ; {
Variable Prototype Enders: ; =</pre><p>The algorithm for finding prototypes is very simple, yet it works really well in practice.&nbsp; All the code following the comment is grabbed until it reaches an ender symbol or another comment.&nbsp; Ender symbols appearing inside parenthesis, brackets, braces, or angle brackets don&rsquo;t count.&nbsp; If it reaches an ender symbol and somewhere in that code is the topic title, the code is accepted as the prototype.</p><p>So in the example above, variables end at semicolons (the end of the declaration) or equal signs (the default value expression, which we don&rsquo;t want to include.)&nbsp; Since the Natural Docs comment for the variable should have appeared right before the definition, that leaves us with the name and type.&nbsp; Functions are handled similarly: they end at a semicolon (the end of a predeclaration) or an opening brace (the beginning of the body) leaving us with the name, parameters, and return type.</p><p>You can do this with any topic type, including custom ones.&nbsp; Any prototypes that look like they have parameters will be formatted as such automatically.</p><div class=SubTopic>Line Breaks</div><p>For some languages, line breaks are significant.&nbsp; To have them end a prototype, use <code>\n</code>.&nbsp; If it has an extender symbol that allows the code to continue on the next line, you can specify that as well.</p><pre class=Example>Function Prototype Ender: \n
Variable Prototype Ender: \n =
Line Extender: _</pre><div class=SubTopic>Colors</div><p>If you&rsquo;re collecting prototypes for a custom topic type, they will not automatically get their own background color like the other types have.&nbsp; <a href="styles.html#CommonCustomizations">You have to define it via CSS.</a></p></div><div class=Topic><a name=IndexPrefixes></a><div class=TopicTitle>Index Prefixes</div><p>Natural Docs has the ability to ignore prefixes in the indexes.&nbsp; This is necessary because in certain languages, variables are prefixed with <code>$</code> or other symbols and we don&rsquo;t want them to get all grouped together under the symbols heading.&nbsp; Instead, they appear in the sidebar and are sorted as if they&rsquo;re not there.</p><div class=NDIndex><table border=0 cellspacing=0 cellpadding=0><tr><td class=IHeading id=IFirstHeading>A</td><td></td></tr><tr><td class=ISymbolPrefix id=IFirstSymbolPrefix>&nbsp;</td><td class=IEntry><span class=ISymbol>AddProperty</span>, <span class=IParent>SomeClass</span></td></tr><tr><td class=ISymbolPrefix>$</td><td class=IEntry><span class=ISymbol>amount</span></td></tr><tr><td class=ISymbolPrefix id=ILastSymbolPrefix>&nbsp;</td><td class=IEntry><span class=ISymbol>Average</span></td></tr></table></div><p>However, we can take advantage of this simply to get around coding conventions.&nbsp; Suppose you prefix all your class names with C.&nbsp; They&rsquo;d all form one gigantic group under C in the index.&nbsp; If you want, you can have it ignored so CCat, CDog, and CMouse get filed under C, D, and M instead.&nbsp; Just add this to your languages file:</p><pre class=Example>Alter Language: <i>[your language]</i>
Add Ignored Class Prefix in Index: C</pre><p>Now C is ignored in your indexes:</p><div class=NDIndex><table border=0 cellspacing=0 cellpadding=0><tr><td class=IHeading id=IFirstHeading>A</td><td></td></tr><tr><td class=ISymbolPrefix id=IFirstSymbolPrefix>C</td><td class=IEntry><span class=ISymbol>Account</span></td></tr><tr><td class=ISymbolPrefix>C</td><td class=IEntry><span class=ISymbol>AccountHolder</span></td></tr><tr><td class=ISymbolPrefix>&nbsp;</td><td class=IEntry><span class=ISymbol>AddProperty</span>, <span class=IParent>SomeClass</span></td></tr><tr><td class=ISymbolPrefix>$</td><td class=IEntry><span class=ISymbol>amount</span></td></tr><tr><td class=ISymbolPrefix id=ILastSymbolPrefix>&nbsp;</td><td class=IEntry><span class=ISymbol>Average</span></td></tr></table></div><p>You can include any number of prefixes and can do this for any topic type.&nbsp; So if you have a bunch of functions that start with <code>COM_</code> and <code>DB_</code>, you can ignore them too:</p><pre class=Example>Alter Language: <i>[your language]</i>
Add Ignored Class Prefix in Index: C
Add Ignored Function Prefixes in Index: COM_ DB_</pre></div><div class=Topic><a name=SpecialLanguages></a><div class=TopicTitle>Special Languages</div><p>There are two languages with special properties: Shebang Script and Text File.</p><p>Shebang Script allows you to define the file extensions where the language is really determined by the shebang (<code>#!</code>) line within it.&nbsp; For example, .cgi files.&nbsp; If Natural Docs finds a .cgi file, it sees that it&rsquo;s a Shebang Script so it opens it up to parse it&rsquo;s shebang line.&nbsp; It then searches it for substrings defined by other languages&rsquo; <code>Shebang String</code> settings to find out what language it really is.&nbsp; Files with no extension are always treated this way.</p><p>With Text File, the entire file is treated like a comment.&nbsp; There are no comment symbols required, you can just put Natural Docs content there in plain text.&nbsp; The most important setting is <code>Extensions</code>.</p><p>However, since it is possible to document classes, functions, etc. in text files, they also have their own <code>Package Separator</code> and <code>Ignored <i>[type]</i> Prefixes in Index</code> settings.&nbsp; To make things easier on you, by default it copies these settings from whichever language has the most source files in your project.&nbsp; You can override this by manually setting them, but you shouldn&rsquo;t need to.</p></div><div class=Topic><a name=SyntaxReference></a><div class=TopicTitle>Syntax Reference</div><p>Unlike other Natural Docs configuration files, comments can only appear on their own lines.&nbsp; They cannot appear after something else on a line because settings may need to use the <code>#</code> symbol.&nbsp; Likewise, lists are separated with spaces instead of commas because commas themselves may need to appear on the list.</p><p>Singular and plural forms are generally both supported, so you can write <code>Extension</code> or <code>Extensions</code>.&nbsp; It doesn&rsquo;t matter if they match how many items are set.&nbsp; Also, you can use either <code>Ignore</code> or <code>Ignored</code>.</p><pre class=Example>Ignore Extensions: <i>[extension] [extension]</i> ...</pre><p>Causes the listed file extensions to be ignored, even if they were previously defined to be part of a language.&nbsp; The list is space-separated.&nbsp; ex. &ldquo;<code>Ignore Extensions: cvs txt</code>&rdquo;</p><pre class=Example>Language: <i>[name]</i>
Alter Language: <i>[name]</i></pre><p>Creates a new language or alters an existing one.&nbsp; Names can use any characters.&nbsp; Note the <a href="#SpecialLanguages">special behavior for languages named Shebang Script and Text File</a>.</p><p>If you&rsquo;re altering an existing language and a property has an <code>[Add/Replace]</code> form, you have to specify whether you&rsquo;re adding to or replacing the list if that property has already been defined.</p><div class=SubTopic>General Language Properties</div><pre class=Example>Extensions: <i>[extension] [extension]</i> ...
<i>[Add/Replace]</i> Extensions: <i>[extension] [extension]</i> ...</pre><p>Defines file extensions for the language&rsquo;s source files.&nbsp; The list is space-separated.&nbsp; ex. &ldquo;<code>Extensions: c cpp</code>&rdquo;.&nbsp; You can use extensions that were previously used by another language to redefine them.&nbsp; You can use <code>*</code> to specify all undefined extensions.</p><pre class=Example>Shebang Strings: <i>[string] [string]</i> ...
<i>[Add/Replace]</i> Shebang Strings: <i>[string] [string]</i> ...</pre><p>Defines a list of strings that can appear in the shebang (<code>#!</code>) line to designate that it&rsquo;s part of this language.&nbsp; They can appear anywhere in the line, so <code>php</code> will work for &ldquo;<code>#!/user/bin/php4</code>&rdquo;.&nbsp; You can use strings that were previously used by another language to redefine them.</p><pre class=Example>Ignore Prefixes in Index: <i>[prefix] [prefix]</i> ...
Ignore <i>[type]</i> Prefixes in Index: <i>[prefix] [prefix]</i> ...
<i>[Add/Replace]</i> Ignored Prefixes in Index: <i>[prefix] [prefix]</i> ...
<i>[Add/Replace]</i> Ignored <i>[type]</i> Prefixes in Index: <i>[prefix] [prefix]</i> ...</pre><p>Specifies prefixes that should be ignored when sorting symbols for an index.&nbsp; Can be specified in general or for a specific topic type.&nbsp; The prefixes will still appear, the symbols will just be sorted as if they&rsquo;re not there.&nbsp; For example, specifying <code>ADO_</code> for functions will mean that <code>ADO_DoSomething</code> will appear under D instead of A.</p><div class=SubTopic>Basic Language Support Properties</div><p>These attributes are only available for languages with basic language support.</p><pre class=Example>Line Comments: <i>[symbol] [symbol]</i> ...</pre><p>Defines a space-separated list of symbols that are used for line comments, if any.&nbsp; ex. &ldquo;<code>Line Comment: //</code>&rdquo;.</p><pre class=Example>Block Comments: <i>[opening symbol] [closing symbol] [o.s.] [c.s.]</i> ...</pre><p>Defines a space-separated list of symbol pairs that are used for block comments, if any.&nbsp; ex. &ldquo;<code>Block Comment: /* */</code>&rdquo;.</p><pre class=Example>Enum Values: <i>[global|under type|under parent]</i></pre><p>Defines the behavior of enum values.&nbsp; The default is global.</p><table border=0 cellspacing=0 cellpadding=0 class=EnumTable><tr><td class=EnumOption>Global</td><td>Enum values are always global and will be referenced as &ldquo;Value&rdquo;.</td></tr><tr><td class=EnumOption>Under Type</td><td>Enum values appear under the type and will be referenced as &ldquo;Package.Enum.Value&rdquo;.</td></tr><tr><td class=EnumOption>Under Parent</td><td>Enum values appear under the parent and will be referenced as &ldquo;Package.Value&rdquo;</td></tr></table><pre class=Example><i>[type]</i> Prototype Enders: <i>[symbol] [symbol]</i> ...</pre><p>When defined, Natural Docs will attempt to collect prototypes from the code following the specified topic type.&nbsp; It grabs code until the first ender symbol or the next Natural Docs comment, and if it contains the topic name, it serves as its prototype.&nbsp; Use <code>\n</code> to specify a line break.&nbsp; ex. &ldquo;<code>Function Prototype Enders: { ;</code>&rdquo;, &ldquo;<code>Variable Prototype Enders: = ;</code>&rdquo;. </p><pre class=Example>Line Extender: <i>[symbol]</i></pre><p>Defines the symbol that allows a prototype to span multiple lines if normally a line break would end it.</p><pre class=Example>Perl Package: <i>[perl package]</i></pre><p>Specifies the Perl package used to fine-tune the language behavior in ways too complex to do in this file.</p><div class=SubTopic>Full Language Support Properties</div><p>These attributes are only available for languages with full language support.</p><pre class=Example>Full Language Support: <i>[perl package]</i></pre><p>Specifies the Perl package that has the parsing routines necessary for full language support.</p></div></td></tr><tr><td></td><td class=SideMenuBottom><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td class=SideMenuBottomLeft><img src="images/menu/bottomleft.png" width=18 height=19></td><td class=SideMenuBottomRight><img src="images/menu/bottomright.png" width=18 height=19></td></tr></table></td><td class=BodyBottom>Copyright &copy; 2003-2008 Greg Valure</td></tr></table><script language=JavaScript><!--
ClosingBrowserTags();// --></script></body></html>

File diff suppressed because one or more lines are too long

View file

@ -1,58 +0,0 @@
<html><head><title>Documenting Your Code - Natural Docs</title><link rel=stylesheet type="text/css" href="styles.css"><link rel=stylesheet type="text/css" href="examples.css"><style type="text/css"><!--
#ReferenceTable {
width: 100%;
}
#ReferenceTable #LeftSide {
padding-right: 4ex;
width: 40%;
}
#ReferenceTable #RightSide {
width: 60%;
}
#LeftSide a:link,
#LeftSide a:hover,
#LeftSide a:visited {
color: #000000;
}
#LeftSide .TopicTitle a:hover,
#LeftSide .TopicTitle a:active {
text-decoration: none;
}
#RightSide .Example {
margin-left: 0;
margin-right: 0;
}
--></style><script language=JavaScript src="javascript/PNGHandling.js"></script><script language=JavaScript src="javascript/BrowserStyles.js"></script></head><body marginwidth=0 marginheight=0 leftmargin=0 topmargin=0><script language=JavaScript><!--
OpeningBrowserTags();// --></script>
<!-- saved from url=(0026)http://www.naturaldocs.org -->
<table width=100% border=0 cellspacing=0 cellpadding=0><tr><td colspan=3 class=Header><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td><img src="images/header/leftside.png" width=30 height=75><a href="index.html"><img src="images/header/logo.png" width=524 height=75 alt="Natural Docs"></a></td><td align=right><img src="images/header/rightside.png" width=30 height=75></td></tr></table></td></tr><tr><td><img src="images/header/overleftmargin.png" width=10 height=6></td><td class=SideMenuTop><img src="images/header/overmenu.png" width=14 height=6></td><td class=BodyTop><img src="images/header/overbody.png" width=24 height=6></td></tr><tr><td></td><td class=SideMenu nowrap><div class=SideMenuSection><div class=SideMenuTitle><img src="images/menu/about.png" width=52 height=13 alt="About"></div><div class=SideMenuBody><a href="languages.html" class=SideMenuEntry>Language Support</a><a href="output.html" class=SideMenuEntry>Output Formats</a></div></div><div class=SideMenuSection><div class=SideMenuTitle><img src="images/menu/using.png" width=45 height=13 alt="Using"></div><div class=SideMenuBody><span class=SideMenuEntry id=SelectedSideMenuEntry>Documenting<br>Your Code</span><a href="keywords.html" class=SideMenuEntry>Keywords</a><a href="running.html" class=SideMenuEntry>Running</a><a href="troubleshooting.html" class=SideMenuEntry>Troubleshooting</a></div></div><div class=SideMenuSection><div class=SideMenuTitle><img src="images/menu/customizing.png" width=96 height=13 alt="Customizing"></div><div class=SideMenuBody><a href="menu.html" class=SideMenuEntry>Organizing the Menu</a><a href="styles.html" class=SideMenuEntry>CSS Styles</a><a href="customizingtopics.html" class=SideMenuEntry>Topics and Keywords</a><a href="customizinglanguages.html" class=SideMenuEntry>Languages, Indexes,<br>and Prototypes</a></div></div><div class=SideMenuSection><div class=SideMenuTitle><img src="images/menu/community.png" width=86 height=13 alt="Community"></div><div class=SideMenuBody><a href="http://www.naturaldocs.org/" class=SideMenuEntry>Web Site</a><a href="http://www.naturaldocs.org/mailinglist.html" class=SideMenuEntry>Mailing Lists</a><a href="http://www.naturaldocs.org/messageboards.html" class=SideMenuEntry>Message Boards</a><a href="http://www.naturaldocs.org/bugs.html" class=SideMenuEntry>Bugs and<br>Feature Requests</a></div></div></td><td class=Body width=100%><div class=PageTitle>Documenting Your Code</div><div class=Topic><table id=ReferenceTable border=0 cellspacing=0 cellpadding=0><tr><td id=LeftSide><div class=Topic><div class=TopicTitle><a href="documenting/walkthrough.html">Walkthrough</a></div><ul><li><a href="documenting/walkthrough.html#OurFirstFunction">Our First Function</a></i><li><a href="documenting/walkthrough.html#ClassesAndScope">Classes and Scope</a></i><li><a href="documenting/walkthrough.html#MoreFormatting">More Formatting</a></i><li><a href="documenting/walkthrough.html#MoreOnLinking">More on Linking</a></i><li><a href="documenting/walkthrough.html#ExtraDocumentation">Extra Documentation</a></i><li><a href="documenting/walkthrough.html#AbbreviatedSyntax">Abbreviated Syntax</a></i></ul></div><div class=Topic><div class=TopicTitle><a href="documenting/reference.html">Reference</a></div><ul><li><a href="documenting/reference.html#Comments">Comments</a></i><li><a href="documenting/reference.html#TextFiles">Text Files</a></i><li><a href="documenting/reference.html#KeywordsTopicsAndScope">Keywords, Topics, and Scope</a></i><li><a href="documenting/reference.html#Linking">Linking</a></i><li><a href="documenting/reference.html#FormattingAndLayout">Formatting and Layout</a></i><li><a href="documenting/reference.html#PageTitles">Page Titles</a></i><li><a href="documenting/reference.html#Summaries">Summaries</a></i><li><a href="documenting/reference.html#JavadocCompatibility">Javadoc Compatibility</a></i></ul></div></td><td id=RightSide><p>Here&rsquo;s a quick example of how to document your code for Natural Docs.&nbsp; If you&rsquo;re a new user, we have <a href="documenting/walkthrough.html">a walkthrough</a> to get you started.&nbsp; Otherwise, visit <a href="documenting/reference.html">the reference</a> for the full details.</p><pre class=Example>/*
Function: Multiply
Multiplies two integers.
Parameters:
x - The first integer.
y - The second integer.
Returns:
The two integers multiplied together.
See Also:
&lt;Divide&gt;
*/
int Multiply (int x, int y)
{ return x * y; };</pre></td></tr></table></div></td></tr><tr><td></td><td class=SideMenuBottom><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td class=SideMenuBottomLeft><img src="images/menu/bottomleft.png" width=18 height=19></td><td class=SideMenuBottomRight><img src="images/menu/bottomright.png" width=18 height=19></td></tr></table></td><td class=BodyBottom>Copyright &copy; 2003-2008 Greg Valure</td></tr></table><script language=JavaScript><!--
ClosingBrowserTags();// --></script></body></html>

File diff suppressed because one or more lines are too long

View file

@ -1,180 +0,0 @@
<html><head><title>Documenting Your Code - Walkthrough - Natural Docs</title><link rel=stylesheet type="text/css" href="../styles.css"><link rel=stylesheet type="text/css" href="../examples.css"><script language=JavaScript src="../javascript/PNGHandling.js"></script><script language=JavaScript src="../javascript/BrowserStyles.js"></script><script language=JavaScript src="../example/NaturalDocs.js"></script></head><body marginwidth=0 marginheight=0 leftmargin=0 topmargin=0><script language=JavaScript><!--
OpeningBrowserTags();// --></script>
<!-- saved from url=(0026)http://www.naturaldocs.org -->
<table width=100% border=0 cellspacing=0 cellpadding=0><tr><td colspan=3 class=Header><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td><img src="../images/header/leftside.png" width=30 height=75><a href="../index.html"><img src="../images/header/logo.png" width=524 height=75 alt="Natural Docs"></a></td><td align=right><img src="../images/header/rightside.png" width=30 height=75></td></tr></table></td></tr><tr><td><img src="../images/header/overleftmargin.png" width=10 height=6></td><td class=SideMenuTop><img src="../images/header/overmenu.png" width=14 height=6></td><td class=BodyTop><img src="../images/header/overbody.png" width=24 height=6></td></tr><tr><td></td><td class=SideMenu nowrap><div class=SideMenuSection><div class=SideMenuTitle><img src="../images/menu/about.png" width=52 height=13 alt="About"></div><div class=SideMenuBody><a href="../languages.html" class=SideMenuEntry>Language Support</a><a href="../output.html" class=SideMenuEntry>Output Formats</a></div></div><div class=SideMenuSection><div class=SideMenuTitle><img src="../images/menu/using.png" width=45 height=13 alt="Using"></div><div class=SideMenuBody><a href="../documenting.html" class=SideMenuEntry id=SelectedSideMenuEntry>Documenting<br>Your Code</a><a href="../keywords.html" class=SideMenuEntry>Keywords</a><a href="../running.html" class=SideMenuEntry>Running</a><a href="../troubleshooting.html" class=SideMenuEntry>Troubleshooting</a></div></div><div class=SideMenuSection><div class=SideMenuTitle><img src="../images/menu/customizing.png" width=96 height=13 alt="Customizing"></div><div class=SideMenuBody><a href="../menu.html" class=SideMenuEntry>Organizing the Menu</a><a href="../styles.html" class=SideMenuEntry>CSS Styles</a><a href="../customizingtopics.html" class=SideMenuEntry>Topics and Keywords</a><a href="../customizinglanguages.html" class=SideMenuEntry>Languages, Indexes,<br>and Prototypes</a></div></div><div class=SideMenuSection><div class=SideMenuTitle><img src="../images/menu/community.png" width=86 height=13 alt="Community"></div><div class=SideMenuBody><a href="http://www.naturaldocs.org/" class=SideMenuEntry>Web Site</a><a href="http://www.naturaldocs.org/mailinglist.html" class=SideMenuEntry>Mailing Lists</a><a href="http://www.naturaldocs.org/messageboards.html" class=SideMenuEntry>Message Boards</a><a href="http://www.naturaldocs.org/bugs.html" class=SideMenuEntry>Bugs and<br>Feature Requests</a></div></div></td><td class=Body width=100%><div class=PageTitle>Documenting Your Code</div><div class=TOC><a href="#OurFirstFunction">Our First Function</a> &middot; <a href="#ClassesAndScope">Classes and Scope</a> &middot; <a href="#MoreFormatting">More Formatting</a><br><a href="#MoreOnLinking">More on Linking</a> &middot; <a href="#ExtraDocumentation">Extra Documentation</a> &middot; <a href="#AbbreviatedSyntax">Abbreviated Syntax</a></div><div class=Topic><a name="OurFirstFunction"></a><div class=TopicTitle>Our First Function</div><p>So you downloaded Natural Docs, you <a href="../running.html">figured out the command line</a>, and now it&rsquo;s time to start documenting your code.&nbsp; Natural Docs tries to make this very straightforward and painless, so let&rsquo;s just dive right in:</p><pre class=Example>/*
Function: Multiply
Multiplies two integers and returns the result.
*/
int Multiply (int x, int y)
{ return x * y; };
</pre><p>That&rsquo;s all you need.&nbsp; Run Natural Docs and here&rsquo;s what appears in your output:</p><div class=NDContent><div class=CFunction><div class=CTopic><h3 class=CTitle><a name="Multiply"></a>Multiply</h3><div class=CBody><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters>int Multiply (</td><td class=PType>int&nbsp;</td><td class=PParameter>x,</td><td></td></tr><tr><td></td><td class=PType>int&nbsp;</td><td class=PParameter>y</td><td class=PAfterParameters>)</td></tr></table></td></tr></table><p class=CParagraph>Multiplies two integers and returns the result.</p></div></div></div></div><p>Okay, so that&rsquo;s all you need, but probably not all you want.&nbsp; After all, you&rsquo;ve got some real functions to document, not little one-liners.&nbsp; Here&rsquo;s something more elaborate:</p><pre class=Example>/*
Function: Multiply
Multiplies two integers.
Parameters:
x - The first integer.
y - The second integer.
Returns:
The two integers multiplied together.
See Also:
&lt;Divide&gt;
*/
int Multiply (int x, int y)
{ return x * y; };
</pre><div class=NDContent><div class=CFunction><div class=CTopic><h3 class=CTitle><a name="Example_Class.Multiply"></a>Multiply</h3><div class=CBody><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters>int Multiply (</td><td class=PType>int&nbsp;</td><td class=PParameter>x,</td><td></td></tr><tr><td></td><td class=PType>int&nbsp;</td><td class=PParameter>y</td><td class=PAfterParameters>)</td></tr></table></td></tr></table><p class=CParagraph>Multiplies two integers.</p><h4 class=CHeading>Parameters</h4><table border=0 cellspacing=0 cellpadding=0 class=CDescriptionList><tr><td class=CDLEntry>x</td><td class=CDLDescription>The first integer.</td></tr><tr><td class=CDLEntry>y</td><td class=CDLDescription>The second integer.</td></tr></table><h4 class=CHeading>Returns</h4><p class=CParagraph>The two integers multiplied together.</p><h4 class=CHeading>See Also</h4><p class=CParagraph><a href="#Example_Class.Divide" class=LFunction id=link116 onMouseOver="ShowTip(event, 'ttDivide', 'link116')" onMouseOut="HideTip('ttDivide')">Divide</a></p></div></div></div></div><div class=CToolTip id="ttAdd"><div class=CFunction><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters>int Add (</td><td class=PType>int&nbsp;</td><td class=PParameter>x,</td><td></td></tr><tr><td></td><td class=PType>int&nbsp;</td><td class=PParameter>y</td><td class=PAfterParameters>)</td></tr></table></td></tr></table>Adds two integers.</div></div><div class=CToolTip id="ttSubtract"><div class=CFunction><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters>int Subtract (</td><td class=PType>int&nbsp;</td><td class=PParameter>x,</td><td></td></tr><tr><td></td><td class=PType>int&nbsp;</td><td class=PParameter>y</td><td class=PAfterParameters>)</td></tr></table></td></tr></table>Subtracts two integers.</div></div><div class=CToolTip id="ttMultiply"><div class=CFunction><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters>int Multiply (</td><td class=PType>int&nbsp;</td><td class=PParameter>x,</td><td></td></tr><tr><td></td><td class=PType>int&nbsp;</td><td class=PParameter>y</td><td class=PAfterParameters>)</td></tr></table></td></tr></table>Multiplies two integers.</div></div><div class=CToolTip id="ttDivide"><div class=CFunction><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters>int Divide (</td><td class=PType>int&nbsp;</td><td class=PParameter>x,</td><td></td></tr><tr><td></td><td class=PType>int&nbsp;</td><td class=PParameter>y</td><td class=PAfterParameters>)</td></tr></table></td></tr></table>Divides two integers.</div></div><div class=CToolTip id="ttIsEqual"><div class=CFunction><table border=0 cellspacing=0 cellpadding=0 class=Prototype><tr><td><table border=0 cellspacing=0 cellpadding=0><tr><td class=PBeforeParameters>bool IsEqual (</td><td class=PType>int&nbsp;</td><td class=PParameter>x,</td><td></td></tr><tr><td></td><td class=PType>int&nbsp;</td><td class=PParameter>y</td><td class=PAfterParameters>)</td></tr></table></td></tr></table>Returns whether two integers are equal.</div></div><p>Still not too scary, huh?&nbsp; Notice the comments are just as readable as the output.&nbsp; No tags littered about, and the structure is very natural.&nbsp; You probably get it just by looking at it, but let&rsquo;s go through the details anyway.</p><pre class=Example>Function: Multiply
</pre><p>Every one of these comments you write (called <i>topics</i>) are going to start with a <i>topic line</i> in the format <code>&ldquo;keyword: title&rdquo;</code>.&nbsp; There are <a href="../keywords.html">a lot of keywords</a>, but they&rsquo;re exactly what you&rsquo;d expect: Function, Class, Variable, etc.&nbsp; There are also a lot of synonyms so instead of Function you could use Func, Procedure, Proc, Method, Constructor, etc.&nbsp; It&rsquo;s designed so you can just use whatever it is you&rsquo;re describing without memorizing anything.&nbsp; You can glance over <a href="../keywords.html">the keyword list</a> but you shouldn&rsquo;t have to consult it very often.</p></p><p>The other part of the topic line is the title.&nbsp; It should match whatever it is you&rsquo;re documenting, in this case the function name Multiply.&nbsp; Natural Docs is case sensitive even if your programming language isn&rsquo;t, so make sure you match it closely or you might not get the prototype in your output, which is the little gray box.&nbsp; You don&rsquo;t need to include the parameters in the title.&nbsp; In fact, it&rsquo;s better if you don&rsquo;t.</p></p><pre class=Example>Parameters:
Returns:
See Also:
</pre><p>You can also define <a href="reference.html#Headings">headings</a> by skipping a line and ending the text with a colon.&nbsp; If you&rsquo;re used to other documentation systems you may think there&rsquo;s only a handful of headings to choose from, but any text formatted this way will become one.&nbsp; If you want a heading called Dependencies you can go right ahead and add it.</p><pre class=Example>x - The first integer.
y - The second integer.
</pre><p>This is what&rsquo;s called a <a href="reference.html#DefinitionLists">definition list.</a>&nbsp; You can use more than one line to finish the definition, as it won&rsquo;t stop until you skip a line.</p><pre class=Example>x - The first integer.
y - The second integer with a long description.
This is still part of the description.
This is a new paragraph because we skipped a line.
</pre><p>Indentation doesn&rsquo;t matter either, so even if the second description line wasn&rsquo;t indented to match the first, it would still be considered part of it.</p><pre class=Example>&lt;Divide&gt;
</pre><p>This is how we link in Natural Docs, with angle brackets.&nbsp; There will be a lot more to say about this later, but for now I&rsquo;ll just show you something cool.&nbsp; Hover over it in the output below:</p><div class=NDContent><div class=CTopic><div class=CBody><p class=CParagraph><a href="#Example_Class.Divide" class=LFunction id=link116 onMouseOver="ShowTip(event, 'ttDivide', 'link216')" onMouseOut="HideTip('ttDivide')">Divide</a></p></div></div></div><p>You get that <i>everywhere</i> in your generated documentation.</p></div><div class=Topic><a name="ClassesAndScope"></a><div class=TopicTitle>Classes and Scope</div><p>So that&rsquo;s good for our one function of questionable usefulness, but what if we have a whole class of questionable usefulness?&nbsp; We can document the class and it&rsquo;s members the same way we documented the individual function, with a Natural Docs comment right above each element.&nbsp; We&rsquo;ll go back to short descriptions to keep the example manageable.</p><pre class=Example>/*
Class: Counter
A class that manages an incrementing counter.
*/
class Counter
{
public:
/*
Constructor: Counter
Initializes the object.
*/
Counter()
{ value = 0; };
/*
Function: Value
Returns the value of the counter.
*/
int Value()
{ return value; };
/*
Function: Increment
Adds one to the counter.
*/
void Increment()
{ value++; };
protected:
/*
Variable: value
The counter's value.
*/
int value;
};
</pre><p>Everything&rsquo;s the same, we just substituted Class and Variable for the Function keyword when it was appropriate.&nbsp; We also used Constructor, but we could have just as easily used Function there too.&nbsp; They&rsquo;re both keywords for the same thing so it doesn&rsquo;t matter.</p><a name="Scope"></a><div class="SubTopic">Scope</div><p>Like the source code itself, Natural Docs topics have <a href="reference.html#Scope">scope.</a>&nbsp; Value and Increment are seen as part of class Counter, just like they are in the code.&nbsp; Why is this important?&nbsp; Linking.&nbsp; Linking from one topic to another has similar rules to how one function can call another.&nbsp; Since Value is in the same class as Increment, it&rsquo;s topic can link to it with just <code>&lt;Increment&gt;</code>.&nbsp; However, linking to Increment from a different class would require <code>&lt;Counter.Increment&gt;</code> instead.&nbsp; You can actually use any of the three most common class/member notations: <code>&lt;Counter.Increment&gt;</code>, <code>&lt;Counter::Increment&gt;</code>, and <code>&lt;Counter-&gt;Increment&gt;</code>.</p><p>If your programming language has <a href="../languages.html">full language support</a>, the scope is determined by the code and applied automatically.&nbsp; However, if you only have <a href="../languages.html">basic language support</a> it follows these rules:</p><ul><li>Any topic that appears under a Class topic (or anything that says <a href="../keywords.html">Starts Scope</a>) is part of that class.</li><li>Any topic that appears under a Section topic (or anything that says <a href="../keywords.html">Ends Scope</a>) is global again.</li><li>Any File topic (or anything that says <a href="../keywords.html">Always Global</a>) is global no matter what and doesn&rsquo;t affect any other topics.</li><p></ul></p><p>Chances are you would have written the same thing even if you didn&rsquo;t know this and it would have just worked.&nbsp; You usually won&rsquo;t need to think about them at all.&nbsp; However, it&rsquo;s still good to be aware of them in case something doesn&rsquo;t behave the way you expected it to.</p><p>You actually know enough to go start documenting now.&nbsp; I know Mr. ScrollBar says there&rsquo;s more on this page you can learn, but if you want to skip out early, you can.&nbsp; Really.&nbsp; I don&rsquo;t mind.</p></div><div class=Topic><a name="MoreFormatting"></a><div class=TopicTitle>More Formatting</div><p>Okay then.&nbsp; On we go.</p><a name="ParagraphsBoldAndUnderline"></a><div class="SubTopic">Paragraphs, Bold, and Underline</div><p>The syntax for these three is exactly what you would expect it to be.</p><pre class=Example>*Bold text*
_Underlined text_
Paragraphs are broken by skipping lines. So the two
lines above each have their own paragraph, but these
three lines are all part of the same one.
</pre><div class=NDContent><div class=CBody><div class=CFunction><div class=CTopic><p><b>Bold text</b></p><p><u>Underlined text</u></p><p>Paragraphs are broken by skipping lines.&nbsp; So the two lines above each have their own paragraph, but these three lines are all part of the same one.</p></div></div></div></div><p>When underlining multiple words, you can use an underscore for each space or only put them at the edges like we did above.&nbsp; Both ways will work.</p><a name="BulletLists"></a><div class="SubTopic">Bullet Lists</div><p>You can add <a href="reference.html#BulletLists">bullet lists</a> by starting a line with a dash, an asterisk, an o, or a plus.&nbsp; Like definition lists, bullets can span multiple lines and indentation doesn&rsquo;t matter.&nbsp; To end a bullet you have to skip a line before doing something else.</p><pre class=Example>- Bullet one.
- Bullet two.
Bullet two continued.
- Bullet three.
Some text after the bullet list.
</pre><div class=NDContent><div class=CFunction><div class=CTopic><div class=CBody><ul class=CBulletList><li>Bullet one.</li><li>Bullet two.&nbsp; Bullet two continued.</li><li>Bullet three.</li></ul><p class=CParagraph>Some text after the bullet list.</p></div></div></div></div><a name="CodeAndTextDiagrams"></a><div class="SubTopic">Code and Text Diagrams</div><p>You can add <a href="reference.html#CodeAndTextDiagrams">example code or text diagrams</a> by starting each line with <code>&gt;</code>, <code>|</code>, or <code>:</code>.</p><pre class=Example>&gt; a = b + c;
&gt; b++;
</pre><div class=NDContent><div class=CFunction><div class=CTopic><div class=CBody><pre class=CCode>a = b + c;<br>b++;</pre></div></div></div></div><p>If you have a long stretch, you can use <code>(start code)</code> and <code>(end)</code> instead.</p><pre class=Example>(start code)
if (x == 0) {
DoSomething();
}
return x;
(end)
</pre><div class=NDContent><div class=CFunction><div class=CTopic><div class=CBody><pre class=CCode>if (x == 0) {<br> DoSomething();<br>}<br><br>return x;</pre></div></div></div></div><p>You can also use <code>example</code>, <code>diagram</code>, or <code>table</code> instead of <code>code</code>.&nbsp; Just use whatever&rsquo;s appropriate.</p><p>As I mentioned before, we don&rsquo;t want you to worry about memorizing minor details, so in that spirit it will also accept <code>begin</code> for <code>start</code> and <code>finish</code> or <code>done</code> for <code>end</code>.&nbsp; You can also write <code>(end code)</code> instead of just <code>(end)</code>.</p><a name="Images"></a><div class="SubTopic">Images</div><p>You can include images in your documentation by writing &ldquo;<code>(see filename)</code>&rdquo;.&nbsp; If you put it alone on a line it will be embedded in place, or if you put it in a paragraph it will appear after it using the file name as a caption.</p><pre class=Example>This is the first paragraph.
(see logo.gif)
This is the second paragraph (see logo.gif) This
is more of the second paragraph.
</pre><div class=NDContent><div class=CFunction><div class=CTopic><div class=CBody><p class=CParagraph>This is the first paragraph.</p><img src="../images/logo.gif" width="268" height="61"><p class=CParagraph>This is the second paragraph <a href="#Image1" class=CImageLink>(see logo)</a>&nbsp; This is more of the second paragraph.</p><div class=CImage><a name="Image1"></a><div class=CImageCaption>logo</div><img src="../images/logo.gif" width="268" height="61"></div></div></div></div></div><p>The image file names are relative to the source file the comment appears in, so if your file is C:\Project\SourceFile.cpp and your image is C:\Project\Images\Logo.gif, you would write <code>(see Images/Logo.gif)</code>.&nbsp; However, you can also specify image directories in <a href="../running.html#CommandLine">the command line with <code>-img</code></a>, so if all your source files are in C:\Project\Source and all your images are in C:\Project\Images, you can put &ldquo;<code>-img C:\Project\Images</code>&rdquo; on the command line and just use <code>(see logo.gif)</code> again.</p></div><div class=Topic><a name="MoreOnLinking"></a><div class=TopicTitle>More on Linking</div><p>Yes, there&rsquo;s still more to linking.&nbsp; You can link to URLs and e-mail addresses, but in this case the angle brackets are optional.</p><pre class=Example>Visit &lt;http://www.website.com&gt; or send messages to
email@address.com.
</pre><div class=NDContent><div class=CFunction><div class=CTopic><div class=CBody><p class=CParagraph>Visit <a href="#" onClick="return false;" class=LURL>http://www.website.com</a> or send messages to <a href="#" onclick="location.href='mai' + 'lto:' + 'em' + 'ail' + '@' + 'addre' + 'ss.com'; return false;" class="LEMail">em<span style="display: none;">.nosp@m.</span>ail<span>@</span>addre<span style="display: none;">.nosp@m.</span>ss.com</a>.</p></div></div></div></div><p>E-mail addresses are protected from spam crawlers.&nbsp; They look and act like regular links (try it above) but you can see the actual HTML that&rsquo;s generated for them <a href="reference.html#URLsAndEMail">here</a>.</p><p>As for regular links, to help them fit into sentences easily you can actually include plurals and possessives inside the angle brackets.&nbsp; In other words, you don&rsquo;t have to use awkward syntax like <code>&lt;Object&gt;s</code>, although that&rsquo;s supported as well.&nbsp; You can simply write <code>&lt;Objects&gt;</code> and it will link to the symbol <code>Object</code> just fine.&nbsp; It can handle any plural and/or possessive form you can throw at it.&nbsp; I&rsquo;m not kidding: <code>Foxes</code>, <code>Fox&rsquo;s</code>, <code>Foxes&rsquo;</code>, <code>Children</code>, <code>Mice</code>, <code>Alumni</code>, <code>Indices</code>, <code>Amoebae</code>, <code>Teeth</code>, just try to trip it up.</p></div><div class=Topic><a name="ExtraDocumentation"></a><div class=TopicTitle>Extra Documentation</div><p>Sometimes you want to include documentation that doesn&rsquo;t correspond directly to a code element.&nbsp; Maybe you want to include license information or architecture notes.&nbsp; There are two ways to do this.</p><a name="FreestandingTopics"></a><div class="SubTopic">Freestanding Topics</div><p>Just because most of the things you write will directly correspond to an element of your source code doesn&rsquo;t mean they have to.&nbsp; You can pick any of <a href="../keywords.html">the available keywords</a> and create a freestanding comment with it.&nbsp; For example:</p><pre class=Example>/*
Class: Counter
A class that manages an incrementing counter.
*/
class Counter
{
public:
/*
About: License
This file is licensed under the GPL.
*/
/*
Constructor: Counter
Initializes the object.
*/
Counter()
{ value = 0; };
...
</pre><p>The extra license topic will be added to the output just like the functions.</p><div class=NDContent><div class=CFunction><div class=CTopic><h3 class=CTitle>License</h3><div class=CBody><p class=CParagraph>This file is licensed under the GPL.</p></div></div></div></div><p>Remember that because of <a href="#Scope">scope</a>, the License topic will actually be considered part of Counter the way it&rsquo;s listed above.&nbsp; You&rsquo;d link to it from outside Counter with <code>&lt;Counter.License&gt;</code>.&nbsp; That idea may take some getting used to, but if an extra topic only applies to one class that&rsquo;s actually the most appropriate way to do it.&nbsp; In this case it&rsquo;s a license, so if it applies to the entire project instead you could put the comment above the class to make it global, just like moving a function there would.</p><a name="TextFiles"></a><div class="SubTopic">Text Files</div><p>You can also add additional documentation with text files.&nbsp; If you put a file with a .txt extension in your source tree and start it with a topic line, it&rsquo;s contents will be treated the same as if it were in a comment in your source code.&nbsp; That means you can define multiple topics within it, you can link between them and topics in your source code, and you can use all available formatting options.</p><pre class=Example>Title: License
This file is licensed under the GPL.
I can link to &lt;Counter&gt; and &lt;Counter.Increment&gt;, and
the documentation in that class can even link back
with &lt;License&gt;.
About: Second Topic
I can create a *second* topic in here too, complete
with formatting.
</pre><p>The thing some people forget though is that you <b>must</b> start it with a topic line, like &ldquo;<code>Title: License</code>&rdquo; above.&nbsp; This is how Natural Docs tells it apart from regular text files.</p></div><div class=Topic><a name="AbbreviatedSyntax"></a><div class=TopicTitle>Abbreviated Syntax</div><p>Here&rsquo;s another useful thing you may want to know about.&nbsp; Suppose you have a lot of little things to document, like constants.&nbsp; Writing a separate topic for each one can be very tedious, no matter how much you compress it:</p><pre class=Example>// Constant: COUNTER_NORMAL
// Causes the counter to increment normally.
#define COUNTER_NORMAL 0
// Constant: COUNTER_ODD
// Causes the counter to only increment in odd numbers.
#define COUNTER_ODD 1
// Constant: COUNTER_EVEN
// Causes the counter to only increment in even numbers.
#define COUNTER_EVEN 2
</pre><p>One thing you may have noticed in the <a href="../keywords.html">keyword list</a> is that they almost all have plural forms.&nbsp; These are used to create what are called <a href="reference.html#ListTopics">list topics.</a>&nbsp; You define a topic using a plural keyword, and then anything appearing in a <a href="reference.html#DefinitionLists">definition list</a> within it creates a linkable symbol as if they each had their own topic.&nbsp; For example:</p><pre class=Example>/*
Constants: Counter Modes
COUNTER_NORMAL - Causes the counter to increment normally.
COUNTER_ODD - Causes the counter to only increment in odd numbers.
COUNTER_EVEN - Causes the counter to only increment in even numbers.
*/
#define COUNTER_NORMAL 0
#define COUNTER_ODD 1
#define COUNTER_EVEN 2
</pre><p>I would now be able to write <code>&lt;COUNTER_ODD&gt;</code> and have it work the same as it would with the first example.</p><p>Using the enum or enumeration keyword is special because it automatically behaves in a similar manner.&nbsp; This allows both the enum and its values to be documented in the same place.</p><pre class=Example>/*
Enum: CounterMode
NORMAL - Causes the counter to increment normally.
ODD - Causes the counter to only increment in odd numbers.
EVEN - Causes the counter to only increment in even numbers.
*/
enum CounterMode { NORMAL, ODD, EVEN };
</pre><p>That&rsquo;s it, you&rsquo;re done with this walkthrough.&nbsp; You should know enough now to make very good use of Natural Docs.&nbsp; If you still want to know more, you can look in <a href="reference.html">the reference</a> for some of the smaller details we may have skipped over.&nbsp; Also, look at the Customizing pages on this web site for even more you can do.</p></div></td></tr><tr><td></td><td class=SideMenuBottom><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td class=SideMenuBottomLeft><img src="../images/menu/bottomleft.png" width=18 height=19></td><td class=SideMenuBottomRight><img src="../images/menu/bottomright.png" width=18 height=19></td></tr></table></td><td class=BodyBottom>Copyright &copy; 2003-2008 Greg Valure</td></tr></table><script language=JavaScript><!--
ClosingBrowserTags();// --></script></body></html>

View file

@ -1,528 +0,0 @@
/*
IMPORTANT: If you're editing this file in the output directory of one of
your projects, your changes will be overwritten the next time you run
Natural Docs. Instead, copy this file to your project directory, make your
changes, and you can use it with -s. Even better would be to make a CSS
file in your project directory with only your changes, which you can then
use with -s [original style] [your changes].
On the other hand, if you're editing this file in the Natural Docs styles
directory, the changes will automatically be applied to all your projects
that use this style the next time Natural Docs is run on them.
This file is part of Natural Docs, which is Copyright © 2003-2004 Greg Valure
Natural Docs is licensed under the GPL
*/
body {
font-family: Verdana, Arial, sans-serif;
color: #000000;
margin: 0px; padding: 0px }
body.UnframedPage {
background-color: #E8E8E8 }
a:link,
a:visited { color: #900000; text-decoration: none }
a:hover { color: #900000; text-decoration: underline }
a:active { color: #FF0000; text-decoration: underline }
td {
vertical-align: top }
/*
Comment out this line to use web-style paragraphs (blank line between
paragraphs, no indent) instead of print-style paragraphs (no blank line,
indented.)
*/
p {
text-indent: 5ex; margin: 0 }
/* Can't use something like display: none or it won't break. */
.HB {
font-size: 1px }
body.FramedMenuPage,
.MenuSection {
font-size: 9pt;
background-color: #E8E8E8;
padding: 10px 0 0 0 }
.MenuSection {
width: 27ex }
.MTitle {
font-size: 16pt; font-weight: bold; font-variant: small-caps;
text-align: center;
padding: 5px 10px 15px 10px;
border-bottom: 1px dotted #000000;
margin-bottom: 15px }
.MSubTitle {
font-size: 9pt; font-weight: normal; font-variant: normal;
margin-top: 1ex; margin-bottom: 5px }
.MEntry a:link,
.MEntry a:hover,
.MEntry a:visited { color: #606060; margin-right: 0 }
.MEntry a:active { color: #A00000; margin-right: 0 }
.MGroup {
font-variant: small-caps; font-weight: bold;
margin: 1em 0 1em 10px }
/* Konqueror just can't do margins. */
.KHTML .MGroup {
margin-bottom: 0; padding-bottom: 1em }
.MGroupContent {
font-variant: normal; font-weight: normal }
.MGroup a:link,
.MGroup a:hover,
.MGroup a:visited { color: #545454; margin-right: 10px }
.MGroup a:active { color: #A00000; margin-right: 10px }
.MFile,
.MText,
.MLink,
.MIndex {
padding: 1px 17px 2px 10px;
margin: .25em 0 .25em 0 }
.MText {
font-size: 8pt; font-style: italic }
.MLink {
font-style: italic }
#MSelected {
color: #000000; background-color: #FFFFFF;
/* Replace padding with border. */
padding: 0 10px 0 10px;
border-width: 1px 2px 2px 0; border-style: solid; border-color: #000000;
margin-right: 5px }
/* Close off the left side when its in a group. */
.MGroup #MSelected {
padding-left: 9px; border-left-width: 1px }
/* A treat for Mozilla users. Blatantly non-standard. Will be replaced with CSS 3 attributes when finalized/supported. */
.Gecko #MSelected {
-moz-border-radius-topright: 10px;
-moz-border-radius-bottomright: 10px }
.Gecko .MGroup #MSelected {
-moz-border-radius-topleft: 10px;
-moz-border-radius-bottomleft: 10px }
body.FramedContentPage,
.ContentSection {
background-color: #FFFFFF;
padding-bottom: 15px }
.ContentSection {
border-width: 0 0 1px 1px; border-style: solid; border-color: #000000 }
.CTopic {
font-size: 10pt;
/* This should be a margin but Konq 3.1.1 sucks. */
padding-bottom: 3em }
.CTitle {
font-size: 12pt; font-weight: bold;
border-width: 0 0 1px 0; border-style: solid; border-color: #A0A0A0;
margin: 0 15px .5em 15px }
.CGroup .CTitle {
font-size: 16pt; font-variant: small-caps;
padding-left: 15px; padding-right: 15px;
border-width: 0 0 2px 0; border-color: #000000;
margin-left: 0; margin-right: 0 }
.CClass .CTitle,
.CInterface .CTitle,
.CDatabase .CTitle,
.CDatabaseTable .CTitle,
.CSection .CTitle {
font-size: 18pt;
color: #FFFFFF; background-color: #A0A0A0;
padding: 10px 15px 10px 15px;
border-width: 2px 0; border-color: #000000;
margin-left: 0; margin-right: 0 }
#MainTopic .CTitle {
font-size: 20pt;
color: #FFFFFF; background-color: #7070C0;
padding: 10px 15px 10px 15px;
border-width: 0 0 3px 0; border-color: #000000;
margin-left: 0; margin-right: 0 }
.CBody {
margin-left: 15px; margin-right: 15px }
.CToolTip {
position: absolute; visibility: hidden;
left: 0; top: 0; max-width: 50%;
background-color: #FFFFE0;
padding: 5px;
border-width: 1px 2px 2px 1px; border-style: solid; border-color: #000000;
font-size: 8pt }
/* Opera 6 gives it a huge height otherwise. */
.Opera6 .CTooltip, .Opera5 .CTooltip {
max-width: 100% }
.CHeading {
font-weight: bold; font-size: 10pt;
margin-top: 1.5em; margin-bottom: .5em }
.CCode {
font: 10pt "Courier New", Courier, monospace;
overflow: auto;
}
.CBulletList {
/* I don't know why CBody's margin doesn't apply, but it's consistent across browsers so whatever.
Reapply it here as padding. */
padding-left: 15px; padding-right: 15px;
margin: .5em 5ex .5em 5ex;
}
.CDescriptionList {
margin: .5em 5ex 0 5ex }
/* IE 4 and Konqueror always makes it too long. */
.IE4 .CDescriptionList,
.KHTML .CDescriptionList {
width: 85% }
.CDLEntry {
font: 10pt "Courier New", Courier, monospace; color: #808080;
padding-bottom: .25em;
white-space: nowrap }
.CDLDescription {
font-size: 10pt; /* For browsers that don't inherit correctly, like Opera 5. */
padding-bottom: .5em; padding-left: 5ex }
.CTopic img {
text-align: center;
display: block;
margin: 1em auto;
}
.CImageCaption {
font-variant: small-caps;
font-size: 8pt;
color: #808080;
text-align: center;
position: relative;
top: 1em;
}
.CImageLink {
color: #808080;
font-style: italic;
}
a.CImageLink:link,
a.CImageLink:visited,
a.CImageLink:hover { color: #808080 }
.Prototype {
font: 10pt "Courier New", Courier, monospace;
padding: 5px 3ex;
border-width: 1px; border-style: solid;
margin: 0 5ex 1.5em 5ex;
}
.Prototype td {
font-size: 10pt;
}
.PDefaultValue,
.PTypePrefix {
color: #8F8F8F;
}
.PTypePrefix {
text-align: right;
}
.IE .Prototype table {
padding: 0;
}
.CFunction .Prototype {
background-color: #F4F4F4; border-color: #D0D0D0 }
.CProperty .Prototype {
background-color: #F4F4FF; border-color: #C0C0E8 }
.CVariable .Prototype {
background-color: #FFFFF0; border-color: #E0E0A0 }
.CDatabaseIndex .Prototype,
.CConstant .Prototype {
background-color: #D0D0D0; border-color: #000000 }
.CType .Prototype {
background-color: #FFF8F8; border-color: #E8C8C8 }
.CDatabaseTrigger .Prototype,
.CEvent .Prototype,
.CDelegate .Prototype {
background-color: #F0FCF0; border-color: #B8E4B8 }
.CToolTip .Prototype {
margin: 0 0 .5em 0;
white-space: nowrap;
}
.Summary {
margin: 1.5em 5ex 0 5ex }
.STitle {
font-size: 12pt; font-weight: bold;
margin-bottom: .5em }
.SBorder {
background-color: #FFFFF0;
padding: 15px;
border: 1px solid #C0C060 }
/* Let's observe the evolution of IE's brokeness, shall we?
IE 4 always makes them too long, there's no way around it. */
.IE4 .SBorder {
width: 85% }
/* IE 5 will make them too long unless you set the width to 100%. Isn't this implied for a div? */
.IE5 .SBorder {
width: 100% }
/* IE 6 behaves like 5 when it's in a frame, but without frames it will be correct without a width or slightly too long
(but not enough to scroll) with a width. This arbitrary weirdness simply astounds me. */
body.FramedContentPage .IE6 .SBorder {
width: 100% }
/* A treat for Mozilla users. Blatantly non-standard. Will be replaced with CSS 3 attributes when finalized/supported. */
.Gecko .SBorder {
-moz-border-radius: 20px }
.STable {
font-size: 9pt; width: 100% }
.SEntrySize {
width: 30% }
.SDescriptionSize {
width: 70% }
.SMarked {
background-color: #F8F8D8 }
.SEntry .SIndent1 {
margin-left: 1.5ex }
.SEntry .SIndent2 {
margin-left: 3ex }
.SEntry .SIndent3 {
margin-left: 4.5ex }
.SEntry .SIndent4 {
margin-left: 6ex }
.SEntry .SIndent5 {
margin-left: 7.5ex }
.SDescription {
padding-left: 3ex }
.SDescription a { color: #800000}
.SDescription a:active { color: #A00000 }
.SGroup {
margin-top: .5em; margin-bottom: .25em }
.SGroup .SEntry {
font-weight: bold; font-variant: small-caps }
.SGroup .SEntry a { color: #800000 }
.SGroup .SEntry a:active { color: #F00000 }
.SMain .SEntry,
.SClass .SEntry,
.SDatabase .SEntry,
.SDatabaseTable .SEntry,
.SSection .SEntry {
font-weight: bold; font-size: 10pt;
margin-bottom: .25em }
.SClass,
.SDatabase,
.SDatabaseTable,
.SSection {
margin-top: 1em }
.SMain .SEntry a,
.SClass .SEntry a,
.SDatabase .SEntry a,
.SDatabaseTable .SEntry a,
.SSection .SEntry a { color: #000000 }
.SMain .SEntry a:active,
.SClass .SEntry a:active,
.SDatabase .SEntry a:active,
.SDatabaseTable .SEntry a:active,
.SSection .SEntry a:active { color: #A00000 }
.ClassHierarchy {
margin: 0 15px 1em 15px }
.CHEntry {
border-width: 1px 2px 2px 1px; border-style: solid; border-color: #A0A0A0;
margin-bottom: 3px;
padding: 2px 2ex;
font-size: 10pt;
background-color: #F4F4F4; color: #606060;
}
.Gecko .CHEntry {
-moz-border-radius: 4px;
}
.CHCurrent .CHEntry {
font-weight: bold;
border-color: #000000;
color: #000000;
}
.CHChildNote .CHEntry {
font-style: italic;
font-size: 8pt;
}
.CHIndent {
margin-left: 3ex;
}
.CHEntry a:link,
.CHEntry a:visited,
.CHEntry a:hover {
color: #606060;
}
.CHEntry a:active {
color: #800000;
}
body.FramedIndexPage,
.IndexSection {
background-color: #FFFFFF;
font-size: 10pt;
padding: 15px }
.IndexSection {
border-width: 0 0 1px 1px; border-style: solid; border-color: #000000 }
.IPageTitle {
font-size: 20pt; font-weight: bold;
color: #FFFFFF; background-color: #7070C0;
padding: 10px 15px 10px 15px;
border-width: 0 0 3px 0; border-color: #000000; border-style: solid;
margin: -15px -15px 0 -15px }
.INavigationBar {
text-align: center;
background-color: #FFFFF0;
padding: 5px;
border-bottom: solid 1px black;
margin: 0 -15px 15px -15px }
.INavigationBar a {
font-weight: bold }
.IHeading {
font-size: 16pt; font-weight: bold;
padding: 2.5em 0 .5em 0;
text-align: center;
width: 3.5ex;
}
#IFirstHeading {
padding-top: 0;
}
.IEntry {
padding-left: 1ex; }
.ISubIndex {
padding-left: 3ex; padding-bottom: .5em }
/* While it may cause some entries to look like links when they aren't, I found it's much easier to read the
index if everything's the same color. */
.ISymbol {
font-weight: bold; color: #900000 }
.ISymbolPrefix {
text-align: right;
color: #C47C7C;
background-color: #F8F8F8;
border-right: 3px solid #E0E0E0;
border-left: 1px solid #E0E0E0;
padding: 0 1px 0 2px;
}
#IFirstSymbolPrefix {
border-top: 1px solid #E0E0E0;
}
#ILastSymbolPrefix {
border-bottom: 1px solid #E0E0E0;
}
#IOnlySymbolPrefix {
border-top: 1px solid #E0E0E0;
border-bottom: 1px solid #E0E0E0;
}
a.IParent,
a.IFile {
display: block;
}
.Footer {
font-size: 8pt; color: #909090 }
body.UnframedPage .Footer {
text-align: right;
margin: 2px }
body.FramedMenuPage .Footer {
text-align: center;
margin: 5em 10px 0 10px}
.Footer a:link,
.Footer a:hover,
.Footer a:visited { color: #909090 }
.Footer a:active { color: #A00000 }

View file

@ -1,204 +0,0 @@
//
// Browser Styles
// ____________________________________________________________________________
var agt=navigator.userAgent.toLowerCase();
var browserType;
var browserVer;
if (agt.indexOf("opera") != -1)
{
browserType = "Opera";
if (agt.indexOf("opera 5") != -1 || agt.indexOf("opera/5") != -1)
{ browserVer = "Opera5"; }
else if (agt.indexOf("opera 6") != -1 || agt.indexOf("opera/6") != -1)
{ browserVer = "Opera6"; }
else if (agt.indexOf("opera 7") != -1 || agt.indexOf("opera/7") != -1)
{ browserVer = "Opera7"; }
}
else if (agt.indexOf("khtml") != -1 || agt.indexOf("konq") != -1 || agt.indexOf("safari") != -1)
{
browserType = "KHTML";
}
else if (agt.indexOf("msie") != -1)
{
browserType = "IE";
if (agt.indexOf("msie 4") != -1)
{ browserVer = "IE4"; }
else if (agt.indexOf("msie 5") != -1)
{ browserVer = "IE5"; }
else if (agt.indexOf("msie 6") != -1)
{ browserVer = "IE6"; }
}
else if (agt.indexOf("gecko") != -1)
{
browserType = "Gecko";
}
// Opera already taken care of.
else if (agt.indexOf("mozilla") != -1 && agt.indexOf("compatible") == -1 && agt.indexOf("spoofer") == -1 &&
agt.indexOf("webtv") == -1 && agt.indexOf("hotjava") == -1)
{
browserType = "Netscape";
if (agt.indexOf("mozilla/4") != -1)
{ browserVer = "Netscape4"; }
}
//
// Menu
// ____________________________________________________________________________
function ToggleMenu(id)
{
if (!window.document.getElementById)
{ return; };
var display = window.document.getElementById(id).style.display;
if (display == "none")
{ display = "block"; }
else
{ display = "none"; }
window.document.getElementById(id).style.display = display;
}
//
// Tooltips
// ____________________________________________________________________________
var tooltipTimer = 0;
function ShowTip(event, tooltipID, linkID)
{
if (tooltipTimer)
{ clearTimeout(tooltipTimer); };
var docX = event.clientX + window.pageXOffset;
var docY = event.clientY + window.pageYOffset;
var showCommand = "ReallyShowTip('" + tooltipID + "', '" + linkID + "', " + docX + ", " + docY + ")";
// KHTML cant handle showing on a timer right now.
if (browserType != "KHTML")
{ tooltipTimer = setTimeout(showCommand, 1000); }
else
{ eval(showCommand); };
}
function ReallyShowTip(tooltipID, linkID, docX, docY)
{
tooltipTimer = 0;
var tooltip;
var link;
if (document.getElementById)
{
tooltip = document.getElementById(tooltipID);
link = document.getElementById(linkID);
}
else if (document.all)
{
tooltip = eval("document.all['" + tooltipID + "']");
link = eval("document.all['" + linkID + "']");
}
if (tooltip)
{
var left = 0;
var top = 0;
// Not everything supports offsetTop/Left/Width, and some, like Konqueror and Opera 5, think they do but do it badly.
if (link && link.offsetWidth != null && browserType != "KHTML" && browserVer != "Opera5")
{
var item = link;
while (item != document.body)
{
left += item.offsetLeft;
item = item.offsetParent;
}
item = link;
while (item != document.body)
{
top += item.offsetTop;
item = item.offsetParent;
}
top += link.offsetHeight;
}
// The fallback method is to use the mouse X and Y relative to the document. We use a separate if and test if its a number
// in case some browser snuck through the above if statement but didn't support everything.
if (!isFinite(top) || top == 0)
{
left = docX;
top = docY;
}
// Some spacing to get it out from under the cursor.
top += 10;
// Make sure the tooltip doesnt get smushed by being too close to the edge, or in some browsers, go off the edge of the
// page. We do it here because Konqueror does get offsetWidth right even if it doesnt get the positioning right.
if (tooltip.offsetWidth != null)
{
var width = tooltip.offsetWidth;
var docWidth = document.body.clientWidth;
if (left + width > docWidth)
{ left = docWidth - width - 1; }
}
// Opera 5 chokes on the px extension, so it can use the Microsoft one instead.
if (tooltip.style.left != null && browserVer != "Opera5")
{
tooltip.style.left = left + "px";
tooltip.style.top = top + "px";
}
else if (tooltip.style.pixelLeft != null)
{
tooltip.style.pixelLeft = left;
tooltip.style.pixelTop = top;
}
tooltip.style.visibility = "visible";
}
}
function HideTip(tooltipID)
{
if (tooltipTimer)
{
clearTimeout(tooltipTimer);
tooltipTimer = 0;
}
var tooltip;
if (document.getElementById)
{ tooltip = document.getElementById(tooltipID); }
else if (document.all)
{ tooltip = eval("document.all['" + tooltipID + "']"); }
if (tooltip)
{ tooltip.style.visibility = "hidden"; }
}

View file

@ -1,90 +0,0 @@
@import URL(example/Default.css);
.NDContent {
color: #000000; background-color: #FFFFFF;
padding: 15px 0;
border-style: solid;
border-width: 1px 3px 3px 1px;
border-color: #c0c0c0 #808080 #808080 #c0c0c0;
margin: 1em 5ex;
-moz-border-radius: 12px;
}
.NDContent p,
.NDContent li,
.NDContent td,
.NDMenu td,
.NDSummary td,
.NDIndex td {
font-size: 10pt;
line-height: normal;
}
.NDContent .CTopic {
padding-bottom: 0;
}
.Prototype td {
font: 10pt Courier New, monospace;
}
.NDIndex .IHeading {
font-size: 16pt;
}
.NDMenu {
font: 9pt Verdana, Arial, sans-serif;
color: #000000; background-color: #E8E8E8;
width: 27ex;
padding: 10px 0;
border-style: solid;
border-width: 1px 3px 3px 1px;
border-color: #808080 #606060 #606060 #808080;
margin: 1em 0 1em 5ex;
-moz-border-radius: 12px;
}
.NDFooter {
font: 8pt Verdana, Arial, sans-serif;
color: #909090; background-color: #E8E8E8;
border-style: solid;
border-width: 1px 3px 3px 1px;
border-color: #808080 #606060 #606060 #808080;
margin: 1em 0 1em 5ex;
-moz-border-radius: 12px;
}
.NDFooter td {
font-size: 8pt;
padding: 0 2ex;
}
.NDFooter a:link,
.NDFooter a:hover,
.NDFooter a:visited { color: #909090 }
.NDFooter a:active { color: #A00000 }
.NDSummary {
padding: 15px;
border-style: solid;
border-width: 1px 3px 3px 1px;
border-color: #c0c0c0 #808080 #808080 #c0c0c0;
margin: 1em 5ex;
-moz-border-radius: 12px;
}
.NDSummary .Summary {
margin-top: 0;
}
.NDIndex {
color: #000000; background-color: #FFFFFF;
padding: 15px;
border-style: solid;
border-width: 1px 3px 3px 1px;
border-color: #c0c0c0 #808080 #808080 #c0c0c0;
margin: 1em 5ex;
-moz-border-radius: 12px;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 188 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 397 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 507 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 575 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 390 B

View file

@ -1,9 +0,0 @@
<html><head><title>Natural Docs</title><link rel=stylesheet type="text/css" href="styles.css"><script language=JavaScript src="javascript/PNGHandling.js"></script><script language=JavaScript src="javascript/BrowserStyles.js"></script></head><body marginwidth=0 marginheight=0 leftmargin=0 topmargin=0><script language=JavaScript><!--
OpeningBrowserTags();// --></script>
<!-- saved from url=(0026)http://www.naturaldocs.org -->
<table width=100% border=0 cellspacing=0 cellpadding=0><tr><td colspan=3 class=Header><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td><img src="images/header/leftside.png" width=30 height=75><a href="index.html"><img src="images/header/logo.png" width=524 height=75 alt="Natural Docs"></a></td><td align=right><img src="images/header/rightside.png" width=30 height=75></td></tr></table></td></tr><tr><td><img src="images/header/overleftmargin.png" width=10 height=6></td><td class=SideMenuTop><img src="images/header/overmenu.png" width=14 height=6></td><td class=BodyTop><img src="images/header/overbody.png" width=24 height=6></td></tr><tr><td></td><td class=SideMenu nowrap><div class=SideMenuSection><div class=SideMenuTitle><img src="images/menu/about.png" width=52 height=13 alt="About"></div><div class=SideMenuBody><a href="languages.html" class=SideMenuEntry>Language Support</a><a href="output.html" class=SideMenuEntry>Output Formats</a></div></div><div class=SideMenuSection><div class=SideMenuTitle><img src="images/menu/using.png" width=45 height=13 alt="Using"></div><div class=SideMenuBody><a href="documenting.html" class=SideMenuEntry>Documenting<br>Your Code</a><a href="keywords.html" class=SideMenuEntry>Keywords</a><a href="running.html" class=SideMenuEntry>Running</a><a href="troubleshooting.html" class=SideMenuEntry>Troubleshooting</a></div></div><div class=SideMenuSection><div class=SideMenuTitle><img src="images/menu/customizing.png" width=96 height=13 alt="Customizing"></div><div class=SideMenuBody><a href="menu.html" class=SideMenuEntry>Organizing the Menu</a><a href="styles.html" class=SideMenuEntry>CSS Styles</a><a href="customizingtopics.html" class=SideMenuEntry>Topics and Keywords</a><a href="customizinglanguages.html" class=SideMenuEntry>Languages, Indexes,<br>and Prototypes</a></div></div><div class=SideMenuSection><div class=SideMenuTitle><img src="images/menu/community.png" width=86 height=13 alt="Community"></div><div class=SideMenuBody><a href="http://www.naturaldocs.org/" class=SideMenuEntry>Web Site</a><a href="http://www.naturaldocs.org/mailinglist.html" class=SideMenuEntry>Mailing Lists</a><a href="http://www.naturaldocs.org/messageboards.html" class=SideMenuEntry>Message Boards</a><a href="http://www.naturaldocs.org/bugs.html" class=SideMenuEntry>Bugs and<br>Feature Requests</a></div></div></td><td class=Body width=100%><div class=PageTitle>Version 1.4</div><div class=Topic><p>This is the Natural Docs help file, a subset of the documentation available at <a href="http://www.naturaldocs.org">the web site</a>.&nbsp; Everything you need is on the menu to the left.</p></div></td></tr><tr><td></td><td class=SideMenuBottom><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td class=SideMenuBottomLeft><img src="images/menu/bottomleft.png" width=18 height=19></td><td class=SideMenuBottomRight><img src="images/menu/bottomright.png" width=18 height=19></td></tr></table></td><td class=BodyBottom>Copyright &copy; 2003-2008 Greg Valure</td></tr></table><script language=JavaScript><!--
ClosingBrowserTags();// --></script></body></html>

View file

@ -1,77 +0,0 @@
//
// Browser Styles
// ____________________________________________________________________________
var agt=navigator.userAgent.toLowerCase();
var browserType;
var browserVer;
if (agt.indexOf("opera") != -1)
{
browserType = "Opera";
if (agt.indexOf("opera 5") != -1 || agt.indexOf("opera/5") != -1)
{ browserVer = "Opera5"; }
else if (agt.indexOf("opera 6") != -1 || agt.indexOf("opera/6") != -1)
{ browserVer = "Opera6"; }
else if (agt.indexOf("opera 7") != -1 || agt.indexOf("opera/7") != -1)
{ browserVer = "Opera7"; }
}
else if (agt.indexOf("khtml") != -1 || agt.indexOf("konq") != -1 || agt.indexOf("safari") != -1)
{
browserType = "KHTML";
}
else if (agt.indexOf("msie") != -1)
{
browserType = "IE";
if (agt.indexOf("msie 4") != -1)
{ browserVer = "IE4"; }
else if (agt.indexOf("msie 5") != -1)
{ browserVer = "IE5"; }
else if (agt.indexOf("msie 6") != -1)
{ browserVer = "IE6"; }
else if (agt.indexOf("msie 7") != -1)
{ browserVer = "IE7"; }
}
else if (agt.indexOf("gecko") != -1)
{
browserType = "Gecko";
}
// Opera already taken care of.
else if (agt.indexOf("mozilla") != -1 && agt.indexOf("compatible") == -1 && agt.indexOf("spoofer") == -1 &&
agt.indexOf("webtv") == -1 && agt.indexOf("hotjava") == -1)
{
browserType = "Netscape";
if (agt.indexOf("mozilla/4") != -1)
{ browserVer = "Netscape4"; }
}
function OpeningBrowserTags()
{
if (browserType)
{
document.write('<div class='+browserType+'>');
if (browserVer)
{ document.write('<div class='+browserVer+'>'); }
}
};
function ClosingBrowserTags()
{
if (browserType)
{
document.write('</div>');
if (browserVer)
{ document.write('</div>'); }
}
};

View file

@ -1,72 +0,0 @@
// Parts derived from:
// Opacity Displayer, Version 1.0
// Copyright Michael Lovitt, 6/2002.
// Distribute freely, but please leave this notice intact.
// http://www.alistapart.com/articles/pngopacity/
// Parts derived from:
// Natural Docs
// Copyright (C) 2003-2004 Greg Valure
// http://www.naturaldocs.org/
var pngTransform;
var pngNormal;
var agt=navigator.userAgent.toLowerCase();
if (agt.indexOf("opera") != -1)
{
if ( (agt.indexOf("opera 5") != -1 || agt.indexOf("opera/5") != -1) &&
agt.indexOf("mac") != -1)
{
pngNormal = 1;
}
else if (agt.indexOf("opera 6") != -1 || agt.indexOf("opera/6") != -1 ||
agt.indexOf("opera 7") != -1 || agt.indexOf("opera/7") != -1)
{
pngNormal = 1;
}
}
else if (agt.indexOf("msie") != -1)
{
if (agt.indexOf("msie 5.5") != -1 || agt.indexOf("msie 6") != -1)
{
if (agt.indexOf("mac") != -1)
{ pngNormal = 1; }
else if (agt.indexOf("win") != -1)
{ pngTransform = 1; };
}
else if (agt.indexOf("msie 5") != -1)
{
if (agt.indexOf("mac") != -1)
{ pngNormal = 1; };
}
else if (agt.indexOf("msie 7") != -1)
{ pngNormal = 1; }
}
else if (agt.indexOf("gecko") != -1)
{
pngNormal = 1;
}
function PNGGIF(strPath, intWidth, intHeight, strAlt, strID)
{
if (pngTransform)
{
document.write('<div style="height:'+intHeight+'px;width:'+intWidth+'px;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\''+strPath+'.png\', sizingMethod=\'scale\')" id="'+strID+'"></div>');
}
else if (pngNormal)
{
document.write('<img src="'+strPath+'.png" width="'+intWidth+'" height="'+intHeight+'" alt="'+strAlt+'" id="'+strID+'"/>');
}
else
{
document.write('<img src="'+strPath+'.gif" width="'+intWidth+'" height="'+intHeight+'" alt="'+strAlt+'" id="'+strID+'" />');
}
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,79 +0,0 @@
<html><head><title>Organizing the Menu - Natural Docs</title><link rel=stylesheet type="text/css" href="styles.css"><link rel=stylesheet type="text/css" href="examples.css"><style type="text/css"><!--
.TimestampTable {
margin: 1em 4ex;
}
.TimestampTable td {
padding: 0 3ex 0 0;
vertical-align: bottom;
}
--></style><script language=JavaScript src="javascript/PNGHandling.js"></script><script language=JavaScript src="javascript/BrowserStyles.js"></script><script language=JavaScript src="example/NaturalDocs.js"></script></head><body marginwidth=0 marginheight=0 leftmargin=0 topmargin=0><script language=JavaScript><!--
OpeningBrowserTags();// --></script>
<!-- saved from url=(0026)http://www.naturaldocs.org -->
<table width=100% border=0 cellspacing=0 cellpadding=0><tr><td colspan=3 class=Header><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td><img src="images/header/leftside.png" width=30 height=75><a href="index.html"><img src="images/header/logo.png" width=524 height=75 alt="Natural Docs"></a></td><td align=right><img src="images/header/rightside.png" width=30 height=75></td></tr></table></td></tr><tr><td><img src="images/header/overleftmargin.png" width=10 height=6></td><td class=SideMenuTop><img src="images/header/overmenu.png" width=14 height=6></td><td class=BodyTop><img src="images/header/overbody.png" width=24 height=6></td></tr><tr><td></td><td class=SideMenu nowrap><div class=SideMenuSection><div class=SideMenuTitle><img src="images/menu/about.png" width=52 height=13 alt="About"></div><div class=SideMenuBody><a href="languages.html" class=SideMenuEntry>Language Support</a><a href="output.html" class=SideMenuEntry>Output Formats</a></div></div><div class=SideMenuSection><div class=SideMenuTitle><img src="images/menu/using.png" width=45 height=13 alt="Using"></div><div class=SideMenuBody><a href="documenting.html" class=SideMenuEntry>Documenting<br>Your Code</a><a href="keywords.html" class=SideMenuEntry>Keywords</a><a href="running.html" class=SideMenuEntry>Running</a><a href="troubleshooting.html" class=SideMenuEntry>Troubleshooting</a></div></div><div class=SideMenuSection><div class=SideMenuTitle><img src="images/menu/customizing.png" width=96 height=13 alt="Customizing"></div><div class=SideMenuBody><span class=SideMenuEntry id=SelectedSideMenuEntry>Organizing the Menu</span><a href="styles.html" class=SideMenuEntry>CSS Styles</a><a href="customizingtopics.html" class=SideMenuEntry>Topics and Keywords</a><a href="customizinglanguages.html" class=SideMenuEntry>Languages, Indexes,<br>and Prototypes</a></div></div><div class=SideMenuSection><div class=SideMenuTitle><img src="images/menu/community.png" width=86 height=13 alt="Community"></div><div class=SideMenuBody><a href="http://www.naturaldocs.org/" class=SideMenuEntry>Web Site</a><a href="http://www.naturaldocs.org/mailinglist.html" class=SideMenuEntry>Mailing Lists</a><a href="http://www.naturaldocs.org/messageboards.html" class=SideMenuEntry>Message Boards</a><a href="http://www.naturaldocs.org/bugs.html" class=SideMenuEntry>Bugs and<br>Feature Requests</a></div></div></td><td class=Body width=100%><div class=PageTitle>Organizing the Menu</div><div class=TOC><a href="#OrderAndTitles">Order and Titles</a> &middot; <a href="#Grouping">Grouping</a> &middot; <a href="#IndexesAndSearch">Indexes and Search</a> &middot; <a href="#AutomaticChanges">Automatic Changes</a><br><a href="#Extras">Extras</a> &middot; <a href="#Errors">Errors</a> &middot; <a href="#PortabilityAndVersioningSystems">Portability and Versioning Systems</a></div><div class=Topic><p>Natural Docs creates a file called <code>Menu.txt</code> in your <a href="running.html#CommandLine">project directory</a> that you can edit to organize the menu.&nbsp; It normally takes care of this on its own, but you have the option of improving it manually if you want to.</p></div><div class=Topic><a name="OrderAndTitles"></a><div class=TopicTitle>Order and Titles</div><p>If you&rsquo;ve never looked in it before, the menu file will have some comments explaining its syntax and a list like you see below.</p><pre class=Example>File: ClassA (ClassA.h)
File: ClassB (ClassB.h)
File: Globals (Globals.h)
</pre><p>The list gets turned into a menu that looks like this:</p><table class=NDMenu><tr><td><div class=MEntry><div class=MFile><a href="#" onClick="return false;">ClassA</a></div></div><div class=MEntry><div class=MFile><a href="#" onClick="return false;">ClassB</a></div></div><div class=MEntry><div class=MFile><a href="#" onClick="return false;">Globals</a></div></div></td></tr></table><p>The lines are in the format &ldquo;<code>File: <i>[title]</i> (<i>[filename]</i>)</code>&rdquo;.&nbsp; When Natural Docs made the menu, it decided on its own what the title of each file should be and then put them in alphabetical order.&nbsp; However, suppose we don&rsquo;t want this.&nbsp; We want Globals above the classes and we want spaces in the menu titles.&nbsp; So we edit the file.</p><pre class=Example>File: Globals (Globals.h)
File: Class A (ClassA.h)
File: Class B (ClassB.h)
</pre><p>Run Natural Docs again and the menu is updated.</p><table class=NDMenu><tr><td><div class=MEntry><div class=MFile><a href="#" onClick="return false;">Globals</a></div></div><div class=MEntry><div class=MFile><a href="#" onClick="return false;">Class A</a></div></div><div class=MEntry><div class=MFile><a href="#" onClick="return false;">Class B</a></div></div></td></tr></table><p>However, open the menu file again and you&rsquo;ll see something interesting.</p><pre class=Example>File: Globals (Globals.h)
File: Class A (no auto-title, ClassA.h)
File: Class B (no auto-title, ClassB.h)
</pre><p>Natural Docs noticed that you changed a couple of the titles and added a <code>no auto-title</code> attribute to each one.&nbsp; This tells it to never change them on it&rsquo;s own in the future, so your changes won&rsquo;t be lost.&nbsp; You don&rsquo;t have to worry about adding this, Natural Docs will always do it automatically.&nbsp; However, to go back to automatic titles you&rsquo;d have to manually remove it.</p></div><div class=Topic><a name="Grouping"></a><div class=TopicTitle>Grouping</div><p>This menu is good for our example, but in the real world they get much, much longer.&nbsp; We can add groups to organize it further.&nbsp; Natural Docs will create them automatically based on the each file&rsquo;s directory, but once again you can improve it manually if that&rsquo;s not good enough.</p><p>You can add groups as shown below.</p><pre class=Example>File: Globals (Globals.h)
Group: Classes {
File: Class A (no auto-title, ClassA.h)
File: Class B (no auto-title, ClassB.h) }
</pre><table class=NDMenu><tr><td><div class=MEntry><div class=MFile><a href="#" onClick="return false;">Globals</a></div></div><div class=MEntry><div class=MGroup><a href="javascript:ToggleMenu('MenuGroup11');">Classes</a><div class=MGroupContent id=MenuGroup11><div class=MEntry><div class=MFile><a href="#" onClick="return false;">Class A</a></div></div><div class=MEntry><div class=MFile><a href="#" onClick="return false;">Class B</a></div></div></div></div></div></td></tr></table><p>You can also nest them inside each other.</p><pre class=Example>File: Globals (Globals.h)
Group: Classes {
File: Class A (no auto-title, ClassA.h)
Group: Nested Group {
File: Class B (no auto-title, ClassB.h) }
}
</pre><table class=NDMenu><tr><td><div class=MEntry><div class=MFile><a href="#" onClick="return false;">Globals</a></div></div><div class=MEntry><div class=MGroup><a href="javascript:ToggleMenu('MenuGroup21');">Classes</a><div class=MGroupContent id=MenuGroup21><div class=MEntry><div class=MFile><a href="#" onClick="return false;">Class A</a></div></div><div class=MEntry><div class=MGroup><a href="javascript:ToggleMenu('MenuGroup22');">Nested Group</a><div class=MGroupContent id=MenuGroup22><div class=MEntry><div class=MFile><a href="#" onClick="return false;">Class B</a></div></div></div></div></div></div></div></div></td></tr></table><p>We&rsquo;ll get rid of the nested group because it doesn&rsquo;t make sense for our example.&nbsp; Run Natural Docs, open up the menu file again and take a look.</p><pre class=Example>File: Globals (Globals.h)
Group: Classes {
File: Class A (no auto-title, ClassA.h)
File: Class B (no auto-title, ClassB.h)
} # Group: Classes
</pre><p>Natural Docs reformatted it.&nbsp; When you&rsquo;re organizing the menu, you don&rsquo;t have to worry about the indentation or otherwise keeping it neat.&nbsp; The file is reformatted every time it changes, so you can make quick and dirty edits and Natural Docs will keep it readable.</p><p>Besides breaking up long lists, groups also serve another purpose.&nbsp; Clicking on them will make it expand and collapse.&nbsp; Go ahead and try it in the examples above.&nbsp; When the menu gets too long its groups will start being collapsed by default, allowing easier navigation on large projects where it would just be impractical to show everything at once.</p></div><div class=Topic><a name="IndexesAndSearch"></a><div class=TopicTitle>Indexes and Search</div><p>Natural Docs will automatically determine what indexes your project needs and add them to the menu.&nbsp; Anything indexed will also be used for the search feature.&nbsp; The entries will look like this:</p><pre class=Example>Group: Index {
Index: Everything
Class Index: Classes
Function Index: Functions
} # Group: Index
</pre><p>Like the file entries we saw before, you can rename them by editing the title and reorder them by cutting and pasting.&nbsp; However, if you decide you don&rsquo;t want a particular index to be generated, just delete its entry and it will go away.&nbsp; Just like before, Natural Docs will detect this and add something new:</p><pre class=Example>Don't Index: Functions
</pre><p>As with <code>no auto-title</code>, Natural Docs adds this automatically to make sure it doesn&rsquo;t later undo your changes.</p></div><div class=Topic><a name="AutomaticChanges"></a><div class=TopicTitle>Automatic Changes</div><p>Natural Docs tries to manage the menu on its own as much as possible so you don&rsquo;t have to worry about it.&nbsp; This is just a peek into some of the things it does so you know what to expect.</p><p>You already saw that by default Natural Docs tries to guess what title should be for each file.&nbsp; If you leave it this way, Natural Docs will always update the menu for you if the file&rsquo;s content changes significantly enough to change its guess, such as if you rename the first class defined in it.&nbsp; If you&rsquo;d like to take advantage of this to define the menu title in each source file instead of in the menu itself, add a &ldquo;<code>Title: [title]</code>&rdquo; comment to the top of the file.</p><p>When you add and delete source files, Natural Docs will automatically add and remove them from the menu file.&nbsp; When adding one it will look for the best group to put it in by directory.&nbsp; If your grouping mirrors the source tree somewhat, this will be a lot more accurate.&nbsp; Also, if the group it&rsquo;s putting it in is alphabetized, Natural Docs will put it in the correct place to maintain that alphabetization.&nbsp; In fact, even if an existing file&rsquo;s automatic title changes, it will change it&rsquo;s position to make sure a previously alphabetized group stays that way.</p><p>There are exceptions in alphabetization for the indexes.&nbsp; If a group only contains indexes, it can be the last item on the menu or in its parent group without making it count as unsorted.&nbsp; Also, within groups that only contain indexes, the general index can be first, also without making the group count as unsorted.</p><p>Finally, if Natural Docs adds some files to a group that causes it to become too long, it will attempt to sub-group it based on directory.&nbsp; However, it will <i>only</i> do this when its adding files on its own, so you don&rsquo;t have to worry about it constantly messing up your groups.&nbsp; Since new files aren&rsquo;t added to a project that often, if you change the menu manually it should stay that way for quite some time.</p></div><div class=Topic><a name="Extras"></a><div class=TopicTitle>Extras</div><p>There&rsquo;s more you can do with the menu than just renaming and reorganizing its entries.&nbsp; Natural Docs has a few extras you can add to it as well.</p><a name="TitleAndSubtitle"></a><div class="SubTopic">Title and Subtitle</div><p>You can add a title and subtitle to your menu.</p><pre class=Example>Title: My Project
SubTitle: Something That Does Something
File: Globals (Globals.h)
Group: Classes
File: Class A (no auto-title, ClassA.h)
File: Class B (no auto-title, ClassB.h)
</pre><table class=NDMenu><tr><td><div class=MTitle>My Project<div class=MSubTitle>Something That Does Something</div></div><div class=MEntry><div class=MFile><a href="#" onClick="return false;">Globals</a></div></div><div class=MEntry><div class=MGroup><a href="javascript:ToggleMenu('MenuGroup31');">Classes</a><div class=MGroupContent id=MenuGroup31><div class=MEntry><div class=MFile><a href="#" onClick="return false;">Class A</a></div></div><div class=MEntry><div class=MFile><a href="#" onClick="return false;">Class B</a></div></div></div></div></div></td></tr></table><p>In addition to adding the title to the menu, the Title tag will also change the HTML page titles from &ldquo;<i>Class A</i>&rdquo; to &ldquo;<i>Class A - My Project</i>&rdquo;, making bookmarks clearer.</p><a name="TextAndWebLinks"></a><div class="SubTopic">Text and Web Links</div><p>You can also add arbitrary text and web links to your menu.</p><pre class=Example>File: Globals (Globals.h)
Group: Classes {
Text: I couldn't think of good names for these classes.
File: Class A (no auto-title, ClassA.h)
File: Class B (no auto-title, ClassB.h)
}
Link: Built with Natural Docs (http://www.naturaldocs.org)
</pre><table class=NDMenu><tr><td><div class=MEntry><div class=MFile><a href="#" onClick="return false;">Globals</a></div></div><div class=MEntry><div class=MGroup><a href="javascript:ToggleMenu('MenuGroup51');">Classes</a><div class=MGroupContent id=MenuGroup51><div class=MEntry><div class=MText>I couldn&rsquo;t think of good names for these classes.</div></div><div class=MEntry><div class=MFile><a href="#" onClick="return false;">Class A</a></div></div><div class=MEntry><div class=MFile><a href="#" onClick="return false;">Class B</a></div></div></div></div></div><div class=MEntry><div class=MLink><a href="#" onClick="return false;">Built with Natural Docs</a></div></div></td></tr></table><p>Even though comments use the # character, adding an anchor to a link (such as &ldquo;http://www.website.com/page.html#anchor&rdquo;) will still work.</p><a name="Footers"></a><div class="SubTopic">Footers</div><p>Finally, you can add a footer to all your pages, such as a copyright notice.&nbsp; Natural Docs will change any (c)&rsquo;s it finds into real copyright symbols.</p><pre class=Example>Footer: Copyright (C) 2008 Me
</pre><table class=NDFooter><tr><td>Copyright &copy; 2008 Me&nbsp; &middot;&nbsp; <a href="http://www.naturaldocs.org">Generated by Natural Docs</a></td></tr></table><p>You can also add a timestamp in any format you want.&nbsp; The tokens you can use in building it are:</p><p><table class=TimestampTable></p><p><tr><td><code>m</code></td><td>One or two digit month.</td><td>January is &ldquo;1&rdquo;</td></tr></p><p><tr><td><code>mm</code></td><td>Always two digit month.</td><td>January is &ldquo;01&rdquo;</td></tr></p><p><tr><td><code>mon</code></td><td>Short month word.</td><td>January is &ldquo;Jan&rdquo;</td></tr></p><p><tr><td><code>month</code></td><td>Long month word.</td><td>January is &ldquo;January&rdquo;</td></tr></p><p><tr><td><code>d</code></td><td>One or two digit day.</td><td>1 is &ldquo;1&rdquo;</td></tr></p><p><tr><td><code>dd</code></td><td>Always two digit day.</td><td>1 is &ldquo;01&rdquo;</td></tr></p><p><tr><td><code>day</code></td><td>Day with letter extension.</td><td>1 is &ldquo;1st&rdquo;</td></tr></p><p><tr><td><code>yy</code></td><td>Two digit year.</td><td>2008 is &ldquo;08&rdquo;</td></tr></p><p><tr><td><code>yyyy</code></td><td>Four digit year.</td><td>2008 is &ldquo;2008&rdquo;</td></tr></p><p><tr><td><code>year</code></td><td>Four digit year.</td><td>2008 is &ldquo;2008&rdquo;</td></tr></p><p></table></p><p>Everything else appears literally, so we can add:</p><pre class=Example>Timestamp: Updated month day, year
</pre><p>and get:</p><table class=NDFooter><tr><td>Copyright &copy; 2008 Me&nbsp; &middot;&nbsp; Updated January 1st, 2008&nbsp; &middot;&nbsp; <a href="http://www.naturaldocs.org">Generated by Natural Docs</a></td></tr></table></div><div class=Topic><a name="Errors"></a><div class=TopicTitle>Errors</div><p>If there&rsquo;s ever an error in the menu file, Natural Docs will tell you when it&rsquo;s run.&nbsp; It also adds a comment for each one in the menu file itself so that you can search for them in a text editor.</p><pre class=Example># There is an error in this file. Search for ERROR to find it.
File: Globals (Globals.h)
Group: Classes {
# ERROR: Txet is not a valid keyword.
Txet: I couldn't think of good names for these classes.
File: Class A (no auto-title, ClassA.h)
File: Class B (no auto-title, ClassB.h)
}
</pre><p>Remember that Natural Docs reformats the menu file whenever it&rsquo;s run, so you only need to correct the error.&nbsp; Natural Docs will remove the error comments on its own.</p></div><div class=Topic><a name="PortabilityAndVersioningSystems"></a><div class=TopicTitle>Portability and Versioning Systems</div><p>If you only use <a href="running.html">one input directory</a>, all the files in the menu will have relative paths.&nbsp; However, if you have more Natural Docs will use the absolute path instead.</p><p>This is not a problem.&nbsp; The menu file can still be shared between machines even if they don&rsquo;t keep the source tree in the exact same location.&nbsp; As long as you have the same layout within the source tree and point to the same base directories in the command line, Natural Docs will be able to convert the paths automatically for the new machine.</p><p>However, if you&rsquo;re putting the menu file in a versioning system like Subversion or SourceSafe, it might be very desirable to only have relative paths so anybody can check it in and only the real changes show.&nbsp; In that case, instead of using multiple input directories, see if it&rsquo;s possible to only have one input directory and use the <a href="running.html#CommandLine"><code>-xi</code> command line option</a> to exclude the subdirectories you don&rsquo;t want scanned.</p></div><div class=Topic><a name="ThatsIt"></a><div class=TopicTitle>That&rsquo;s It!</div><p>And we&rsquo;re done.&nbsp; The syntax to do all of this is included in the menu file itself, so you don&rsquo;t need to memorize everything.&nbsp; You shouldn&rsquo;t need to organize the menu very often, just after a lot of new files have been added and if you don&rsquo;t like the default.</p><p>Note that if you&rsquo;re using the non-framed HTML output format, changing the menu does require every output file to be updated.&nbsp; However, Natural Docs has a special process just for this so it won&rsquo;t take nearly as long as if it were rebuilding them all from scratch.&nbsp; Still, if you&rsquo;re working on a large project, it may be worth considering the framed HTML output format.</p></div></td></tr><tr><td></td><td class=SideMenuBottom><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td class=SideMenuBottomLeft><img src="images/menu/bottomleft.png" width=18 height=19></td><td class=SideMenuBottomRight><img src="images/menu/bottomright.png" width=18 height=19></td></tr></table></td><td class=BodyBottom>Copyright &copy; 2003-2008 Greg Valure</td></tr></table><script language=JavaScript><!--
ClosingBrowserTags();// --></script></body></html>

View file

@ -1,84 +0,0 @@
<html><head><title>Output Formats - Natural Docs</title><link rel=stylesheet type="text/css" href="styles.css"><style type="text/css"><!--
.FormatTable {
margin-top: 1em;
}
.FormatTable td {
padding-bottom: .5em;
line-height: 150%;
}
.FormatName {
font: bold 12pt Georgia, serif;
padding-left: 5ex;
}
.FormatExample
{
padding-left: 3ex;
}
.FormatDescription {
width: 100%;
padding-left: 3ex;
padding-right: 5ex;
}
.BrowserTable {
margin-top: 1em;
}
.BrowserTable td {
padding-bottom: .5em;
line-height: 150%;
}
.BrowserName {
font: bold 12pt Georgia, serif;
padding-left: 5ex;
}
.BrowserSubNames {
font: italic 8pt Georgia, serif;
}
.BrowserVersion {
padding-left: 3ex;
}
.BrowserDescription {
width: 100%;
line-height: 150%;
padding-left: 3ex;
padding-right: 5ex;
}
.FormatExample,
.FormatDescription,
.BrowserVersion,
.BrowserDescription {
padding-top: 4px;
}
.IE .FormatExample,
.IE .FormatDescription,
.IE .BrowserVersion,
.IE .BrowserDescription {
padding-top: 3px;
}
.IE .FormatTable,
.IE .BrowserTable {
}
--></style><script language=JavaScript src="javascript/PNGHandling.js"></script><script language=JavaScript src="javascript/BrowserStyles.js"></script></head><body marginwidth=0 marginheight=0 leftmargin=0 topmargin=0><script language=JavaScript><!--
OpeningBrowserTags();// --></script>
<!-- saved from url=(0026)http://www.naturaldocs.org -->
<table width=100% border=0 cellspacing=0 cellpadding=0><tr><td colspan=3 class=Header><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td><img src="images/header/leftside.png" width=30 height=75><a href="index.html"><img src="images/header/logo.png" width=524 height=75 alt="Natural Docs"></a></td><td align=right><img src="images/header/rightside.png" width=30 height=75></td></tr></table></td></tr><tr><td><img src="images/header/overleftmargin.png" width=10 height=6></td><td class=SideMenuTop><img src="images/header/overmenu.png" width=14 height=6></td><td class=BodyTop><img src="images/header/overbody.png" width=24 height=6></td></tr><tr><td></td><td class=SideMenu nowrap><div class=SideMenuSection><div class=SideMenuTitle><img src="images/menu/about.png" width=52 height=13 alt="About"></div><div class=SideMenuBody><a href="languages.html" class=SideMenuEntry>Language Support</a><span class=SideMenuEntry id=SelectedSideMenuEntry>Output Formats</span></div></div><div class=SideMenuSection><div class=SideMenuTitle><img src="images/menu/using.png" width=45 height=13 alt="Using"></div><div class=SideMenuBody><a href="documenting.html" class=SideMenuEntry>Documenting<br>Your Code</a><a href="keywords.html" class=SideMenuEntry>Keywords</a><a href="running.html" class=SideMenuEntry>Running</a><a href="troubleshooting.html" class=SideMenuEntry>Troubleshooting</a></div></div><div class=SideMenuSection><div class=SideMenuTitle><img src="images/menu/customizing.png" width=96 height=13 alt="Customizing"></div><div class=SideMenuBody><a href="menu.html" class=SideMenuEntry>Organizing the Menu</a><a href="styles.html" class=SideMenuEntry>CSS Styles</a><a href="customizingtopics.html" class=SideMenuEntry>Topics and Keywords</a><a href="customizinglanguages.html" class=SideMenuEntry>Languages, Indexes,<br>and Prototypes</a></div></div><div class=SideMenuSection><div class=SideMenuTitle><img src="images/menu/community.png" width=86 height=13 alt="Community"></div><div class=SideMenuBody><a href="http://www.naturaldocs.org/" class=SideMenuEntry>Web Site</a><a href="http://www.naturaldocs.org/mailinglist.html" class=SideMenuEntry>Mailing Lists</a><a href="http://www.naturaldocs.org/messageboards.html" class=SideMenuEntry>Message Boards</a><a href="http://www.naturaldocs.org/bugs.html" class=SideMenuEntry>Bugs and<br>Feature Requests</a></div></div></td><td class=Body width=100%><div class=PageTitle>Output Formats</div><div class=Topic><p>These are the output formats that are currently implemented in Natural Docs.</p><table width=100% border=0 cellspacing=0 cellpadding=0 class=FormatTable><tr><td class=FormatName>HTML</td><td class=FormatDescription>HTML output.&nbsp; Each page is self-contained.&nbsp; Linking to specific pages is easy, but every file has to be updated whenever the menu changes.</td></tr><tr><td class=FormatName>FramedHTML</td><td class=FormatDescription>HTML output based on frames.&nbsp; The menu is updated quickly, but linking to individual pages is difficult and some people just plain hate frames.</td></tr></table></div><div class=Topic><div class=TopicTitle>HTML Compatibility</div><p>These are the browsers Natural Docs&rsquo; HTML output has been tested with.&nbsp; All browsers will be able to view and navigate it, some of the older ones just may not be able to use advanced features like search correctly.</p><table width=100% border=0 cellspacing=0 cellpadding=0 class=BrowserTable><tr><td class=BrowserName nowrap>FireFox</td><td class=BrowserDescription>Tested with 1.0, 1.5, and 2.0.</td></tr><tr><td class=BrowserName nowrap>Internet Explorer</td><td class=BrowserDescription>Tested with 6 and 7.</td></tr><tr><td class=BrowserName nowrap>Safari</td><td class=BrowserDescription>Tested with 2 and 3.&nbsp; Search doesn&rsquo;t work with unframed HTML in 2.</td></tr><tr><td class=BrowserName nowrap>Opera</td><td class=BrowserDescription>Tested with 7.0, 7.5, 8.0, 8.5, and 9.0.&nbsp; Search doesn&rsquo;t work with 7.0, and sometimes tooltips.</td></tr><tr><td class=BrowserName nowrap>Konqueror</td><td class=BrowserDescription>Tested with 3.5.5.&nbsp; Search doesn&rsquo;t work.</td></tr></table></div></td></tr><tr><td></td><td class=SideMenuBottom><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td class=SideMenuBottomLeft><img src="images/menu/bottomleft.png" width=18 height=19></td><td class=SideMenuBottomRight><img src="images/menu/bottomright.png" width=18 height=19></td></tr></table></td><td class=BodyBottom>Copyright &copy; 2003-2008 Greg Valure</td></tr></table><script language=JavaScript><!--
ClosingBrowserTags();// --></script></body></html>

File diff suppressed because one or more lines are too long

View file

@ -1,290 +0,0 @@
body {
background: #FFFFFF;
margin: 18px 15px 25px 15px !important;
}
body,
td,
li {
font: 9pt Verdana, sans-serif;
}
p,
td,
li {
line-height: 150%;
}
p {
text-indent: 4ex;
margin: 0;
}
td {
vertical-align: top;
}
a:link,
a:visited { color: #900000; text-decoration: none }
a:hover { color: #900000; text-decoration: underline }
a:active { color: #FF0000; text-decoration: underline }
.Opera wbr:after {
content: "\00200B";
}
.NoIndent p
{ text-indent: 0; }
img {
border: none;
}
.First {
margin-top: 0 !important;
padding-top: 0 !important;
}
.Last {
margin-bottom: 0 !important;
padding-bottom: 0 !important;
}
.Header {
background-image: URL("images/header/background.png");
background-color: #7070C0;
}
.SideMenuTop {
background: URL("images/header/overmenubg.png");
}
.SideMenuBottom {
vertical-align: bottom;
}
.BodyTop {
background: URL("images/header/overbodybg.png");
text-align: right;
}
.BodyBottom {
vertical-align: bottom;
text-align: right;
font: italic 8pt Georgia, serif;
color: #C0C0C0;
padding-right: 10px;
}
.Body {
padding: 15px 20px 0 25px;
}
#SourceForgeLogo {
border: 1px solid #D8D8D8;
margin-top: 2em;
}
pre, code, .Example {
font: 10pt Courier New, Courier, monospace;
color: #606060;
}
a code {
color: #C06060;
}
.Example {
overflow: auto;
}
.PageTitle {
font: bold italic 21pt Trebuchet MS, sans-serif; letter-spacing: .5ex; text-transform: uppercase;
margin-bottom: .5em }
.IE .PageTitle {
letter-spacing: 1.25ex;
}
.Topic {
margin-bottom: 2em }
.TopicTitle {
font: 18pt Georgia, serif;
border-width: 0 0 1px 0; border-style: solid; border-color: #C0C0C0;
margin-bottom: .5em
}
#SubscribeTopicTitle {
margin-bottom: 0;
}
.Subscribe {
font-size: 8pt;
margin-bottom: 2em;
color: #909090;
}
.Subscribe a:link,
.Subscribe a:hover,
.Subscribe a:visited {
color: #909090 }
.SubTopic {
font-weight: bold; font-size: 10pt;
padding-top: 1.5em; padding-bottom: .5em;
}
.MiniTopic {
font-weight: bold;
padding-top: 1em; padding-bottom: 0em;
}
.TOC {
text-align: center;
font: 8pt Verdana, sans-serif;
text-transform: uppercase;
background-color: #F8F8F8;
border-width: 1px; border-style: solid; border-color: #C0C0C0;
margin-bottom: 1.5em;
padding: 2px 0;
-moz-border-radius: 14px;
}
.TOC a {
margin: 0 0.75ex; }
.TOC a:link,
.TOC a:hover,
.TOC a:visited {
color: #404040 }
.Example {
background-color: #FDFDFD;
padding: 15px;
border: 1px solid #C0C0C0;
border-width: 1px 1px 1px 6px;
border-style: dashed dashed dashed solid;
color: #707070;
margin: 15px 5ex;
}
.LastUpdated {
font: italic 10pt Georgia, serif;
color: #A0A0A0;
margin: 1em 0;
}
.FAQSummary {
margin-bottom: 3em;
}
.FAQSummaryGroup {
font: bold 12pt Georgia, serif;
margin: 1em 0 .25em 0;
}
.FAQGroup {
font: 18pt Georgia, serif;
border-bottom: 1px solid #C0C0C0;
margin-bottom: .5em;
margin-top: 1.5em;
}
.FAQSummaryEntry:link,
.FAQSummaryEntry:visited,
.FAQSummaryEntry:hover,
.FAQSummaryEntry:active {
}
.FAQEntry {
margin-bottom: 3em;
}
.FAQEntryTitle {
font: bold 12pt Georgia, serif;
margin-bottom: .5em;
}
.FAQEntry .SubTopic {
font: italic 9pt Verdana, sans-serif;
}
.SideMenu {
width: 175px; /* 195 minus padding */
text-align: center;
padding-top: 15px;
background-color: #F0F0F0;
}
.SideMenuBottom {
background-color: #F0F0F0;
}
.SideMenuBottomRight {
text-align: right;
}
.SideMenuSection {
margin-bottom: 3em;
}
.SideMenuTitle {
padding-bottom: 3px;
border-bottom: 1px solid #D0D0D0;
}
.SideMenuBody {
padding-top: 1em;
background: URL("images/menu/background.png") repeat-x;
}
.SideMenuEntry {
font: 8pt Verdana, sans-serif;
margin: 0 10px 1em 10px;
display: block;
}
a.SideMenuEntry:link,
a.SideMenuEntry:visited {
color: #000000;
padding: 1px 10px 2px 9px;
}
a.SideMenuEntry:hover,
a.SideMenuEntry:active,
#SelectedSideMenuEntry {
border-style: solid;
border-width: 1px 2px 2px 1px;
padding: 0 8px;
text-decoration: none;
-moz-border-radius: 10px;
}
a.SideMenuEntry:hover,
a.SideMenuEntry:active {
color: #000000;
border-color: #C8C8C8;
background-color: #F8F8F8;
}
#SelectedSideMenuEntry {
color: #000000;
border-color: #606060;
background-color: #FFFFFF;
}
.SideMenuSourceForge {
padding-top: 5px;
}
/* Needed by the release notes for 1.3 */
.ExPrototype {
font: 10pt Courier New, Courier, monospace;
padding: 5px 3ex;
background-color: #F4F4F4;
border: 1px solid #D0D0D0;
margin: 1em 0;
}
.ExPrototype td {
font: 10pt Courier New, Courier, monospace;
}
.ExPrototype .Fade {
color: #8F8F8F;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,947 +0,0 @@
Architecture: CSS Structure
_______________________________________________________________________________
It's important to understand the internal HTML file structure and styles in order to design your own CSS style for Natural Docs. If
you're content with the default styles, there's no need to read this document.
Topic: Diagram Conventions
The diagrams are designed for clarity. In the actual HTML, you'd obviously see "<table class=CDescriptionList></table>"
instead of "<table CDescriptionList></table CDescriptionList>".
- A tag with just a style, for example "CTitle", means an unspecified element with that class. Style with .CTitle.
- A tag that includes a #, for example "#Menu", means an unspecified element with that ID. Style with #Menu.
- A tag that includes a HTML element as well, for example "table CDescriptionList", means it will always be that element. You
can style with either .CDescriptionList or table.CDescriptionList.
- A tag that has multiple classes or has an "and" in it, for example "CType and CTopic", means that both styles will apply to the
same element. You can style it with .CType.CTopic, noting that the space between them must be omitted.
- A tag that has an "or" in it, for example "#Content or #Index", is just shorthand for either of those elements. The diagram
applies to both of them but only one will actually appear at a time in the output.
- A tag or style with a question mark means that tag or style will only be there in certain situations.
Topic: Page Structure
_______________________________________________________________________________
The body tag is used to distinguish between the types of pages.
Unframed Content/Index Page:
(start diagram)
<body ContentPage or IndexPage)>
[browser styles]
<#Content or #Index>
Content or Index
</#Content or #Index>
<#Menu>
Menu
</#Menu>
<#Footer>
Footer
</#Footer>
[/browser styles]
</body ContentPage or IndexPage)>
(end diagram)
Unframed Search Results Popup Page:
(start diagram)
<body PopupSearchResultsPage>
[browser styles]
<#Index>
Index
</#Index>
[browser styles]
</body PopupSearchResultsPage>
(end diagram)
Framed Menu Page:
(start diagram)
<body FramedMenuPage>
[browser styles]
<#Menu>
Menu
</#Menu>
<#Footer>
Footer
</#Footer>
[browser styles]
</body FramedMenuPage>
(end diagram)
Framed Content/Index/SearchResults Page:
(start diagram)
<body FramedContentPage or FramedIndexPage or FramedSearchResultsPage>
[browser styles]
<#Content or #Index>
Content or Index
</#Content or #Index>
[browser styles]
</body FramedContentPage or FramedIndexPage or FramedSearchResultsPage>
(end diagram)
Styles: Page Styles
ContentPage - An unframed content page.
IndexPage - An unframed index page.
PopupSearchResultsPage - A search results page for use in a popup iframe.
FramedContentPage - A framed content page.
FramedIndexPage - A framed index page.
FramedSearchResultsPage - A framed search results page.
#Footer - The page footer. Will be in a framed menu page or on its own in a non-framed page.
See Also:
- <#Content>
- <#Menu>
- <#Index>
- <#Footer>
Styles: Browser Styles
_______________________________________________________________________________
Natural Docs pages include JavaScript to detect which browser the user is running and apply styles so that you can work
around browser quirks right in the CSS file.
The browser type and version styles will be applied immediately after the body tag. However, neither are guaranteed to be
there; the user may have JavaScript turned off or be using a browser that isn't detected. These styles should only be used to
correct minor flaws and should not be heavily relied on.
> <body>
> <browser type>?
> <browser version>?
>
> Page Content
>
> <browser version>?
> <browser type>?
> </body>
For example, if a <CTopic>'s style is giving you problems in Internet Explorer 6, override it with .IE6 .CTopic. If a <MTitle>'s
style gives you a problem in Opera 7 but only in frames, override it with .Framed.Opera7 .MTitle.
Browser Types:
If the browser is not one of the types below, neither this nor the browser version will be present. There's the possibility that
some obscure browser will appear as one of the others by spoofing, but the most prominent of these, Opera, Konqueror, and
Safari, are taken care of.
IE - Internet Explorer
Firefox - Firefox and anything else based on the Gecko rendering engine.
Opera - Opera
Safari - Safari
Konqueror - Konqueror and anything else based on the KHTML rendering engine except Safari.
Browser Versions:
If the browser is not one of the versions below, this style will not be present. The browser type still may be.
IE6 - Internet Explorer 6.x.
IE7 - Internet Explorer 7.x.
Firefox1 - Firefox 1.0.x and anything else based on Gecko 1.7.x.
Firefox15 - Firefox 1.5.x and anything else based on Gecko 1.8.0.x.
Firefox2 - Firefox 2.0.x and anything else based on Gecko 1.8.1.x.
Opera7 - Opera 7.x.
Opera8 - Opera 8.x.
Opera9 - Opera 9.x.
Safari2 - Safari 2.x.
Safari3 - Safari 3.x.
Notes:
Why not apply them to the body tag itself? The JavaScript is easy enough and everything supports multiple classes, right?
Because IE 6 doesn't support multiple selectors so I wouldn't be able to combine browser and page styles.
.Opera.ContentPage will apply to all ContentPages in IE because it treats it as if only the last class is there.
Topic: Content Structure
_______________________________________________________________________________
All the topics of a given file is contained in a <#Content>. All other content styles are prefixed with a C.
Surrounding each piece of content is a <CTopic> and its type; for example, CFunction for a function. Inside that are the
<CTitle> and if necessary, <CBody>. Inside <CBody> are analogues to all the top-level <NDMarkup> tags: <h1>, <p>, etc.
In addition to the top-level <NDMarkup> tags, you also have prototypes, class hierarchies, and summaries which are
described in their own sections.
(start diagram)
<#Content>
<CType (CFunction, CVariable, etc.)>
<CTopic and #MainTopic?>
<CTitle>
Topic title
</CTitle>
<CBody>
[Class Hierarchy]
[Prototype]
<CHeading>
Heading
<CHeading>
<p>
Paragraph
</p>
<pre>
Code or text diagram
</pre>
<ul>
<li>
Bullet item
</li>
</ul>
<CImageCaption>?
Caption
</CImageCaption>?
<img>
<a CImageLink>
text
</a CImageLink>
<table CDescriptionList>
<tr>
<td CDLEntry>
Entry
</td CDLEntry>
<td CDLDescription>
Description
</td CDLDescription>
</tr>
</table CDescriptionList>
[Summary]
</CBody>
</CTopic and #MainTopic?>
</CType (CFunction, CVariable, etc.)>
</#Content>
(end diagram)
Take advantange of the CSS inheritance model. For example, you can style all titles via .CTitle, and you can style
specific titles with .CType .CTitle.
Styles: Content Styles
#Content - Parent element containing all topics.
CTopic - An individual topic.
CTitle - The title of a topic.
CBody - The body of a topic. May not exist.
CHeading - Surrounds a heading.
CImageCaption - Surrounds an image caption.
CImageLink - Surrounds a link to an image.
CDescriptionList - A description list, which is the type of list you're reading right now. Is implemented with a table.
CDLEntry - A description list entry, which is the left side.
CDLDescription - A description list description, which is the right side.
#MainTopic - The ID given to the main topic, which is the first in the file. It is applied to the <CTopic>.
CType - A placeholder for all type-specific styles. The actual styles will be C followed by the alphanumeric-only topic type name.
So the CType of a "PL/SQL Function" topic will actually be CPLSQLFunction.
Topic: Menu Structure
_______________________________________________________________________________
Everything is enclosed in a <#Menu>. All other menu styles are prefixed with an M.
The title is an <MTitle> and will always be at the beginning of the menu if it exists. If a subtitle exists as well, it will appear
as an <MSubTitle> inside <MTitle>. Subtitles aren't allowed without titles. Most other entries in the menu are contained in
<MEntries>. Here's the diagram:
(start diagram)
<#Menu>
<MTitle>
Menu title
<MSubTitle>
Menu sub title
</MSubTitle>
</MTitle>
<MEntry>
<MFile (and #MSelected?)>
<a href>File</a href>
</MFile>
</MEntry>
<MEntry>
<MIndex (and #MSelected?)>
<a href>File</a href>
</MIndex>
</MEntry>
<MEntry>
<MText>
Text
</MText>
</MEntry>
<MEntry>
<MLink>
<a href>Link</a href>
</MLink>
</MEntry>
<MEntry>
<MGroup>
<a href>Group</a href>
<MGroupContent>
(MEntries)
</MGroupContent>
</MGroup>
</MEntry>
<#MSearchPanel and MSearchPanelActive/Inactive>
<input #MSeachField>
<select #MSearchType>
<option #MSearchEverything>
<option>
<option>
</select #MSearchType>
</#MSearchPanel and MSearchPanelActive/Inactive>
</#Menu>
(if in unframed HTML)
<#MSearchResultsWindow>
<iframe #MSearchResults>
</iframe #MSearchResults>
<a #MSearchResultsWindowClose>
</#MSearchResultsWindow>
(end)
The <MFile> or <MIndex> entry that's currently selected will have the <#MSelected> ID, so you can reference it in CSS via
.MFile#MSelected.
The search panel is has its own ID, <#MSearchPanel>, but also has one of the classes <MSearchPanelActive> or
<MSearchPanelInactive> depending on whether any of the controls are selected or the results window is open.
<#MSearchResultsWindow> is separate because it may be floating.
Styles: Menu Styles
#Menu - Parent element containing the entire menu.
MTitle - The title of the menu.
MSubTitle - The subtitle of the menu. Will appear within <MTitle>.
MFile - A file entry.
MGroup - A group entry.
MGroupContent - A container for a <MGroup's> content.
MText - A plain text entry.
MLink - An external link entry.
MIndex - An index entry.
#MSelected - The ID of the currently selected <MFile> or <MIndex>.
MType - <MFile>, <MGroup>, <MText>, <MLink>, or <MIndex>.
#MSearchPanel - Contains all the search controls.
MSearchPanelActive - Applied to <#MSearchPanel> when any of the controls are selected or the results window is open.
MSearchPanelInactive - Applied to <#MSearchPanel> when not in use.
#MSearchField - The text input field of the search panel.
#MSearchType - The drop down type selector of the search panel.
#MSearchEverything - The <#MSearchType> option for the Everything index.
#MSearchResultsWindow - Contains all the search results elements.
#MSearchResults - Contains the iframe that will hold the results.
#MSearchRseultsWindowClose - The link to manually close the search results window.
Topic: Class Hierarchy Structure
_______________________________________________________________________________
Everything is contained in a single <ClassHierarchy>. Each entry is surrounded by its type, such as <CHParent>, and the
generic <CHEntry>. Depending on the context, entries may be surrounded by one or more <CHIndents>.
(start diagram)
<ClassHierarchy>
<CHIndent>?
<CHType>
<CHEntry>
<a href>?
Entry
</a href>
</CHEntry>
</CHType>
</CHIndent>?
</ClassHierarchy>
(end diagram)
Styles: Class Hierarchy Styles
ClassHierarchy - The topmost style containing everything.
CHEntry - A generic class entry.
CHParent - The style for a parent class.
CHCurrent - The style for the current class, which is the one the hierarchy is generated for.
CHChild - The style for a child class.
CHChildNote - The style for when a child is added that just shows how many other children were omitted.
CHIndent - A style used to indent a level.
CHType - <CHParent>, <CHCurrent>, <CHChild>, or <CHChildNote>.
Topic: Summary Structure
_______________________________________________________________________________
Everything is enclosed in a single <Summary>. All the other summary styles are prefixed with an S.
<STitle> holds the actual word "Summary" and <SBorder> and <STable> hold the content. <SBorder> exists because different
browsers apply table padding attributes in different ways. <STable> exists as a class to separate the main table from any other
tables that may be necessary. Here's a diagram:
> <Summary>
>
> <STitle>
> Title
> </STitle>
>
> <SBorder>
> <table STable>
> ...
> </table STable>
> </SBorder>
>
> </Summary>
On to the table content.
> <tr SType and SEntry (and SIndent#?) (and SMarked?)>
> <td SEntry>
>
> <a href>Entry</a href>
>
> </td SEntry>
> <td SDescription>
>
> Description
>
> </td SDescription>
> </tr SType and SEntry (and SIndent#?) (and SMarked?)>
<SIndent#> exist to allow indenting. They're necessary because implementing it as nested tables, while structurally cleaner,
won't allow the desciptions to line up on the right throughout the entire summary. <SMarked> will be applied on almost every
other row to allow for tinting to improve readability.
Use the power of CSS's inheritance rules to specify styles. For example, to set the style of a group entry, apply it to
.SGroup .SEntry. However, you could also apply a style to both the group's entry and description by applying the
style to .SGroup td. Or, you could apply a style to all the entries by applying it to .SEntry. And so on.
Styles: Summary Styles
Summary - The topmost style containing the entire summary.
STitle - Contains the summary title, which is the part that actually says "Summary".
SBorder - Surrounds <STable>, since some browsers can't do table padding right. A hack, I know.
STable - The actual summary table. This class separates it from other layout tables that may appear.
SMarked - A class applied to rows that should have a slightly different color than the rest of the rows to make them easier to
read.
SEntry - The entry (left) side of the table.
SDescription - The description (right) side of the table.
SIndent# - Surrounding entries and descriptions that are part of a group and need to be indented. Actual styles will be
SIndent1, SIndent2, etc.
SType - A placeholder for all topic-specific styles. The actual styles will be S followed by the alphanumeric-only topic type name.
So the SType of a "PL/SQL Function" topic will actually be SPLSQLFunction.
Topic: Prototype Structure
_______________________________________________________________________________
Everything is enclosed in a <Prototype>. All other styles are prefixed with a P.
Parameter Type First Style:
For prototypes such as
> void Function (unsigned int* a, int b = 0)
where the types come first.
(start diagram)
<table Prototype>
<td PBeforeParameters>
"void Function ("
</td PBeforeParameters>
<td PTypePrefix>
"unsigned"
</td PTypePrefix>
<td PType>
"int"
</td PType>
<td PParameterPrefix>
"*"
</td PParameterPrefix>
<td PParameter>
"a", "b"
</td PParameter>
<td PDefaultValuePrefix>
"="
</td PDefaultValuePrefix>
<td PDefaultValue>
"0"
</td PDefaultValue>
(repeated as necessary)
<td PAfterParameters>
")"
</td PAfterParameters>
</table Prototype>
(end diagram)
Parameter Name First Style:
For prototypes such as
> function Function (a, b: int; c: int := 0)
where the parameters come first.
(start diagram)
<table Prototype>
<td PBeforeParameters>
"function Function ("
</td PBeforeParameters>
<td PParameter>
"a,", "b:", "c:"
</td PParameter>
<td PType>
"int"
</td PType>
<td PDefaultValuePrefix>
":="
</td PDefaultValuePrefix>
<td PDefaultValue>
"0"
</td PDefaultValue>
(repeated as necessary)
<td PAfterParameters>
")"
</td PAfterParameters>
</table Prototype>
(end diagram)
Note that any section may not exist. For example, there will be no <PTypePrefix> cells generated if none of the parameters
have it.
Styles: Prototype Styles
Prototype - The style encompassing the entire prototype.
PBeforeParameters - The part of the prototype that comes before the parameters.
PAfterParameters - The part of the prototype that comes after the parameters.
PType - The parameter type.
PTypePrefix - The prefix of a parameter type.
PParameter - The parameter name.
PParameterPrefix - The prefix of a parameter name.
PDefaultValue - The default value expression for a parameter.
PDefaultValuePrefix - The prefix of the default value expression.
Topic: Link Structure
_______________________________________________________________________________
All links to symbols have a type style prefixed with L. The only exceptions are summary entries; summary descriptions use
them as well.
> <a LType>
> Link
> </a LType>
You can use this to make links to different symbols appear in different styles. For example, making .LClass bold will make all
links to classes bold, except when appearing in summary entries. You can combine this with other styles to be even more
specific. For example, you can apply a style to function links appearing in summary descriptions with .SDescription .LFunction.
Styles: Link Styles
LType - A placeholder for all topic-specific styles. The actual styles will be L followed by the alphanumeric-only topic type name.
So the LType of a "PL/SQL Function" topic will actually be LPLSQLFunction.
Topic: Index Structure
_______________________________________________________________________________
Everything is enclosed in an <#Index>. Combine with <Framed> and <Unframed> to distinguish between output formats. All
other index styles are prefixed with an I.
(start diagram)
<#Index>
<IPageTitle>
Page Title
</IPageTitle>
<INavigationBar>
A - <a href>B</a href> - C ...
</INavigationBar>
<table>
<IHeading>
Heading (A, B, etc.)
</IHeading>
<td ISymbolPrefix>
Prefix, if any
</td ISymbolPrefix>
<td IEntry>
Entry
</td IEntry>
...
</table>
</#Index>
(end diagram)
Every index entry, including headings, are rows in a table. The first column of a non-heading are <ISymbolPrefixes> so that
the non-prefix portions align correctly. The other column are <IEntries>, of which there are multiple formats, described below.
(start diagram)
<a href ISymbol>
Symbol
</a href ISymbol>,
<IParent>
Class
</IParent>
<ISymbol>
Symbol
</ISymbol>
<ISubIndex>
<a href IParent>
Class
</a href IParent>
...
</ISubIndex>
<ISymbol>
Symbol
</ISymbol>
<ISubIndex>
<IParent>
Class
</IParent>
<ISubIndex>
<a href IFile>
File
</a href IFile>
...
</ISubIndex>
...
</ISubIndex>
(end diagram)
Each part of the entry is surrounded by its type, which may or may not be a link. If an entry has more than one defining class
or file, they're broken out into <ISubIndexes>.
It's called <IParent> instead of <IClass> because class entries are <ISymbols>. <IParents> are only used when the symbol
has a class. If the symbol _is_ a class, the symbol is global.
Styles: Index Styles
#Index - Parent element for the entire index.
IPageTitle - The page title.
INavigationBar - The navigation bar.
IHeading - An index heading, such as the letter for the group.
IEntry - An entry in the index.
ISymbolPrefix - The stripped prefix of the entry.
ISymbol - The entry symbol.
IParent - The entry parent class. If the entry _is_ a class, this isn't defined because classes are global and don't have parent
classes. This is why it's called IParent instead of IClass; hopefully it's less confusing.
IFile - The file the entry is defined in.
ISubIndex - The surrounding block if an entry needs to be broken out into a sub-index.
#IFirstHeading - The ID of the first <IHeading> to appear in the file.
#IFirstSymbolPrefix - The ID for the first <ISymbolPrefix> to appear under an <IHeading>.
#ILastSymbolPrefix - The ID for the last <ISymbolPrefix> to appear under an <IHeading>.
#IOnlySymbolPrefix - The ID if there is only one <ISymbolPrefix> for an <IHeading>.
Topic: Search Results Structure
_______________________________________________________________________________
The search results use virtually the same structure and styles as the indexes, except that <#SearchResults> replaces
<#Index>, there's a new <SRResult> style, and there are a few additional <SRStatus> blocks.
Visibility:
Visibility is *very* important to making the search work correctly. JavaScript will handle most of it, but your CSS needs to
abide by these rules.
- <SRStatus> sections are visible by default.
- <SRResult> sections are *not* visible by default. They must use display: none.
- <ISubIndex> should be display: none when under <#SearchResults>.
Styles: Search Results Styles
#SearchResults - Parent element for the entire page.
SRStatus - Status message. Must be visible by default.
SRResult - A result. All you need to do for this class is set it to display: none. Nothing else should be set on it.
Topic: Tool Tip Structure
_______________________________________________________________________________
Tool tips may appear anywhere in the page, mainly because it's assumed that they will use position: absolute and
visibility: hidden.
The entire tool tip is found in a <CToolTip> style, with a CType style inside it. CTypes are normally outside their elements, but
that would cause it to be partially visible in this case. We need <CToolTip> to be the outermost style so its visibility and
position can be manipulated in JavaScript.
Inside there's a <CPrototype> and/or the description text. The description text has no special surrounding tags.
> <CToolTip>
>
> <CPrototype>
> Prototype
> </CPrototype>
>
> Summary text
>
> </CToolTip>
Styles: Tool Tip Styles
CToolTip - Surrounds the entire tool tip. This *must* have position: absolute and visibility: hidden for the tool tip mechanism
to work.
See also <CPrototype>.
Styles: Miscellaneous Styles
blockquote - This HTML element should surround anything that needs to be scrolled if it's too wide, like prototypes and text
diagrams. It's not a style because this makes it much easier to do the JavaScript necessary to get this working
in IE.
Group: History
Topic: Revisions
_______________________________________________________________________________
How the page structure has changed throughout the various releases.
1.4:
- Replaced UnframedPage with <ContentPage> and <IndexPage>.
- Added <#Menu>, <#Content>, <#Footer>, and <#Index>. They were previously shown in the diagrams as classes but did
not actually appear in the generated output.
- Removed MenuSection, ContentSection, and IndexSection. Use things like ".ContentPage #Menu" instead.
- Removed tables from the unframed <Page Structure>. Use CSS to position the elements instead.
- <#MainTopic> is applied to <CTopic> instead of <CType>.
- IE4, IE5, Opera5, Opera6, Netscape, and Netscape4 browser styles have been removed. <IE7>, <Opera8>,
and <Opera9> have been added. Gecko has been replaced by <Firefox>, <Firefox1>, <Firefox15>, and <Firefox2>.
KHTML has been replaced by <Safari>, <Safari2>, <Safari3>, and <Konqueror>.
- Removed redundant CParagraph, CCode, and CBulletList classes. Use <CBody> with p, pre, and ul instead.
- Added <CImageCaption> and <CImageLink>.
- Added <#MSearchPanel>, <#MSearchResultsWindow>, and all related styles.
- Added <Search Results Structure>, <Search Results Styles>, and <FramedSearchResultsPage>.
- Removed SEntrySize. Apply the width to <SEntry> and <SDescription> instead.
- <SType>, <SEntry>, and <SIndent#> were moved from the td and divs into the tr.
- Removed HB style. Now using wbr tag.
1.33:
- Added <PDefaultValuePrefix>.
1.32:
- <blockquotes> now surround elements that should scroll if they're too wide for the page.
1.3:
- Removed CPrototype. See the replacement <Prototype Structure> and <Prototype Styles>.
- Removed SInGroup, SInClass, and SInSection in favor of more general <SIndent#>.
- <CTypes>, <STypes>, and <LTypes> are now completely determined by <Topics.txt> configuration files.
- <CTypes>, <STypes>, and <LTypes> no longer have separate list types. A CFunctionList is now just a CFunction.
- Indexes are now done with tables.
- ISection was removed.
- <IEntries> are only used for the entry cell, not for each entry in an <ISubIndex>.
- Added <ISymbolPrefix>, related IDs, and <#IFirstHeading>.
- Merged <CType> and <CTopic> into the same element. Must now be styled with .CType.CTopic (no space) while all
sub-elements will still be .CType .CElement (with space.)
1.21:
- Added <TOPIC_PROPERTY> and TOPIC_PROPERTY_LIST styles, so they get corresponding <CTypes>, <STypes>, and
<LTypes>.
1.2:
- Added <Class Hierarchy Styles> since 1.2 added class hierarchies.
1.16:
- Changed the first topic from having a CMain type to having a normal type with a <#MainTopic> ID.
1.1:
- Added <Tool Tip Styles>.
- Renamed HiddenBreak to <HB>.
- Added <TOPIC_CONSTANT>, TOPIC_CONSTANT_LIST, <TOPIC_TYPE>, and TOPIC_TYPE_LIST types, so they get
corresponding <CTypes>, <STypes>, and <LTypes>.
1.0:
- The <CType> tags now appear arround the <CTopic> tags instead of vice versa.
- Added a <CBody> tag to surround non-<CTitle> elements.
- <SMarked> now appears in tr's instead of td's, where it belonged in the first place.
0.95:
- Added <Browser Styles>.
- Redid <Page Structure>, replacing generic styles like Menu with page type styles like UnframedPage/MenuSection and
FramedMenuPage.
0.91:
- Added <LURL> and <LEMail> link styles, since 0.91 added URL and e-mail links.
- Added <ISection> style, which is better than <IHeading> floating on its own.
0.9:
- Added <Index Styles>, since 0.9 added indexes.

View file

@ -1,83 +0,0 @@
Architecture: File Parsing
####################################################################################
This is the architecture and code path for general file parsing. We pick it up at <NaturalDocs::Parser->Parse()> because we're not interested in how the files are gathered and their languages determined for the purposes of this document. We are just interested in the process each individual file goes through when it's decided that it should be parsed.
Stage: Preparation and Differentiation
_______________________________________________________________________________________________________
<NaturalDocs::Parser->Parse()> can be called from one of two places, <NaturalDocs::Parser->ParseForInformation()> and <NaturalDocs::Parser->ParseForBuild()>, which correspond to the parsing and building phases of Natural Docs. There is no noteworthy work done in either of them before they call Parse().
Stage: Basic File Processing
_______________________________________________________________________________________________________
The nitty-gritty file handling is no longer done in <NaturalDocs::Parser> itself due to the introduction of full language support in 1.3, as it required two completely different code paths for full and basic language support. Instead it's handled in NaturalDocs::Languages::Base->ParseFile(), which is really a virtual function that leads to <NaturalDocs::Languages::Simple->ParseFile()> for basic language support or a version appearing in a package derived from <NaturalDocs::Languages::Advanced> for full language support.
The mechinations of how these functions work is for another document, but their responsibility is to feed all comments Natural Docs should be interested in back to the parser via <NaturalDocs::Parser->OnComment()>.
Stage: Comment Processing
_______________________________________________________________________________________________________
<NaturalDocs::Parser->OnComment()> receives the comment sans comment symbols, since that's language specific. All comment symbols are replaced by spaces in the text instead of removed so any indentation is properly preserved. Also passed is whether it's a JavaDoc styled comment, as that varies by language as well.
OnComment() runs what it receives through <NaturalDocs::Parser->CleanComment()> which normalizes the text by removing comment boxes and horizontal lines, expanding tabs, etc.
Stage: Comment Type Determination
_______________________________________________________________________________________________________
OnComment() sends the comment to <NaturalDocs::Parser::Native->IsMine()> to test if it's definitely Natural Docs content, such as by starting with a recognized header line. If so, it sends it to <NaturalDocs::Parser::Native->ParseComment()>.
If not, OnComment() sends the comment to <NaturalDocs::Parser::JavaDoc->IsMine()> to test if it's definitely JavaDoc content, such as by having JavaDoc tags. If so, it sends it to <NaturalDocs::Parser::JavaDoc->ParseComment()>.
If not, the content is ambiguous. If it's a JavaDoc-styled comment it goes to <NaturalDocs::Parser::Native->ParseComment()> to be treated as a headerless Natural Docs comment. It is ignored otherwise, which lets normal comments slip through. Note that it's only ambiguous if neither parser claims it; there's no test to see if they both do. Instead Natural Docs always wins.
We will not go into the JavaDoc code path for the purposes of this document. It simply converts the JavaDoc comment into <NDMarkup> as best it can, which will never be perfectly, and adds a <NaturalDocs::Parser::ParsedTopic> to the list for that file. Each of those ParsedTopics will be headerless as indicated by having an undefined <NaturalDocs::Parser::ParsedTopic->Title()>.
Stage: Native Comment Parsing
_______________________________________________________________________________________________________
At this point, parsing is handed off to <NaturalDocs::Parser::Native->ParseComment()>. It searches for header lines within the comment and divides the content into individual topics. It also detects (start code) and (end) sections so that anything that would normally be interpreted as a header line can appear there without breaking the topic.
The content between the header lines is sent to <NaturalDocs::Parser::Native->FormatBody()> which handles all the block level formatting such as paragraphs, bullet lists, and code sections. That function in turn calls <NaturalDocs::Parser::Native->RichFormatTextBlock()> on certain snippets of the text to handle all inline formatting, such as bold, underline, and links, both explicit and automatic.
<NaturalDocs::Parser::Native->ParseComment()> then has the body in <NDMarkup> so it makes a <NaturalDocs::Parser::ParsedTopic> to add to the list. It keeps track of the scoping via topic scoping, regardless of whether we're using full or basic language support. Headerless topics are given normal scope regardless of whether they might be classes or other scoped types.
Group: Post Processing
_______________________________________________________________________________________________________
After all the comments have been parsed into ParsedTopics and execution has been returned to <NaturalDocs::Parser->Parse()>, it's time for some after the fact cleanup. Some things are done like breaking topic lists, determining the menu title, and adding automatic group headings that we won't get into here. There are two processes that are very relevant though.
Stage: Repairing Packages
_______________________________________________________________________________________________________
If the file we parsed had full language support, the <NaturalDocs::Languages::Advanced> parser would have done more than just generate various OnComment() calls. It would also return a scope record, as represented by <NaturalDocs::Languages::Advanced::ScopeChange> objects, and a second set of ParsedTopics it extracted purely from the code, which we'll refer to as autotopics. The scope record shows, purely from the source, what scope each line of code appears in. This is then combined with the topic scoping to update ParsedTopics that come from the comments in the function <NaturalDocs::Parser->RepairPackages()>.
If a comment topic changes the scope, that's honored until the next autotopic or scope change from the code. This allows someone to document a class that doesn't appear in the code purely with topic scoping without throwing off anything else. Any other comment topics have their scope changed to the current scope no matter how it's arrived at. This allows someone to manually document a function without manually documenting the class and still have it appear under that class. The scope record will change the scope to part of that class even if topic scoping did not. Essentially the previous topic scoping is thrown out, which I guess is something that can be improved.
None of this affects the autotopics, as they are known to have the correct scoping since they are gleaned from the code with a dedicated parser. Wouldn't there be duplication of manually documented code elements, which would appear both in the autotopics and in the comment topics? Yes. That brings us to our next stage, which is...
Stage: Merging Auto Topics
_______________________________________________________________________________________________________
As mentioned above, ParseFile() also returns a set of ParsedTopics gleaned from the code called autotopics. The function <NaturalDocs::Parser->MergeAutoTopics()> merges this list with the comment topics.
The list is basically merged by line number. Since named topics should appear directly above the thing that they're documenting, topics are tested that way and combined into one if they match. The description and title of the comment topic is merged with the prototype of the autotopic. JavaDoc styled comments are also merged in this function, as they should appear directly above the code element they're documenting. Any headerless topics that don't, either by appearing past the last autotopic or above another comment topic, are discarded.
Stage: Conclusion
_______________________________________________________________________________________________________
Thus ends all processing by <NaturalDocs::Parser->Parse()>. The file is now a single list of <NaturalDocs::Parser::ParsedTopics> with all the body content in <NDMarkup>. If we were using <NaturalDocs::Parser->ParseForBuild()>, that's pretty much it and it's ready to be converted into the output format. If we were using <NaturalDocs::Parser->ParseForInformation()> though, the resulting file is scanned for all relevant information to feed into other packages such as <NaturalDocs::SymbolTable>.
Note that no prototype processing was done in this process, only the possible tranferring of prototypes from one ParsedTopic to another when merging autotopics with comment topics. Obtaining prototypes and formatting them is handled by <NaturalDocs::Languages::Simple> and <NaturalDocs::Languages::Advanced> derived packages.

View file

@ -1,269 +0,0 @@
###############################################################################
#
# File: Browser Testing
#
###############################################################################
#
# This file tests Natural Docs' generated output. Particularly useful when testing various browsers.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
#
# About: Browsers
#
# The specific browser versions tested are below. Everything is tested on Windows Vista unless otherwise noted.
#
# Firefox 2.0.0.10 - 2.0 released October 2006.
# Firefox 1.5.0.8 - 1.5 released Novemer 2005.
# Firefox 1.0.8 - 1.0 released November 2004. Not critical to support.
#
# IE 7.0 - 7.0 released October 2006.
# IE 6.0 - 6.0 released August 2001. Tested on Windows XP SP2 via Virtual PC.
#
# Safari 3.0.4 - 3.0 released June 2007. Tested Windows version.
# Safari 2.0.4 - 2.0 released April 2005. Tested on Mac OS X 10.4 Tiger.
#
# Opera 9.02 - 9.0 released June 2006.
# Opera 8.54 - 8.5 released September 2005.
# Opera 8.02 - 8.0 released April 2005.
# Opera 7.51 - 7.5 released around August 2004 I think. Not critical to support.
# Opera 7.02 - 7.0 released January 2003. Not critical to support.
#
# Konqueror 3.5.5 - Tested on openSUSE 10.2 via VMware Player.
#
###############################################################################
# Group: Search
#
# Topic: Unframed HTML Search
#
# Tests:
#
# - Make sure the search box appears and disappears correctly on hover.
# - Type to bring up results. Type further to narrow them. Narrow until there's no results.
# - Backspace to bring the results back. Backspacing to empty closes the results.
# - Type to bring up results with a different first letter. (Tests iframe content switch.)
# - Type *Z* to bring up empty page when there's nothing with that first letter. (Tests generic no results page.)
# - Type *Name* in Everything search to test expanding and collapsing, especially between two that differ only by case.
# - Change filter to *Functions* to test changing filter while results are open. Change to *Types* to switch to one with
# no results.
# - Test Close button on results. Should deactivate panel as well.
# - Clicking away should deactivate panel if the box is empty, not have an effect if there are results open.
# - Text should always change back to "Search" when deactivating.
#
# Results:
#
# Firefox 2.0 - OK
# Firefox 1.5 - OK
# Firefox 1.0 - OK
#
# IE 7.0 - OK
# IE 6.0 - Functionally OK. Search panel doesn't activate on hover. Works fine when clicked.
#
# Safari 3.0 - OK
# Safari 2.0 - *Broken.* Results panel doesn't show up. Border around deactivated search box.
#
# Opera 9.0 - OK
# Opera 8.5 - OK
# Opera 8.0 - OK
# Opera 7.5 - Functionally OK. Search panel has sunken border when deactivated, minor pixel shifting.
# Opera 7.0 - *Broken.* Completely.
#
# Konqueror 3.5 - *Broken.* Results panel doesn't show up. Seems to fail on "resultsFrame = window.frames.MSearchResults;"
#
#
# Topic: Framed HTML Search
#
# Tests:
#
# - Make sure the search box appears and disappears correctly on hover.
# - Type to bring up results on right. Type further to narrow them. Narrow until there's no results.
# - Backspace to bring the results back.
# - Type to bring up results with a different first letter. (Tests frame content switch.)
# - Type *Z* to bring up empty page when there's nothing with that first letter. (Tests generic no results page.)
# - Type *Name* in Everything search to see that there's no collapsing in this mode.
# - Change filter to *Functions* to test changing filter while results are open. Change to *Types* to switch to one with
# no results.
# - Clicking away should deactivate panel.
# - Clicking a result should deactivate panel and show up in correct frame.
# - Text should always change back to "Search" when deactivating.
#
# Results:
#
# Firefox 2.0 - OK
# Firefox 1.5 - OK
# Firefox 1.0 - OK
#
# IE 7.0 - OK
# IE 6.0 - Functionally OK. Search panel doesn't activate on hover, is a little wide. Works fine when clicked.
#
# Safari 3.0 - OK
# Safari 2.0 - Functionally OK. Has a sunken border around the deactivated seach field.
#
# Opera 9.0 - OK
# Opera 8.5 - OK
# Opera 8.0 - OK
# Opera 7.5 - Functionally OK. Search panel has sunken border when deactivated, minor pixel shifting.
# Opera 7.0 - *Broken.*
#
# Konqueror 3.5 - Functionally OK. Panel doesn't reset and deactivate when clicking a result link.
#
###############################################################################
# Group: Other
#
# Topic: Images
#
# Tests:
#
# - Here is an embedded image on its own line.
#
# (see images/logo.png)
#
# - Here is a reference in the middle of a sentence, in the middle of a bullet list: (see images/logo.png) It should have been
# converted to a link with the image appearing below the bullet list and the file name used as a caption. Make sure the
# caption positions correctly.
# - Here's a link to a non-existent image, which should appear literally: (see images/doesntexist.jpg)
# - Here is an embedded image that doesn't exist on it's own line.
#
# (see images/doesntexist.png)
#
# - Here is a link using the "(see)" syntax which shouldn't be interpreted as an image link because it doesn't end with an
# acceptable extension. Also, links should still resolve because of that. (see <Framed HTML Search>)
#
# Results:
#
# Firefox 2.0 - OK
# Firefox 1.5 - OK
# Firefox 1.0 - OK
#
# IE 7.0 - OK
# IE 6.0 - OK
#
# Safari 3.0 - OK
# Safari 2.0 - OK
#
# Opera 9.0 - OK
# Opera 8.5 - OK
# Opera 8.0 - OK
# Opera 7.5 - OK
# Opera 7.0 - OK
#
# Konqueror 3.5 - OK
#
# Topic: Prototypes and Tooltips
#
# Hover over <NaturalDocs::Parser::JavaDoc->ParseComment()> and <NaturalDocs::Parser::JavaDoc->IsMine()>
#
# Tests:
#
# - A tooltip should appear about a second after you hover over the link above.
# - It should go away when you move the cursor away.
# - It shoud be positioned directly underneath with a slight gap.
# - The prototype should be formatted cleanly with each parameter on its own line and aligned in columns.
# - The asterisk should be in a separate column.
# - Test it with the link too close to the edge of the window so the pop-up has to shift left to fit.
#
# Results:
#
# Firefox 2.0 - OK
# Firefox 1.5 - OK
# Firefox 1.0 - OK
#
# IE 7.0 - OK
# IE 6.0 - OK
#
# Safari 3.0 - OK
# Safari 2.0 - OK
#
# Opera 9.0 - OK. Has its own tooltips turned on by default which can cover it up though.
# Opera 8.5 - OK. Has its own tooltips turned on by default which can cover it up though.
# Opera 8.0 - OK. Has its own tooltips turned on by default which can cover it up though.
# Opera 7.5 - OK. Has its own tooltips turned on by default which can cover it up though.
# Opera 7.0 - *Broken.* Usually works, if the window is too narrow may collapse completely.
#
# Konqueror 3.5 - OK
#
#
# Topic: Long code block scrolling
#
# Go to <Prototype Parameter Styles>.
#
# Tests:
#
# - Shrink the browser window so that a line extends past the end of it. Only the line should have a scrollbar, not the
# entire page.
# - Expand the browser window. The scrollbar should disappear.
#
# Results:
#
# Firefox 2.0 - OK
# Firefox 1.5 - OK
# Firefox 1.0 - OK
#
# IE 7.0 - OK
# IE 6.0 - OK
#
# Safari 3.0 - OK
# Safari 2.0 - OK
#
# Opera 9.0 - OK
# Opera 8.5 - OK
# Opera 8.0 - OK
# Opera 7.5 - OK
# Opera 7.0 - OK
#
# Konqueror 3.5 - OK
#
#
# Topic: Menu and Class Hierarchies
#
# Go to <NaturalDocs::Languages::Simple>.
#
# Tests:
#
# - Class hierarchy should look okay.
# - Make sure the menu hierarchy opens up on its own when the page is loaded.
# - You should be able to click on groups to open and close them.
#
# Results:
#
# Firefox 2.0 - OK
# Firefox 1.5 - OK
# Firefox 1.0 - OK
#
# IE 7.0 - OK
# IE 6.0 - OK
#
# Safari 3.0 - OK
# Safari 2.0 - OK
#
# Opera 9.0 - OK
# Opera 8.5 - OK
# Opera 8.0 - OK
# Opera 7.5 - OK
# Opera 7.0 - OK
#
# Konqueror 3.5 - OK
#
1;

View file

@ -1,107 +0,0 @@
Title: Language Notes
_______________________________________________________________________________
This is more for my personal reference than anything else.
___________________________________________________________________________
Topic: Prototype Parameter Styles
___________________________________________________________________________
Parameters via Commas, Typed via Spaces:
> FunctionName ( type indentifier, type identifier = value, modifier type identifier )
> FunctionName ( indentifier, identifier = value )
The general idea is that parameters are separated by commas. Identifiers cannot contain spaces. Types and modifiers,
if available, are separated from the identifiers with spaces. There may be an equals sign to set the default value.
So parsing means splitting by commas, stripping everything past an equals sign for the default value, stripping everything
after the last space for the identifier, and the rest is the type. If there are no internal spaces after the default value is
stripped, it's all identifier.
Note that internal parenthesis, brackets, braces, and angle brackets should be parsed out. They may be present in default
values or types and any commas and equal signs in them should not be included.
Applies to C++, Java, C#, JavaScript, Python, PHP, Ruby.
Applies to Perl as well, even though it doesn't have any real parameter declaration structure. Just adding it with comments
is fine.
Parameters via Semicolons and Commas, Typed via Colons:
> FunctionName ( identifier: type; identifier, identifier: type; identifier: type := value )
Parameters via semicolons, types via colons. However, there can be more than one parameter per type via commas.
Default values via colon-equals.
Applies to Pascal, Ada.
SQL:
> FunctionName ( identifier type, identifier modifier type, identifier type := value )
Parameters separated by commas. Identifiers come before the types and are separated by a space. Default values are
specified with colon-equals.
> FunctionName @identifier type, @dentifier modifier type, @identifier type = value
Microsoft's SQL uses equals instead of colon-equals, doesn't need parenthesis, and starts its parameter names with an @
symbol.
Visual Basic:
> FunctionName ( modifiers identifier as type, identifier = value )
Parameters separated by commas. Default values via equals. However, any number of modifiers may appear before the
identifier. Those modifiers are ByVal, ByRef, Optional, and ParamArray.
Tcl:
> FunctionName { identifier identifier { whatever } } { code }
Identifiers are specified in the first set of braces and have no commas. However, they can be broken out into sub-braces.
___________________________________________________________________________
Topic: Syntax References
___________________________________________________________________________
C++ - http://www.csci.csusb.edu/dick/c++std/syntax.html
C# - http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csspec/html/CSharpSpecStart.asp. Open in IE.
Java - http://cui.unige.ch/db-research/Enseignement/analyseinfo/
Ada - http://cui.unige.ch/db-research/Enseignement/analyseinfo/
SQL - http://cui.unige.ch/db-research/Enseignement/analyseinfo/,
<http://www.cs.umb.edu/cs634/ora9idocs/appdev.920/a96624/13_elems.htm>, or
<http://msdn.microsoft.com/library/default.asp?url=/library/en-us/tsqlref/ts_tsqlcon_6lyk.asp?frame=true> (open in IE).
JavaScript - http://academ.hvcc.edu/~kantopet/javascript/index.php
Python - http://www.python.org/doc/2.3.4/ref/ref.html
PHP - http://www.php.net/manual/en/langref.php
Visual Basic - http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbls7/html/vbspecstart.asp. Open in IE.
Pascal - <http://pages.cpsc.ucalgary.ca/~becker/231/SyntaxDiagrams/pascal-syntax_files/frame.htm>. Open in IE.
Ruby - http://www.rubycentral.com/book/
ActionScript 2 - <http://download.macromedia.com/pub/documentation/en/flash/fl8/fl8_as2lr.pdf>
ActionScript 3 - <http://download.macromedia.com/pub/documentation/en/flex/2/prog_actionscript30.pdf>
E2X - http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-357.pdf
R - Somewhere on http://www.r-project.org.
ColdFusion - <http://livedocs.macromedia.com/coldfusion/6/Developing_ColdFusion_MX_Applications_with_CFML/contents.htm>
Eiffel - http://www.gobosoft.com/eiffel/syntax/

View file

@ -1,91 +0,0 @@
Architecture: NDMarkup
_______________________________________________________________________________
A markup format used by the parser, both internally and in <NaturalDocs::Parser::ParsedTopic> objects. Text formatted in
NDMarkup will only have the tags documented below.
About: Top-Level Tags
All content will be surrounded by one of the top-level tags. These tags will not appear within each other.
<p></p> - Surrounds a paragraph. Paragraph breaks will replace double line breaks, and single line breaks will
be removed completely.
<code></code> - Surrounds code or text diagrams that should appear literally in the output.
<h></h> - Surrounds a heading.
<ul></ul> - Surrounds a bulleted (unordered) list.
<dl></dl> - Surrounds a description list, which is what you are reading.
<img mode="inline" target="" original=""> - An inline image. Target contains the image target, and original contains the
original text in case it doesn't resolve.
About: List Item Tags
These tags will only appear within their respective lists.
<li></li> - Surrounds a bulleted list item.
<de></de> - Surrounds a description list entry, which is the left side. It will always be followed by a description list
description.
<ds></ds> - Surrounds a description list symbol. This is the same as a description list entry, except that the content
is also a referenceable symbol. This occurs when inside a list topic. This tag will always
be followed by a description list description.
<dd></dd> - Surrounds a description list description, which is the right side. It will always be preceded by a description
list entry or symbol.
About: Text Tags
These tags will only appear in paragraphs, headings, or description list descriptions.
<b></b> - Bold
<i></i> - Italics
<u></u> - Underline
<link target="" name="" original=""> - Surrounds a potential link to a symbol; potential because the target is not guaranteed to
exist. This tag merely designates an attempted link. Target is what is attempting to be
linked to, name is the text that should appear for a successful link, and original is the
original text in case the link doesn't resolve.
<url target="" name=""> - An external link. There's no need for an original attribute because it will always be
turned into an actual link.
<email target="" name=""> - A link to an e-mail address.
<img mode="link" target="" original=""> - An image link. Target contains the image target, and original contains the original
text in case it doesn't resolve.
About: Amp Chars
These are the only amp chars supported, and will appear everywhere. Every other character will appear as is.
&amp; - The ampersand &.
&quot; - The double quote ".
&lt; - The less than sign <.
&gt; - The greater than sign >.
About: Tabs
NDMarkup will not contain tab characters, only spaces. Any tab characters appearing in the source files will be
expanded/replaced as necessary.
About: General Tag Properties
Since the tags are generated, they will always have the following properties, which will make pattern matching much
easier.
- Tags and amp chars will always be in all lowercase.
- Properties will appear exactly as documented here. They will be in all lowercase, in the documented order, and will have no
extraneous whitespace. Anything appearing in the properties will have amp chars.
- All code is valid, meaning tags will always be closed, <li>s will only appear within <ul>s, etc.
So, for example, you can match description list entries with /<de>(.+?)<\/de>/ and $1 will be the text. No surprises or
gotchas. No need for sophisticated parsing routines.
Remember that for symbol definitions, the text should appear as is, but internally (such as for the anchor) they need to
be passed through <NaturalDocs::SymbolTable->Defines()> so that the output file is just as tolerant as
<NaturalDocs::SymbolTable>.

View file

@ -1,59 +0,0 @@
Architecture: Symbol Management
####################################################################################
This is the architecture and code path for symbol management. This is almost exclusively managed by <NaturalDocs::SymbolTable>, but it's complicated enough that I want a plain-English walk through of the code paths anyway.
An important thing to remember is that each section below is simplified initially and then expanded upon in later sections as more facets of the code are introduced. You will not get the whole story of what a function does by reading just one section.
Topic: Symbol Storage
_______________________________________________________________________________________________________
Symbols are indexed primarily by their <SymbolString>, which is the normalized, pre-parsed series of identifiers that make it up. A symbol can have any number of definitions, including none, but can only have one definition per file. If a symbol is defined more than once in a file, only the first definition is counted. Stored for each definition is the <TopicType>, summary, and prototype.
Each symbol that has a definition has one designated as the global definition. This is the one linked to by other files, unless that file happens to have its own definition which then takes precedence. Which definition is chosen is rather arbitrary at this point; probably the first one that got defined. Similarly, if the global definition is deleted, which one is chosen to replace it is completely arbitrary.
Each symbol also stores a list of references to it. Note that references can be interpreted as multiple symbols, and each of those symbols will store a link back to the reference. In other words, every reference a symbol stores is one that _can_ be interpreted as that symbol, but that is not necessarily the interpretation the reference actually uses. A reference could have a better interpretation it uses instead.
For example, suppose there are two functions, MyFunction() and MyClass.MyFunction(). The reference text "MyFunction()" appearing in MyClass can be interpreted as either MyClass.MyFunction(), or if that doesn't exist, the global MyFunction(). Both the symbols for MyFunction() and MyClass.MyFunction() will store that it's referenced by the link, even though the class scoped one serves as the actual definition.
This is also the reason a symbol can exist that has no definitions: it has references. We want symbols to be created in the table for each reference interpretation, even if it doesn't exist. These are called potential symbols. The reason is so we know whether a new symbol definition fulfills an existing reference, since it may be a better interpretation for the reference than what is currently used.
Topic: Reference Storage
_______________________________________________________________________________________________________
References are indexed primarily by their <ReferenceString>, which is actually an elaborate data structure packed into a string. It includes a <SymbolString> of the text that appears in the link and a bunch of other data that determines the rules by which the link can be resolved. For example, it includes the scope it appears in and any "using" statements in effect, which are alternate possible scopes. It includes the type of link it is (text links, the ones you explicitly put in comments, aren't the only kind) and resolving flags which encode the language-specific rules of non-text links. But the bottom line is the <ReferenceString> encodes everything that influences how it may be resolved, so if two links come up with the same rules, they're considered two definitions of the same reference. This is the understanding of the word "reference" that will used in this document.
Like symbols, each reference stores a list of definitions. However, it only stores the name as all the other relevant information is encoded in the <ReferenceString> itself. Unlike a symbol, which can be linked to the same no matter what kind of definitions it has, references that are in any way different might be interpreted differently and so need their own distinct entries in the symbol table.
References also store a list of interpretations. Every possible interpretation of the reference is stored and given a numeric score. The higher the score, the better it suits the reference. In the MyFunction() example from before, MyClass.MyFunction() would have a higher score than just MyFunction() because the local scope should win. Each interpretation has a unique score, there are no duplicates.
So the symbol and reference data structures are complimentary. Each symbol has a list of every reference that might be interpreted as it, and every reference has a list of each symbol that it could be interpreted as. Again, objects are created for potential symbols (those with references but no definitions) so that this structure always remains intact.
The interpretation with the highest score which actually exists is deemed the current interpretation of the reference. Unlike symbols where the next global definition is arbitrary, the succession of reference interpretations is very controlled and predictable.
Topic: Change Detection
_______________________________________________________________________________________________________
Change management is handled a couple of ways. First, there is a secondary file index in <NaturalDocs::SymbolTable> that stores which symbols and references are stored in each file. It doesn't have any information other than a list of <SymbolStrings> and <ReferenceStrings> since they can be used in the main structures to look up the details. If a file is deleted, the symbol table can then prune any definitions that should no longer be in the table.
Another way deals with how the information parsing stage works. Files parsed for information just have their symbols and references added to the table regardless of whether this was the first time it was ever parsed or if it had been parsed before. If it had been parsed before, all the information from the previous parse should be in the symbol table and file indexes already. If a new symbol or reference is defined, that's fine, it's added to the table normally. However, if a symbol is redefined it's ignored because only the first definition matters. Also, this won't detect things that disappear.
Enter watched files. <NaturalDocs::Parser> tells <NaturalDocs::SymbolTable> to designate a file as watched before it starts parsing it, and then says to analyze the changes when it's done. The watched file is a second index of all the symbols and references that were defined since the watch started, including the specific details on the symbol definitions. When the analysis is done, it compares the list of symbols and references to the one in the main file index. Any that appear in the main file index but not the watched one are deleted because they didn't show up the second time around. Any symbol definitions that are different in the watched file than the main file are changed to the former, since the first definition that appeared the second time around was different than the original.
Topic: Change Management
_______________________________________________________________________________________________________
When a symbol's global definition changes, either because it switches to another file or because the details of the current file's definition changed (prototype, summary, etc.) it goes through all the references that can be interpreted as that symbol, finds the ones that use it as their current definition, and marks all the files that define them for rebuilding. The links in their output files have to be changed to the new definition or at least have their tooltips updated.
When a symbol's last definition is deleted, it goes through all the references that can be interpreted as that symbol, finds the ones that use it as their current definition, and has them reinterpreted to the definition with the next highest score. The files that define them are also marked for rebuilding.
When a potential symbol's first definition is found, it goes through all the references that can be interpreted as it and sees if it can serve as a higher scored interpretation than the current one. If so, the interpretations are changed and all the files that define them are marked for rebuilding.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View file

@ -1,836 +0,0 @@
// This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
// Natural Docs is licensed under the GPL
//
// Browser Styles
// ____________________________________________________________________________
var agt=navigator.userAgent.toLowerCase();
var browserType;
var browserVer;
if (agt.indexOf("opera") != -1)
{
browserType = "Opera";
if (agt.indexOf("opera 7") != -1 || agt.indexOf("opera/7") != -1)
{ browserVer = "Opera7"; }
else if (agt.indexOf("opera 8") != -1 || agt.indexOf("opera/8") != -1)
{ browserVer = "Opera8"; }
else if (agt.indexOf("opera 9") != -1 || agt.indexOf("opera/9") != -1)
{ browserVer = "Opera9"; }
}
else if (agt.indexOf("applewebkit") != -1)
{
browserType = "Safari";
if (agt.indexOf("version/3") != -1)
{ browserVer = "Safari3"; }
else if (agt.indexOf("safari/4") != -1)
{ browserVer = "Safari2"; }
}
else if (agt.indexOf("khtml") != -1)
{
browserType = "Konqueror";
}
else if (agt.indexOf("msie") != -1)
{
browserType = "IE";
if (agt.indexOf("msie 6") != -1)
{ browserVer = "IE6"; }
else if (agt.indexOf("msie 7") != -1)
{ browserVer = "IE7"; }
}
else if (agt.indexOf("gecko") != -1)
{
browserType = "Firefox";
if (agt.indexOf("rv:1.7") != -1)
{ browserVer = "Firefox1"; }
else if (agt.indexOf("rv:1.8)") != -1 || agt.indexOf("rv:1.8.0") != -1)
{ browserVer = "Firefox15"; }
else if (agt.indexOf("rv:1.8.1") != -1)
{ browserVer = "Firefox2"; }
}
//
// Support Functions
// ____________________________________________________________________________
function GetXPosition(item)
{
var position = 0;
if (item.offsetWidth != null)
{
while (item != document.body && item != null)
{
position += item.offsetLeft;
item = item.offsetParent;
};
};
return position;
};
function GetYPosition(item)
{
var position = 0;
if (item.offsetWidth != null)
{
while (item != document.body && item != null)
{
position += item.offsetTop;
item = item.offsetParent;
};
};
return position;
};
function MoveToPosition(item, x, y)
{
// Opera 5 chokes on the px extension, so it can use the Microsoft one instead.
if (item.style.left != null)
{
item.style.left = x + "px";
item.style.top = y + "px";
}
else if (item.style.pixelLeft != null)
{
item.style.pixelLeft = x;
item.style.pixelTop = y;
};
};
//
// Menu
// ____________________________________________________________________________
function ToggleMenu(id)
{
if (!window.document.getElementById)
{ return; };
var display = window.document.getElementById(id).style.display;
if (display == "none")
{ display = "block"; }
else
{ display = "none"; }
window.document.getElementById(id).style.display = display;
}
function HideAllBut(ids, max)
{
if (document.getElementById)
{
ids.sort( function(a,b) { return a - b; } );
var number = 1;
while (number < max)
{
if (ids.length > 0 && number == ids[0])
{ ids.shift(); }
else
{
document.getElementById("MGroupContent" + number).style.display = "none";
};
number++;
};
};
}
//
// Tooltips
// ____________________________________________________________________________
var tooltipTimer = 0;
function ShowTip(event, tooltipID, linkID)
{
if (tooltipTimer)
{ clearTimeout(tooltipTimer); };
var docX = event.clientX + window.pageXOffset;
var docY = event.clientY + window.pageYOffset;
var showCommand = "ReallyShowTip('" + tooltipID + "', '" + linkID + "', " + docX + ", " + docY + ")";
tooltipTimer = setTimeout(showCommand, 1000);
}
function ReallyShowTip(tooltipID, linkID, docX, docY)
{
tooltipTimer = 0;
var tooltip;
var link;
if (document.getElementById)
{
tooltip = document.getElementById(tooltipID);
link = document.getElementById(linkID);
}
/* else if (document.all)
{
tooltip = eval("document.all['" + tooltipID + "']");
link = eval("document.all['" + linkID + "']");
}
*/
if (tooltip)
{
var left = GetXPosition(link);
var top = GetYPosition(link);
top += link.offsetHeight;
// The fallback method is to use the mouse X and Y relative to the document. We use a separate if and test if its a number
// in case some browser snuck through the above if statement but didn't support everything.
if (!isFinite(top) || top == 0)
{
left = docX;
top = docY;
}
// Some spacing to get it out from under the cursor.
top += 10;
// Make sure the tooltip doesnt get smushed by being too close to the edge, or in some browsers, go off the edge of the
// page. We do it here because Konqueror does get offsetWidth right even if it doesnt get the positioning right.
if (tooltip.offsetWidth != null)
{
var width = tooltip.offsetWidth;
var docWidth = document.body.clientWidth;
if (left + width > docWidth)
{ left = docWidth - width - 1; }
// If there's a horizontal scroll bar we could go past zero because it's using the page width, not the window width.
if (left < 0)
{ left = 0; };
}
MoveToPosition(tooltip, left, top);
tooltip.style.visibility = "visible";
}
}
function HideTip(tooltipID)
{
if (tooltipTimer)
{
clearTimeout(tooltipTimer);
tooltipTimer = 0;
}
var tooltip;
if (document.getElementById)
{ tooltip = document.getElementById(tooltipID); }
else if (document.all)
{ tooltip = eval("document.all['" + tooltipID + "']"); }
if (tooltip)
{ tooltip.style.visibility = "hidden"; }
}
//
// Blockquote fix for IE
// ____________________________________________________________________________
function NDOnLoad()
{
if (browserVer == "IE6")
{
var scrollboxes = document.getElementsByTagName('blockquote');
if (scrollboxes.item(0))
{
NDDoResize();
window.onresize=NDOnResize;
};
};
};
var resizeTimer = 0;
function NDOnResize()
{
if (resizeTimer != 0)
{ clearTimeout(resizeTimer); };
resizeTimer = setTimeout(NDDoResize, 250);
};
function NDDoResize()
{
var scrollboxes = document.getElementsByTagName('blockquote');
var i;
var item;
i = 0;
while (item = scrollboxes.item(i))
{
item.style.width = 100;
i++;
};
i = 0;
while (item = scrollboxes.item(i))
{
item.style.width = item.parentNode.offsetWidth;
i++;
};
clearTimeout(resizeTimer);
resizeTimer = 0;
}
/* ________________________________________________________________________________________________________
Class: SearchPanel
________________________________________________________________________________________________________
A class handling everything associated with the search panel.
Parameters:
name - The name of the global variable that will be storing this instance. Is needed to be able to set timeouts.
mode - The mode the search is going to work in. Pass <NaturalDocs::Builder::Base->CommandLineOption()>, so the
value will be something like "HTML" or "FramedHTML".
________________________________________________________________________________________________________
*/
function SearchPanel(name, mode, resultsPath)
{
if (!name || !mode || !resultsPath)
{ alert("Incorrect parameters to SearchPanel."); };
// Group: Variables
// ________________________________________________________________________
/*
var: name
The name of the global variable that will be storing this instance of the class.
*/
this.name = name;
/*
var: mode
The mode the search is going to work in, such as "HTML" or "FramedHTML".
*/
this.mode = mode;
/*
var: resultsPath
The relative path from the current HTML page to the results page directory.
*/
this.resultsPath = resultsPath;
/*
var: keyTimeout
The timeout used between a keystroke and when a search is performed.
*/
this.keyTimeout = 0;
/*
var: keyTimeoutLength
The length of <keyTimeout> in thousandths of a second.
*/
this.keyTimeoutLength = 500;
/*
var: lastSearchValue
The last search string executed, or an empty string if none.
*/
this.lastSearchValue = "";
/*
var: lastResultsPage
The last results page. The value is only relevant if <lastSearchValue> is set.
*/
this.lastResultsPage = "";
/*
var: deactivateTimeout
The timeout used between when a control is deactivated and when the entire panel is deactivated. Is necessary
because a control may be deactivated in favor of another control in the same panel, in which case it should stay
active.
*/
this.deactivateTimout = 0;
/*
var: deactivateTimeoutLength
The length of <deactivateTimeout> in thousandths of a second.
*/
this.deactivateTimeoutLength = 200;
// Group: DOM Elements
// ________________________________________________________________________
// Function: DOMSearchField
this.DOMSearchField = function()
{ return document.getElementById("MSearchField"); };
// Function: DOMSearchType
this.DOMSearchType = function()
{ return document.getElementById("MSearchType"); };
// Function: DOMPopupSearchResults
this.DOMPopupSearchResults = function()
{ return document.getElementById("MSearchResults"); };
// Function: DOMPopupSearchResultsWindow
this.DOMPopupSearchResultsWindow = function()
{ return document.getElementById("MSearchResultsWindow"); };
// Function: DOMSearchPanel
this.DOMSearchPanel = function()
{ return document.getElementById("MSearchPanel"); };
// Group: Event Handlers
// ________________________________________________________________________
/*
Function: OnSearchFieldFocus
Called when focus is added or removed from the search field.
*/
this.OnSearchFieldFocus = function(isActive)
{
this.Activate(isActive);
};
/*
Function: OnSearchFieldChange
Called when the content of the search field is changed.
*/
this.OnSearchFieldChange = function()
{
if (this.keyTimeout)
{
clearTimeout(this.keyTimeout);
this.keyTimeout = 0;
};
var searchValue = this.DOMSearchField().value.replace(/ +/g, "");
if (searchValue != this.lastSearchValue)
{
if (searchValue != "")
{
this.keyTimeout = setTimeout(this.name + ".Search()", this.keyTimeoutLength);
}
else
{
if (this.mode == "HTML")
{ this.DOMPopupSearchResultsWindow().style.display = "none"; };
this.lastSearchValue = "";
};
};
};
/*
Function: OnSearchTypeFocus
Called when focus is added or removed from the search type.
*/
this.OnSearchTypeFocus = function(isActive)
{
this.Activate(isActive);
};
/*
Function: OnSearchTypeChange
Called when the search type is changed.
*/
this.OnSearchTypeChange = function()
{
var searchValue = this.DOMSearchField().value.replace(/ +/g, "");
if (searchValue != "")
{
this.Search();
};
};
// Group: Action Functions
// ________________________________________________________________________
/*
Function: CloseResultsWindow
Closes the results window.
*/
this.CloseResultsWindow = function()
{
this.DOMPopupSearchResultsWindow().style.display = "none";
this.Activate(false, true);
};
/*
Function: Search
Performs a search.
*/
this.Search = function()
{
this.keyTimeout = 0;
var searchValue = this.DOMSearchField().value.replace(/^ +/, "");
var searchTopic = this.DOMSearchType().value;
var pageExtension = searchValue.substr(0,1);
if (pageExtension.match(/^[a-z]/i))
{ pageExtension = pageExtension.toUpperCase(); }
else if (pageExtension.match(/^[0-9]/))
{ pageExtension = 'Numbers'; }
else
{ pageExtension = "Symbols"; };
var resultsPage;
var resultsPageWithSearch;
var hasResultsPage;
// indexSectionsWithContent is defined in searchdata.js
if (indexSectionsWithContent[searchTopic][pageExtension] == true)
{
resultsPage = this.resultsPath + '/' + searchTopic + pageExtension + '.html';
resultsPageWithSearch = resultsPage+'?'+escape(searchValue);
hasResultsPage = true;
}
else
{
resultsPage = this.resultsPath + '/NoResults.html';
resultsPageWithSearch = resultsPage;
hasResultsPage = false;
};
var resultsFrame;
if (this.mode == "HTML")
{ resultsFrame = window.frames.MSearchResults; }
else if (this.mode == "FramedHTML")
{ resultsFrame = window.top.frames['Content']; };
if (resultsPage != this.lastResultsPage ||
// Bug in IE. If everything becomes hidden in a run, none of them will be able to be reshown in the next for some
// reason. It counts the right number of results, and you can even read the display as "block" after setting it, but it
// just doesn't work in IE 6 or IE 7. So if we're on the right page but the previous search had no results, reload the
// page anyway to get around the bug.
(browserType == "IE" && hasResultsPage &&
(!resultsFrame.searchResults || resultsFrame.searchResults.lastMatchCount == 0)) )
{
resultsFrame.location.href = resultsPageWithSearch;
}
// So if the results page is right and there's no IE bug, reperform the search on the existing page. We have to check if there
// are results because NoResults.html doesn't have any JavaScript, and it would be useless to do anything on that page even
// if it did.
else if (hasResultsPage)
{
// We need to check if this exists in case the frame is present but didn't finish loading.
if (resultsFrame.searchResults)
{ resultsFrame.searchResults.Search(searchValue); }
// Otherwise just reload instead of waiting.
else
{ resultsFrame.location.href = resultsPageWithSearch; };
};
var domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow();
if (this.mode == "HTML" && domPopupSearchResultsWindow.style.display != "block")
{
var domSearchType = this.DOMSearchType();
var left = GetXPosition(domSearchType);
var top = GetYPosition(domSearchType) + domSearchType.offsetHeight;
MoveToPosition(domPopupSearchResultsWindow, left, top);
domPopupSearchResultsWindow.style.display = 'block';
};
this.lastSearchValue = searchValue;
this.lastResultsPage = resultsPage;
};
// Group: Activation Functions
// Functions that handle whether the entire panel is active or not.
// ________________________________________________________________________
/*
Function: Activate
Activates or deactivates the search panel, resetting things to their default values if necessary. You can call this on every
control's OnBlur() and it will handle not deactivating the entire panel when focus is just switching between them transparently.
Parameters:
isActive - Whether you're activating or deactivating the panel.
ignoreDeactivateDelay - Set if you're positive the action will deactivate the panel and thus want to skip the delay.
*/
this.Activate = function(isActive, ignoreDeactivateDelay)
{
// We want to ignore isActive being false while the results window is open.
if (isActive || (this.mode == "HTML" && this.DOMPopupSearchResultsWindow().style.display == "block"))
{
if (this.inactivateTimeout)
{
clearTimeout(this.inactivateTimeout);
this.inactivateTimeout = 0;
};
this.DOMSearchPanel().className = 'MSearchPanelActive';
var searchField = this.DOMSearchField();
if (searchField.value == 'Search')
{ searchField.value = ""; }
}
else if (!ignoreDeactivateDelay)
{
this.inactivateTimeout = setTimeout(this.name + ".InactivateAfterTimeout()", this.inactivateTimeoutLength);
}
else
{
this.InactivateAfterTimeout();
};
};
/*
Function: InactivateAfterTimeout
Called by <inactivateTimeout>, which is set by <Activate()>. Inactivation occurs on a timeout because a control may
receive OnBlur() when focus is really transferring to another control in the search panel. In this case we don't want to
actually deactivate the panel because not only would that cause a visible flicker but it could also reset the search value.
So by doing it on a timeout instead, there's a short period where the second control's OnFocus() can cancel the deactivation.
*/
this.InactivateAfterTimeout = function()
{
this.inactivateTimeout = 0;
this.DOMSearchPanel().className = 'MSearchPanelInactive';
this.DOMSearchField().value = "Search";
this.lastSearchValue = "";
this.lastResultsPage = "";
};
};
/* ________________________________________________________________________________________________________
Class: SearchResults
_________________________________________________________________________________________________________
The class that handles everything on the search results page.
_________________________________________________________________________________________________________
*/
function SearchResults(name, mode)
{
/*
var: mode
The mode the search is going to work in, such as "HTML" or "FramedHTML".
*/
this.mode = mode;
/*
var: lastMatchCount
The number of matches from the last run of <Search()>.
*/
this.lastMatchCount = 0;
/*
Function: Toggle
Toggles the visibility of the passed element ID.
*/
this.Toggle = function(id)
{
if (this.mode == "FramedHTML")
{ return; };
var parentElement = document.getElementById(id);
var element = parentElement.firstChild;
while (element && element != parentElement)
{
if (element.nodeName == 'DIV' && element.className == 'ISubIndex')
{
if (element.style.display == 'block')
{ element.style.display = "none"; }
else
{ element.style.display = 'block'; }
};
if (element.nodeName == 'DIV' && element.hasChildNodes())
{ element = element.firstChild; }
else if (element.nextSibling)
{ element = element.nextSibling; }
else
{
do
{
element = element.parentNode;
}
while (element && element != parentElement && !element.nextSibling);
if (element && element != parentElement)
{ element = element.nextSibling; };
};
};
};
/*
Function: Search
Searches for the passed string. If there is no parameter, it takes it from the URL query.
Always returns true, since other documents may try to call it and that may or may not be possible.
*/
this.Search = function(search)
{
if (!search)
{
search = window.location.search;
search = search.substring(1); // Remove the leading ?
search = unescape(search);
};
search = search.replace(/^ +/, "");
search = search.replace(/ +$/, "");
search = search.toLowerCase();
if (search.match(/[^a-z0-9]/)) // Just a little speedup so it doesn't have to go through the below unnecessarily.
{
search = search.replace(/\_/g, "_und");
search = search.replace(/\ +/gi, "_spc");
search = search.replace(/\~/g, "_til");
search = search.replace(/\!/g, "_exc");
search = search.replace(/\@/g, "_att");
search = search.replace(/\#/g, "_num");
search = search.replace(/\$/g, "_dol");
search = search.replace(/\%/g, "_pct");
search = search.replace(/\^/g, "_car");
search = search.replace(/\&/g, "_amp");
search = search.replace(/\*/g, "_ast");
search = search.replace(/\(/g, "_lpa");
search = search.replace(/\)/g, "_rpa");
search = search.replace(/\-/g, "_min");
search = search.replace(/\+/g, "_plu");
search = search.replace(/\=/g, "_equ");
search = search.replace(/\{/g, "_lbc");
search = search.replace(/\}/g, "_rbc");
search = search.replace(/\[/g, "_lbk");
search = search.replace(/\]/g, "_rbk");
search = search.replace(/\:/g, "_col");
search = search.replace(/\;/g, "_sco");
search = search.replace(/\"/g, "_quo");
search = search.replace(/\'/g, "_apo");
search = search.replace(/\</g, "_lan");
search = search.replace(/\>/g, "_ran");
search = search.replace(/\,/g, "_com");
search = search.replace(/\./g, "_per");
search = search.replace(/\?/g, "_que");
search = search.replace(/\//g, "_sla");
search = search.replace(/[^a-z0-9\_]i/gi, "_zzz");
};
var resultRows = document.getElementsByTagName("div");
var matches = 0;
var i = 0;
while (i < resultRows.length)
{
var row = resultRows.item(i);
if (row.className == "SRResult")
{
var rowMatchName = row.id.toLowerCase();
rowMatchName = rowMatchName.replace(/^sr\d*_/, '');
if (search.length <= rowMatchName.length && rowMatchName.substr(0, search.length) == search)
{
row.style.display = "block";
matches++;
}
else
{ row.style.display = "none"; };
};
i++;
};
document.getElementById("Searching").style.display="none";
if (matches == 0)
{ document.getElementById("NoMatches").style.display="block"; }
else
{ document.getElementById("NoMatches").style.display="none"; }
this.lastMatchCount = matches;
return true;
};
};

View file

@ -1,341 +0,0 @@
File: GNU General Public Licence
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Topic: Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
Topic: Terms and Conditions for Copying, Distribution, and Modification
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY:
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
Topic: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View file

@ -1,294 +0,0 @@
###############################################################################
#
# Package: NaturalDocs::BinaryFile
#
###############################################################################
#
# A package to manage Natural Docs' binary data files.
#
# Usage:
#
# - Only one data file can be managed with this package at a time. You must close the file before opening another
# one.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
package NaturalDocs::BinaryFile;
use vars qw(@EXPORT @ISA);
require Exporter;
@ISA = qw(Exporter);
@EXPORT = ('BINARY_FORMAT');
###############################################################################
# Group: Format
#
# Topic: Standard Header
#
# > [UInt8: BINARY_FORMAT]
# > [VersionInt: app version]
#
# The first byte is <BINARY_FORMAT>, which distinguishes binary configuration files from text ones, since Natural Docs
# used to use text data files with the same name.
#
# The next section is the version of Natural Docs that wrote the file, as defined by <NaturalDocs::Settings->AppVersion>
# and written by <NaturalDocs::Version->ToBinaryFile()>.
#
#
# Topic: Data Types
#
# All the integer data types are written most significant byte first, aka big endian.
#
# An AString16 is a UInt16 followed by that many 8-bit ASCII characters. It doesn't include a null character at the end. Undef
# strings are represented by a zero for the UInt16 and nothing following it.
#
#
# Constant: BINARY_FORMAT
#
# An 8-bit constant that's used as the first byte of binary data files. This is used so that you can easily distinguish between
# binary and old-style text data files. It's not a character that would appear in plain text files.
#
use constant BINARY_FORMAT => pack('C', 0x06);
# Which is ACK or acknowledge in ASCII. Is the cool spade character in DOS displays.
###############################################################################
# Group: Variables
#
# handle: FH_BINARYDATAFILE
#
# The file handle used for the data file.
#
#
# string: currentFile
#
# The <FileName> for the current configuration file being parsed.
#
my $currentFile;
###############################################################################
# Group: File Functions
#
# Function: OpenForReading
#
# Opens a binary file for reading.
#
# Parameters:
#
# minimumVersion - The minimum version of the file format that is acceptible. May be undef.
#
# Returns:
#
# The format <VersionInt> or undef if it failed. It could fail for any of the following reasons.
#
# - The file doesn't exist.
# - The file couldn't be opened.
# - The file didn't have the proper header.
# - Either the application or the file was from a development release, and they're not the exact same development release.
# - The file's format was less than the minimum version, if one was defined.
# - The file was from a later application version than the current.
#
sub OpenForReading #(FileName file, optional VersionInt minimumVersion) => VersionInt
{
my ($self, $file, $minimumVersion) = @_;
if (defined $currentFile)
{ die "Tried to open binary file " . $file . " for reading when " . $currentFile . " was already open."; };
$currentFile = $file;
if (open(FH_BINARYDATAFILE, '<' . $currentFile))
{
# See if it's binary.
binmode(FH_BINARYDATAFILE);
my $firstChar;
read(FH_BINARYDATAFILE, $firstChar, 1);
if ($firstChar == ::BINARY_FORMAT())
{
my $version = NaturalDocs::Version->FromBinaryFile(\*FH_BINARYDATAFILE);
if (NaturalDocs::Version->CheckFileFormat($version, $minimumVersion))
{ return $version; };
};
close(FH_BINARYDATAFILE);
};
$currentFile = undef;
return undef;
};
#
# Function: OpenForWriting
#
# Opens a binary file for writing and writes the standard header. Dies if the file cannot be opened.
#
sub OpenForWriting #(FileName file)
{
my ($self, $file) = @_;
if (defined $currentFile)
{ die "Tried to open binary file " . $file . " for writing when " . $currentFile . " was already open."; };
$currentFile = $file;
open (FH_BINARYDATAFILE, '>' . $currentFile)
or die "Couldn't save " . $file . ".\n";
binmode(FH_BINARYDATAFILE);
print FH_BINARYDATAFILE '' . ::BINARY_FORMAT();
NaturalDocs::Version->ToBinaryFile(\*FH_BINARYDATAFILE, NaturalDocs::Settings->AppVersion());
};
#
# Function: Close
#
# Closes the current configuration file.
#
sub Close
{
my $self = shift;
if (!$currentFile)
{ die "Tried to close a binary file when one wasn't open."; };
close(FH_BINARYDATAFILE);
$currentFile = undef;
};
###############################################################################
# Group: Reading Functions
#
# Function: GetUInt8
# Reads and returns a UInt8 from the open file.
#
sub GetUInt8 # => UInt8
{
my $raw;
read(FH_BINARYDATAFILE, $raw, 1);
return unpack('C', $raw);
};
#
# Function: GetUInt16
# Reads and returns a UInt16 from the open file.
#
sub GetUInt16 # => UInt16
{
my $raw;
read(FH_BINARYDATAFILE, $raw, 2);
return unpack('n', $raw);
};
#
# Function: GetUInt32
# Reads and returns a UInt32 from the open file.
#
sub GetUInt32 # => UInt32
{
my $raw;
read(FH_BINARYDATAFILE, $raw, 4);
return unpack('N', $raw);
};
#
# Function: GetAString16
# Reads and returns an AString16 from the open file. Supports undef strings.
#
sub GetAString16 # => string
{
my $rawLength;
read(FH_BINARYDATAFILE, $rawLength, 2);
my $length = unpack('n', $rawLength);
if (!$length)
{ return undef; };
my $string;
read(FH_BINARYDATAFILE, $string, $length);
return $string;
};
###############################################################################
# Group: Writing Functions
#
# Function: WriteUInt8
# Writes a UInt8 to the open file.
#
sub WriteUInt8 #(UInt8 value)
{
my ($self, $value) = @_;
print FH_BINARYDATAFILE pack('C', $value);
};
#
# Function: WriteUInt16
# Writes a UInt32 to the open file.
#
sub WriteUInt16 #(UInt16 value)
{
my ($self, $value) = @_;
print FH_BINARYDATAFILE pack('n', $value);
};
#
# Function: WriteUInt32
# Writes a UInt32 to the open file.
#
sub WriteUInt32 #(UInt32 value)
{
my ($self, $value) = @_;
print FH_BINARYDATAFILE pack('N', $value);
};
#
# Function: WriteAString16
# Writes an AString16 to the open file. Supports undef strings.
#
sub WriteAString16 #(string value)
{
my ($self, $string) = @_;
if (length($string))
{ print FH_BINARYDATAFILE pack('nA*', length($string), $string); }
else
{ print FH_BINARYDATAFILE pack('n', 0); };
};
1;

View file

@ -1,280 +0,0 @@
###############################################################################
#
# Package: NaturalDocs::Builder
#
###############################################################################
#
# A package that takes parsed source file and builds the output for it.
#
# Usage and Dependencies:
#
# - <Add()> can be called immediately.
# - <OutputPackages()> and <OutputPackageOf()> can be called once all sub-packages have been registered via <Add()>.
# Since this is normally done in their INIT functions, they should be available to all normal functions immediately.
#
# - Prior to calling <Run()>, <NaturalDocs::Settings>, <NaturalDocs::Project>, <NaturalDocs::Menu>, and
# <NaturalDocs::Parser> must be initialized. <NaturalDocs::Settings->GenerateDirectoryNames()> must be called.
# <NaturalDocs::SymbolTable> and <NaturalDocs::ClassHierarchy> must be initialized and fully resolved.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
use NaturalDocs::Builder::Base;
use NaturalDocs::Builder::HTML;
use NaturalDocs::Builder::FramedHTML;
package NaturalDocs::Builder;
###############################################################################
# Group: Variables
#
# Array: outputPackages
#
# An array of the output packages available for use.
#
my @outputPackages;
###############################################################################
# Group: Functions
#
# Function: OutputPackages
#
# Returns an arrayref of the output packages available for use. The arrayref is not a copy of the data, so don't change it.
#
# Add output packages to this list with the <Add()> function.
#
sub OutputPackages
{ return \@outputPackages; };
#
# Function: OutputPackageOf
#
# Returns the output package corresponding to the passed command line option, or undef if none.
#
sub OutputPackageOf #(commandLineOption)
{
my ($self, $commandLineOption) = @_;
$commandLineOption = lc($commandLineOption);
foreach my $package (@outputPackages)
{
if (lc($package->CommandLineOption()) eq $commandLineOption)
{ return $package; };
};
return undef;
};
#
# Function: Add
#
# Adds an output package to those available for use. All output packages must call this function in order to be recognized.
#
# Parameters:
#
# package - The package name.
#
sub Add #(package)
{
my ($self, $package) = @_;
# Output packages shouldn't register themselves more than once, so we don't need to check for it.
push @outputPackages, $package;
};
#
# Function: Run
#
# Runs the build process. This must be called *every time* Natural Docs is run, regardless of whether any source files changed
# or not. Some output packages have dependencies on files outside of the source tree that need to be checked.
#
# Since there are multiple stages to the build process, this function will handle its own status messages. There's no need to print
# "Building files..." or something similar beforehand.
#
sub Run
{
my ($self) = @_;
# Determine what we're doing.
my $buildTargets = NaturalDocs::Settings->BuildTargets();
my $filesToBuild = NaturalDocs::Project->FilesToBuild();
my $numberOfFilesToBuild = (scalar keys %$filesToBuild) * (scalar @$buildTargets);
my $filesToPurge = NaturalDocs::Project->FilesToPurge();
my $numberOfFilesToPurge = (scalar keys %$filesToPurge) * (scalar @$buildTargets);
my $imagesToUpdate = NaturalDocs::Project->ImageFilesToUpdate();
my $numberOfImagesToUpdate = (scalar keys %$imagesToUpdate) * (scalar @$buildTargets);
my $imagesToPurge = NaturalDocs::Project->ImageFilesToPurge();
my $numberOfImagesToPurge = (scalar keys %$imagesToPurge) * (scalar @$buildTargets);
my %indexesToBuild;
my %indexesToPurge;
my $currentIndexes = NaturalDocs::Menu->Indexes();
my $previousIndexes = NaturalDocs::Menu->PreviousIndexes();
foreach my $index (keys %$currentIndexes)
{
if (NaturalDocs::SymbolTable->IndexChanged($index) || !exists $previousIndexes->{$index})
{
$indexesToBuild{$index} = 1;
};
};
# All indexes that still exist should have been deleted.
foreach my $index (keys %$previousIndexes)
{
if (!exists $currentIndexes->{$index})
{
$indexesToPurge{$index} = 1;
};
};
my $numberOfIndexesToBuild = (scalar keys %indexesToBuild) * (scalar @$buildTargets);
my $numberOfIndexesToPurge = (scalar keys %indexesToPurge) * (scalar @$buildTargets);
# Start the build process
foreach my $buildTarget (@$buildTargets)
{
$buildTarget->Builder()->BeginBuild( $numberOfFilesToBuild || $numberOfFilesToPurge ||
$numberOfImagesToUpdate || $numberOfImagesToPurge ||
$numberOfIndexesToBuild || $numberOfIndexesToPurge ||
NaturalDocs::Menu->HasChanged() );
};
if ($numberOfFilesToPurge)
{
NaturalDocs::StatusMessage->Start('Purging ' . $numberOfFilesToPurge
. ' file' . ($numberOfFilesToPurge > 1 ? 's' : '') . '...',
scalar @$buildTargets);
foreach my $buildTarget (@$buildTargets)
{
$buildTarget->Builder()->PurgeFiles($filesToPurge);
NaturalDocs::StatusMessage->CompletedItem();
};
};
if ($numberOfIndexesToPurge)
{
NaturalDocs::StatusMessage->Start('Purging ' . $numberOfIndexesToPurge
. ' index' . ($numberOfIndexesToPurge > 1 ? 'es' : '') . '...',
scalar @$buildTargets);
foreach my $buildTarget (@$buildTargets)
{
$buildTarget->Builder()->PurgeIndexes(\%indexesToPurge);
NaturalDocs::StatusMessage->CompletedItem();
};
};
if ($numberOfImagesToPurge)
{
NaturalDocs::StatusMessage->Start('Purging ' . $numberOfImagesToPurge
. ' image' . ($numberOfImagesToPurge > 1 ? 's' : '') . '...',
scalar @$buildTargets);
foreach my $buildTarget (@$buildTargets)
{
$buildTarget->Builder()->PurgeImages($imagesToPurge);
NaturalDocs::StatusMessage->CompletedItem();
};
};
if ($numberOfFilesToBuild)
{
NaturalDocs::StatusMessage->Start('Building ' . $numberOfFilesToBuild
. ' file' . ($numberOfFilesToBuild > 1 ? 's' : '') . '...',
$numberOfFilesToBuild);
foreach my $file (keys %$filesToBuild)
{
my $parsedFile = NaturalDocs::Parser->ParseForBuild($file);
NaturalDocs::Error->OnStartBuilding($file);
foreach my $buildTarget (@$buildTargets)
{
$buildTarget->Builder()->BuildFile($file, $parsedFile);
NaturalDocs::StatusMessage->CompletedItem();
};
NaturalDocs::Error->OnEndBuilding($file);
};
};
if ($numberOfIndexesToBuild)
{
NaturalDocs::StatusMessage->Start('Building ' . $numberOfIndexesToBuild
. ' index' . ($numberOfIndexesToBuild > 1 ? 'es' : '') . '...',
$numberOfIndexesToBuild);
foreach my $index (keys %indexesToBuild)
{
foreach my $buildTarget (@$buildTargets)
{
$buildTarget->Builder()->BuildIndex($index);
NaturalDocs::StatusMessage->CompletedItem();
};
};
};
if ($numberOfImagesToUpdate)
{
NaturalDocs::StatusMessage->Start('Updating ' . $numberOfImagesToUpdate
. ' image' . ($numberOfImagesToUpdate > 1 ? 's' : '') . '...',
$numberOfImagesToUpdate);
foreach my $image (keys %$imagesToUpdate)
{
foreach my $buildTarget (@$buildTargets)
{
$buildTarget->Builder()->UpdateImage($image);
NaturalDocs::StatusMessage->CompletedItem();
};
};
};
if (NaturalDocs::Menu->HasChanged())
{
if (!NaturalDocs::Settings->IsQuiet())
{ print "Updating menu...\n"; };
foreach my $buildTarget (@$buildTargets)
{ $buildTarget->Builder()->UpdateMenu(); };
};
foreach my $buildTarget (@$buildTargets)
{
$buildTarget->Builder()->EndBuild($numberOfFilesToBuild || $numberOfFilesToPurge ||
$numberOfIndexesToBuild || $numberOfIndexesToPurge ||
$numberOfImagesToUpdate || $numberOfImagesToPurge ||
NaturalDocs::Menu->HasChanged());
};
};
1;

View file

@ -1,348 +0,0 @@
###############################################################################
#
# Class: NaturalDocs::Builder::Base
#
###############################################################################
#
# A base class for all Builder output formats.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
package NaturalDocs::Builder::Base;
###############################################################################
# Group: Notes
#
# Topic: Implementation
#
# Builder packages are implemented as blessed arrayrefs, not hashrefs. This is done for all objects in Natural Docs for
# efficiency reasons. You create members by defining constants via <NaturalDocs::DefineMembers> and using them as
# indexes into the array.
#
#
# Topic: Function Order
#
# The functions in the build process will always be called in the following order.
#
# - <BeginBuild()> will always be called.
# - <PurgeFiles()> will be called next only if there's files that need to be purged.
# - <PurgeIndexes()> will be called next only if there's indexes that need to be purged.
# - <PurgeImages()> will e called next only if there's images that need to be purged.
# - <BuildFile()> will be called once for each file that needs to be built, if any.
# - <BuildIndex()> will be called once for each index that changed and is part of the menu, if any.
# - <UpdateImage()> will be called once for each image that needs to be updated, if any.
# - <UpdateMenu()> will be called next only if the menu changed.
# - <EndBuild()> will always be called.
#
#
# Topic: How to Approach
#
# Here's an idea of how to approach making packages for different output types.
#
#
# Multiple Output Files, Embedded Menu:
#
# This example is for when you want to build one output file per source file, each with its own copy of the menu within it.
# This is how <NaturalDocs::Builder::HTML> works.
#
# Make sure you create a function that generates just the menu for a particular source file. We'll need to generate menus for
# both building a file from scratch and for updating the menu on an existing output file, so it's better to give it its own function.
# You may want to surround it with something that can be easily detected in the output file to make replacing easier.
#
# <BeginBuild()> isn't important. You don't need to implement it.
#
# Implement <PurgeFiles()> to delete the output files associated with the purged files.
#
# Implement <PurgeIndexes()> to delete the output files associated with the purged indexes.
#
# Implement <BuildFile()> to create an output file for the parsed source file. Use the menu function described earlier.
#
# Implement <BuildIndex()> to create an output file for each index. Use the menu function described earlier for each page.
#
# Implement <UpdateMenu()> to go through the list of unbuilt files and update their menus. You can get the list from
# <NaturalDocs::Project->UnbuiltFilesWithContent()>. You need to open their output files, replace the menu, and save it back
# to disk. Yes, it would be simpler from a programmer's point of view to just rebuild the file completely, but that would be
# _very_ inefficient since there could potentially be a _lot_ of files in this group.
#
# Also make sure <UpdateMenu()> goes through the unchanged indexes and updates them as well.
#
# <EndBuild()> isn't important. You don't need to implement it.
#
#
# Multiple Output Files, Menu in File:
#
# This example is for when you want to build one output file per source file, but keep the menu in its own separate file. This
# is how <NaturalDocs::Builder::FramedHTML> works.
#
# <BeginBuild()> isn't important. You don't need to implement it.
#
# Implement <PurgeFiles()> to delete the output files associated with the purged files.
#
# Implement <PurgeIndexes()> to delete the output files associated with the purged indexes.
#
# Implement <BuildFile()> to generate an output file from the parsed source file.
#
# Implement <BuildIndex()> to generate an output file for each index.
#
# Implement <UpdateMenu()> to rebuild the menu file.
#
# <EndBuild()> isn't important. You don't need to implement it.
#
#
# Single Output File using Intermediate Files:
#
# This example is for when you want to build one output file, such as a PDF file, but use intermediate files to handle differential
# building. This would be much like how a compiler compiles each source file into a object file, and then a linker stitches them
# all together into the final executable file.
#
# <BeginBuild()> isn't important. You don't need to implement it.
#
# Implement <PurgeFiles()> to delete the intermediate files associated with the purged files.
#
# Implement <PurgeIndexes()> to delete the intermediate files associated with the purged indexes.
#
# Implement <BuildFile()> to generate an intermediate file from the parsed source file.
#
# Implement <BuildIndex()> to generate an intermediate file for the specified index.
#
# Implement <UpdateMenu()> to generate the intermediate file for the menu.
#
# Implement <EndBuild()> so that if the project changed, it stitches the intermediate files together into the final
# output file. Make sure you check the parameter because the function will be called when nothing changes too.
#
#
# Single Output File using Direct Changes:
#
# This example is for when you want to build one output file, such as a PDF file, but engineering it in such a way that you don't
# need to use intermediate files. In other words, you're able to add, delete, and modify entries directly in the output file.
#
# Implement <BeginBuild()> so that if the project changed, it opens the output file and does anything it needs to do
# to get ready for editing.
#
# Implement <PurgeFiles()> to remove the entries associated with the purged files.
#
# Implement <PurgeIndexes()> to remove the entries associated with the purged indexes.
#
# Implement <BuildFile()> to add or replace a section of the output file with a new one generated from the parsed file.
#
# Implement <BuildIndex()> to add or replace an index in the output file with a new one generated from the specified index.
#
# Implement <EndBuild()> so that if the project changed, it saves the output file to disk.
#
# How you handle the menu depends on how the output file references other sections of itself. If it can do so by name, then
# you can implement <UpdateMenu()> to update the menu section of the file and you're done. If it has to reference itself
# by address or offset, it gets trickier. You should skip <UpdateMenu()> and instead rebuild the menu in <EndBuild()> if
# the parameter is true. This lets you do it whenever anything changes in a file, rather than just when the menu
# visibly changes. How you keep track of the locations and how they change is your problem.
#
###############################################################################
#
# Group: Required Interface Functions
#
# All Builder classes *must* define these functions.
#
#
# Function: INIT
#
# Define this function to call <NaturalDocs::Builder->Add()> so that <NaturalDocs::Builder> knows about this package.
# Packages are defined this way so that new ones can be added without messing around in other code.
#
#
# Function: CommandLineOption
#
# Define this function to return the text that should be put in the command line after -o to use this package. It cannot have
# spaces and is not case sensitive.
#
# For example, <NaturalDocs::Builder::HTML> returns 'html' so someone could use -o html [directory] to use that package.
#
sub CommandLineOption
{
NaturalDocs::Error->SoftDeath($_[0] . " didn't define CommandLineOption().");
};
#
# Function: BuildFile
#
# Define this function to convert a parsed file to this package's output format. This function will be called once for every source
# file that needs to be rebuilt. However, if a file hasn't changed since the last time Natural Docs was run, it will not be sent to
# this function. All packages must support differential build.
#
# Parameters:
#
# sourceFile - The name of the source file.
# parsedFile - The parsed source file, as an arrayref of <NaturalDocs::Parser::ParsedTopic> objects.
#
sub BuildFile #(sourceFile, parsedFile)
{
NaturalDocs::Error->SoftDeath($_[0] . " didn't define BuildFile().");
};
###############################################################################
#
# Group: Optional Interface Functions
#
# These functions can be implemented but packages are not required to do so.
#
#
# Function: New
#
# Creates and returns a new object.
#
# Note that this is the only function where the first parameter will be the package name, not the object itself.
#
sub New
{
my $package = shift;
my $object = [ ];
bless $object, $package;
return $object;
};
#
# Function: BeginBuild
#
# Define this function if the package needs to do anything at the beginning of the build process. This function will be called
# every time Natural Docs is run, even if the project hasn't changed. This allows you to manage dependencies specific
# to the output format that may change independently from the source tree and menu. For example,
# <NaturalDocs::Builder::HTML> needs to keep the CSS files in sync regardless of whether the source tree changed or not.
#
# Parameters:
#
# hasChanged - Whether the project has changed, such as source files or the menu file. If false, nothing else is going to be
# called except <EndBuild()>.
#
sub BeginBuild #(hasChanged)
{
};
#
# Function: EndBuild
#
# Define this function if the package needs to do anything at the end of the build process. This function will be called every time
# Natural Docs is run, even if the project hasn't changed. This allows you to manage dependencies specific to the output
# format that may change independently from the source tree. For example, <NaturalDocs::Builder::HTML> needs to keep the
# CSS files in sync regardless of whether the source tree changed or not.
#
# Parameters:
#
# hasChanged - Whether the project has changed, such as source files or the menu file. If false, the only other function that
# was called was <BeginBuild()>.
#
sub EndBuild #(hasChanged)
{
};
#
# Function: BuildIndex
#
# Define this function to create an index for the passed topic. You can get the index from
# <NaturalDocs::SymbolTable->Index()>.
#
# The reason it's not passed directly to this function is because indexes may be time-consuming to create. As such, they're
# generated on demand because some output packages may choose not to implement them.
#
# Parameters:
#
# topic - The <TopicType> to limit the index by.
#
sub BuildIndex #(topic)
{
};
#
# Function: UpdateImage
#
# Define this function to add or update the passed image in the output.
#
# Parameters:
#
# file - The image <FileName>
#
sub UpdateImage #(file)
{
};
#
# Function: PurgeFiles
#
# Define this function to make the package remove all output related to the passed files. These files no longer have Natural Docs
# content.
#
# Parameters:
#
# files - An existence hashref of the files to purge.
#
sub PurgeFiles #(files)
{
};
#
# Function: PurgeIndexes
#
# Define this function to make the package remove all output related to the passed indexes. These indexes are no longer part
# of the menu.
#
# Parameters:
#
# indexes - An existence hashref of the <TopicTypes> of the indexes to purge.
#
sub PurgeIndexes #(indexes)
{
};
#
# Function: PurgeImages
#
# Define this function to make the package remove all output related to the passed image files. These files are no longer used
# by the documentation.
#
# Parameters:
#
# files - An existence hashref of the image <FileNames> to purge.
#
sub PurgeImages #(files)
{
};
#
# Function: UpdateMenu
#
# Define this function to make the package update the menu. It will only be called if the menu changed.
#
sub UpdateMenu
{
};
1;

View file

@ -1,345 +0,0 @@
###############################################################################
#
# Package: NaturalDocs::Builder::FramedHTML
#
###############################################################################
#
# A package that generates output in HTML with frames.
#
# All functions are called with Package->Function() notation.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
package NaturalDocs::Builder::FramedHTML;
use base 'NaturalDocs::Builder::HTMLBase';
###############################################################################
# Group: Implemented Interface Functions
#
# Function: INIT
#
# Registers the package with <NaturalDocs::Builder>.
#
sub INIT
{
NaturalDocs::Builder->Add(__PACKAGE__);
};
#
# Function: CommandLineOption
#
# Returns the option to follow -o to use this package. In this case, "html".
#
sub CommandLineOption
{
return 'FramedHTML';
};
#
# Function: BuildFile
#
# Builds the output file from the parsed source file.
#
# Parameters:
#
# sourcefile - The <FileName> of the source file.
# parsedFile - An arrayref of the source file as <NaturalDocs::Parser::ParsedTopic> objects.
#
sub BuildFile #(sourceFile, parsedFile)
{
my ($self, $sourceFile, $parsedFile) = @_;
my $outputFile = $self->OutputFileOf($sourceFile);
# 99.99% of the time the output directory will already exist, so this will actually be more efficient. It only won't exist
# if a new file was added in a new subdirectory and this is the first time that file was ever parsed.
if (!open(OUTPUTFILEHANDLE, '>' . $outputFile))
{
NaturalDocs::File->CreatePath( NaturalDocs::File->NoFileName($outputFile) );
open(OUTPUTFILEHANDLE, '>' . $outputFile)
or die "Couldn't create output file " . $outputFile . "\n";
};
print OUTPUTFILEHANDLE
# IE 6 doesn't like any doctype here at all. Add one (strict or transitional doesn't matter) and it makes the page slightly too
# wide for the frame. Mozilla and Opera handle it like champs either way because they Don't Suck(tm).
# '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" '
# . '"http://www.w3.org/TR/REC-html40/loose.dtd">' . "\n\n"
'<html><head>'
. (NaturalDocs::Settings->CharSet() ?
'<meta http-equiv="Content-Type" content="text/html; charset=' . NaturalDocs::Settings->CharSet() . '">' : '')
. '<title>'
. $self->BuildTitle($sourceFile)
. '</title>'
. '<link rel="stylesheet" type="text/css" href="' . $self->MakeRelativeURL($outputFile, $self->MainCSSFile(), 1) . '">'
. '<script language=JavaScript src="' . $self->MakeRelativeURL($outputFile, $self->MainJavaScriptFile(), 1) . '"></script>'
. '</head><body class="FramedContentPage" onLoad="NDOnLoad()">'
. $self->OpeningBrowserStyles()
. $self->StandardComments()
. "\n\n\n"
. $self->BuildContent($sourceFile, $parsedFile)
. "\n\n\n"
. $self->BuildToolTips()
. $self->ClosingBrowserStyles()
. '</body></html>';
close(OUTPUTFILEHANDLE);
};
#
# Function: BuildIndex
#
# Builds an index for the passed type.
#
# Parameters:
#
# type - The <TopicType> to limit the index to, or undef if none.
#
sub BuildIndex #(type)
{
my ($self, $type) = @_;
my $indexTitle = $self->IndexTitleOf($type);
my $indexFile = $self->IndexFileOf($type);
my $startIndexPage =
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" '
. '"http://www.w3.org/TR/REC-html40/loose.dtd">' . "\n\n"
. '<html><head>'
. (NaturalDocs::Settings->CharSet() ?
'<meta http-equiv="Content-Type" content="text/html; charset=' . NaturalDocs::Settings->CharSet() . '">' : '')
. '<title>';
if (defined NaturalDocs::Menu->Title())
{ $startIndexPage .= $self->StringToHTML(NaturalDocs::Menu->Title()) . ' - '; };
$startIndexPage .=
$indexTitle
. '</title>'
. '<link rel="stylesheet" type="text/css" href="' . $self->MakeRelativeURL($indexFile, $self->MainCSSFile(), 1) . '">'
. '<script language=JavaScript src="' . $self->MakeRelativeURL($indexFile, $self->MainJavaScriptFile(), 1) . '"></script>'
. '</head><body class="FramedIndexPage" onLoad="NDOnLoad()">'
. $self->OpeningBrowserStyles()
. "\n\n\n"
. $self->StandardComments()
. "\n\n\n"
. '<div id=Index>'
. '<div class=IPageTitle>'
. $indexTitle
. '</div>';
my $endIndexPage =
'</div><!--Index-->'
. "\n\n\n"
. $self->ClosingBrowserStyles()
. '</body></html>';
my $startSearchResultsPage =
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" '
. '"http://www.w3.org/TR/REC-html40/loose.dtd">' . "\n\n"
. '<html><head>'
. (NaturalDocs::Settings->CharSet() ?
'<meta http-equiv="Content-Type" content="text/html; charset=' . NaturalDocs::Settings->CharSet() . '">' : '')
. '<link rel="stylesheet" type="text/css" href="' . $self->MakeRelativeURL($indexFile, $self->MainCSSFile(), 1) . '">'
. '<script language=JavaScript src="' . $self->MakeRelativeURL($indexFile, $self->MainJavaScriptFile(), 1) . '"></script>'
. '<script language=JavaScript src="' . $self->MakeRelativeURL($indexFile, $self->SearchDataJavaScriptFile(), 1) . '">'
. '</script>'
. '</head><body class="FramedSearchResultsPage" onLoad="NDOnLoad()">'
. $self->OpeningBrowserStyles()
. "\n\n\n"
. $self->StandardComments()
. "\n\n\n"
. '<div id=Index>'
. '<div class=IPageTitle>'
. 'Search Results'
. '</div>';
my $endSearchResultsPage =
'</div><!--Index-->'
. "\n\n\n"
. $self->ClosingBrowserStyles()
. '</body></html>';
my $indexContent = NaturalDocs::SymbolTable->Index($type);
my $pageCount = $self->BuildIndexPages($type, $indexContent, $startIndexPage, $endIndexPage,
$startSearchResultsPage, $endSearchResultsPage);
$self->PurgeIndexFiles($type, $indexContent, $pageCount + 1);
};
#
# Function: UpdateMenu
#
# Builds the menu file. Also generates index.html.
#
sub UpdateMenu
{
my $self = shift;
my $outputDirectory = NaturalDocs::Settings->OutputDirectoryOf($self);
my $outputFile = NaturalDocs::File->JoinPaths($outputDirectory, 'menu.html');
open(OUTPUTFILEHANDLE, '>' . $outputFile)
or die "Couldn't create output file " . $outputFile . "\n";
my $title = 'Menu';
if (defined $title)
{ $title .= ' - ' . NaturalDocs::Menu->Title(); };
$title = $self->StringToHTML($title);
print OUTPUTFILEHANDLE
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" '
. '"http://www.w3.org/TR/REC-html40/loose.dtd">' . "\n\n"
. '<html><head>'
. (NaturalDocs::Settings->CharSet() ?
'<meta http-equiv="Content-Type" content="text/html; charset=' . NaturalDocs::Settings->CharSet() . '">' : '')
. '<title>'
. $title
. '</title>'
. '<base target="Content">'
. '<link rel="stylesheet" type="text/css" href="' . $self->MakeRelativeURL($outputFile, $self->MainCSSFile(), 1) . '">'
. '<script language=JavaScript src="' . $self->MakeRelativeURL($outputFile, $self->MainJavaScriptFile(), 1) . '"></script>'
. '<script language=JavaScript src="' . $self->MakeRelativeURL($outputFile, $self->SearchDataJavaScriptFile(), 1) . '">'
. '</script>'
. '</head><body class="FramedMenuPage" onLoad="NDOnLoad()">'
. $self->OpeningBrowserStyles()
. $self->StandardComments()
. "\n\n\n"
. $self->BuildMenu(undef, undef)
. "\n\n\n"
. $self->BuildFooter(1)
. "\n\n\n"
. $self->ClosingBrowserStyles()
. '</body></html>';
close(OUTPUTFILEHANDLE);
# Update index.html
my $firstMenuEntry = $self->FindFirstFile();
my $indexFile = NaturalDocs::File->JoinPaths( NaturalDocs::Settings->OutputDirectoryOf($self), 'index.html' );
# We have to check because it's possible that there may be no files with Natural Docs content and thus no files on the menu.
if (defined $firstMenuEntry)
{
open(INDEXFILEHANDLE, '>' . $indexFile)
or die "Couldn't create output file " . $indexFile . ".\n";
print INDEXFILEHANDLE
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN" '
. '"http://www.w3.org/TR/REC-html40/frameset.dtd">'
. '<html>'
. '<head>'
. (NaturalDocs::Settings->CharSet() ?
'<meta http-equiv="Content-Type" content="text/html; charset=' . NaturalDocs::Settings->CharSet() . '">' : '')
. '<title>'
. $self->StringToHTML(NaturalDocs::Menu->Title())
. '</title>'
. '</head>'
. $self->StandardComments()
. '<frameset cols="185,*">'
. '<frame name=Menu src="menu.html">'
. '<frame name=Content src="'
. $self->MakeRelativeURL($indexFile, $self->OutputFileOf($firstMenuEntry->Target()), 1) . '">'
. '</frameset>'
. '<noframes>'
. 'This documentation was designed for use with frames. However, you can still use it by '
. '<a href="menu.html">starting from the menu page</a>.'
. "<script language=JavaScript><!--\n"
. 'location.href="menu.html";'
. "\n// --></script>"
. '</noframes>'
. '</html>';
close INDEXFILEHANDLE;
}
elsif (-e $indexFile)
{
unlink($indexFile);
};
};
1;

View file

@ -1,398 +0,0 @@
###############################################################################
#
# Package: NaturalDocs::Builder::HTML
#
###############################################################################
#
# A package that generates output in HTML.
#
# All functions are called with Package->Function() notation.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
package NaturalDocs::Builder::HTML;
use base 'NaturalDocs::Builder::HTMLBase';
###############################################################################
# Group: Implemented Interface Functions
#
# Function: INIT
#
# Registers the package with <NaturalDocs::Builder>.
#
sub INIT
{
NaturalDocs::Builder->Add(__PACKAGE__);
};
#
# Function: CommandLineOption
#
# Returns the option to follow -o to use this package. In this case, "html".
#
sub CommandLineOption
{
return 'HTML';
};
#
# Function: BuildFile
#
# Builds the output file from the parsed source file.
#
# Parameters:
#
# sourcefile - The <FileName> of the source file.
# parsedFile - An arrayref of the source file as <NaturalDocs::Parser::ParsedTopic> objects.
#
sub BuildFile #(sourceFile, parsedFile)
{
my ($self, $sourceFile, $parsedFile) = @_;
my $outputFile = $self->OutputFileOf($sourceFile);
# 99.99% of the time the output directory will already exist, so this will actually be more efficient. It only won't exist
# if a new file was added in a new subdirectory and this is the first time that file was ever parsed.
if (!open(OUTPUTFILEHANDLE, '>' . $outputFile))
{
NaturalDocs::File->CreatePath( NaturalDocs::File->NoFileName($outputFile) );
open(OUTPUTFILEHANDLE, '>' . $outputFile)
or die "Couldn't create output file " . $outputFile . "\n";
};
print OUTPUTFILEHANDLE
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" '
. '"http://www.w3.org/TR/REC-html40/strict.dtd">' . "\n\n"
. '<html><head>'
. (NaturalDocs::Settings->CharSet() ?
'<meta http-equiv="Content-Type" content="text/html; charset=' . NaturalDocs::Settings->CharSet() . '">' : '')
. '<title>'
. $self->BuildTitle($sourceFile)
. '</title>'
. '<link rel="stylesheet" type="text/css" href="' . $self->MakeRelativeURL($outputFile, $self->MainCSSFile(), 1) . '">'
. '<script language=JavaScript src="' . $self->MakeRelativeURL($outputFile, $self->MainJavaScriptFile(), 1) . '">'
. '</script>'
. '<script language=JavaScript src="' . $self->MakeRelativeURL($outputFile, $self->SearchDataJavaScriptFile(), 1) . '">'
. '</script>'
. '</head><body class="ContentPage" onLoad="NDOnLoad()">'
. $self->OpeningBrowserStyles()
. $self->StandardComments()
. "\n\n\n"
. $self->BuildContent($sourceFile, $parsedFile)
. "\n\n\n"
. $self->BuildFooter()
. "\n\n\n"
. $self->BuildMenu($sourceFile, undef)
. "\n\n\n"
. $self->BuildToolTips()
. "\n\n\n"
. '<div id=MSearchResultsWindow>'
. '<iframe src="" frameborder=0 name=MSearchResults id=MSearchResults></iframe>'
. '<a href="javascript:searchPanel.CloseResultsWindow()" id=MSearchResultsWindowClose>Close</a>'
. '</div>'
. "\n\n\n"
. $self->ClosingBrowserStyles()
. '</body></html>';
close(OUTPUTFILEHANDLE);
};
#
# Function: BuildIndex
#
# Builds an index for the passed type.
#
# Parameters:
#
# type - The <TopicType> to limit the index to, or undef if none.
#
sub BuildIndex #(type)
{
my ($self, $type) = @_;
my $indexTitle = $self->IndexTitleOf($type);
my $startIndexPage =
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" '
. '"http://www.w3.org/TR/REC-html40/strict.dtd">' . "\n\n"
. '<html><head>'
. (NaturalDocs::Settings->CharSet() ?
'<meta http-equiv="Content-Type" content="text/html; charset=' . NaturalDocs::Settings->CharSet() . '">' : '')
. '<title>'
. $indexTitle;
if (defined NaturalDocs::Menu->Title())
{ $startIndexPage .= ' - ' . $self->StringToHTML(NaturalDocs::Menu->Title()); };
$startIndexPage .=
'</title>'
. '<link rel="stylesheet" type="text/css" href="' . $self->MakeRelativeURL($self->IndexDirectory(),
$self->MainCSSFile()) . '">'
. '<script language=JavaScript src="' . $self->MakeRelativeURL($self->IndexDirectory(),
$self->MainJavaScriptFile()) . '"></script>'
. '<script language=JavaScript src="' . $self->MakeRelativeURL($self->IndexDirectory(),
$self->SearchDataJavaScriptFile()) . '">'
. '</script>'
. '</head><body class="IndexPage" onLoad="NDOnLoad()">'
. $self->OpeningBrowserStyles()
. $self->StandardComments()
. "\n\n\n"
. '<div id=Index>'
. '<div class=IPageTitle>'
. $indexTitle
. '</div>';
my $endIndexPage =
'</div><!--Index-->'
. "\n\n\n"
. $self->BuildFooter()
. "\n\n\n"
. $self->BuildMenu(undef, $type)
. "\n\n\n"
. '<div id=MSearchResultsWindow>'
. '<iframe src="" frameborder=0 name=MSearchResults id=MSearchResults></iframe>'
. '<a href="javascript:searchPanel.CloseResultsWindow()" id=MSearchResultsWindowClose>Close</a>'
. '</div>'
. "\n\n\n"
. $self->ClosingBrowserStyles()
. '</body></html>';
my $startSearchResultsPage =
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" '
. '"http://www.w3.org/TR/REC-html40/strict.dtd">' . "\n\n"
. '<html><head>'
. (NaturalDocs::Settings->CharSet() ?
'<meta http-equiv="Content-Type" content="text/html; charset=' . NaturalDocs::Settings->CharSet() . '">' : '')
. '<link rel="stylesheet" type="text/css" href="' . $self->MakeRelativeURL($self->SearchResultsDirectory(),
$self->MainCSSFile()) . '">'
. '<script language=JavaScript src="' . $self->MakeRelativeURL($self->SearchResultsDirectory(),
$self->MainJavaScriptFile()) . '"></script>'
. '</head><body class="PopupSearchResultsPage" onLoad="NDOnLoad()">'
. $self->OpeningBrowserStyles()
. $self->StandardComments()
. "\n\n\n"
. '<div id=Index>';
my $endSearchResultsPage =
'</div>'
. $self->ClosingBrowserStyles()
. '</body></html>';
my $indexContent = NaturalDocs::SymbolTable->Index($type);
my $pageCount = $self->BuildIndexPages($type, $indexContent, $startIndexPage, $endIndexPage,
$startSearchResultsPage, $endSearchResultsPage);
$self->PurgeIndexFiles($type, $indexContent, $pageCount + 1);
};
#
# Function: UpdateMenu
#
# Updates the menu in all the output files that weren't rebuilt. Also generates index.html.
#
sub UpdateMenu
{
my $self = shift;
# Update the menu on unbuilt files.
my $filesToUpdate = NaturalDocs::Project->UnbuiltFilesWithContent();
foreach my $sourceFile (keys %$filesToUpdate)
{
$self->UpdateFile($sourceFile);
};
# Update the menu on unchanged index files.
my $indexes = NaturalDocs::Menu->Indexes();
foreach my $index (keys %$indexes)
{
if (!NaturalDocs::SymbolTable->IndexChanged($index))
{
$self->UpdateIndex($index);
};
};
# Update index.html
my $firstMenuEntry = $self->FindFirstFile();
my $indexFile = NaturalDocs::File->JoinPaths( NaturalDocs::Settings->OutputDirectoryOf($self), 'index.html' );
# We have to check because it's possible that there may be no files with Natural Docs content and thus no files on the menu.
if (defined $firstMenuEntry)
{
open(INDEXFILEHANDLE, '>' . $indexFile)
or die "Couldn't create output file " . $indexFile . ".\n";
print INDEXFILEHANDLE
'<html><head>'
. '<meta http-equiv="Refresh" CONTENT="0; URL='
. $self->MakeRelativeURL( NaturalDocs::File->JoinPaths( NaturalDocs::Settings->OutputDirectoryOf($self), 'index.html'),
$self->OutputFileOf($firstMenuEntry->Target()), 1 ) . '">'
. '</head></html>';
close INDEXFILEHANDLE;
}
elsif (-e $indexFile)
{
unlink($indexFile);
};
};
###############################################################################
# Group: Support Functions
#
# Function: UpdateFile
#
# Updates an output file. Replaces the menu, HTML title, and footer. It opens the output file, makes the changes, and saves it
# back to disk, which is much quicker than rebuilding the file from scratch if these were the only things that changed.
#
# Parameters:
#
# sourceFile - The source <FileName>.
#
# Dependencies:
#
# - Requires <Builder::BuildMenu()> to surround its content with the exact strings "<div id=Menu>" and "</div><!--Menu-->".
# - Requires <Builder::BuildFooter()> to surround its content with the exact strings "<div id=Footer>" and
# "</div><!--Footer-->".
#
sub UpdateFile #(sourceFile)
{
my ($self, $sourceFile) = @_;
my $outputFile = $self->OutputFileOf($sourceFile);
if (open(OUTPUTFILEHANDLE, '<' . $outputFile))
{
my $content;
read(OUTPUTFILEHANDLE, $content, -s OUTPUTFILEHANDLE);
close(OUTPUTFILEHANDLE);
$content =~ s{<title>[^<]*<\/title>}{'<title>' . $self->BuildTitle($sourceFile) . '</title>'}e;
$content =~ s/<div id=Menu>.*?<\/div><!--Menu-->/$self->BuildMenu($sourceFile, undef)/es;
$content =~ s/<div id=Footer>.*?<\/div><!--Footer-->/$self->BuildFooter()/e;
open(OUTPUTFILEHANDLE, '>' . $outputFile);
print OUTPUTFILEHANDLE $content;
close(OUTPUTFILEHANDLE);
};
};
#
# Function: UpdateIndex
#
# Updates an index's output file. Replaces the menu and footer. It opens the output file, makes the changes, and saves it
# back to disk, which is much quicker than rebuilding the file from scratch if these were the only things that changed.
#
# Parameters:
#
# type - The index <TopicType>, or undef if none.
#
sub UpdateIndex #(type)
{
my ($self, $type) = @_;
my $page = 1;
my $outputFile = $self->IndexFileOf($type, $page);
my $newMenu = $self->BuildMenu(undef, $type);
my $newFooter = $self->BuildFooter();
while (-e $outputFile)
{
open(OUTPUTFILEHANDLE, '<' . $outputFile)
or die "Couldn't open output file " . $outputFile . ".\n";
my $content;
read(OUTPUTFILEHANDLE, $content, -s OUTPUTFILEHANDLE);
close(OUTPUTFILEHANDLE);
$content =~ s/<div id=Menu>.*?<\/div><!--Menu-->/$newMenu/es;
$content =~ s/<div id=Footer>.*<\/div><!--Footer-->/$newFooter/e;
open(OUTPUTFILEHANDLE, '>' . $outputFile)
or die "Couldn't save output file " . $outputFile . ".\n";
print OUTPUTFILEHANDLE $content;
close(OUTPUTFILEHANDLE);
$page++;
$outputFile = $self->IndexFileOf($type, $page);
};
};
1;

File diff suppressed because it is too large Load diff

View file

@ -1,860 +0,0 @@
###############################################################################
#
# Package: NaturalDocs::ClassHierarchy
#
###############################################################################
#
# A package that handles all the gory details of managing the class hierarchy. It handles the hierarchy itself, which files define
# them, rebuilding the files that are affected by changes, and loading and saving them to a file.
#
# Usage and Dependencies:
#
# - <NaturalDocs::Settings> and <NaturalDocs::Project> must be initialized before use.
#
# - <NaturalDocs::SymbolTable> must be initialized before <Load()> is called. It must reflect the state as of the last time
# Natural Docs was run.
#
# - <Load()> must be called to initialize the package. At this point, the <Information Functions> will return the state as
# of the last time Natural Docs was run. You are free to resolve <NaturalDocs::SymbolTable()> afterwards.
#
# - <Purge()> must be called, and then <NaturalDocs::Parser->ParseForInformation()> must be called on all files that
# have changed so it can fully resolve the hierarchy via the <Modification Functions()>. Afterwards the
# <Information Functions> will reflect the current state of the code.
#
# - <Save()> must be called to commit any changes to the symbol table back to disk.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
use NaturalDocs::ClassHierarchy::Class;
use NaturalDocs::ClassHierarchy::File;
package NaturalDocs::ClassHierarchy;
###############################################################################
# Group: Variables
#
# handle: CLASS_HIERARCHY_FILEHANDLE
# The file handle used with <ClassHierarchy.nd>.
#
#
# hash: classes
#
# A hash of all the classes. The keys are the class <SymbolStrings> and the values are <NaturalDocs::ClassHierarchy::Classes>.
#
my %classes;
#
# hash: files
#
# A hash of the hierarchy information referenced by file. The keys are the <FileNames>, and the values are
# <NaturalDocs::ClassHierarchy::File>s.
#
my %files;
#
# hash: parentReferences
#
# A hash of all the parent reference strings and what they resolve to. The keys are the <ReferenceStrings> and the values are
# the class <SymbolStrings> that they resolve to.
#
my %parentReferences;
#
# object: watchedFile
#
# A <NaturalDocs::ClassHierarchy::File> object of the file being watched for changes. This is compared to the version in <files>
# to see if anything was changed since the last parse.
#
my $watchedFile;
#
# string: watchedFileName
#
# The <FileName> of the watched file, if any. If there is no watched file, this will be undef.
#
my $watchedFileName;
#
# bool: dontRebuildFiles
#
# A bool to set if you don't want changes in the hierarchy to cause files to be rebuilt.
#
my $dontRebuildFiles;
###############################################################################
# Group: Files
#
# File: ClassHierarchy.nd
#
# Stores the class hierarchy on disk.
#
# Format:
#
# > [BINARY_FORMAT]
# > [VersionInt: app version]
#
# The standard <BINARY_FORMAT> and <VersionInt> header.
#
# > [SymbolString: class or undef to end]
#
# Next we begin a class segment with its <SymbolString>. These continue until the end of the file. Only defined classes are
# included.
#
# > [UInt32: number of files]
# > [AString16: file] [AString16: file] ...
#
# Next there is the number of files that define that class. It's a UInt32, which seems like overkill, but I could imagine every
# file in a huge C++ project being under the same namespace, and thus contributing its own definition. It's theoretically
# possible.
#
# Following the number is that many file names. You must remember the index of each file, as they will be important later.
# Indexes start at one because zero has a special meaning.
#
# > [UInt8: number of parents]
# > ( [ReferenceString (no type): parent]
# > [UInt32: file index] [UInt32: file index] ... [UInt32: 0] ) ...
#
# Next there is the number of parents defined for this class. For each one, we define a parent segment, which consists of
# its <ReferenceString>, and then a zero-terminated string of indexes of the files that define that parent as part of that class.
# The indexes start at one, and are into the list of files we saw previously.
#
# Note that we do store class segments for classes without parents, but not for undefined classes.
#
# This concludes a class segment. These segments continue until an undef <SymbolString>.
#
# See Also:
#
# <File Format Conventions>
#
# Revisions:
#
# 1.22:
#
# - Classes and parents switched from AString16s to <SymbolStrings> and <ReferenceStrings>.
# - A ending undef <SymbolString> was added to the end. Previously it stopped when the file ran out.
#
# 1.2:
#
# - This file was introduced in 1.2.
#
###############################################################################
# Group: File Functions
#
# Function: Load
#
# Loads the class hierarchy from disk.
#
sub Load
{
my ($self) = @_;
$dontRebuildFiles = 1;
my $fileIsOkay;
my $fileName = NaturalDocs::Project->DataFile('ClassHierarchy.nd');
if (!NaturalDocs::Settings->RebuildData() && open(CLASS_HIERARCHY_FILEHANDLE, '<' . $fileName))
{
# See if it's binary.
binmode(CLASS_HIERARCHY_FILEHANDLE);
my $firstChar;
read(CLASS_HIERARCHY_FILEHANDLE, $firstChar, 1);
if ($firstChar != ::BINARY_FORMAT())
{
close(CLASS_HIERARCHY_FILEHANDLE);
}
else
{
my $version = NaturalDocs::Version->FromBinaryFile(\*CLASS_HIERARCHY_FILEHANDLE);
# Minor bugs were fixed in 1.33 that may affect the stored data.
if (NaturalDocs::Version->CheckFileFormat( $version, NaturalDocs::Version->FromString('1.33') ))
{ $fileIsOkay = 1; }
else
{ close(CLASS_HIERARCHY_FILEHANDLE); };
};
};
if (!$fileIsOkay)
{
NaturalDocs::Project->ReparseEverything();
}
else
{
my $raw;
for (;;)
{
# [SymbolString: class or undef to end]
my $class = NaturalDocs::SymbolString->FromBinaryFile(\*CLASS_HIERARCHY_FILEHANDLE);
if (!defined $class)
{ last; };
# [UInt32: number of files]
read(CLASS_HIERARCHY_FILEHANDLE, $raw, 4);
my $numberOfFiles = unpack('N', $raw);
my @files;
while ($numberOfFiles)
{
# [AString16: file]
read(CLASS_HIERARCHY_FILEHANDLE, $raw, 2);
my $fileLength = unpack('n', $raw);
my $file;
read(CLASS_HIERARCHY_FILEHANDLE, $file, $fileLength);
push @files, $file;
$self->AddClass($file, $class, NaturalDocs::Languages->LanguageOf($file)->Name());
$numberOfFiles--;
};
# [UInt8: number of parents]
read(CLASS_HIERARCHY_FILEHANDLE, $raw, 1);
my $numberOfParents = unpack('C', $raw);
while ($numberOfParents)
{
# [ReferenceString (no type): parent]
my $parent = NaturalDocs::ReferenceString->FromBinaryFile(\*CLASS_HIERARCHY_FILEHANDLE,
::BINARYREF_NOTYPE(),
::REFERENCE_CH_PARENT());
for (;;)
{
# [UInt32: file index or 0]
read(CLASS_HIERARCHY_FILEHANDLE, $raw, 4);
my $fileIndex = unpack('N', $raw);
if ($fileIndex == 0)
{ last; }
$self->AddParentReference( $files[$fileIndex - 1], $class, $parent );
};
$numberOfParents--;
};
};
close(CLASS_HIERARCHY_FILEHANDLE);
};
$dontRebuildFiles = undef;
};
#
# Function: Save
#
# Saves the class hierarchy to disk.
#
sub Save
{
my ($self) = @_;
open (CLASS_HIERARCHY_FILEHANDLE, '>' . NaturalDocs::Project->DataFile('ClassHierarchy.nd'))
or die "Couldn't save " . NaturalDocs::Project->DataFile('ClassHierarchy.nd') . ".\n";
binmode(CLASS_HIERARCHY_FILEHANDLE);
print CLASS_HIERARCHY_FILEHANDLE '' . ::BINARY_FORMAT();
NaturalDocs::Version->ToBinaryFile(\*CLASS_HIERARCHY_FILEHANDLE, NaturalDocs::Settings->AppVersion());
while (my ($class, $classObject) = each %classes)
{
if ($classObject->IsDefined())
{
# [SymbolString: class or undef to end]
NaturalDocs::SymbolString->ToBinaryFile(\*CLASS_HIERARCHY_FILEHANDLE, $class);
# [UInt32: number of files]
my @definitions = $classObject->Definitions();
my %definitionIndexes;
print CLASS_HIERARCHY_FILEHANDLE pack('N', scalar @definitions);
for (my $i = 0; $i < scalar @definitions; $i++)
{
# [AString16: file]
print CLASS_HIERARCHY_FILEHANDLE pack('nA*', length($definitions[$i]), $definitions[$i]);
$definitionIndexes{$definitions[$i]} = $i + 1;
};
# [UInt8: number of parents]
my @parents = $classObject->ParentReferences();
print CLASS_HIERARCHY_FILEHANDLE pack('C', scalar @parents);
foreach my $parent (@parents)
{
# [ReferenceString (no type): parent]
NaturalDocs::ReferenceString->ToBinaryFile(\*CLASS_HIERARCHY_FILEHANDLE, $parent, ::BINARYREF_NOTYPE());
# [UInt32: file index]
my @parentDefinitions = $classObject->ParentReferenceDefinitions($parent);
foreach my $parentDefinition (@parentDefinitions)
{
print CLASS_HIERARCHY_FILEHANDLE pack('N', $definitionIndexes{$parentDefinition});
};
# [UInt32: 0]
print CLASS_HIERARCHY_FILEHANDLE pack('N', 0);
};
};
};
# [SymbolString: class or undef to end]
NaturalDocs::SymbolString->ToBinaryFile(\*CLASS_HIERARCHY_FILEHANDLE, undef);
close(CLASS_HIERARCHY_FILEHANDLE);
};
#
# Function: Purge
#
# Purges the hierarchy of files that no longer have Natural Docs content.
#
sub Purge
{
my ($self) = @_;
my $filesToPurge = NaturalDocs::Project->FilesToPurge();
foreach my $file (keys %$filesToPurge)
{
$self->DeleteFile($file);
};
};
###############################################################################
# Group: Interface Functions
#
# Function: OnInterpretationChange
#
# Called by <NaturalDocs::SymbolTable> whenever a class hierarchy reference's intepretation changes, meaning it switched
# from one symbol to another.
#
# reference - The <ReferenceString> whose current interpretation changed.
#
sub OnInterpretationChange #(reference)
{
my ($self, $reference) = @_;
if (NaturalDocs::ReferenceString->TypeOf($reference) == ::REFERENCE_CH_PARENT())
{
# The approach here is simply to completely delete the reference and readd it. This is less than optimal efficiency, since it's
# being removed and added from %files too, even though that isn't required. However, the simpler code is worth it
# considering this will only happen when a parent reference becomes defined or undefined, or on the rare languages (like C#)
# that allow relative parent references.
my $oldTargetSymbol = $parentReferences{$reference};
my $oldTargetObject = $classes{$oldTargetSymbol};
my @classesWithReferenceParent = $oldTargetObject->Children();
# Each entry is an arrayref of file names. Indexes are the same as classesWithReferenceParent's.
my @filesDefiningReferenceParent;
foreach my $classWithReferenceParent (@classesWithReferenceParent)
{
my $fileList = [ $classes{$classWithReferenceParent}->ParentReferenceDefinitions($reference) ];
push @filesDefiningReferenceParent, $fileList;
foreach my $fileDefiningReferenceParent (@$fileList)
{
$self->DeleteParentReference($fileDefiningReferenceParent, $classWithReferenceParent, $reference);
};
};
# This will force the reference to be reinterpreted on the next add.
delete $parentReferences{$reference};
# Now we can just readd it.
for (my $i = 0; $i < scalar @classesWithReferenceParent; $i++)
{
foreach my $file (@{$filesDefiningReferenceParent[$i]})
{
$self->AddParentReference($file, $classesWithReferenceParent[$i], $reference);
};
};
};
# The only way for a REFERENCE_CH_CLASS reference to change is if the symbol is deleted. That will be handled by
# <AnalyzeChanges()>, so we don't need to do anything here.
};
#
# Function: OnTargetSymbolChange
#
# Called by <NaturalDocs::SymbolTable> whenever a class hierarchy reference's target symbol changes, but the reference
# still resolves to the same symbol.
#
# Parameters:
#
# reference - The <ReferenceString> that was affected by the change.
#
sub OnTargetSymbolChange #(reference)
{
my ($self, $reference) = @_;
my $type = NaturalDocs::ReferenceString->TypeOf($reference);
my $class;
if ($type == ::REFERENCE_CH_PARENT())
{ $class = $parentReferences{$reference}; }
else # ($type == ::REFERENCE_CH_CLASS())
{
# Class references are global absolute, so we can just yank the symbol.
(undef, $class, undef, undef, undef, undef) = NaturalDocs::ReferenceString->InformationOf($reference);
};
$self->RebuildFilesFor($class, 1, 0, 1);
};
###############################################################################
# Group: Modification Functions
#
# Function: AddClass
#
# Adds a class to the hierarchy.
#
# Parameters:
#
# file - The <FileName> the class was defined in.
# class - The class <SymbolString>.
# languageName - The name of the language this applies to.
#
# Note:
#
# The file parameter must be defined when using this function externally. It may be undef for internal use only.
#
sub AddClass #(file, class, languageName)
{
my ($self, $file, $class, $languageName) = @_;
if (!exists $classes{$class})
{
$classes{$class} = NaturalDocs::ClassHierarchy::Class->New();
NaturalDocs::SymbolTable->AddReference($self->ClassReferenceOf($class, $languageName), $file)
};
if (defined $file)
{
# If this was the first definition for this class...
if ($classes{$class}->AddDefinition($file))
{ $self->RebuildFilesFor($class, 1, 1, 1); };
if (!exists $files{$file})
{ $files{$file} = NaturalDocs::ClassHierarchy::File->New(); };
$files{$file}->AddClass($class);
if (defined $watchedFileName)
{ $watchedFile->AddClass($class); };
};
};
#
# Function: AddParentReference
#
# Adds a class-parent relationship to the hierarchy. The classes will be created if they don't already exist.
#
# Parameters:
#
# file - The <FileName> the reference was defined in.
# class - The class <SymbolString>.
# symbol - The parent class <SymbolString>.
# scope - The package <SymbolString> that the reference appeared in.
# using - An arrayref of package <SymbolStrings> that the reference has access to via "using" statements.
# resolvingFlags - Any <Resolving Flags> to be used when resolving the reference.
#
# Alternate Parameters:
#
# file - The <FileName> the reference was defined in.
# class - The class <SymbolString>.
# reference - The parent <ReferenceString>.
#
sub AddParentReference #(file, class, symbol, scope, using, resolvingFlags) or (file, class, reference)
{
my ($self, $file, $class, $symbol, $parentReference);
if (scalar @_ == 7)
{
my ($scope, $using, $resolvingFlags);
($self, $file, $class, $symbol, $scope, $using, $resolvingFlags) = @_;
$parentReference = NaturalDocs::ReferenceString->MakeFrom(::REFERENCE_CH_PARENT(), $symbol,
NaturalDocs::Languages->LanguageOf($file)->Name(),
$scope, $using, $resolvingFlags);
}
else
{
($self, $file, $class, $parentReference) = @_;
$symbol = (NaturalDocs::ReferenceString->InformationOf($parentReference))[1];
};
# In case it doesn't already exist.
$self->AddClass($file, $class);
my $parent;
if (exists $parentReferences{$parentReference})
{
$parent = $parentReferences{$parentReference};
}
else
{
NaturalDocs::SymbolTable->AddReference($parentReference, $file);
my $parentTarget = NaturalDocs::SymbolTable->References($parentReference);
if (defined $parentTarget)
{ $parent = $parentTarget->Symbol(); }
else
{ $parent = $symbol; };
# In case it doesn't already exist.
$self->AddClass(undef, $parent);
$parentReferences{$parentReference} = $parent;
};
# If this defined a new parent...
if ($classes{$class}->AddParentReference($parentReference, $file, \%parentReferences))
{
$classes{$parent}->AddChild($class);
$self->RebuildFilesFor($class, 0, 1, 0);
$self->RebuildFilesFor($parent, 0, 1, 0);
};
$files{$file}->AddParentReference($class, $parentReference);
if (defined $watchedFileName)
{ $watchedFile->AddParentReference($class, $parentReference); };
};
#
# Function: WatchFileForChanges
#
# Watches a file for changes, which can then be applied by <AnalyzeChanges()>. Definitions are not deleted via a DeleteClass()
# function. Instead, a file is watched for changes, reparsed, and then a comparison is made to look for definitions that
# disappeared and any other relevant changes.
#
# Parameters:
#
# file - The <FileName> to watch.
#
sub WatchFileForChanges #(file)
{
my ($self, $file) = @_;
$watchedFile = NaturalDocs::ClassHierarchy::File->New();
$watchedFileName = $file;
};
#
# Function: AnalyzeChanges
#
# Checks the watched file for any changes that occured since the last time is was parsed, and updates the hierarchy as
# necessary. Also sends any files that are affected to <NaturalDocs::Project->RebuildFile()>.
#
sub AnalyzeChanges
{
my ($self) = @_;
# If the file didn't have any classes before, and it still doesn't, it wont be in %files.
if (exists $files{$watchedFileName})
{
my @originalClasses = $files{$watchedFileName}->Classes();
foreach my $originalClass (@originalClasses)
{
# If the class isn't there the second time around...
if (!$watchedFile->HasClass($originalClass))
{ $self->DeleteClass($watchedFileName, $originalClass); }
else
{
my @originalParents = $files{$watchedFileName}->ParentReferencesOf($originalClass);
foreach my $originalParent (@originalParents)
{
# If the parent reference wasn't there the second time around...
if (!$watchedFile->HasParentReference($originalClass, $originalParent))
{ $self->DeleteParentReference($watchedFileName, $originalClass, $originalParent); };
};
};
};
};
$watchedFile = undef;
$watchedFileName = undef;
};
###############################################################################
# Group: Information Functions
#
# Function: ParentsOf
# Returns a <SymbolString> array of the passed class' parents, or an empty array if none. Note that not all of them may be
# defined.
#
sub ParentsOf #(class)
{
my ($self, $class) = @_;
if (exists $classes{$class})
{ return $classes{$class}->Parents(); }
else
{ return ( ); };
};
#
# Function: ChildrenOf
# Returns a <SymbolString> array of the passed class' children, or an empty array if none. Note that not all of them may be
# defined.
#
sub ChildrenOf #(class)
{
my ($self, $class) = @_;
if (exists $classes{$class})
{ return $classes{$class}->Children(); }
else
{ return ( ); };
};
###############################################################################
# Group: Support Functions
#
# Function: DeleteFile
#
# Deletes a file and everything defined in it.
#
# Parameters:
#
# file - The <FileName>.
#
sub DeleteFile #(file)
{
my ($self, $file) = @_;
if (!exists $files{$file})
{ return; };
my @classes = $files{$file}->Classes();
foreach my $class (@classes)
{
$self->DeleteClass($file, $class);
};
delete $files{$file};
};
#
# Function: DeleteClass
#
# Deletes a class definition from a file. Will also delete any parent references from this class and file. Will rebuild any file
# affected unless <dontRebuildFiles> is set.
#
# Parameters:
#
# file - The <FileName> that defines the class.
# class - The class <SymbolString>.
#
sub DeleteClass #(file, class)
{
my ($self, $file, $class) = @_;
my @parents = $files{$file}->ParentReferencesOf($class);
foreach my $parent (@parents)
{
$self->DeleteParentReference($file, $class, $parent);
};
$files{$file}->DeleteClass($class);
# If we're deleting the last definition of this class.
if ($classes{$class}->DeleteDefinition($file))
{
if (!$classes{$class}->HasChildren())
{
delete $classes{$class};
if (!$dontRebuildFiles)
{ NaturalDocs::Project->RebuildFile($file); };
}
else
{ $self->RebuildFilesFor($class, 0, 1, 1); };
};
};
#
# Function: DeleteParentReference
#
# Deletes a class' parent reference and returns whether it resulted in the loss of a parent class. Will rebuild any file affected
# unless <dontRebuildFiles> is set.
#
# Parameters:
#
# file - The <FileName> that defines the reference.
# class - The class <SymbolString>.
# reference - The parent <ReferenceString>.
#
# Returns:
#
# If the class lost a parent as a result of this, it will return its <SymbolString>. It will return undef otherwise.
#
sub DeleteParentReference #(file, class, reference)
{
my ($self, $file, $class, $reference) = @_;
if (!exists $classes{$class})
{ return; };
$files{$file}->DeleteParentReference($class, $reference);
my $deletedParent = $classes{$class}->DeleteParentReference($reference, $file, \%parentReferences);
if (defined $deletedParent)
{
my $deletedParentObject = $classes{$deletedParent};
$deletedParentObject->DeleteChild($class);
$self->RebuildFilesFor($deletedParent, 0, 1, 0);
$self->RebuildFilesFor($class, 0, 1, 0);
if (!$deletedParentObject->HasChildren() && !$deletedParentObject->IsDefined())
{
delete $classes{$deletedParent};
NaturalDocs::SymbolTable->DeleteReference(
$self->ClassReferenceOf($class, NaturalDocs::Languages->LanguageOf($file)->Name()) );
};
return $deletedParent;
};
return undef;
};
#
# Function: ClassReferenceOf
#
# Returns the <REFERENCE_CH_CLASS> <ReferenceString> of the passed class <SymbolString>.
#
sub ClassReferenceOf #(class, languageName)
{
my ($self, $class, $languageName) = @_;
return NaturalDocs::ReferenceString->MakeFrom(::REFERENCE_CH_CLASS(), $class, $languageName, undef, undef,
::RESOLVE_ABSOLUTE() | ::RESOLVE_NOPLURAL());
};
#
# Function: RebuildFilesFor
#
# Calls <NaturalDocs::Project->RebuildFile()> for every file defining the passed class, its parents, and/or its children.
# Returns without doing anything if <dontRebuildFiles> is set.
#
# Parameters:
#
# class - The class <SymbolString>.
# rebuildParents - Whether to rebuild the class' parents.
# rebuildSelf - Whether to rebuild the class.
# rebuildChildren - Whether to rebuild the class' children.
#
sub RebuildFilesFor #(class, rebuildParents, rebuildSelf, rebuildChildren)
{
my ($self, $class, $rebuildParents, $rebuildSelf, $rebuildChildren) = @_;
if ($dontRebuildFiles)
{ return; };
my @classesToBuild;
if ($rebuildParents)
{ @classesToBuild = $classes{$class}->Parents(); };
if ($rebuildSelf)
{ push @classesToBuild, $class; };
if ($rebuildChildren)
{ push @classesToBuild, $classes{$class}->Children(); };
foreach my $classToBuild (@classesToBuild)
{
my @definitions = $classes{$classToBuild}->Definitions();
foreach my $definition (@definitions)
{ NaturalDocs::Project->RebuildFile($definition); };
};
};
1;

View file

@ -1,412 +0,0 @@
###############################################################################
#
# Class: NaturalDocs::ClassHierarchy::Class
#
###############################################################################
#
# An object that stores information about a class in the hierarchy. It does not store its <SymbolString>; it assumes that it will
# be stored in a hashref where the key is the <SymbolString>.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
package NaturalDocs::ClassHierarchy::Class;
#
# Constants: Members
#
# The class is implemented as a blessed arrayref. The keys are the constants below.
#
# DEFINITIONS - An existence hashref of all the <FileNames> which define this class. Undef if none.
# PARENTS - An existence hashref of the <SymbolStrings> of all the parents this class has.
# CHILDREN - An existence hashref of the <SymbolStrings> of all the children this class has.
# PARENT_REFERENCES - A hashref of the parent <ReferenceStrings> this class has. The keys are the <ReferenceStrings>,
# and the values are existence hashrefs of all the <FileNames> that define them. Undef if none.
#
use NaturalDocs::DefineMembers 'DEFINITIONS', 'PARENTS', 'CHILDREN', 'PARENT_REFERENCES';
# Dependency: New() depends on the order of these constants, as well as the class not being derived from any other.
###############################################################################
# Group: Modification Functions
#
# Function: New
#
# Creates and returns a new class.
#
sub New
{
# Dependency: This function depends on the order of the constants, as well as the class not being derived from any other.
my ($package, $definitionFile) = @_;
my $object = [ undef, undef, undef, undef ];
bless $object, $package;
return $object;
};
#
# Function: AddDefinition
#
# Adds a rew definition of this class and returns if that was the first definition.
#
# Parameters:
#
# file - The <FileName> the definition appears in.
#
# Returns:
#
# Whether this was the first definition of this class.
#
sub AddDefinition #(file)
{
my ($self, $file) = @_;
my $wasFirst;
if (!defined $self->[DEFINITIONS])
{
$self->[DEFINITIONS] = { };
$wasFirst = 1;
};
$self->[DEFINITIONS]->{$file} = 1;
return $wasFirst;
};
#
# Function: DeleteDefinition
#
# Removes the definition of this class and returns if there are no more definitions. Note that if there are no more
# definitions, you may still want to keep the object around if <HasChildren()> returns true.
#
# Parameters:
#
# file - The <FileName> the definition appears in.
#
# Returns:
#
# Whether this deleted the last definition of this class.
#
sub DeleteDefinition #(file)
{
my ($self, $file) = @_;
if (defined $self->[DEFINITIONS])
{
delete $self->[DEFINITIONS]->{$file};
if (!scalar keys %{$self->[DEFINITIONS]})
{
$self->[DEFINITIONS] = undef;
return 1;
};
};
return undef;
};
#
# Function: AddParentReference
#
# Adds a parent reference to the class and return whether it resulted in a new parent class.
#
# Parameters:
#
# reference - The <ReferenceString> used to determine the parent.
# file - The <FileName> the parent reference is in.
# referenceTranslations - A hashref of what each reference currently resolves to. The keys are the
# <ReferenceStrings> and the values are class <SymbolStrings>. It should include an entry for
# the reference parameter above.
#
# Returns:
#
# If the reference adds a new parent, it will return that parent's <SymbolString>. Otherwise it will return undef.
#
sub AddParentReference #(reference, file, referenceTranslations)
{
my ($self, $reference, $file, $referenceTranslations) = @_;
if (!defined $self->[PARENT_REFERENCES])
{ $self->[PARENT_REFERENCES] = { }; };
if (!defined $self->[PARENTS])
{ $self->[PARENTS] = { }; };
if (!exists $self->[PARENT_REFERENCES]->{$reference})
{
$self->[PARENT_REFERENCES]->{$reference} = { $file => 1 };
my $symbol = $referenceTranslations->{$reference};
if (!exists $self->[PARENTS]->{$symbol})
{
$self->[PARENTS]->{$symbol} = 1;
return $symbol;
}
else
{ return undef; };
}
else
{
$self->[PARENT_REFERENCES]->{$reference}->{$file} = 1;
return undef;
};
};
#
# Function: DeleteParentReference
#
# Deletes a parent reference from the class and return whether it resulted in a loss of a parent class.
#
# Parameters:
#
# reference - The <ReferenceString> used to determine the parent.
# file - The <FileName> the parent declaration is in.
# referenceTranslations - A hashref of what each reference currently resolves to. The keys are the
# <ReferenceStrings> and the values are class <SymbolStrings>. It should include an entry for
# the reference parameter above.
#
# Returns:
#
# If this causes a parent class to be lost, it will return that parent's <SymbolString>. Otherwise it will return undef.
#
sub DeleteParentReference #(reference, file, referenceTranslations)
{
my ($self, $reference, $file, $referenceTranslations) = @_;
if (defined $self->[PARENT_REFERENCES] && exists $self->[PARENT_REFERENCES]->{$reference} &&
exists $self->[PARENT_REFERENCES]->{$reference}->{$file})
{
delete $self->[PARENT_REFERENCES]->{$reference}->{$file};
# Quit if there are other definitions of this reference.
if (scalar keys %{$self->[PARENT_REFERENCES]->{$reference}})
{ return undef; };
delete $self->[PARENT_REFERENCES]->{$reference};
if (!scalar keys %{$self->[PARENT_REFERENCES]})
{ $self->[PARENT_REFERENCES] = undef; };
my $parent = $referenceTranslations->{$reference};
# Check if any other references resolve to the same parent.
if (defined $self->[PARENT_REFERENCES])
{
foreach my $parentReference (keys %{$self->[PARENT_REFERENCES]})
{
if ($referenceTranslations->{$parentReference} eq $parent)
{ return undef; };
};
};
# If we got this far, no other parent references resolve to this symbol.
delete $self->[PARENTS]->{$parent};
if (!scalar keys %{$self->[PARENTS]})
{ $self->[PARENTS] = undef; };
return $parent;
}
else
{ return undef; };
};
#
# Function: AddChild
# Adds a child <SymbolString> to the class. Unlike <AddParentReference()>, this does not keep track of anything other than
# whether it has it or not.
#
# Parameters:
#
# child - The <SymbolString> to add.
#
sub AddChild #(child)
{
my ($self, $child) = @_;
if (!defined $self->[CHILDREN])
{ $self->[CHILDREN] = { }; };
$self->[CHILDREN]->{$child} = 1;
};
#
# Function: DeleteChild
# Deletes a child <SymbolString> from the class. Unlike <DeleteParentReference()>, this does not keep track of anything other
# than whether it has it or not.
#
# Parameters:
#
# child - The <SymbolString> to delete.
#
sub DeleteChild #(child)
{
my ($self, $child) = @_;
if (defined $self->[CHILDREN])
{
delete $self->[CHILDREN]->{$child};
if (!scalar keys %{$self->[CHILDREN]})
{ $self->[CHILDREN] = undef; };
};
};
###############################################################################
# Group: Information Functions
#
# Function: Definitions
# Returns an array of the <FileNames> that define this class, or an empty array if none.
#
sub Definitions
{
my ($self) = @_;
if (defined $self->[DEFINITIONS])
{ return keys %{$self->[DEFINITIONS]}; }
else
{ return ( ); };
};
#
# Function: IsDefinedIn
# Returns whether the class is defined in the passed <FileName>.
#
sub IsDefinedIn #(file)
{
my ($self, $file) = @_;
if (defined $self->[DEFINITIONS])
{ return exists $self->[DEFINITIONS]->{$file}; }
else
{ return 0; };
};
#
# Function: IsDefined
# Returns whether the class is defined in any files.
#
sub IsDefined
{
my ($self) = @_;
return defined $self->[DEFINITIONS];
};
#
# Function: ParentReferences
# Returns an array of the parent <ReferenceStrings>, or an empty array if none.
#
sub ParentReferences
{
my ($self) = @_;
if (defined $self->[PARENT_REFERENCES])
{ return keys %{$self->[PARENT_REFERENCES]}; }
else
{ return ( ); };
};
#
# Function: HasParentReference
# Returns whether the class has the passed parent <ReferenceString>.
#
sub HasParentReference #(reference)
{
my ($self, $reference) = @_;
return (defined $self->[PARENT_REFERENCES] && exists $self->[PARENT_REFERENCES]->{$reference});
};
#
# Function: HasParentReferences
# Returns whether the class has any parent <ReferenceStrings>.
#
sub HasParentReferences
{
my ($self) = @_;
return defined $self->[PARENT_REFERENCES];
};
#
# Function: Parents
# Returns an array of the parent <SymbolStrings>, or an empty array if none.
#
sub Parents
{
my ($self) = @_;
if (defined $self->[PARENTS])
{ return keys %{$self->[PARENTS]}; }
else
{ return ( ); };
};
#
# Function: HasParents
# Returns whether the class has any parent <SymbolStrings> defined.
#
sub HasParents
{
my ($self) = @_;
return defined $self->[PARENTS];
};
#
# Function: Children
# Returns an array of the child <SymbolStrings>, or an empty array if none.
#
sub Children
{
my ($self) = @_;
if (defined $self->[CHILDREN])
{ return keys %{$self->[CHILDREN]}; }
else
{ return ( ); };
};
#
# Function: HasChildren
# Returns whether any child <SymbolStrings> are defined.
#
sub HasChildren
{
my ($self) = @_;
return defined $self->[CHILDREN];
};
#
# Function: ParentReferenceDefinitions
# Returns an array of the <FileNames> which define the passed parent <ReferenceString>, or an empty array if none.
#
sub ParentReferenceDefinitions #(reference)
{
my ($self, $reference) = @_;
if (defined $self->[PARENT_REFERENCES] && exists $self->[PARENT_REFERENCES]->{$reference})
{ return keys %{$self->[PARENT_REFERENCES]->{$reference}}; }
else
{ return ( ); };
};
1;

View file

@ -1,157 +0,0 @@
###############################################################################
#
# Class: NaturalDocs::ClassHierarchy::File
#
###############################################################################
#
# An object that stores information about what hierarchy information is present in a file. It does not store its <FileName>; it
# assumes that it will be stored in a hashref where the key is the <FileName>.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
package NaturalDocs::ClassHierarchy::File;
#
# Topic: Implementation
#
# Since there's only one member in the class, and it's a hashref, the class is simply the hashref itself blessed as a class.
# The keys are the class <SymbolStrings> that are defined in the file, and the values are existence hashrefs of each class'
# parent <ReferenceStrings>, or undef if none.
#
###############################################################################
# Group: Modification Functions
#
# Function: New
#
# Creates and returns a new class.
#
sub New
{
my ($package) = @_;
my $object = { };
bless $object, $package;
return $object;
};
#
# Function: AddClass
# Adds a rew class <SymbolString> to the file.
#
sub AddClass #(class)
{
my ($self, $class) = @_;
if (!exists $self->{$class})
{ $self->{$class} = undef; };
};
#
# Function: DeleteClass
# Deletes a class <SymbolString> from the file.
#
sub DeleteClass #(class)
{
my ($self, $class) = @_;
delete $self->{$class};
};
#
# Function: AddParentReference
# Adds a parent <ReferenceString> to a class <SymbolString>.
#
sub AddParentReference #(class, parentReference)
{
my ($self, $class, $parent) = @_;
if (!exists $self->{$class} || !defined $self->{$class})
{ $self->{$class} = { }; };
$self->{$class}->{$parent} = 1;
};
#
# Function: DeleteParentReference
# Deletes a parent <ReferenceString> from a class <SymbolString>.
#
sub DeleteParentReference #(class, parent)
{
my ($self, $class, $parent) = @_;
if (exists $self->{$class})
{
delete $self->{$class}->{$parent};
if (!scalar keys %{$self->{$class}})
{ $self->{$class} = undef; };
};
};
###############################################################################
# Group: Information Functions
#
# Function: Classes
# Returns an array of the class <SymbolStrings> that are defined by this file, or an empty array if none.
#
sub Classes
{
my ($self) = @_;
return keys %{$self};
};
#
# Function: HasClass
# Returns whether the file defines the passed class <SymbolString>.
#
sub HasClass #(class)
{
my ($self, $class) = @_;
return exists $self->{$class};
};
#
# Function: ParentReferencesOf
# Returns an array of the parent <ReferenceStrings> that are defined by the class, or an empty array if none.
#
sub ParentReferencesOf #(class)
{
my ($self, $class) = @_;
if (!exists $self->{$class} || !defined $self->{$class})
{ return ( ); }
else
{ return keys %{$self->{$class}}; };
};
#
# Function: HasParentReference
# Returns whether the file defines the passed class <SymbolString> and parent <ReferenceString>.
#
sub HasParentReference #(class, parent)
{
my ($self, $class, $parent) = @_;
if (!$self->HasClass($class))
{ return undef; };
return exists $self->{$class}->{$parent};
};
1;

View file

@ -1,497 +0,0 @@
###############################################################################
#
# Package: NaturalDocs::ConfigFile
#
###############################################################################
#
# A package to manage Natural Docs' configuration files.
#
# Usage:
#
# - Only one configuration file can be managed with this package at a time. You must close the file before opening another
# one.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
package NaturalDocs::ConfigFile;
#
# Topic: Format
#
# All configuration files are text files.
#
# > # [comment]
#
# Comments start with the # character.
#
# > Format: [version]
#
# All configuration files *must* have a format line as its first line containing content. Whitespace and comments are permitted
# ahead of it.
#
# > [keyword]: [value]
#
# Keywords can only contain <CFChars>. Keywords are not case sensitive. Values can be anything and run until the end of
# the line or a comment.
#
# > [value]
#
# Lines that don't start with a valid keyword format are considered to be all value.
#
# > [line] { [line] } [line]
#
# Files supporting brace groups (specified in <Open()>) may also have braces that can appear anywhere. It allows more than
# one thing to appear per line, which isn't supported otherwise. Consequently, values may not have braces.
#
#
# Type: CFChars
#
# The characters that can appear in configuration file keywords and user-defined element names: letters, numbers, spaces,
# dashes, slashes, apostrophes, and periods.
#
# Although the list above is exhaustive, it should be noted that you especially can *not* use colons (messes up keyword: value
# sequences) commas (messes up item, item, item list sequences) and hashes (messes up comment detection.)
#
# You can search the source code for [CFChars] to find all the instances where this definition is used.
#
###############################################################################
# Group: Variables
#
# handle: CONFIG_FILEHANDLE
#
# The file handle used for the configuration file.
#
#
# string: file
#
# The <FileName> for the current configuration file being parsed.
#
my $file;
#
# array: errors
#
# An array of errors added by <AddError()>. Every odd entry is the line number, and every even entry following is the
# error message.
#
my @errors;
#
# var: lineNumber
#
# The current line number for the configuration file.
#
my $lineNumber;
#
# bool: hasBraceGroups
#
# Whether the file has brace groups or not.
#
my $hasBraceGroups;
#
# array: virtualLines
#
# An array of virtual lines if a line from the file contained more than one.
#
# Files with brace groups may have more than one virtual line per actual file line, such as "Group: A { Group: B". When that
# happens, any extra virtual lines are put into here so they can be returned on the next call.
#
my @virtualLines;
###############################################################################
# Group: Functions
#
# Function: Open
#
# Opens a configuration file for parsing and returns the format <VersionInt>.
#
# Parameters:
#
# file - The <FileName> to parse.
# hasBraceGroups - Whether the file supports brace groups or not. If so, lines with braces will be split apart behind the
# scenes.
#
# Returns:
#
# The <VersionInt> of the file, or undef if the file doesn't exist.
#
sub Open #(file, hasBraceGroups)
{
my $self;
($self, $file, $hasBraceGroups) = @_;
@errors = ( );
# It will be incremented to one when the first line is read from the file.
$lineNumber = 0;
open(CONFIG_FILEHANDLE, '<' . $file) or return undef;
# Get the format line.
my ($keyword, $value, $comment) = $self->GetLine();
if ($keyword eq 'format')
{ return NaturalDocs::Version->FromString($value); }
else
{ die "The first content line in " . $file . " must be the Format: line.\n"; };
};
#
# Function: Close
#
# Closes the current configuration file.
#
sub Close
{
my $self = shift;
close(CONFIG_FILEHANDLE);
};
#
# Function: GetLine
#
# Returns the next line containing content, or an empty array if none.
#
# Returns:
#
# Returns the array ( keyword, value, comment ), or an empty array if none. All tabs will be converted to spaces, and all
# whitespace will be condensed into a single space.
#
# keyword - The keyword part of the line, if any. Is converted to lowercase and doesn't include the colon. If the file supports
# brace groups, opening and closing braces will be returned as keywords.
# value - The value part of the line, minus any whitespace. Keeps its original case.
# comment - The comment following the line, if any. This includes the # symbol and a leading space if there was
# any whitespace, since it may be significant. Otherwise undef. Used for lines where the # character needs to be
# accepted as part of the value.
#
sub GetLine
{
my $self = shift;
my ($line, $comment);
# Get the next line with content.
do
{
# Get the next line.
my $isFileLine;
if (scalar @virtualLines)
{
$line = shift @virtualLines;
$isFileLine = 0;
}
else
{
$line = <CONFIG_FILEHANDLE>;
$lineNumber++;
if (!defined $line)
{ return ( ); };
::XChomp(\$line);
# Condense spaces and tabs into a single space.
$line =~ tr/\t / /s;
$isFileLine = 1;
};
# Split off the comment.
if ($line =~ /^(.*?)( ?#.*)$/)
{ ($line, $comment) = ($1, $2); }
else
{ $comment = undef; };
# Split any brace groups.
if ($isFileLine && $hasBraceGroups && $line =~ /[\{\}]/)
{
($line, @virtualLines) = split(/([\{\}])/, $line);
$virtualLines[-1] .= $comment;
$comment = undef;
};
# Remove whitespace.
$line =~ s/^ //;
$line =~ s/ $//;
$comment =~ s/ $//;
# We want to keep the leading space on a comment.
}
while (!$line);
# Process the line.
if ($hasBraceGroups && ($line eq '{' || $line eq '}'))
{
return ($line, undef, undef);
};
if ($line =~ /^([a-z0-9\ \'\/\.\-]+?) ?: ?(.*)$/i) # [CFChars]
{
my ($keyword, $value) = ($1, $2);
return (lc($keyword), $value, $comment);
}
else
{
return (undef, $line, $comment);
};
};
#
# Function: LineNumber
#
# Returns the line number for the line last returned by <GetLine()>.
#
sub LineNumber
{ return $lineNumber; };
###############################################################################
# Group: Error Functions
#
# Function: AddError
#
# Stores an error for the current configuration file. Will be attached to the last line read by <GetLine()>.
#
# Parameters:
#
# message - The error message.
# lineNumber - The line number to use. If not specified, it will use the line number from the last call to <GetLine()>.
#
sub AddError #(message, lineNumber)
{
my ($self, $message, $messageLineNumber) = @_;
if (!defined $messageLineNumber)
{ $messageLineNumber = $lineNumber; };
push @errors, $messageLineNumber, $message;
};
#
# Function: ErrorCount
#
# Returns how many errors the configuration file has.
#
sub ErrorCount
{
return (scalar @errors) / 2;
};
#
# Function: PrintErrorsAndAnnotateFile
#
# Prints the errors to STDERR in the standard GNU format and annotates the configuration file with them. It does *not* end
# execution. <Close()> *must* be called before this function.
#
sub PrintErrorsAndAnnotateFile
{
my ($self) = @_;
if (scalar @errors)
{
open(CONFIG_FILEHANDLE, '<' . $file);
my @lines = <CONFIG_FILEHANDLE>;
close(CONFIG_FILEHANDLE);
# We need to keep track of both the real and the original line numbers. The original line numbers are for matching errors in
# the errors array, and don't include any comment lines added or deleted. Line number is the current line number including
# those comment lines for sending to the display.
my $lineNumber = 1;
my $originalLineNumber = 1;
open(CONFIG_FILEHANDLE, '>' . $file);
# We don't want to keep the old error header, if present.
if ($lines[0] =~ /^\# There (?:is an error|are \d+ errors) in this file\./)
{
shift @lines;
$originalLineNumber++;
# We want to drop the blank line after it as well.
if ($lines[0] eq "\n")
{
shift @lines;
$originalLineNumber++;
};
};
if ($self->ErrorCount() == 1)
{
print CONFIG_FILEHANDLE
"# There is an error in this file. Search for ERROR to find it.\n\n";
}
else
{
print CONFIG_FILEHANDLE
"# There are " . $self->ErrorCount() . " errors in this file. Search for ERROR to find them.\n\n";
};
$lineNumber += 2;
foreach my $line (@lines)
{
while (scalar @errors && $originalLineNumber == $errors[0])
{
my $errorLine = shift @errors;
my $errorMessage = shift @errors;
print CONFIG_FILEHANDLE "# ERROR: " . $errorMessage . "\n";
# Use the GNU error format, which should make it easier to handle errors when Natural Docs is part of a build process.
# See http://www.gnu.org/prep/standards_15.html
$errorMessage = lcfirst($errorMessage);
$errorMessage =~ s/\.$//;
print STDERR 'NaturalDocs:' . $file . ':' . $lineNumber . ': ' . $errorMessage . "\n";
$lineNumber++;
};
# We want to remove error lines from previous runs.
if (substr($line, 0, 9) ne '# ERROR: ')
{
print CONFIG_FILEHANDLE $line;
$lineNumber++;
};
$originalLineNumber++;
};
# Clean up any remaining errors.
while (scalar @errors)
{
my $errorLine = shift @errors;
my $errorMessage = shift @errors;
print CONFIG_FILEHANDLE "# ERROR: " . $errorMessage . "\n";
# Use the GNU error format, which should make it easier to handle errors when Natural Docs is part of a build process.
# See http://www.gnu.org/prep/standards_15.html
$errorMessage = lcfirst($errorMessage);
$errorMessage =~ s/\.$//;
print STDERR 'NaturalDocs:' . $file . ':' . $lineNumber . ': ' . $errorMessage . "\n";
};
close(CONFIG_FILEHANDLE);
};
};
###############################################################################
# Group: Misc Functions
#
# Function: HasOnlyCFChars
#
# Returns whether the passed string contains only <CFChars>.
#
sub HasOnlyCFChars #(string)
{
my ($self, $string) = @_;
return ($string =~ /^[a-z0-9\ \.\-\/\']*$/i); # [CFChars]
};
#
# Function: CFCharNames
#
# Returns a plain-english list of <CFChars> which can be embedded in a sentence. For example, "You can only use
# [CFCharsList()] in the name.
#
sub CFCharNames
{
# [CFChars]
return 'letters, numbers, spaces, periods, dashes, slashes, and apostrophes';
};
#
# Function: Obscure
#
# Obscures the passed text so that it is not user editable and returns it. The encoding method is not secure; it is just designed
# to be fast and to discourage user editing.
#
sub Obscure #(text)
{
my ($self, $text) = @_;
# ` is specifically chosen to encode to space because of its rarity. We don't want a trailing one to get cut off before decoding.
$text =~ tr{a-zA-Z0-9\ \\\/\.\:\_\-\`}
{pY9fGc\`R8lAoE\\uIdH6tN\/7sQjKx0B5mW\.vZ41PyFg\:CrLaO\_eUi2DhT\-nSqJkXb3MwVz\ };
return $text;
};
#
# Function: Unobscure
#
# Restores text encoded with <Obscure()> and returns it.
#
sub Unobscure #(text)
{
my ($self, $text) = @_;
$text =~ tr{pY9fGc\`R8lAoE\\uIdH6tN\/7sQjKx0B5mW\.vZ41PyFg\:CrLaO\_eUi2DhT\-nSqJkXb3MwVz\ }
{a-zA-Z0-9\ \\\/\.\:\_\-\`};
return $text;
};
1;

View file

@ -1,165 +0,0 @@
###############################################################################
#
# Package: NaturalDocs::Constants
#
###############################################################################
#
# Constants that are used throughout the script. All are exported by default.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
package NaturalDocs::Constants;
use vars qw(@EXPORT @ISA);
require Exporter;
@ISA = qw(Exporter);
@EXPORT = ('MENU_TITLE', 'MENU_SUBTITLE', 'MENU_FILE', 'MENU_GROUP', 'MENU_TEXT', 'MENU_LINK', 'MENU_FOOTER',
'MENU_INDEX', 'MENU_FORMAT', 'MENU_ENDOFORIGINAL', 'MENU_DATA',
'MENU_FILE_NOAUTOTITLE', 'MENU_GROUP_UPDATETITLES', 'MENU_GROUP_UPDATESTRUCTURE',
'MENU_GROUP_UPDATEORDER', 'MENU_GROUP_HASENDOFORIGINAL',
'MENU_GROUP_UNSORTED', 'MENU_GROUP_FILESSORTED',
'MENU_GROUP_FILESANDGROUPSSORTED', 'MENU_GROUP_EVERYTHINGSORTED',
'MENU_GROUP_ISINDEXGROUP',
'FILE_NEW', 'FILE_CHANGED', 'FILE_SAME', 'FILE_DOESNTEXIST');
#
# Topic: Assumptions
#
# - No constant here will ever be zero.
# - All constants are exported by default.
#
###############################################################################
# Group: Virtual Types
# These are only groups of constants, but should be treated like typedefs or enums. Each one represents a distinct type and
# their values should only be one of their constants or undef.
#
# Constants: MenuEntryType
#
# The types of entries that can appear in the menu.
#
# MENU_TITLE - The title of the menu.
# MENU_SUBTITLE - The sub-title of the menu.
# MENU_FILE - A source file, relative to the source directory.
# MENU_GROUP - A group.
# MENU_TEXT - Arbitrary text.
# MENU_LINK - A web link.
# MENU_FOOTER - Footer text.
# MENU_INDEX - An index.
# MENU_FORMAT - The version of Natural Docs the menu file was generated with.
# MENU_ENDOFORIGINAL - A dummy entry that marks where the original group content ends. This is used when automatically
# changing the groups so that the alphabetization or lack thereof can be detected without being
# affected by new entries tacked on to the end.
# MENU_DATA - Data not meant for user editing.
#
# Dependency:
#
# <PreviousMenuState.nd> depends on these values all being able to fit into a UInt8, i.e. <= 255.
#
use constant MENU_TITLE => 1;
use constant MENU_SUBTITLE => 2;
use constant MENU_FILE => 3;
use constant MENU_GROUP => 4;
use constant MENU_TEXT => 5;
use constant MENU_LINK => 6;
use constant MENU_FOOTER => 7;
use constant MENU_INDEX => 8;
use constant MENU_FORMAT => 9;
use constant MENU_ENDOFORIGINAL => 10;
use constant MENU_DATA => 11;
#
# Constants: FileStatus
#
# What happened to a file since Natural Docs' last execution.
#
# FILE_NEW - The file has been added since the last run.
# FILE_CHANGED - The file has been modified since the last run.
# FILE_SAME - The file hasn't been modified since the last run.
# FILE_DOESNTEXIST - The file doesn't exist, or was deleted.
#
use constant FILE_NEW => 1;
use constant FILE_CHANGED => 2;
use constant FILE_SAME => 3;
use constant FILE_DOESNTEXIST => 4;
###############################################################################
# Group: Flags
# These constants can be combined with each other.
#
# Constants: Menu Entry Flags
#
# The various flags that can apply to a menu entry. You cannot mix flags of different types, since they may overlap.
#
# File Flags:
#
# MENU_FILE_NOAUTOTITLE - Whether the file is auto-titled or not.
#
# Group Flags:
#
# MENU_GROUP_UPDATETITLES - The group should have its auto-titles regenerated.
# MENU_GROUP_UPDATESTRUCTURE - The group should be checked for structural changes, such as being removed or being
# split into subgroups.
# MENU_GROUP_UPDATEORDER - The group should be resorted.
#
# MENU_GROUP_HASENDOFORIGINAL - Whether the group contains a dummy <MENU_ENDOFORIGINAL> entry.
# MENU_GROUP_ISINDEXGROUP - Whether the group is used primarily for <MENU_INDEX> entries. <MENU_TEXT> entries
# are tolerated.
#
# MENU_GROUP_UNSORTED - The group's contents are not sorted.
# MENU_GROUP_FILESSORTED - The group's files are sorted alphabetically.
# MENU_GROUP_FILESANDGROUPSSORTED - The group's files and sub-groups are sorted alphabetically.
# MENU_GROUP_EVERYTHINGSORTED - All entries in the group are sorted alphabetically.
#
use constant MENU_FILE_NOAUTOTITLE => 0x0001;
use constant MENU_GROUP_UPDATETITLES => 0x0001;
use constant MENU_GROUP_UPDATESTRUCTURE => 0x0002;
use constant MENU_GROUP_UPDATEORDER => 0x0004;
use constant MENU_GROUP_HASENDOFORIGINAL => 0x0008;
# This could really be a two-bit field instead of four flags, but it's not worth the effort since it's only used internally.
use constant MENU_GROUP_UNSORTED => 0x0010;
use constant MENU_GROUP_FILESSORTED => 0x0020;
use constant MENU_GROUP_FILESANDGROUPSSORTED => 0x0040;
use constant MENU_GROUP_EVERYTHINGSORTED => 0x0080;
use constant MENU_GROUP_ISINDEXGROUP => 0x0100;
###############################################################################
# Group: Support Functions
#
# Function: IsClassHierarchyReference
# Returns whether the passed <ReferenceType> belongs to <NaturalDocs::ClassHierarchy>.
#
sub IsClassHierarchyReference #(reference)
{
my ($self, $reference) = @_;
return ($reference == ::REFERENCE_CH_CLASS() || $reference == ::REFERENCE_CH_PARENT());
};
1;

View file

@ -1,100 +0,0 @@
###############################################################################
#
# Package: NaturalDocs::DefineMembers
#
###############################################################################
#
# A custom Perl pragma to define member constants and accessors for use in Natural Docs objects while supporting inheritance.
#
# Each member will be defined as a numeric constant which should be used as that variable's index into the object arrayref.
# They will be assigned sequentially from zero, and take into account any members defined this way in parent classes. Note
# that you can *not* use multiple inheritance with this method.
#
# If a parameter ends in parenthesis, it will be generated as an accessor for the previous member. If it also starts with "Set",
# the accessor will accept a single parameter to replace the value with. If it's followed with "duparrayref", it will assume the
# parameter is either an arrayref or undef, and if the former, will duplicate it to set the value.
#
# Example:
#
# > package MyPackage;
# >
# > use NaturalDocs::DefineMembers 'VAR_A', 'VarA()', 'SetVarA()',
# > 'VAR_B', 'VarB()',
# > 'VAR_C',
# > 'VAR_D', 'VarD()', 'SetVarD() duparrayref';
# >
# > sub SetC #(C)
# > {
# > my ($self, $c) = @_;
# > $self->[VAR_C] = $c;
# > };
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
package NaturalDocs::DefineMembers;
sub import #(member, member, ...)
{
my ($self, @parameters) = @_;
my $package = caller();
no strict 'refs';
my $parent = ${$package . '::ISA'}[0];
use strict 'refs';
my $memberConstant = 0;
my $lastMemberName;
if (defined $parent && $parent->can('END_OF_MEMBERS'))
{ $memberConstant = $parent->END_OF_MEMBERS(); };
my $code = '{ package ' . $package . ";\n";
foreach my $parameter (@parameters)
{
if ($parameter =~ /^(.+)\(\) *(duparrayref)?$/i)
{
my ($functionName, $pragma) = ($1, lc($2));
if ($functionName =~ /^Set/)
{
if ($pragma eq 'duparrayref')
{
$code .=
'sub ' . $functionName . '
{
if (defined $_[1])
{ $_[0]->[' . $lastMemberName . '] = [ @{$_[1]} ]; }
else
{ $_[0]->[' . $lastMemberName . '] = undef; };
};' . "\n";
}
else
{
$code .= 'sub ' . $functionName . ' { $_[0]->[' . $lastMemberName . '] = $_[1]; };' . "\n";
};
}
else
{
$code .= 'sub ' . $functionName . ' { return $_[0]->[' . $lastMemberName . ']; };' . "\n";
};
}
else
{
$code .= 'use constant ' . $parameter . ' => ' . $memberConstant . ";\n";
$memberConstant++;
$lastMemberName = $parameter;
};
};
$code .= 'use constant END_OF_MEMBERS => ' . $memberConstant . ";\n";
$code .= '};';
eval $code;
};
1;

View file

@ -1,305 +0,0 @@
###############################################################################
#
# Package: NaturalDocs::Error
#
###############################################################################
#
# Manages all aspects of error handling in Natural Docs.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
$SIG{'__DIE__'} = \&NaturalDocs::Error::CatchDeath;
package NaturalDocs::Error;
###############################################################################
# Group: Variables
#
# handle: FH_CRASHREPORT
# The filehandle used for generating crash reports.
#
#
# var: stackTrace
# The stack trace generated by <CatchDeath()>.
#
my $stackTrace;
#
# var: softDeath
# Whether the program exited using <SoftDeath()>.
#
my $softDeath;
#
# var: currentAction
# What Natural Docs was doing when it crashed. This stores strings generated by functions like <OnStartParsing()>.
#
my $currentAction;
###############################################################################
# Group: Functions
#
# Function: SoftDeath
#
# Generates a "soft" death, which means the program exits like with Perl's die(), but no crash report will be generated.
#
# Parameter:
#
# message - The error message to die with.
#
sub SoftDeath #(message)
{
my ($self, $message) = @_;
$softDeath = 1;
if ($message !~ /\n$/)
{ $message .= "\n"; };
die $message;
};
#
# Function: OnStartParsing
#
# Called whenever <NaturalDocs::Parser> starts parsing a source file.
#
sub OnStartParsing #(FileName file)
{
my ($self, $file) = @_;
$currentAction = 'Parsing ' . $file;
};
#
# Function: OnEndParsing
#
# Called whenever <NaturalDocs::Parser> is done parsing a source file.
#
sub OnEndParsing #(FileName file)
{
my ($self, $file) = @_;
$currentAction = undef;
};
#
# Function: OnStartBuilding
#
# Called whenever <NaturalDocs::Builder> starts building a source file.
#
sub OnStartBuilding #(FileName file)
{
my ($self, $file) = @_;
$currentAction = 'Building ' . $file;
};
#
# Function: OnEndBuilding
#
# Called whenever <NaturalDocs::Builder> is done building a source file.
#
sub OnEndBuilding #(FileName file)
{
my ($self, $file) = @_;
$currentAction = undef;
};
#
# Function: HandleDeath
#
# Should be called whenever Natural Docs dies out of execution.
#
sub HandleDeath
{
my $self = shift;
my $reason = $::EVAL_ERROR;
$reason =~ s/[\n\r]+$//;
my $errorMessage =
"\n"
. "Natural Docs encountered the following error and was stopped:\n"
. "\n"
. " " . $reason . "\n"
. "\n"
. "You can get help at the following web site:\n"
. "\n"
. " " . NaturalDocs::Settings->AppURL() . "\n"
. "\n";
if (!$softDeath)
{
my $crashReport = $self->GenerateCrashReport();
if ($crashReport)
{
$errorMessage .=
"If sending an error report, please include the information found in the\n"
. "following file:\n"
. "\n"
. " " . $crashReport . "\n"
. "\n";
}
else
{
$errorMessage .=
"If sending an error report, please include the following information:\n"
. "\n"
. " Natural Docs version: " . NaturalDocs::Settings->TextAppVersion() . "\n"
. " Perl version: " . $self->PerlVersion() . " on " . $::OSNAME . "\n"
. "\n";
};
};
die $errorMessage;
};
###############################################################################
# Group: Support Functions
#
# Function: PerlVersion
# Returns the current Perl version as a string.
#
sub PerlVersion
{
my $self = shift;
my $perlVersion;
if ($^V)
{ $perlVersion = sprintf('%vd', $^V); }
if (!$perlVersion || substr($perlVersion, 0, 1) eq '%')
{ $perlVersion = $]; };
return $perlVersion;
};
#
# Function: GenerateCrashReport
#
# Generates a report and returns the <FileName> it's located at. Returns undef if it could not generate one.
#
sub GenerateCrashReport
{
my $self = shift;
my $errorMessage = $::EVAL_ERROR;
$errorMessage =~ s/[\r\n]+$//;
my $reportDirectory = NaturalDocs::Settings->ProjectDirectory();
if (!$reportDirectory || !-d $reportDirectory)
{ return undef; };
my $file = NaturalDocs::File->JoinPaths($reportDirectory, 'LastCrash.txt');
open(FH_CRASHREPORT, '>' . $file) or return undef;
print FH_CRASHREPORT
'Crash Message:' . "\n\n"
. ' ' . $errorMessage . "\n\n";
if ($currentAction)
{
print FH_CRASHREPORT
'Current Action:' . "\n\n"
. ' ' . $currentAction . "\n\n";
};
print FH_CRASHREPORT
'Natural Docs version ' . NaturalDocs::Settings->TextAppVersion() . "\n"
. 'Perl version ' . $self->PerlVersion . ' on ' . $::OSNAME . "\n\n"
. 'Command Line:' . "\n\n"
. ' ' . join(' ', @ARGV) . "\n\n";
if ($stackTrace)
{
print FH_CRASHREPORT
'Stack Trace:' . "\n\n"
. $stackTrace;
}
else
{
print FH_CRASHREPORT
'Stack Trace not available.' . "\n\n";
};
close(FH_CRASHREPORT);
return $file;
};
###############################################################################
# Group: Signal Handlers
#
# Function: CatchDeath
#
# Catches Perl die calls.
#
# *IMPORTANT:* This function is a signal handler and should not be called manually. Also, because of this, it does not have
# a $self parameter.
#
# Parameters:
#
# message - The error message to die with.
#
sub CatchDeath #(message)
{
# No $self because it's a signal handler.
my $message = shift;
if (!$NaturalDocs::Error::softDeath)
{
my $i = 0;
my ($lastPackage, $lastFile, $lastLine, $lastFunction);
while (my ($package, $file, $line, $function) = caller($i))
{
if ($i != 0)
{ $stackTrace .= ', called from' . "\n"; };
$stackTrace .= ' ' . $function;
if (defined $lastLine)
{
$stackTrace .= ', line ' . $lastLine;
if ($function !~ /^NaturalDocs::/)
{ $stackTrace .= ' of ' . $lastFile; };
};
($lastPackage, $lastFile, $lastLine, $lastFunction) = ($package, $file, $line, $function);
$i++;
};
};
};
1;

View file

@ -1,540 +0,0 @@
###############################################################################
#
# Package: NaturalDocs::File
#
###############################################################################
#
# A package to manage file access across platforms. Incorporates functions from various standard File:: packages, but more
# importantly, works around the glorious suckage present in File::Spec, at least in version 0.82 and earlier. Read the "Why oh
# why?" sections for why this package was necessary.
#
# Usage and Dependencies:
#
# - The package doesn't depend on any other Natural Docs packages and is ready to use immediately.
#
# - All functions except <CanonizePath()> assume that all parameters are canonized.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use File::Spec ();
use File::Path ();
use File::Copy ();
use strict;
use integer;
package NaturalDocs::File;
#
# Function: CheckCompatibility
#
# Checks if the standard packages required by this one are up to snuff and dies if they aren't. This is done because I can't
# tell which versions of File::Spec have splitpath just by the version numbers.
#
sub CheckCompatibility
{
my ($self) = @_;
eval {
File::Spec->splitpath('');
};
if ($@)
{
NaturalDocs::Error->SoftDeath("Natural Docs requires a newer version of File::Spec than you have. "
. "You must either upgrade it or upgrade Perl.");
};
};
###############################################################################
# Group: Path String Functions
#
# Function: CanonizePath
#
# Takes a path and returns a logically simplified version of it.
#
# Why oh why?:
#
# Because File::Spec->canonpath doesn't strip quotes on Windows. So if you pass in "a b\c" or "a b"\c, they still end up as
# different strings even though they're logically the same.
#
# It also doesn't remove things like "..", so "a/b/../c" doesn't simplify to "a/c" like it should.
#
sub CanonizePath #(path)
{
my ($self, $path) = @_;
if ($::OSNAME eq 'MSWin32')
{
# We don't have to use a smarter algorithm for dropping quotes because they're invalid characters for actual file and
# directory names.
$path =~ s/\"//g;
};
$path = File::Spec->canonpath($path);
# Condense a/b/../c into a/c.
my $upDir = File::Spec->updir();
if (index($path, $upDir) != -1)
{
my ($volume, $directoryString, $file) = $self->SplitPath($path);
my @directories = $self->SplitDirectories($directoryString);
my $i = 1;
while ($i < scalar @directories)
{
if ($i > 0 && $directories[$i] eq $upDir && $directories[$i - 1] ne $upDir)
{
splice(@directories, $i - 1, 2);
$i--;
}
else
{ $i++; };
};
$directoryString = $self->JoinDirectories(@directories);
$path = $self->JoinPath($volume, $directoryString, $file);
};
return $path;
};
#
# Function: PathIsAbsolute
#
# Returns whether the passed path is absolute.
#
sub PathIsAbsolute #(path)
{
my ($self, $path) = @_;
return File::Spec->file_name_is_absolute($path);
};
#
# Function: JoinPath
#
# Creates a path from its elements.
#
# Parameters:
#
# volume - The volume, such as the drive letter on Windows. Undef if none.
# dirString - The directory string. Create with <JoinDirectories()> if necessary.
# file - The file name, or undef if none.
#
# Returns:
#
# The joined path.
#
sub JoinPath #(volume, dirString, $file)
{
my ($self, $volume, $dirString, $file) = @_;
return File::Spec->catpath($volume, $dirString, $file);
};
#
# Function: JoinPaths
#
# Joins two paths.
#
# Parameters:
#
# basePath - May be a relative path, an absolute path, or undef.
# extraPath - May be a relative path, a file, a relative path and file together, or undef.
# noFileInExtra - Set this to true if extraPath is a relative path only, and doesn't have a file.
#
# Returns:
#
# The joined path.
#
# Why oh why?:
#
# Because nothing in File::Spec will simply slap two paths together. They have to be split up for catpath/file, and rel2abs
# requires the base to be absolute.
#
sub JoinPaths #(basePath, extraPath, noFileInExtra)
{
my ($self, $basePath, $extraPath, $noFileInExtra) = @_;
# If both are undef, it will return undef, which is what we want.
if (!defined $basePath)
{ return $extraPath; }
elsif (!defined $extraPath)
{ return $basePath; };
my ($baseVolume, $baseDirString, $baseFile) = File::Spec->splitpath($basePath, 1);
my ($extraVolume, $extraDirString, $extraFile) = File::Spec->splitpath($extraPath, $noFileInExtra);
my @baseDirectories = $self->SplitDirectories($baseDirString);
my @extraDirectories = $self->SplitDirectories($extraDirString);
my $fullDirString = $self->JoinDirectories(@baseDirectories, @extraDirectories);
my $fullPath = File::Spec->catpath($baseVolume, $fullDirString, $extraFile);
return $self->CanonizePath($fullPath);
};
#
# Function: SplitPath
#
# Takes a path and returns its elements.
#
# Parameters:
#
# path - The path to split.
# noFile - Set to true if the path doesn't have a file at the end.
#
# Returns:
#
# The array ( volume, directoryString, file ). If any don't apply, they will be undef. Use <SplitDirectories()> to split the
# directory string if desired.
#
# Why oh Why?:
#
# Because File::Spec->splitpath may leave a trailing slash/backslash/whatever on the directory string, which makes
# it a bit hard to match it with results from File::Spec->catdir.
#
sub SplitPath #(path, noFile)
{
my ($self, $path, $noFile) = @_;
my @segments = File::Spec->splitpath($path, $noFile);
if (!length $segments[0])
{ $segments[0] = undef; };
if (!length $segments[2])
{ $segments[2] = undef; };
$segments[1] = File::Spec->catdir( File::Spec->splitdir($segments[1]) );
return @segments;
};
#
# Function: JoinDirectories
#
# Creates a directory string from an array of directory names.
#
# Parameters:
#
# directory - A directory name. There may be as many of these as desired.
#
sub JoinDirectories #(directory, directory, ...)
{
my ($self, @directories) = @_;
return File::Spec->catdir(@directories);
};
#
# Function: SplitDirectories
#
# Takes a string of directories and returns an array of its elements.
#
# Why oh why?:
#
# Because File::Spec->splitdir might leave an empty element at the end of the array, which screws up both joining in
# <ConvertToURL> and navigation in <MakeRelativePath>.
#
sub SplitDirectories #(directoryString)
{
my ($self, $directoryString) = @_;
my @directories = File::Spec->splitdir($directoryString);
if (!length $directories[-1])
{ pop @directories; };
return @directories;
};
#
# Function: MakeRelativePath
#
# Takes two paths and returns a relative path between them.
#
# Parameters:
#
# basePath - The starting path. May be relative or absolute, so long as the target path is as well.
# targetPath - The target path. May be relative or absolute, so long as the base path is as well.
#
# If both paths are relative, they are assumed to be relative to the same base.
#
# Returns:
#
# The target path relative to base.
#
# Why oh why?:
#
# First, there's nothing that gives a relative path between two relative paths.
#
# Second, if target and base are absolute but on different volumes, File::Spec->abs2rel creates a totally non-functional
# relative path. It should return the target as is, since there is no relative path.
#
# Third, File::Spec->abs2rel between absolute paths on the same volume, at least on Windows, leaves the drive letter
# on. So abs2rel('a:\b\c\d', 'a:\b') returns 'a:c\d' instead of the expected 'c\d'. That makes no sense whatsoever. It's
# not like it was designed to handle only directory names, either; the documentation says 'path' and the code seems to
# explicitly handle it. There's just an 'unless' in there that tacks on the volume, defeating the purpose of a *relative* path
# and making the function worthless.
#
sub MakeRelativePath #(basePath, targetPath)
{
my ($self, $basePath, $targetPath) = @_;
my ($baseVolume, $baseDirString, $baseFile) = $self->SplitPath($basePath, 1);
my ($targetVolume, $targetDirString, $targetFile) = $self->SplitPath($targetPath);
# If the volumes are different, there is no possible relative path.
if ($targetVolume ne $baseVolume)
{ return $targetPath; };
my @baseDirectories = $self->SplitDirectories($baseDirString);
my @targetDirectories = $self->SplitDirectories($targetDirString);
# Skip the parts of the path that are the same.
while (scalar @baseDirectories && @targetDirectories && $baseDirectories[0] eq $targetDirectories[0])
{
shift @baseDirectories;
shift @targetDirectories;
};
# Back out of the base path until it reaches where they were similar.
for (my $i = 0; $i < scalar @baseDirectories; $i++)
{
unshift @targetDirectories, File::Spec->updir();
};
$targetDirString = $self->JoinDirectories(@targetDirectories);
return File::Spec->catpath(undef, $targetDirString, $targetFile);
};
#
# Function: IsSubPathOf
#
# Returns whether the path is a descendant of another path.
#
# Parameters:
#
# base - The base path to test against.
# path - The possible subpath to test.
#
# Returns:
#
# Whether path is a descendant of base.
#
sub IsSubPathOf #(base, path)
{
my ($self, $base, $path) = @_;
# This is a quick test that should find a false quickly.
if ($base eq substr($path, 0, length($base)))
{
# This doesn't guarantee true, because it could be "C:\A B" and "C:\A B C\File". So we test for it by seeing if the last
# directory in base is the same as the equivalent directory in path.
my ($baseVolume, $baseDirString, $baseFile) = NaturalDocs::File->SplitPath($base, 1);
my @baseDirectories = NaturalDocs::File->SplitDirectories($baseDirString);
my ($pathVolume, $pathDirString, $pathFile) = NaturalDocs::File->SplitPath($path);
my @pathDirectories = NaturalDocs::File->SplitDirectories($pathDirString);
return ( $baseDirectories[-1] eq $pathDirectories[ scalar @baseDirectories - 1 ] );
}
else
{ return undef; };
};
#
# Function: ConvertToURL
#
# Takes a relative path and converts it from the native format to a relative URL. Note that it _doesn't_ convert special characters
# to amp chars.
#
sub ConvertToURL #(path)
{
my ($self, $path) = @_;
my ($pathVolume, $pathDirString, $pathFile) = $self->SplitPath($path);
my @pathDirectories = $self->SplitDirectories($pathDirString);
my $i = 0;
while ($i < scalar @pathDirectories && $pathDirectories[$i] eq File::Spec->updir())
{
$pathDirectories[$i] = '..';
$i++;
};
return join('/', @pathDirectories, $pathFile);
};
#
# Function: NoUpwards
#
# Takes an array of directory entries and returns one without all the entries that refer to the parent directory, such as '.' and '..'.
#
sub NoUpwards #(array)
{
my ($self, @array) = @_;
return File::Spec->no_upwards(@array);
};
#
# Function: NoFileName
#
# Takes a path and returns a version without the file name. Useful for sending paths to <CreatePath()>.
#
sub NoFileName #(path)
{
my ($self, $path) = @_;
my ($pathVolume, $pathDirString, $pathFile) = File::Spec->splitpath($path);
return File::Spec->catpath($pathVolume, $pathDirString, undef);
};
#
# Function: NoExtension
#
# Returns the path without an extension.
#
sub NoExtension #(path)
{
my ($self, $path) = @_;
my $extension = $self->ExtensionOf($path);
if ($extension)
{ $path = substr($path, 0, length($path) - length($extension) - 1); };
return $path;
};
#
# Function: ExtensionOf
#
# Returns the extension of the passed path, or undef if none.
#
sub ExtensionOf #(path)
{
my ($self, $path) = @_;
my ($pathVolume, $pathDirString, $pathFile) = File::Spec->splitpath($path);
# We need the leading dot in the regex so files that start with a dot but don't have an extension count as extensionless files.
if ($pathFile =~ /.\.([^\.]+)$/)
{ return $1; }
else
{ return undef; };
};
#
# Function: IsCaseSensitive
#
# Returns whether the current platform has case-sensitive paths.
#
sub IsCaseSensitive
{
return !(File::Spec->case_tolerant());
};
###############################################################################
# Group: Disk Functions
#
# Function: CreatePath
#
# Creates a directory tree corresponding to the passed path, regardless of how many directories do or do not already exist.
# Do _not_ include a file name in the path. Use <NoFileName()> first if you need to.
#
sub CreatePath #(path)
{
my ($self, $path) = @_;
File::Path::mkpath($path);
};
#
# Function: RemoveEmptyTree
#
# Removes an empty directory tree. The passed directory will be removed if it's empty, and it will keep removing its parents
# until it reaches one that's not empty or a set limit.
#
# Parameters:
#
# path - The path to start from. It will try to remove this directory and work it's way down.
# limit - The path to stop at if it doesn't find any non-empty directories first. This path will *not* be removed.
#
sub RemoveEmptyTree #(path, limit)
{
my ($self, $path, $limit) = @_;
my ($volume, $directoryString) = $self->SplitPath($path, 1);
my @directories = $self->SplitDirectories($directoryString);
my $directory = $path;
while (-d $directory && $directory ne $limit)
{
opendir FH_ND_FILE, $directory;
my @entries = readdir FH_ND_FILE;
closedir FH_ND_FILE;
@entries = $self->NoUpwards(@entries);
if (scalar @entries || !rmdir($directory))
{ last; };
pop @directories;
$directoryString = $self->JoinDirectories(@directories);
$directory = $self->JoinPath($volume, $directoryString);
};
};
#
# Function: Copy
#
# Copies a file from one path to another. If the destination file exists, it is overwritten.
#
# Parameters:
#
# source - The file to copy.
# destination - The destination to copy to.
#
# Returns:
#
# Whether it succeeded
#
sub Copy #(source, destination) => bool
{
my ($self, $source, $destination) = @_;
return File::Copy::copy($source, $destination);
};
1;

View file

@ -1,383 +0,0 @@
###############################################################################
#
# Package: NaturalDocs::ImageReferenceTable
#
###############################################################################
#
# A <NaturalDocs::SourceDB>-based package that manages all the image references appearing in source files.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
use NaturalDocs::ImageReferenceTable::String;
use NaturalDocs::ImageReferenceTable::Reference;
package NaturalDocs::ImageReferenceTable;
use base 'NaturalDocs::SourceDB::Extension';
###############################################################################
# Group: Information
#
# Topic: Usage
#
# - <NaturalDocs::Project> and <NaturalDocs::SourceDB> must be initialized before this package can be used.
#
# - Call <Register()> before using.
#
#
# Topic: Programming Notes
#
# When working on this code, remember that there are three things it has to juggle.
#
# - The information in <NaturalDocs::SourceDB>.
# - Image file references in <NaturalDocs::Project>.
# - Source file rebuilding on changes.
#
# Managing the actual image files will be handled between <NaturalDocs::Project> and the <NaturalDocs::Builder>
# sub-packages.
#
#
# Topic: Implementation
#
# Managing image references is simpler than managing the references in <NaturalDocs::SymbolTable>. In SymbolTable,
# you have to worry about reference targets popping into and out of existence. A link may go to a file that hasn't been
# reparsed yet and the target may no longer exist. We have to deal with that when we know it, which may be after the
# reference's file was parsed. Also, a new definition may appear that serves as a better interpretation of a link than its
# current target, and again we may only know that after the reference's file has been parsed already. So we have to deal
# with scores and potential symbols and each symbol knowing exactly what links to it and so forth.
#
# Not so with image references. All possible targets (all possible image files) are known by <NaturalDocs::Project> early
# on and will remain consistent throughout execution. So because of that, we can get away with only storing reference
# counts with each image and determining exactly where a reference points to as we find them.
#
# Reference counts are stored with the image file information in <NaturalDocs::Project>. However, it is not loaded and
# saved to disk by it. Rather, it is regenerated by this package when it loads <ImageReferenceTable.nd>.
# NaturalDocs::Project only stores the last modification time (so it can add files to the build list if they've changed) and
# whether it had any references at all on the last run (so it knows whether it should care if they've changed.)
# ImageReferenceTable.nd stores each reference's target, width, and height. Whether their interpretations have changed is
# dealt with in the <Load()> function, again since the list of targets (image files) is constant.
#
# The package is based on <NaturalDocs::SourceDB>, so read it's documentation for more information on how it works.
#
###############################################################################
# Group: Variables
#
# var: extensionID
# The <ExtensionID> granted by <NaturalDocs::SourceDB>.
#
my $extensionID;
###############################################################################
# Group: Files
#
# File: ImageReferenceTable.nd
#
# The data file which stores all the image references from the last run of Natural Docs.
#
# Format:
#
# > [Standard Binary Header]
#
# It starts with the standard binary header from <NaturalDocs::BinaryFile>.
#
# > [Image Reference String or undef]
# > [AString16: target file]
# > [UInt16: target width or 0]
# > [UInt16: target height or 0]
#
# For each <ImageReferenceString>, it's target, width, and height are stored. The target is needed so we can tell if it
# changed from the last run, and the dimensions are needed because if the target hasn't changed but the file's dimensions
# have, the source files need to be rebuilt.
#
# <ImageReferenceStrings> are encoded by <NaturalDocs::ImageReferenceTable::String>.
#
# > [AString16: definition file or undef] ...
#
# Then comes a series of AString16s for all the files that define the reference until it hits an undef.
#
# This whole series is repeated for each <ImageReferenceString> until it hits an undef.
#
# Revisions:
#
# 1.4:
#
# - The file was added to Natural Docs.
#
###############################################################################
# Group: Functions
#
# Function: Register
# Registers the package with <NaturalDocs::SourceDB>.
#
sub Register
{
my $self = shift;
$extensionID = NaturalDocs::SourceDB->RegisterExtension($self, 0);
};
#
# Function: Load
#
# Loads the data from <ImageReferenceTable.nd>. Returns whether it was successful.
#
sub Load # => bool
{
my $self = shift;
if (NaturalDocs::Settings->RebuildData())
{ return 0; };
# The file format hasn't changed since it was introduced.
if (!NaturalDocs::BinaryFile->OpenForReading( NaturalDocs::Project->DataFile('ImageReferenceTable.nd') ))
{ return 0; };
# [Image Reference String or undef]
while (my $referenceString = NaturalDocs::ImageReferenceTable::String->FromBinaryFile())
{
NaturalDocs::SourceDB->AddItem($extensionID, $referenceString,
NaturalDocs::ImageReferenceTable::Reference->New());
# [AString16: target file]
# [UInt16: target width or 0]
# [UInt16: target height or 0]
my $targetFile = NaturalDocs::BinaryFile->GetAString16();
my $width = NaturalDocs::BinaryFile->GetUInt16();
my $height = NaturalDocs::BinaryFile->GetUInt16();
my $newTargetFile = $self->SetReferenceTarget($referenceString);
my $newWidth;
my $newHeight;
if ($newTargetFile)
{
NaturalDocs::Project->AddImageFileReference($newTargetFile);
($newWidth, $newHeight) = NaturalDocs::Project->ImageFileDimensions($newTargetFile);
};
my $rebuildDefinitions = ($newTargetFile ne $targetFile || $newWidth != $width || $newHeight != $height);
# [AString16: definition file or undef] ...
while (my $definitionFile = NaturalDocs::BinaryFile->GetAString16())
{
NaturalDocs::SourceDB->AddDefinition($extensionID, $referenceString, $definitionFile);
if ($rebuildDefinitions)
{ NaturalDocs::Project->RebuildFile($definitionFile); };
};
};
NaturalDocs::BinaryFile->Close();
return 1;
};
#
# Function: Save
#
# Saves the data to <ImageReferenceTable.nd>.
#
sub Save
{
my $self = shift;
my $references = NaturalDocs::SourceDB->GetAllItemsHashRef($extensionID);
NaturalDocs::BinaryFile->OpenForWriting( NaturalDocs::Project->DataFile('ImageReferenceTable.nd') );
while (my ($referenceString, $referenceObject) = each %$references)
{
# [Image Reference String or undef]
# [AString16: target file]
# [UInt16: target width or 0]
# [UInt16: target height or 0]
NaturalDocs::ImageReferenceTable::String->ToBinaryFile($referenceString);
my $target = $referenceObject->Target();
my ($width, $height);
if ($target)
{ ($width, $height) = NaturalDocs::Project->ImageFileDimensions($target); };
NaturalDocs::BinaryFile->WriteAString16( $referenceObject->Target() );
NaturalDocs::BinaryFile->WriteUInt16( ($width || 0) );
NaturalDocs::BinaryFile->WriteUInt16( ($height || 0) );
# [AString16: definition file or undef] ...
my $definitions = $referenceObject->GetAllDefinitionsHashRef();
foreach my $definition (keys %$definitions)
{ NaturalDocs::BinaryFile->WriteAString16($definition); };
NaturalDocs::BinaryFile->WriteAString16(undef);
};
NaturalDocs::ImageReferenceTable::String->ToBinaryFile(undef);
NaturalDocs::BinaryFile->Close();
};
#
# Function: AddReference
#
# Adds a new image reference.
#
sub AddReference #(FileName file, string referenceText)
{
my ($self, $file, $referenceText) = @_;
my $referenceString = NaturalDocs::ImageReferenceTable::String->Make($file, $referenceText);
if (!NaturalDocs::SourceDB->HasItem($extensionID, $referenceString))
{
my $referenceObject = NaturalDocs::ImageReferenceTable::Reference->New();
NaturalDocs::SourceDB->AddItem($extensionID, $referenceString, $referenceObject);
my $target = $self->SetReferenceTarget($referenceString);
if ($target)
{ NaturalDocs::Project->AddImageFileReference($target); };
};
NaturalDocs::SourceDB->AddDefinition($extensionID, $referenceString, $file);
};
#
# Function: OnDeletedDefinition
#
# Called for each definition deleted by <NaturalDocs::SourceDB>. This is called *after* the definition has been deleted from
# the database, so don't expect to be able to read it.
#
sub OnDeletedDefinition #(ImageReferenceString referenceString, FileName file, bool wasLastDefinition)
{
my ($self, $referenceString, $file, $wasLastDefinition) = @_;
if ($wasLastDefinition)
{
my $referenceObject = NaturalDocs::SourceDB->GetItem($extensionID, $referenceString);
my $target = $referenceObject->Target();
if ($target)
{ NaturalDocs::Project->DeleteImageFileReference($target); };
NaturalDocs::SourceDB->DeleteItem($extensionID, $referenceString);
};
};
#
# Function: GetReferenceTarget
#
# Returns the image file the reference resolves to, or undef if none.
#
# Parameters:
#
# sourceFile - The source <FileName> the reference appears in.
# text - The reference text.
#
sub GetReferenceTarget #(FileName sourceFile, string text) => FileName
{
my ($self, $sourceFile, $text) = @_;
my $referenceString = NaturalDocs::ImageReferenceTable::String->Make($sourceFile, $text);
my $reference = NaturalDocs::SourceDB->GetItem($extensionID, $referenceString);
if (!defined $reference)
{ return undef; }
else
{ return $reference->Target(); };
};
#
# Function: SetReferenceTarget
#
# Determines the best target for the passed <ImageReferenceString> and sets it on the
# <NaturalDocs::ImageReferenceTable::Reference> object. Returns the new target <FileName>. Does *not* add any source
# files to the bulid list.
#
sub SetReferenceTarget #(ImageReferenceString referenceString) => FileName
{
my ($self, $referenceString) = @_;
my $referenceObject = NaturalDocs::SourceDB->GetItem($extensionID, $referenceString);
my ($sourcePath, $text) = NaturalDocs::ImageReferenceTable::String->InformationOf($referenceString);
# Try the path relative to the source file first.
my $target;
my $imageFile = NaturalDocs::File->JoinPaths($sourcePath, $text);
my $exists = NaturalDocs::Project->ImageFileExists($imageFile);
# Then try relative image directories.
if (!$exists)
{
my $relativeImageDirectories = NaturalDocs::Settings->RelativeImageDirectories();
for (my $i = 0; $i < scalar @$relativeImageDirectories && !$exists; $i++)
{
$imageFile = NaturalDocs::File->JoinPaths($sourcePath, $relativeImageDirectories->[$i], 1);
$imageFile = NaturalDocs::File->JoinPaths($imageFile, $text);
$exists = NaturalDocs::Project->ImageFileExists($imageFile);
};
};
# Then try absolute image directories.
if (!$exists)
{
my $imageDirectories = NaturalDocs::Settings->ImageDirectories();
for (my $i = 0; $i < scalar @$imageDirectories && !$exists; $i++)
{
$imageFile = NaturalDocs::File->JoinPaths($imageDirectories->[$i], $text);
$exists = NaturalDocs::Project->ImageFileExists($imageFile);
};
};
if ($exists)
{ $target = NaturalDocs::Project->ImageFileCapitalization($imageFile); };
#else leave it as undef.
$referenceObject->SetTarget($target);
return $target;
};
1;

View file

@ -1,44 +0,0 @@
###############################################################################
#
# Package: NaturalDocs::ImageReferenceTable::Reference
#
###############################################################################
#
# A class for references being tracked in <NaturalDocs::SourceDB>.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
package NaturalDocs::ImageReferenceTable::Reference;
use base 'NaturalDocs::SourceDB::Item';
use NaturalDocs::DefineMembers 'TARGET', 'Target()', 'SetTarget()',
'NEEDS_REBUILD', 'NeedsRebuild()', 'SetNeedsRebuild()';
#
# Variables: Members
#
# The following constants are indexes into the object array.
#
# TARGET - The image <FileName> this reference resolves to, or undef if none.
#
#
# Functions: Member Functions
#
# Target - Returns the image <FileName> this reference resolves to, or undef if none.
# SetTarget - Replaces the image <FileName> this reference resolves to, or undef if none.
#
1;

View file

@ -1,110 +0,0 @@
###############################################################################
#
# Package: NaturalDocs::ImageReferenceTable::String
#
###############################################################################
#
# A package for creating and managing <ImageReferenceStrings>.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
package NaturalDocs::ImageReferenceTable::String;
#
# Type: ImageReferenceString
#
# A string representing a unique image reference. It's composed of the reference text and the directory of the source file.
# The source file name itself isn't included because two files in the same directory with the same reference text will always go
# to the same targets.
#
#
# Function: Make
#
# Converts a source <FileName> and the reference text to an <ImageReferenceString>.
#
sub Make #(FileName sourceFile, string text) => ImageReferenceString
{
my ($self, $sourceFile, $text) = @_;
my $path = NaturalDocs::File->NoFileName($sourceFile);
# Condense whitespace and remove any separator characters.
$path =~ tr/ \t\r\n\x1C/ /s;
$text =~ tr/ \t\r\n\x1C/ /s;
return $path . "\x1C" . $text;
};
#
# Function: InformationOf
#
# Returns the information contained in the <ImageReferenceString> as the array ( path, text ).
#
sub InformationOf #(ImageReferenceString referenceString)
{
my ($self, $referenceString) = @_;
return split(/\x1C/, $referenceString);
};
#
# Function: ToBinaryFile
#
# Writes an <ImageReferenceString> to <NaturalDocs::BinaryFile>. Can also encode an undef.
#
# Format:
#
# > [AString16: path] [AString16: reference text] ...
#
# Undef is represented by the first AString16 being undef.
#
sub ToBinaryFile #(ImageReferenceString referenceString)
{
my ($self, $referenceString) = @_;
if (defined $referenceString)
{
my ($path, $text) = split(/\x1C/, $referenceString);
NaturalDocs::BinaryFile->WriteAString16($path);
NaturalDocs::BinaryFile->WriteAString16($text);
}
else
{
NaturalDocs::BinaryFile->WriteAString16(undef);
};
};
#
# Function: FromBinaryFile
#
# Loads an <ImageReferenceString> or undef from <NaturalDocs::BinaryFile> and returns it.
#
sub FromBinaryFile
{
my $self = shift;
my $path = NaturalDocs::BinaryFile->GetAString16();
if (!defined $path)
{ return undef; };
my $text = NaturalDocs::BinaryFile->GetAString16();
return $path . "\x1C" . $text;
};
1;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,38 +0,0 @@
###############################################################################
#
# Class: NaturalDocs::Languages::Ada
#
###############################################################################
#
# A subclass to handle the language variations of Ada
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
package NaturalDocs::Languages::Ada;
use base 'NaturalDocs::Languages::Simple';
#
# Function: ParseParameterLine
# Overridden because Ada uses Pascal-style parameters
#
sub ParseParameterLine #(...)
{
my ($self, @params) = @_;
return $self->SUPER::ParsePascalParameterLine(@params);
};
sub TypeBeforeParameter
{
return 0;
};
1;

View file

@ -1,828 +0,0 @@
###############################################################################
#
# Class: NaturalDocs::Languages::Advanced
#
###############################################################################
#
# The base class for all languages that have full support in Natural Docs. Each one will have a custom parser capable
# of documenting undocumented aspects of the code.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
use NaturalDocs::Languages::Advanced::Scope;
use NaturalDocs::Languages::Advanced::ScopeChange;
package NaturalDocs::Languages::Advanced;
use base 'NaturalDocs::Languages::Base';
#############################################################################
# Group: Implementation
#
# Constants: Members
#
# The class is implemented as a blessed arrayref. The following constants are used as indexes.
#
# TOKENS - An arrayref of tokens used in all the <Parsing Functions>.
# SCOPE_STACK - An arrayref of <NaturalDocs::Languages::Advanced::Scope> objects serving as a scope stack for parsing.
# There will always be one available, with a symbol of undef, for the top level.
# SCOPE_RECORD - An arrayref of <NaturalDocs::Languages::Advanced::ScopeChange> objects, as generated by the scope
# stack. If there is more than one change per line, only the last is stored.
# AUTO_TOPICS - An arrayref of <NaturalDocs::Parser::ParsedTopics> generated automatically from the code.
#
use NaturalDocs::DefineMembers 'TOKENS', 'SCOPE_STACK', 'SCOPE_RECORD', 'AUTO_TOPICS';
#############################################################################
# Group: Functions
#
# Function: New
#
# Creates and returns a new object.
#
# Parameters:
#
# name - The name of the language.
#
sub New #(name)
{
my ($package, @parameters) = @_;
my $object = $package->SUPER::New(@parameters);
$object->[TOKENS] = undef;
$object->[SCOPE_STACK] = undef;
$object->[SCOPE_RECORD] = undef;
return $object;
};
# Function: Tokens
# Returns the tokens found by <ParseForCommentsAndTokens()>.
sub Tokens
{ return $_[0]->[TOKENS]; };
# Function: SetTokens
# Replaces the tokens.
sub SetTokens #(tokens)
{ $_[0]->[TOKENS] = $_[1]; };
# Function: ClearTokens
# Resets the token list. You may want to do this after parsing is over to save memory.
sub ClearTokens
{ $_[0]->[TOKENS] = undef; };
# Function: AutoTopics
# Returns the arrayref of automatically generated topics, or undef if none.
sub AutoTopics
{ return $_[0]->[AUTO_TOPICS]; };
# Function: AddAutoTopic
# Adds a <NaturalDocs::Parser::ParsedTopic> to <AutoTopics()>.
sub AddAutoTopic #(topic)
{
my ($self, $topic) = @_;
if (!defined $self->[AUTO_TOPICS])
{ $self->[AUTO_TOPICS] = [ ]; };
push @{$self->[AUTO_TOPICS]}, $topic;
};
# Function: ClearAutoTopics
# Resets the automatic topic list. Not necessary if you call <ParseForCommentsAndTokens()>.
sub ClearAutoTopics
{ $_[0]->[AUTO_TOPICS] = undef; };
# Function: ScopeRecord
# Returns an arrayref of <NaturalDocs::Languages::Advanced::ScopeChange> objects describing how and when the scope
# changed thoughout the file. There will always be at least one entry, which will be for line 1 and undef as the scope.
sub ScopeRecord
{ return $_[0]->[SCOPE_RECORD]; };
###############################################################################
#
# Group: Parsing Functions
#
# These functions are good general language building blocks. Use them to create your language-specific parser.
#
# All functions work on <Tokens()> and assume it is set by <ParseForCommentsAndTokens()>.
#
#
# Function: ParseForCommentsAndTokens
#
# Loads the passed file, sends all appropriate comments to <NaturalDocs::Parser->OnComment()>, and breaks the rest into
# an arrayref of tokens. Tokens are defined as
#
# - All consecutive alphanumeric and underscore characters.
# - All consecutive whitespace.
# - A single line break. It will always be "\n"; you don't have to worry about platform differences.
# - A single character not included above, which is usually a symbol. Multiple consecutive ones each get their own token.
#
# The result will be placed in <Tokens()>.
#
# Parameters:
#
# sourceFile - The source <FileName> to load and parse.
# lineCommentSymbols - An arrayref of symbols that designate line comments, or undef if none.
# blockCommentSymbols - An arrayref of symbol pairs that designate multiline comments, or undef if none. Symbol pairs are
# designated as two consecutive array entries, the opening symbol appearing first.
# javadocLineCommentSymbols - An arrayref of symbols that designate the start of a JavaDoc comment, or undef if none.
# javadocBlockCommentSymbols - An arrayref of symbol pairs that designate multiline JavaDoc comments, or undef if none.
#
# Notes:
#
# - This function automatically calls <ClearAutoTopics()> and <ClearScopeStack()>. You only need to call those functions
# manually if you override this one.
# - To save parsing time, all comment lines sent to <NaturalDocs::Parser->OnComment()> will be replaced with blank lines
# in <Tokens()>. It's all the same to most languages.
#
sub ParseForCommentsAndTokens #(FileName sourceFile, string[] lineCommentSymbols, string[] blockCommentSymbols, string[] javadocLineCommentSymbols, string[] javadocBlockCommentSymbols)
{
my ($self, $sourceFile, $lineCommentSymbols, $blockCommentSymbols,
$javadocLineCommentSymbols, $javadocBlockCommentSymbols) = @_;
open(SOURCEFILEHANDLE, '<' . $sourceFile)
or die "Couldn't open input file " . $sourceFile . "\n";
my $tokens = [ ];
$self->SetTokens($tokens);
# For convenience.
$self->ClearAutoTopics();
$self->ClearScopeStack();
# Load and preprocess the file
my @lines;
my $line = <SOURCEFILEHANDLE>;
# On the very first line, remove a Unicode BOM if present. Information on it available at:
# http://www.unicode.org/faq/utf_bom.html#BOM
$line =~ s/^\xEF\xBB\xBF//;
while (defined $line)
{
::XChomp(\$line);
push @lines, $line;
$line = <SOURCEFILEHANDLE>;
};
close(SOURCEFILEHANDLE);
$self->PreprocessFile(\@lines);
# Go through the file
my $lineIndex = 0;
while ($lineIndex < scalar @lines)
{
$line = $lines[$lineIndex];
my @commentLines;
my $commentLineNumber;
my $isJavaDoc;
my $closingSymbol;
# Retrieve single line comments. This leaves $lineIndex at the next line.
if ( ($isJavaDoc = $self->StripOpeningJavaDocSymbols(\$line, $javadocLineCommentSymbols)) ||
$self->StripOpeningSymbols(\$line, $lineCommentSymbols))
{
$commentLineNumber = $lineIndex + 1;
do
{
push @commentLines, $line;
push @$tokens, "\n";
$lineIndex++;
if ($lineIndex >= scalar @lines)
{ goto EndDo; };
$line = $lines[$lineIndex];
}
while ($self->StripOpeningSymbols(\$line, $lineCommentSymbols));
EndDo: # I hate Perl sometimes.
}
# Retrieve multiline comments. This leaves $lineIndex at the next line.
elsif ( ($isJavaDoc = $self->StripOpeningJavaDocBlockSymbols(\$line, $javadocBlockCommentSymbols)) ||
($closingSymbol = $self->StripOpeningBlockSymbols(\$line, $blockCommentSymbols)) )
{
$commentLineNumber = $lineIndex + 1;
if ($isJavaDoc)
{ $closingSymbol = $isJavaDoc; };
# Note that it is possible for a multiline comment to start correctly but not end so. We want those comments to stay in
# the code. For example, look at this prototype with this splint annotation:
#
# int get_array(integer_t id,
# /*@out@*/ array_t array);
#
# The annotation starts correctly but doesn't end so because it is followed by code on the same line.
my ($lineRemainder, $isMultiLine);
for (;;)
{
$lineRemainder = $self->StripClosingSymbol(\$line, $closingSymbol);
push @commentLines, $line;
# If we found an end comment symbol...
if (defined $lineRemainder)
{ last; };
push @$tokens, "\n";
$lineIndex++;
$isMultiLine = 1;
if ($lineIndex >= scalar @lines)
{ last; };
$line = $lines[$lineIndex];
};
if ($lineRemainder !~ /^[ \t]*$/)
{
# If there was something past the closing symbol this wasn't an acceptable comment.
if ($isMultiLine)
{ $self->TokenizeLine($lineRemainder); }
else
{
# We go back to the original line if it wasn't a multiline comment because we want the comment to stay in the
# code. Otherwise the /*@out@*/ from the example would be removed.
$self->TokenizeLine($lines[$lineIndex]);
};
@commentLines = ( );
}
else
{
push @$tokens, "\n";
};
$lineIndex++;
}
# Otherwise just add it to the code.
else
{
$self->TokenizeLine($line);
$lineIndex++;
};
# If there were comments, send them to Parser->OnComment().
if (scalar @commentLines)
{
NaturalDocs::Parser->OnComment(\@commentLines, $commentLineNumber, $isJavaDoc);
@commentLines = ( );
$isJavaDoc = undef;
};
# $lineIndex was incremented by the individual code paths above.
}; # while ($lineIndex < scalar @lines)
};
#
# Function: PreprocessFile
#
# An overridable function if you'd like to preprocess the file before it goes into <ParseForCommentsAndTokens()>.
#
# Parameters:
#
# lines - An arrayref to the file's lines. Each line has its line break stripped off, but is otherwise untouched.
#
sub PreprocessFile #(lines)
{
};
#
# Function: TokenizeLine
#
# Converts the passed line to tokens as described in <ParseForCommentsAndTokens> and adds them to <Tokens()>. Also
# adds a line break token after it.
#
sub TokenizeLine #(line)
{
my ($self, $line) = @_;
push @{$self->Tokens()}, $line =~ /(\w+|[ \t]+|.)/g, "\n";
};
#
# Function: TryToSkipString
#
# If the position is on a string delimiter, moves the position to the token following the closing delimiter, or past the end of the
# tokens if there is none. Assumes all other characters are allowed in the string, the delimiter itself is allowed if it's preceded by
# a backslash, and line breaks are allowed in the string.
#
# Parameters:
#
# indexRef - A reference to the position's index into <Tokens()>.
# lineNumberRef - A reference to the position's line number.
# openingDelimiter - The opening string delimiter, such as a quote or an apostrophe.
# closingDelimiter - The closing string delimiter, if different. If not defined, assumes the same as openingDelimiter.
# startContentIndexRef - A reference to a variable in which to store the index of the first token of the string's content.
# May be undef.
# endContentIndexRef - A reference to a variable in which to store the index of the end of the string's content, which is one
# past the last index of content. May be undef.
#
# Returns:
#
# Whether the position was on the passed delimiter or not. The index, line number, and content index ref variables will be
# updated only if true.
#
sub TryToSkipString #(indexRef, lineNumberRef, openingDelimiter, closingDelimiter, startContentIndexRef, endContentIndexRef)
{
my ($self, $index, $lineNumber, $openingDelimiter, $closingDelimiter, $startContentIndexRef, $endContentIndexRef) = @_;
my $tokens = $self->Tokens();
if (!defined $closingDelimiter)
{ $closingDelimiter = $openingDelimiter; };
if ($tokens->[$$index] ne $openingDelimiter)
{ return undef; };
$$index++;
if (defined $startContentIndexRef)
{ $$startContentIndexRef = $$index; };
while ($$index < scalar @$tokens)
{
if ($tokens->[$$index] eq "\\")
{
# Skip the token after it.
$$index += 2;
}
elsif ($tokens->[$$index] eq "\n")
{
$$lineNumber++;
$$index++;
}
elsif ($tokens->[$$index] eq $closingDelimiter)
{
if (defined $endContentIndexRef)
{ $$endContentIndexRef = $$index; };
$$index++;
last;
}
else
{
$$index++;
};
};
if ($$index >= scalar @$tokens && defined $endContentIndexRef)
{ $$endContentIndexRef = scalar @$tokens; };
return 1;
};
#
# Function: SkipRestOfLine
#
# Moves the position to the token following the next line break, or past the end of the tokens array if there is none. Useful for
# line comments.
#
# Note that it skips blindly. It assumes there cannot be anything of interest, such as a string delimiter, between the position
# and the end of the line.
#
# Parameters:
#
# indexRef - A reference to the position's index into <Tokens()>.
# lineNumberRef - A reference to the position's line number.
sub SkipRestOfLine #(indexRef, lineNumberRef)
{
my ($self, $index, $lineNumber) = @_;
my $tokens = $self->Tokens();
while ($$index < scalar @$tokens)
{
if ($tokens->[$$index] eq "\n")
{
$$lineNumber++;
$$index++;
last;
}
else
{
$$index++;
};
};
};
#
# Function: SkipUntilAfter
#
# Moves the position to the token following the next occurance of a particular token sequence, or past the end of the tokens
# array if it never occurs. Useful for multiline comments.
#
# Note that it skips blindly. It assumes there cannot be anything of interest, such as a string delimiter, between the position
# and the end of the line.
#
# Parameters:
#
# indexRef - A reference to the position's index.
# lineNumberRef - A reference to the position's line number.
# token - A token that must be matched. Can be specified multiple times to match a sequence of tokens.
#
sub SkipUntilAfter #(indexRef, lineNumberRef, token, token, ...)
{
my ($self, $index, $lineNumber, @target) = @_;
my $tokens = $self->Tokens();
while ($$index < scalar @$tokens)
{
if ($tokens->[$$index] eq $target[0] && ($$index + scalar @target) <= scalar @$tokens)
{
my $match = 1;
for (my $i = 1; $i < scalar @target; $i++)
{
if ($tokens->[$$index+$i] ne $target[$i])
{
$match = 0;
last;
};
};
if ($match)
{
$$index += scalar @target;
return;
};
};
if ($tokens->[$$index] eq "\n")
{
$$lineNumber++;
$$index++;
}
else
{
$$index++;
};
};
};
#
# Function: IsFirstLineToken
#
# Returns whether the position is at the first token of a line, not including whitespace.
#
# Parameters:
#
# index - The index of the position.
#
sub IsFirstLineToken #(index)
{
my ($self, $index) = @_;
my $tokens = $self->Tokens();
if ($index == 0)
{ return 1; };
$index--;
if ($tokens->[$index] =~ /^[ \t]/)
{ $index--; };
if ($index <= 0 || $tokens->[$index] eq "\n")
{ return 1; }
else
{ return undef; };
};
#
# Function: IsLastLineToken
#
# Returns whether the position is at the last token of a line, not including whitespace.
#
# Parameters:
#
# index - The index of the position.
#
sub IsLastLineToken #(index)
{
my ($self, $index) = @_;
my $tokens = $self->Tokens();
do
{ $index++; }
while ($index < scalar @$tokens && $tokens->[$index] =~ /^[ \t]/);
if ($index >= scalar @$tokens || $tokens->[$index] eq "\n")
{ return 1; }
else
{ return undef; };
};
#
# Function: IsAtSequence
#
# Returns whether the position is at a sequence of tokens.
#
# Parameters:
#
# index - The index of the position.
# token - A token to match. Specify multiple times to specify the sequence.
#
sub IsAtSequence #(index, token, token, token ...)
{
my ($self, $index, @target) = @_;
my $tokens = $self->Tokens();
if ($index + scalar @target > scalar @$tokens)
{ return undef; };
for (my $i = 0; $i < scalar @target; $i++)
{
if ($tokens->[$index + $i] ne $target[$i])
{ return undef; };
};
return 1;
};
#
# Function: IsBackslashed
#
# Returns whether the position is after a backslash.
#
# Parameters:
#
# index - The index of the postition.
#
sub IsBackslashed #(index)
{
my ($self, $index) = @_;
my $tokens = $self->Tokens();
if ($index > 0 && $tokens->[$index - 1] eq "\\")
{ return 1; }
else
{ return undef; };
};
###############################################################################
#
# Group: Scope Functions
#
# These functions provide a nice scope stack implementation for language-specific parsers to use. The default implementation
# makes the following assumptions.
#
# - Packages completely replace one another, rather than concatenating. You need to concatenate manually if that's the
# behavior.
#
# - Packages inherit, so if a scope level doesn't set its own, the package is the same as the parent scope's.
#
#
# Function: ClearScopeStack
#
# Clears the scope stack for a new file. Not necessary if you call <ParseForCommentsAndTokens()>.
#
sub ClearScopeStack
{
my ($self) = @_;
$self->[SCOPE_STACK] = [ NaturalDocs::Languages::Advanced::Scope->New(undef, undef) ];
$self->[SCOPE_RECORD] = [ NaturalDocs::Languages::Advanced::ScopeChange->New(undef, 1) ];
};
#
# Function: StartScope
#
# Records a new scope level.
#
# Parameters:
#
# closingSymbol - The closing symbol of the scope.
# lineNumber - The line number where the scope begins.
# package - The package <SymbolString> of the scope. Undef means no change.
#
sub StartScope #(closingSymbol, lineNumber, package)
{
my ($self, $closingSymbol, $lineNumber, $package) = @_;
push @{$self->[SCOPE_STACK]},
NaturalDocs::Languages::Advanced::Scope->New($closingSymbol, $package, $self->CurrentUsing());
$self->AddToScopeRecord($self->CurrentScope(), $lineNumber);
};
#
# Function: EndScope
#
# Records the end of the current scope level. Note that this is blind; you need to manually check <ClosingScopeSymbol()> if
# you need to determine if it is correct to do so.
#
# Parameters:
#
# lineNumber - The line number where the scope ends.
#
sub EndScope #(lineNumber)
{
my ($self, $lineNumber) = @_;
if (scalar @{$self->[SCOPE_STACK]} > 1)
{ pop @{$self->[SCOPE_STACK]}; };
$self->AddToScopeRecord($self->CurrentScope(), $lineNumber);
};
#
# Function: ClosingScopeSymbol
#
# Returns the symbol that ends the current scope level, or undef if we are at the top level.
#
sub ClosingScopeSymbol
{
my ($self) = @_;
return $self->[SCOPE_STACK]->[-1]->ClosingSymbol();
};
#
# Function: CurrentScope
#
# Returns the current calculated scope, or undef if global. The default implementation just returns <CurrentPackage()>. This
# is a separate function because C++ may need to track namespaces and classes separately, and so the current scope would
# be a concatenation of them.
#
sub CurrentScope
{
return $_[0]->CurrentPackage();
};
#
# Function: CurrentPackage
#
# Returns the current calculated package or class, or undef if none.
#
sub CurrentPackage
{
my ($self) = @_;
my $package;
for (my $index = scalar @{$self->[SCOPE_STACK]} - 1; $index >= 0 && !defined $package; $index--)
{
$package = $self->[SCOPE_STACK]->[$index]->Package();
};
return $package;
};
#
# Function: SetPackage
#
# Sets the package for the current scope level.
#
# Parameters:
#
# package - The new package <SymbolString>.
# lineNumber - The line number the new package starts on.
#
sub SetPackage #(package, lineNumber)
{
my ($self, $package, $lineNumber) = @_;
$self->[SCOPE_STACK]->[-1]->SetPackage($package);
$self->AddToScopeRecord($self->CurrentScope(), $lineNumber);
};
#
# Function: CurrentUsing
#
# Returns the current calculated arrayref of <SymbolStrings> from Using statements, or undef if none.
#
sub CurrentUsing
{
my ($self) = @_;
return $self->[SCOPE_STACK]->[-1]->Using();
};
#
# Function: AddUsing
#
# Adds a Using <SymbolString> to the current scope.
#
sub AddUsing #(using)
{
my ($self, $using) = @_;
$self->[SCOPE_STACK]->[-1]->AddUsing($using);
};
###############################################################################
# Group: Support Functions
#
# Function: AddToScopeRecord
#
# Adds a change to the scope record, condensing unnecessary entries.
#
# Parameters:
#
# newScope - What the scope <SymbolString> changed to.
# lineNumber - Where the scope changed.
#
sub AddToScopeRecord #(newScope, lineNumber)
{
my ($self, $scope, $lineNumber) = @_;
my $scopeRecord = $self->ScopeRecord();
if ($scope ne $scopeRecord->[-1]->Scope())
{
if ($scopeRecord->[-1]->LineNumber() == $lineNumber)
{ $scopeRecord->[-1]->SetScope($scope); }
else
{ push @$scopeRecord, NaturalDocs::Languages::Advanced::ScopeChange->New($scope, $lineNumber); };
};
};
#
# Function: CreateString
#
# Converts the specified tokens into a string and returns it.
#
# Parameters:
#
# startIndex - The starting index to convert.
# endIndex - The ending index, which is *not inclusive*.
#
# Returns:
#
# The string.
#
sub CreateString #(startIndex, endIndex)
{
my ($self, $startIndex, $endIndex) = @_;
my $tokens = $self->Tokens();
my $string;
while ($startIndex < $endIndex && $startIndex < scalar @$tokens)
{
$string .= $tokens->[$startIndex];
$startIndex++;
};
return $string;
};
1;

View file

@ -1,95 +0,0 @@
###############################################################################
#
# Class: NaturalDocs::Languages::Advanced::Scope
#
###############################################################################
#
# A class used to store a scope level.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
package NaturalDocs::Languages::Advanced::Scope;
#
# Constants: Implementation
#
# The object is implemented as a blessed arrayref. The constants below are used as indexes.
#
# CLOSING_SYMBOL - The closing symbol character of the scope.
# PACKAGE - The package <SymbolString> of the scope.
# USING - An arrayref of <SymbolStrings> for using statements, or undef if none.
#
use NaturalDocs::DefineMembers 'CLOSING_SYMBOL', 'PACKAGE', 'USING';
# Dependency: New() depends on the order of these constants as well as that there is no inherited members.
#
# Function: New
#
# Creates and returns a new object.
#
# Parameters:
#
# closingSymbol - The closing symbol character of the scope.
# package - The package <SymbolString> of the scope.
# using - An arrayref of using <SymbolStrings>, or undef if none. The contents of the array will be duplicated.
#
# If package is set to undef, it is assumed that it inherits the value of the previous scope on the stack.
#
sub New #(closingSymbol, package, using)
{
# Dependency: This depends on the order of the parameters matching the constants, and that there are no inherited
# members.
my $package = shift;
my $object = [ @_ ];
bless $object, $package;
if (defined $object->[USING])
{ $object->[USING] = [ @{$object->[USING]} ]; };
return $object;
};
# Function: ClosingSymbol
# Returns the closing symbol character of the scope.
sub ClosingSymbol
{ return $_[0]->[CLOSING_SYMBOL]; };
# Function: Package
# Returns the package <SymbolString> of the scope, or undef if none.
sub Package
{ return $_[0]->[PACKAGE]; };
# Function: SetPackage
# Sets the package <SymbolString> of the scope.
sub SetPackage #(package)
{ $_[0]->[PACKAGE] = $_[1]; };
# Function: Using
# Returns an arrayref of <SymbolStrings> for using statements, or undef if none
sub Using
{ return $_[0]->[USING]; };
# Function: AddUsing
# Adds a <SymbolString> to the <Using()> array.
sub AddUsing #(using)
{
my ($self, $using) = @_;
if (!defined $self->[USING])
{ $self->[USING] = [ ]; };
push @{$self->[USING]}, $using;
};
1;

View file

@ -1,70 +0,0 @@
###############################################################################
#
# Class: NaturalDocs::Languages::Advanced::ScopeChange
#
###############################################################################
#
# A class used to store a scope change.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
package NaturalDocs::Languages::Advanced::ScopeChange;
#
# Constants: Implementation
#
# The object is implemented as a blessed arrayref. The constants below are used as indexes.
#
# SCOPE - The new scope <SymbolString>.
# LINE_NUMBER - The line number of the change.
#
use NaturalDocs::DefineMembers 'SCOPE', 'LINE_NUMBER';
# Dependency: New() depends on the order of these constants as well as that there is no inherited members.
#
# Function: New
#
# Creates and returns a new object.
#
# Parameters:
#
# scope - The <SymbolString> the scope was changed to.
# lineNumber - What line it occurred on.
#
sub New #(scope, lineNumber)
{
# Dependency: This depends on the order of the parameters matching the constants, and that there are no inherited
# members.
my $self = shift;
my $object = [ @_ ];
bless $object, $self;
return $object;
};
# Function: Scope
# Returns the <SymbolString> the scope was changed to.
sub Scope
{ return $_[0]->[SCOPE]; };
# Function: SetScope
# Replaces the <SymbolString> the scope was changed to.
sub SetScope #(scope)
{ $_[0]->[SCOPE] = $_[1]; };
# Function: LineNumber
# Returns the line number of the change.
sub LineNumber
{ return $_[0]->[LINE_NUMBER]; };
1;

View file

@ -1,832 +0,0 @@
###############################################################################
#
# Class: NaturalDocs::Languages::Base
#
###############################################################################
#
# A base class for all programming language parsers.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
package NaturalDocs::Languages::Base;
use NaturalDocs::DefineMembers 'NAME', 'Name()',
'EXTENSIONS', 'Extensions()', 'SetExtensions() duparrayref',
'SHEBANG_STRINGS', 'ShebangStrings()', 'SetShebangStrings() duparrayref',
'IGNORED_PREFIXES',
'ENUM_VALUES';
use base 'Exporter';
our @EXPORT = ('ENUM_GLOBAL', 'ENUM_UNDER_TYPE', 'ENUM_UNDER_PARENT');
#
# Constants: EnumValuesType
#
# How enum values are handled in the language.
#
# ENUM_GLOBAL - Values are always global and thus 'value'.
# ENUM_UNDER_TYPE - Values are under the type in the hierarchy, and thus 'package.enum.value'.
# ENUM_UNDER_PARENT - Values are under the parent in the hierarchy, putting them on the same level as the enum itself. Thus
# 'package.value'.
#
use constant ENUM_GLOBAL => 1;
use constant ENUM_UNDER_TYPE => 2;
use constant ENUM_UNDER_PARENT => 3;
#
# Handle: SOURCEFILEHANDLE
#
# The handle of the source file currently being parsed.
#
#
# Function: New
#
# Creates and returns a new object.
#
# Parameters:
#
# name - The name of the language.
#
sub New #(name)
{
my ($selfPackage, $name) = @_;
my $object = [ ];
$object->[NAME] = $name;
bless $object, $selfPackage;
return $object;
};
#
# Functions: Members
#
# Name - Returns the language's name.
# Extensions - Returns an arrayref of the language's file extensions, or undef if none.
# SetExtensions - Replaces the arrayref of the language's file extensions.
# ShebangStrings - Returns an arrayref of the language's shebang strings, or undef if none.
# SetShebangStrings - Replaces the arrayref of the language's shebang strings.
#
#
# Function: PackageSeparator
# Returns the language's package separator string.
#
sub PackageSeparator
{ return '.'; };
#
# Function: PackageSeparatorWasSet
# Returns whether the language's package separator string was ever changed from the default.
#
sub PackageSeparatorWasSet
{ return 0; };
#
# Function: EnumValues
# Returns the <EnumValuesType> that describes how the language handles enums.
#
sub EnumValues
{ return ENUM_GLOBAL; };
#
# Function: IgnoredPrefixesFor
#
# Returns an arrayref of ignored prefixes for the passed <TopicType>, or undef if none. The array is sorted so that the longest
# prefixes are first.
#
sub IgnoredPrefixesFor #(type)
{
my ($self, $type) = @_;
if (defined $self->[IGNORED_PREFIXES])
{ return $self->[IGNORED_PREFIXES]->{$type}; }
else
{ return undef; };
};
#
# Function: SetIgnoredPrefixesFor
#
# Replaces the arrayref of ignored prefixes for the passed <TopicType>.
#
sub SetIgnoredPrefixesFor #(type, prefixes)
{
my ($self, $type, $prefixesRef) = @_;
if (!defined $self->[IGNORED_PREFIXES])
{ $self->[IGNORED_PREFIXES] = { }; };
if (!defined $prefixesRef)
{ delete $self->[IGNORED_PREFIXES]->{$type}; }
else
{
my $prefixes = [ @$prefixesRef ];
# Sort prefixes to be longest to shortest.
@$prefixes = sort { length $b <=> length $a } @$prefixes;
$self->[IGNORED_PREFIXES]->{$type} = $prefixes;
};
};
#
# Function: HasIgnoredPrefixes
#
# Returns whether the language has any ignored prefixes at all.
#
sub HasIgnoredPrefixes
{ return defined $_[0]->[IGNORED_PREFIXES]; };
#
# Function: CopyIgnoredPrefixesOf
#
# Copies all the ignored prefix settings of the passed <NaturalDocs::Languages::Base> object.
#
sub CopyIgnoredPrefixesOf #(language)
{
my ($self, $language) = @_;
if ($language->HasIgnoredPrefixes())
{
$self->[IGNORED_PREFIXES] = { };
while (my ($topicType, $prefixes) = each %{$language->[IGNORED_PREFIXES]})
{
$self->[IGNORED_PREFIXES]->{$topicType} = [ @$prefixes ];
};
};
};
###############################################################################
# Group: Parsing Functions
#
# Function: ParseFile
#
# Parses the passed source file, sending comments acceptable for documentation to <NaturalDocs::Parser->OnComment()>.
# This *must* be defined by a subclass.
#
# Parameters:
#
# sourceFile - The <FileName> of the source file to parse.
# topicList - A reference to the list of <NaturalDocs::Parser::ParsedTopics> being built by the file.
#
# Returns:
#
# The array ( autoTopics, scopeRecord ).
#
# autoTopics - An arrayref of automatically generated <NaturalDocs::Parser::ParsedTopics> from the file, or undef if none.
# scopeRecord - An arrayref of <NaturalDocs::Languages::Advanced::ScopeChanges>, or undef if none.
#
#
# Function: ParsePrototype
#
# Parses the prototype and returns it as a <NaturalDocs::Languages::Prototype> object.
#
# Parameters:
#
# type - The <TopicType>.
# prototype - The text prototype.
#
# Returns:
#
# A <NaturalDocs::Languages::Prototype> object.
#
sub ParsePrototype #(type, prototype)
{
my ($self, $type, $prototype) = @_;
my $isClass = NaturalDocs::Topics->TypeInfo($type)->ClassHierarchy();
if ($prototype !~ /\(.*[^ ].*\)/ && (!$isClass || $prototype !~ /\{.*[^ ].*\}/))
{
my $object = NaturalDocs::Languages::Prototype->New($prototype);
return $object;
};
# Parse the parameters out of the prototype.
my @tokens = $prototype =~ /([^\(\)\[\]\{\}\<\>\'\"\,\;]+|.)/g;
my $parameter;
my @parameterLines;
my @symbolStack;
my $finishedParameters;
my ($beforeParameters, $afterParameters);
foreach my $token (@tokens)
{
if ($finishedParameters)
{ $afterParameters .= $token; }
elsif ($symbolStack[-1] eq '\'' || $symbolStack[-1] eq '"')
{
if ($symbolStack[0] eq '(' || ($isClass && $symbolStack[0] eq '{'))
{ $parameter .= $token; }
else
{ $beforeParameters .= $token; };
if ($token eq $symbolStack[-1])
{ pop @symbolStack; };
}
elsif ($token =~ /^[\(\[\{\<\'\"]$/)
{
if ($symbolStack[0] eq '(' || ($isClass && $symbolStack[0] eq '{'))
{ $parameter .= $token; }
else
{ $beforeParameters .= $token; };
push @symbolStack, $token;
}
elsif ( ($token eq ')' && $symbolStack[-1] eq '(') ||
($token eq ']' && $symbolStack[-1] eq '[') ||
($token eq '}' && $symbolStack[-1] eq '{') ||
($token eq '>' && $symbolStack[-1] eq '<') )
{
if ($symbolStack[0] eq '(')
{
if ($token eq ')' && scalar @symbolStack == 1)
{
if ($parameter ne ' ')
{ push @parameterLines, $parameter; };
$finishedParameters = 1;
$afterParameters .= $token;
}
else
{ $parameter .= $token; };
}
elsif ($isClass && $symbolStack[0] eq '{')
{
if ($token eq '}' && scalar @symbolStack == 1)
{
if ($parameter ne ' ')
{ push @parameterLines, $parameter; };
$finishedParameters = 1;
$afterParameters .= $token;
}
else
{ $parameter .= $token; };
}
else
{
$beforeParameters .= $token;
};
pop @symbolStack;
}
elsif ($token eq ',' || $token eq ';')
{
if ($symbolStack[0] eq '(' || ($isClass && $symbolStack[0] eq '{'))
{
if (scalar @symbolStack == 1)
{
push @parameterLines, $parameter . $token;
$parameter = undef;
}
else
{
$parameter .= $token;
};
}
else
{
$beforeParameters .= $token;
};
}
else
{
if ($symbolStack[0] eq '(' || ($isClass && $symbolStack[0] eq '{'))
{ $parameter .= $token; }
else
{ $beforeParameters .= $token; };
};
};
foreach my $part (\$beforeParameters, \$afterParameters)
{
$$part =~ s/^ //;
$$part =~ s/ $//;
};
my $prototypeObject = NaturalDocs::Languages::Prototype->New($beforeParameters, $afterParameters);
# Parse the actual parameters.
foreach my $parameterLine (@parameterLines)
{
$prototypeObject->AddParameter( $self->ParseParameterLine($parameterLine) );
};
return $prototypeObject;
};
#
# Function: ParseParameterLine
#
# Parses a prototype parameter line and returns it as a <NaturalDocs::Languages::Prototype::Parameter> object.
#
# This vesion assumes a C++ style line. If you need a Pascal style line, override this function to forward to
# <ParsePascalParameterLine()>.
#
# > Function(parameter, type parameter, type parameter = value);
#
sub ParseParameterLine #(line)
{
my ($self, $line) = @_;
$line =~ s/^ //;
$line =~ s/ $//;
my @tokens = $line =~ /([^ \(\)\{\}\[\]\<\>\'\"\=]+|.)/g;
my @symbolStack;
my @parameterWords = ( undef );
my ($defaultValue, $defaultValuePrefix, $inDefaultValue);
foreach my $token (@tokens)
{
if ($inDefaultValue)
{ $defaultValue .= $token; }
elsif ($symbolStack[-1] eq '\'' || $symbolStack[-1] eq '"')
{
$parameterWords[-1] .= $token;
if ($token eq $symbolStack[-1])
{ pop @symbolStack; };
}
elsif ($token =~ /^[\(\[\{\<\'\"]$/)
{
push @symbolStack, $token;
$parameterWords[-1] .= $token;
}
elsif ( ($token eq ')' && $symbolStack[-1] eq '(') ||
($token eq ']' && $symbolStack[-1] eq '[') ||
($token eq '}' && $symbolStack[-1] eq '{') ||
($token eq '>' && $symbolStack[-1] eq '<') )
{
pop @symbolStack;
$parameterWords[-1] .= $token;
}
elsif ($token eq ' ')
{
if (!scalar @symbolStack)
{ push @parameterWords, undef; }
else
{ $parameterWords[-1] .= $token; };
}
elsif ($token eq '=')
{
if (!scalar @symbolStack)
{
$defaultValuePrefix = $token;
$inDefaultValue = 1;
}
else
{ $parameterWords[-1] .= $token; };
}
else
{
$parameterWords[-1] .= $token;
};
};
my ($name, $namePrefix, $type, $typePrefix);
if (!$parameterWords[-1])
{ pop @parameterWords; };
$name = pop @parameterWords;
if ($parameterWords[-1]=~ /([\*\&]+)$/)
{
$namePrefix = $1;
$parameterWords[-1] = substr($parameterWords[-1], 0, 0 - length($namePrefix));
$parameterWords[-1] =~ s/ $//;
if (!$parameterWords[-1])
{ pop @parameterWords; };
}
elsif ($name =~ /^([\*\&]+)/)
{
$namePrefix = $1;
$name = substr($name, length($namePrefix));
$name =~ s/^ //;
};
$type = pop @parameterWords;
$typePrefix = join(' ', @parameterWords);
if ($typePrefix)
{ $typePrefix .= ' '; };
if ($type =~ /^([a-z0-9_\:\.]+(?:\.|\:\:))[a-z0-9_]/i)
{
my $attachedTypePrefix = $1;
$typePrefix .= $attachedTypePrefix;
$type = substr($type, length($attachedTypePrefix));
};
$defaultValue =~ s/ $//;
return NaturalDocs::Languages::Prototype::Parameter->New($type, $typePrefix, $name, $namePrefix,
$defaultValue, $defaultValuePrefix);
};
#
# Function: ParsePascalParameterLine
#
# Parses a Pascal-like prototype parameter line and returns it as a <NaturalDocs::Languages::Prototype::Parameter> object.
# Pascal lines are as follows:
#
# > Function (name: type; name, name: type := value)
#
# Also supports ActionScript lines
#
# > Function (name: type, name, name: type = value)
#
sub ParsePascalParameterLine #(line)
{
my ($self, $line) = @_;
$line =~ s/^ //;
$line =~ s/ $//;
my @tokens = $line =~ /([^\(\)\{\}\[\]\<\>\'\"\=\:]+|\:\=|.)/g;
my ($type, $name, $defaultValue, $defaultValuePrefix, $afterName, $afterDefaultValue);
my @symbolStack;
foreach my $token (@tokens)
{
if ($afterDefaultValue)
{ $defaultValue .= $token; }
elsif ($symbolStack[-1] eq '\'' || $symbolStack[-1] eq '"')
{
if ($afterName)
{ $type .= $token; }
else
{ $name .= $token; };
if ($token eq $symbolStack[-1])
{ pop @symbolStack; };
}
elsif ($token =~ /^[\(\[\{\<\'\"]$/)
{
push @symbolStack, $token;
if ($afterName)
{ $type .= $token; }
else
{ $name .= $token; };
}
elsif ( ($token eq ')' && $symbolStack[-1] eq '(') ||
($token eq ']' && $symbolStack[-1] eq '[') ||
($token eq '}' && $symbolStack[-1] eq '{') ||
($token eq '>' && $symbolStack[-1] eq '<') )
{
pop @symbolStack;
if ($afterName)
{ $type .= $token; }
else
{ $name .= $token; };
}
elsif ($afterName)
{
if (($token eq ':=' || $token eq '=') && !scalar @symbolStack)
{
$defaultValuePrefix = $token;
$afterDefaultValue = 1;
}
else
{ $type .= $token; };
}
elsif ($token eq ':' && !scalar @symbolStack)
{
$name .= $token;
$afterName = 1;
}
else
{ $name .= $token; };
};
foreach my $part (\$type, \$name, \$defaultValue)
{
$$part =~ s/^ //;
$$part =~ s/ $//;
};
return NaturalDocs::Languages::Prototype::Parameter->New($type, undef, $name, undef, $defaultValue, $defaultValuePrefix);
};
#
# Function: TypeBeforeParameter
#
# Returns whether the type appears before the parameter in prototypes.
#
# For example, it does in C++
# > void Function (int a, int b)
#
# but does not in Pascal
# > function Function (a: int; b, c: int)
#
sub TypeBeforeParameter
{
return 1;
};
#
# Function: IgnoredPrefixLength
#
# Returns the length of the prefix that should be ignored in the index, or zero if none.
#
# Parameters:
#
# name - The name of the symbol.
# type - The symbol's <TopicType>.
#
# Returns:
#
# The length of the prefix to ignore, or zero if none.
#
sub IgnoredPrefixLength #(name, type)
{
my ($self, $name, $type) = @_;
foreach my $prefixes ($self->IgnoredPrefixesFor($type), $self->IgnoredPrefixesFor(::TOPIC_GENERAL()))
{
if (defined $prefixes)
{
foreach my $prefix (@$prefixes)
{
if (substr($name, 0, length($prefix)) eq $prefix)
{ return length($prefix); };
};
};
};
return 0;
};
###############################################################################
# Group: Support Functions
#
# Function: StripOpeningSymbols
#
# Determines if the line starts with any of the passed symbols, and if so, replaces it with spaces. This only happens
# if the only thing before it on the line is whitespace.
#
# Parameters:
#
# lineRef - A reference to the line to check.
# symbols - An arrayref of the symbols to check for.
#
# Returns:
#
# If the line starts with any of the passed comment symbols, it will replace it in the line with spaces and return the symbol.
# If the line doesn't, it will leave the line alone and return undef.
#
sub StripOpeningSymbols #(lineRef, symbols)
{
my ($self, $lineRef, $symbols) = @_;
if (!defined $symbols)
{ return undef; };
my ($index, $symbol) = ::FindFirstSymbol($$lineRef, $symbols);
if ($index != -1 && substr($$lineRef, 0, $index) =~ /^[ \t]*$/)
{
return substr($$lineRef, $index, length($symbol), ' ' x length($symbol));
};
return undef;
};
#
# Function: StripOpeningJavaDocSymbols
#
# Determines if the line starts with any of the passed symbols, and if so, replaces it with spaces. This only happens
# if the only thing before it on the line is whitespace and the next character after it is whitespace or the end of the line.
#
# Parameters:
#
# lineRef - A reference to the line to check.
# symbols - An arrayref of the symbols to check for.
#
# Returns:
#
# If the line starts with any of the passed comment symbols, it will replace it in the line with spaces and return the symbol.
# If the line doesn't, it will leave the line alone and return undef.
#
sub StripOpeningJavaDocSymbols #(lineRef, symbols)
{
my ($self, $lineRef, $symbols) = @_;
if (!defined $symbols)
{ return undef; };
my ($index, $symbol) = ::FindFirstSymbol($$lineRef, $symbols);
if ($index != -1 && substr($$lineRef, 0, $index) =~ /^[ \t]*$/ && substr($$lineRef, $index + length($symbol), 1) =~ /^[ \t]?$/)
{
return substr($$lineRef, $index, length($symbol), ' ' x length($symbol));
};
return undef;
};
#
# Function: StripOpeningBlockSymbols
#
# Determines if the line starts with any of the opening symbols in the passed symbol pairs, and if so, replaces it with spaces.
# This only happens if the only thing before it on the line is whitespace.
#
# Parameters:
#
# lineRef - A reference to the line to check.
# symbolPairs - An arrayref of the symbol pairs to check for. Pairs are specified as two consecutive array entries, with the
# opening symbol first.
#
# Returns:
#
# If the line starts with any of the opening symbols, it will replace it in the line with spaces and return the closing symbol.
# If the line doesn't, it will leave the line alone and return undef.
#
sub StripOpeningBlockSymbols #(lineRef, symbolPairs)
{
my ($self, $lineRef, $symbolPairs) = @_;
if (!defined $symbolPairs)
{ return undef; };
for (my $i = 0; $i < scalar @$symbolPairs; $i += 2)
{
my $index = index($$lineRef, $symbolPairs->[$i]);
if ($index != -1 && substr($$lineRef, 0, $index) =~ /^[ \t]*$/)
{
substr($$lineRef, $index, length($symbolPairs->[$i]), ' ' x length($symbolPairs->[$i]));
return $symbolPairs->[$i + 1];
};
};
return undef;
};
#
# Function: StripOpeningJavaDocBlockSymbols
#
# Determines if the line starts with any of the opening symbols in the passed symbol pairs, and if so, replaces it with spaces.
# This only happens if the only thing before it on the line is whitespace and the next character is whitespace or the end of the line.
#
# Parameters:
#
# lineRef - A reference to the line to check.
# symbolPairs - An arrayref of the symbol pairs to check for. Pairs are specified as two consecutive array entries, with the
# opening symbol first.
#
# Returns:
#
# If the line starts with any of the opening symbols, it will replace it in the line with spaces and return the closing symbol.
# If the line doesn't, it will leave the line alone and return undef.
#
sub StripOpeningJavaDocBlockSymbols #(lineRef, symbolPairs)
{
my ($self, $lineRef, $symbolPairs) = @_;
if (!defined $symbolPairs)
{ return undef; };
for (my $i = 0; $i < scalar @$symbolPairs; $i += 2)
{
my $index = index($$lineRef, $symbolPairs->[$i]);
if ($index != -1 && substr($$lineRef, 0, $index) =~ /^[ \t]*$/ &&
substr($$lineRef, $index + length($symbolPairs->[$i]), 1) =~ /^[ \t]?$/)
{
substr($$lineRef, $index, length($symbolPairs->[$i]), ' ' x length($symbolPairs->[$i]));
return $symbolPairs->[$i + 1];
};
};
return undef;
};
#
# Function: StripClosingSymbol
#
# Determines if the line contains a symbol, and if so, truncates it just before the symbol.
#
# Parameters:
#
# lineRef - A reference to the line to check.
# symbol - The symbol to check for.
#
# Returns:
#
# The remainder of the line, or undef if the symbol was not found.
#
sub StripClosingSymbol #(lineRef, symbol)
{
my ($self, $lineRef, $symbol) = @_;
my $index = index($$lineRef, $symbol);
if ($index != -1)
{
my $lineRemainder = substr($$lineRef, $index + length($symbol));
$$lineRef = substr($$lineRef, 0, $index);
return $lineRemainder;
}
else
{ return undef; };
};
#
# Function: NormalizePrototype
#
# Normalizes a prototype. Specifically, condenses spaces, tabs, and line breaks into single spaces and removes leading and
# trailing ones.
#
# Parameters:
#
# prototype - The original prototype string.
#
# Returns:
#
# The normalized prototype.
#
sub NormalizePrototype #(prototype)
{
my ($self, $prototype) = @_;
$prototype =~ tr/ \t\r\n/ /s;
$prototype =~ s/^ //;
$prototype =~ s/ $//;
return $prototype;
};
1;

File diff suppressed because it is too large Load diff

View file

@ -1,319 +0,0 @@
###############################################################################
#
# Class: NaturalDocs::Languages::PLSQL
#
###############################################################################
#
# A subclass to handle the language variations of PL/SQL.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
package NaturalDocs::Languages::PLSQL;
use base 'NaturalDocs::Languages::Simple';
#
# Function: OnPrototypeEnd
#
# Microsoft's SQL specifies parameters as shown below.
#
# > CREATE PROCEDURE Test @as int, @foo int AS ...
#
# Having a parameter @is or @as is perfectly valid even though those words are also used to end the prototype. We need to
# ignore text-based enders preceded by an at sign. Also note that it does not have parenthesis for parameter lists. We need to
# skip all commas if the prototype doesn't have parenthesis but does have @ characters.
#
# Identifiers such as function names may contain the characters $, #, and _, so if "as" or "is" appears directly after one of them
# we need to ignore the ender there as well.
#
# > FUNCTION Something_is_something ...
#
# Parameters:
#
# type - The <TopicType> of the prototype.
# prototypeRef - A reference to the prototype so far, minus the ender in dispute.
# ender - The ender symbol.
#
# Returns:
#
# ENDER_ACCEPT - The ender is accepted and the prototype is finished.
# ENDER_IGNORE - The ender is rejected and parsing should continue. Note that the prototype will be rejected as a whole
# if all enders are ignored before reaching the end of the code.
# ENDER_ACCEPT_AND_CONTINUE - The ender is accepted so the prototype may stand as is. However, the prototype might
# also continue on so continue parsing. If there is no accepted ender between here and
# the end of the code this version will be accepted instead.
# ENDER_REVERT_TO_ACCEPTED - The expedition from ENDER_ACCEPT_AND_CONTINUE failed. Use the last accepted
# version and end parsing.
#
sub OnPrototypeEnd #(type, prototypeRef, ender)
{
my ($self, $type, $prototypeRef, $ender) = @_;
# _ should be handled already.
if ($ender =~ /^[a-z]+$/i && substr($$prototypeRef, -1) =~ /^[\@\$\#]$/)
{ return ::ENDER_IGNORE(); }
elsif ($type eq ::TOPIC_FUNCTION() && $ender eq ',')
{
if ($$prototypeRef =~ /^[^\(]*\@/)
{ return ::ENDER_IGNORE(); }
else
{ return ::ENDER_ACCEPT(); };
}
else
{ return ::ENDER_ACCEPT(); };
};
#
# Function: ParsePrototype
#
# Overridden to handle Microsoft's parenthesisless version. Otherwise just throws to the parent.
#
# Parameters:
#
# type - The <TopicType>.
# prototype - The text prototype.
#
# Returns:
#
# A <NaturalDocs::Languages::Prototype> object.
#
sub ParsePrototype #(type, prototype)
{
my ($self, $type, $prototype) = @_;
my $noParenthesisParameters = ($type eq ::TOPIC_FUNCTION() && $prototype =~ /^[^\(]*\@/);
if ($prototype !~ /\(.*[^ ].*\)/ && !$noParenthesisParameters)
{ return $self->SUPER::ParsePrototype($type, $prototype); };
my ($beforeParameters, $afterParameters, $isAfterParameters);
if ($noParenthesisParameters)
{
($beforeParameters, $prototype) = split(/\@/, $prototype, 2);
$prototype = '@' . $prototype;
};
my @tokens = $prototype =~ /([^\(\)\[\]\{\}\<\>\'\"\,]+|.)/g;
my $parameter;
my @parameterLines;
my @symbolStack;
foreach my $token (@tokens)
{
if ($isAfterParameters)
{ $afterParameters .= $token; }
elsif ($symbolStack[-1] eq '\'' || $symbolStack[-1] eq '"')
{
if ($noParenthesisParameters || $symbolStack[0] eq '(')
{ $parameter .= $token; }
else
{ $beforeParameters .= $token; };
if ($token eq $symbolStack[-1])
{ pop @symbolStack; };
}
elsif ($token =~ /^[\(\[\{\<\'\"]$/)
{
if ($noParenthesisParameters || $symbolStack[0] eq '(')
{ $parameter .= $token; }
else
{ $beforeParameters .= $token; };
push @symbolStack, $token;
}
elsif ( ($token eq ')' && $symbolStack[-1] eq '(') ||
($token eq ']' && $symbolStack[-1] eq '[') ||
($token eq '}' && $symbolStack[-1] eq '{') ||
($token eq '>' && $symbolStack[-1] eq '<') )
{
if (!$noParenthesisParameters && $token eq ')' && scalar @symbolStack == 1 && $symbolStack[0] eq '(')
{
$afterParameters .= $token;
$isAfterParameters = 1;
}
else
{ $parameter .= $token; };
pop @symbolStack;
}
elsif ($token eq ',')
{
if (!scalar @symbolStack)
{
if ($noParenthesisParameters)
{
push @parameterLines, $parameter . $token;
$parameter = undef;
}
else
{
$beforeParameters .= $token;
};
}
else
{
if (scalar @symbolStack == 1 && $symbolStack[0] eq '(' && !$noParenthesisParameters)
{
push @parameterLines, $parameter . $token;
$parameter = undef;
}
else
{
$parameter .= $token;
};
};
}
else
{
if ($noParenthesisParameters || $symbolStack[0] eq '(')
{ $parameter .= $token; }
else
{ $beforeParameters .= $token; };
};
};
push @parameterLines, $parameter;
foreach my $item (\$beforeParameters, \$afterParameters)
{
$$item =~ s/^ //;
$$item =~ s/ $//;
}
my $prototypeObject = NaturalDocs::Languages::Prototype->New($beforeParameters, $afterParameters);
# Parse the actual parameters.
foreach my $parameterLine (@parameterLines)
{
$prototypeObject->AddParameter( $self->ParseParameterLine($parameterLine) );
};
return $prototypeObject;
};
#
# Function: ParseParameterLine
#
# Parses a prototype parameter line and returns it as a <NaturalDocs::Languages::Prototype::Parameter> object.
#
sub ParseParameterLine #(line)
{
my ($self, $line) = @_;
$line =~ s/^ //;
$line =~ s/ $//;
my @tokens = $line =~ /([^\(\)\[\]\{\}\<\>\'\"\:\=\ ]+|\:\=|.)/g;
my ($name, $type, $defaultValue, $defaultValuePrefix, $inType, $inDefaultValue);
my @symbolStack;
foreach my $token (@tokens)
{
if ($inDefaultValue)
{ $defaultValue .= $token; }
elsif ($symbolStack[-1] eq '\'' || $symbolStack[-1] eq '"')
{
if ($inType)
{ $type .= $token; }
else
{ $name .= $token; };
if ($token eq $symbolStack[-1])
{ pop @symbolStack; };
}
elsif ($token =~ /^[\(\[\{\<\'\"]$/)
{
if ($inType)
{ $type .= $token; }
else
{ $name .= $token; };
push @symbolStack, $token;
}
elsif ( ($token eq ')' && $symbolStack[-1] eq '(') ||
($token eq ']' && $symbolStack[-1] eq '[') ||
($token eq '}' && $symbolStack[-1] eq '{') ||
($token eq '>' && $symbolStack[-1] eq '<') )
{
if ($inType)
{ $type .= $token; }
else
{ $name .= $token; };
pop @symbolStack;
}
elsif ($token eq ' ')
{
if ($inType)
{ $type .= $token; }
elsif (!scalar @symbolStack)
{ $inType = 1; }
else
{ $name .= $token; };
}
elsif ($token eq ':=' || $token eq '=')
{
if (!scalar @symbolStack)
{
$defaultValuePrefix = $token;
$inDefaultValue = 1;
}
elsif ($inType)
{ $type .= $token; }
else
{ $name .= $token; };
}
else
{
if ($inType)
{ $type .= $token; }
else
{ $name .= $token; };
};
};
foreach my $part (\$type, \$defaultValue)
{
$$part =~ s/ $//;
};
return NaturalDocs::Languages::Prototype::Parameter->New($type, undef, $name, undef, $defaultValue, $defaultValuePrefix);
};
sub TypeBeforeParameter
{ return 0; };
1;

View file

@ -1,143 +0,0 @@
###############################################################################
#
# Class: NaturalDocs::Languages::Pascal
#
###############################################################################
#
# A subclass to handle the language variations of Pascal and Delphi.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
package NaturalDocs::Languages::Pascal;
use base 'NaturalDocs::Languages::Simple';
#
# hash: prototypeDirectives
#
# An existence hash of all the directives that can appear after a function prototype and will be included. The keys are the all
# lowercase keywords.
#
my %prototypeDirectives = ( 'overload' => 1,
'override' => 1,
'virtual' => 1,
'abstract' => 1,
'reintroduce' => 1,
'export' => 1,
'public' => 1,
'interrupt' => 1,
'register' => 1,
'pascal' => 1,
'cdecl' => 1,
'stdcall' => 1,
'popstack' => 1,
'saveregisters' => 1,
'inline' => 1,
'safecall' => 1 );
#
# hash: longPrototypeDirectives
#
# An existence hash of all the directives with parameters that can appear after a function prototype and will be included. The
# keys are the all lowercase keywords.
#
my %longPrototypeDirectives = ( 'alias' => 1,
'external' => 1 );
#
# bool: checkingForDirectives
#
# Set after the first function semicolon, which means we're in directives mode.
#
my $checkingForDirectives;
#
# Function: OnCode
#
# Just overridden to reset <checkingForDirectives>.
#
sub OnCode #(...)
{
my ($self, @parameters) = @_;
$checkingForDirectives = 0;
return $self->SUPER::OnCode(@parameters);
};
#
# Function: OnPrototypeEnd
#
# Pascal's syntax has directives after the prototype that should be included.
#
# > function MyFunction ( param1: type ); virtual; abstract;
#
# Parameters:
#
# type - The <TopicType> of the prototype.
# prototypeRef - A reference to the prototype so far, minus the ender in dispute.
# ender - The ender symbol.
#
# Returns:
#
# ENDER_ACCEPT - The ender is accepted and the prototype is finished.
# ENDER_IGNORE - The ender is rejected and parsing should continue. Note that the prototype will be rejected as a whole
# if all enders are ignored before reaching the end of the code.
# ENDER_ACCEPT_AND_CONTINUE - The ender is accepted so the prototype may stand as is. However, the prototype might
# also continue on so continue parsing. If there is no accepted ender between here and
# the end of the code this version will be accepted instead.
# ENDER_REVERT_TO_ACCEPTED - The expedition from ENDER_ACCEPT_AND_CONTINUE failed. Use the last accepted
# version and end parsing.
#
sub OnPrototypeEnd #(type, prototypeRef, ender)
{
my ($self, $type, $prototypeRef, $ender) = @_;
if ($type eq ::TOPIC_FUNCTION() && $ender eq ';')
{
if (!$checkingForDirectives)
{
$checkingForDirectives = 1;
return ::ENDER_ACCEPT_AND_CONTINUE();
}
elsif ($$prototypeRef =~ /;[ \t]*([a-z]+)([^;]*)$/i)
{
my ($lastDirective, $extra) = (lc($1), $2);
if (exists $prototypeDirectives{$lastDirective} && $extra =~ /^[ \t]*$/)
{ return ::ENDER_ACCEPT_AND_CONTINUE(); }
elsif (exists $longPrototypeDirectives{$lastDirective})
{ return ::ENDER_ACCEPT_AND_CONTINUE(); }
else
{ return ::ENDER_REVERT_TO_ACCEPTED(); };
}
else
{ return ::ENDER_REVERT_TO_ACCEPTED(); };
}
else
{ return ::ENDER_ACCEPT(); };
};
sub ParseParameterLine #(...)
{
my ($self, @params) = @_;
return $self->SUPER::ParsePascalParameterLine(@params);
};
sub TypeBeforeParameter
{
return 0;
};
1;

File diff suppressed because it is too large Load diff

View file

@ -1,92 +0,0 @@
###############################################################################
#
# Class: NaturalDocs::Languages::Prototype
#
###############################################################################
#
# A data class for storing parsed prototypes.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
use NaturalDocs::Languages::Prototype::Parameter;
package NaturalDocs::Languages::Prototype;
use NaturalDocs::DefineMembers 'BEFORE_PARAMETERS', 'BeforeParameters()', 'SetBeforeParameters()',
'AFTER_PARAMETERS', 'AfterParameters()', 'SetAfterParameters()',
'PARAMETERS', 'Parameters()';
# Dependency: New(), constant order, no parents.
#
# Function: New
#
# Creates and returns a new prototype object.
#
# Parameters:
#
# beforeParameters - The part of the prototype before the parameter list.
# afterParameters - The part of the prototype after the parameter list.
#
# You cannot set the parameters from here. Use <AddParameter()>.
#
sub New #(beforeParameters, afterParameters)
{
my ($package, @params) = @_;
# Dependency: Constant order, no parents.
my $object = [ @params ];
bless $object, $package;
return $object;
};
#
# Functions: Members
#
# BeforeParameters - Returns the part of the prototype before the parameter list. If there is no parameter list, this will be the
# only thing that returns content.
# SetBeforeParameters - Replaces the part of the prototype before the parameter list.
# AfterParameters - Returns the part of the prototype after the parameter list, if any.
# SetAfterParameters - Replaces the part of the prototype after the parameter list.
# Parameters - Returns the parameter list as an arrayref of <NaturalDocs::Languages::Prototype::Parameters>, or undef if none.
#
#
# Function: AddParameter
#
# Adds a <NaturalDocs::Languages::Prototype::Parameter> to the list.
#
sub AddParameter #(parameter)
{
my ($self, $parameter) = @_;
if (!defined $self->[PARAMETERS])
{ $self->[PARAMETERS] = [ ]; };
push @{$self->[PARAMETERS]}, $parameter;
};
#
# Function: OnlyBeforeParameters
#
# Returns whether <BeforeParameters()> is the only thing set.
#
sub OnlyBeforeParameters
{
my $self = shift;
return (!defined $self->[PARAMETERS] && !defined $self->[AFTER_PARAMETERS]);
};
1;

View file

@ -1,87 +0,0 @@
###############################################################################
#
# Class: NaturalDocs::Languages::Prototype::Parameter
#
###############################################################################
#
# A data class for storing parsed prototype parameters.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
package NaturalDocs::Languages::Prototype::Parameter;
use NaturalDocs::DefineMembers 'TYPE', 'Type()', 'SetType()',
'TYPE_PREFIX', 'TypePrefix()', 'SetTypePrefix()',
'NAME', 'Name()', 'SetName()',
'NAME_PREFIX', 'NamePrefix()', 'SetNamePrefix()',
'DEFAULT_VALUE', 'DefaultValue()', 'SetDefaultValue()',
'DEFAULT_VALUE_PREFIX', 'DefaultValuePrefix()', 'SetDefaultValuePrefix()';
# Dependency: New() depends on the order of these constants and that they don't inherit from another class.
#
# Constants: Members
#
# The object is implemented as a blessed arrayref, with the following constants as its indexes.
#
# TYPE - The parameter type, if any.
# TYPE_PREFIX - The parameter type prefix which should be aligned separately, if any.
# NAME - The parameter name.
# NAME_PREFIX - The parameter name prefix which should be aligned separately, if any.
# DEFAULT_VALUE - The default value expression, if any.
# DEFAULT_VALUE_PREFIX - The default value prefix which should be aligned separately, if any.
#
#
# Function: New
#
# Creates and returns a new prototype object.
#
# Parameters:
#
# type - The parameter type, if any.
# typePrefix - The parameter type prefix which should be aligned separately, if any.
# name - The parameter name.
# namePrefix - The parameter name prefix which should be aligned separately, if any.
# defaultValue - The default value expression, if any.
# defaultValuePrefix - The default value prefix which should be aligned separately, if any.
#
sub New #(type, typePrefix, name, namePrefix, defaultValue, defaultValuePrefix)
{
my ($package, @params) = @_;
# Dependency: This depends on the order of the parameters being the same as the order of the constants, and that the
# constants don't inherit from another class.
my $object = [ @params ];
bless $object, $package;
return $object;
};
#
# Functions: Members
#
# Type - The parameter type, if any.
# SetType - Replaces the parameter type.
# TypePrefix - The parameter type prefix, which should be aligned separately, if any.
# SetTypePrefix - Replaces the parameter type prefix.
# Name - The parameter name.
# SetName - Replaces the parameter name.
# NamePrefix - The parameter name prefix, which should be aligned separately, if any.
# SetNamePrefix - Replaces the parameter name prefix.
# DefaultValue - The default value expression, if any.
# SetDefaultValue - Replaces the default value expression.
# DefaultValuePrefix - The default value prefix, which should be aligned separately, if any.
# SetDefaultValuePrefix - Replaces the default value prefix.
#
1;

View file

@ -1,503 +0,0 @@
###############################################################################
#
# Class: NaturalDocs::Languages::Simple
#
###############################################################################
#
# A class containing the characteristics of a particular programming language for basic support within Natural Docs.
# Also serves as a base class for languages that break from general conventions, such as not having parameter lists use
# parenthesis and commas.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
package NaturalDocs::Languages::Simple;
use base 'NaturalDocs::Languages::Base';
use base 'Exporter';
our @EXPORT = ( 'ENDER_ACCEPT', 'ENDER_IGNORE', 'ENDER_ACCEPT_AND_CONTINUE', 'ENDER_REVERT_TO_ACCEPTED' );
use NaturalDocs::DefineMembers 'LINE_COMMENT_SYMBOLS', 'LineCommentSymbols()', 'SetLineCommentSymbols() duparrayref',
'BLOCK_COMMENT_SYMBOLS', 'BlockCommentSymbols()',
'SetBlockCommentSymbols() duparrayref',
'PROTOTYPE_ENDERS',
'LINE_EXTENDER', 'LineExtender()', 'SetLineExtender()',
'PACKAGE_SEPARATOR', 'PackageSeparator()',
'PACKAGE_SEPARATOR_WAS_SET', 'PackageSeparatorWasSet()',
'ENUM_VALUES', 'EnumValues()',
'ENUM_VALUES_WAS_SET', 'EnumValuesWasSet()';
#
# Function: New
#
# Creates and returns a new object.
#
# Parameters:
#
# name - The name of the language.
#
sub New #(name)
{
my ($selfPackage, $name) = @_;
my $object = $selfPackage->SUPER::New($name);
$object->[ENUM_VALUES] = ::ENUM_GLOBAL();
$object->[PACKAGE_SEPARATOR] = '.';
return $object;
};
#
# Functions: Members
#
# LineCommentSymbols - Returns an arrayref of symbols that start a line comment, or undef if none.
# SetLineCommentSymbols - Replaces the arrayref of symbols that start a line comment.
# BlockCommentSymbols - Returns an arrayref of start/end symbol pairs that specify a block comment, or undef if none. Pairs
# are specified with two consecutive array entries.
# SetBlockCommentSymbols - Replaces the arrayref of start/end symbol pairs that specify a block comment. Pairs are
# specified with two consecutive array entries.
# LineExtender - Returns the symbol to ignore a line break in languages where line breaks are significant.
# SetLineExtender - Replaces the symbol to ignore a line break in languages where line breaks are significant.
# PackageSeparator - Returns the package separator symbol.
# PackageSeparatorWasSet - Returns whether the package separator symbol was ever changed from the default.
#
#
# Function: SetPackageSeparator
# Replaces the language's package separator string.
#
sub SetPackageSeparator #(separator)
{
my ($self, $separator) = @_;
$self->[PACKAGE_SEPARATOR] = $separator;
$self->[PACKAGE_SEPARATOR_WAS_SET] = 1;
};
#
# Functions: Members
#
# EnumValues - Returns the <EnumValuesType> that describes how the language handles enums.
# EnumValuesWasSet - Returns whether <EnumValues> was ever changed from the default.
#
# Function: SetEnumValues
# Replaces the <EnumValuesType> that describes how the language handles enums.
#
sub SetEnumValues #(EnumValuesType newBehavior)
{
my ($self, $behavior) = @_;
$self->[ENUM_VALUES] = $behavior;
$self->[ENUM_VALUES_WAS_SET] = 1;
};
#
# Function: PrototypeEndersFor
#
# Returns an arrayref of prototype ender symbols for the passed <TopicType>, or undef if none.
#
sub PrototypeEndersFor #(type)
{
my ($self, $type) = @_;
if (defined $self->[PROTOTYPE_ENDERS])
{ return $self->[PROTOTYPE_ENDERS]->{$type}; }
else
{ return undef; };
};
#
# Function: SetPrototypeEndersFor
#
# Replaces the arrayref of prototype ender symbols for the passed <TopicType>.
#
sub SetPrototypeEndersFor #(type, enders)
{
my ($self, $type, $enders) = @_;
if (!defined $self->[PROTOTYPE_ENDERS])
{ $self->[PROTOTYPE_ENDERS] = { }; };
if (!defined $enders)
{ delete $self->[PROTOTYPE_ENDERS]->{$type}; }
else
{
$self->[PROTOTYPE_ENDERS]->{$type} = [ @$enders ];
};
};
###############################################################################
# Group: Parsing Functions
#
# Function: ParseFile
#
# Parses the passed source file, sending comments acceptable for documentation to <NaturalDocs::Parser->OnComment()>
# and all other sections to <OnCode()>.
#
# Parameters:
#
# sourceFile - The <FileName> of the source file to parse.
# topicList - A reference to the list of <NaturalDocs::Parser::ParsedTopics> being built by the file.
#
# Returns:
#
# Since this class cannot automatically document the code or generate a scope record, it always returns ( undef, undef ).
#
sub ParseFile #(sourceFile, topicsList)
{
my ($self, $sourceFile, $topicsList) = @_;
open(SOURCEFILEHANDLE, '<' . $sourceFile)
or die "Couldn't open input file " . $sourceFile . "\n";
my @commentLines;
my @codeLines;
my $lastCommentTopicCount = 0;
if ($self->Name() eq 'Text File')
{
my $line = <SOURCEFILEHANDLE>;
# On the very first line, remove a Unicode BOM if present. Information on it available at:
# http://www.unicode.org/faq/utf_bom.html#BOM
$line =~ s/^\xEF\xBB\xBF//;
while ($line)
{
::XChomp(\$line);
push @commentLines, $line;
$line = <SOURCEFILEHANDLE>;
};
NaturalDocs::Parser->OnComment(\@commentLines, 1);
}
else
{
my $line = <SOURCEFILEHANDLE>;
my $lineNumber = 1;
# On the very first line, remove a Unicode BOM if present. Information on it available at:
# http://www.unicode.org/faq/utf_bom.html#BOM
$line =~ s/^\xEF\xBB\xBF//;
while (defined $line)
{
::XChomp(\$line);
my $originalLine = $line;
# Retrieve single line comments. This leaves $line at the next line.
if ($self->StripOpeningSymbols(\$line, $self->LineCommentSymbols()))
{
do
{
push @commentLines, $line;
$line = <SOURCEFILEHANDLE>;
if (!defined $line)
{ goto EndDo; };
::XChomp(\$line);
}
while ($self->StripOpeningSymbols(\$line, $self->LineCommentSymbols()));
EndDo: # I hate Perl sometimes.
}
# Retrieve multiline comments. This leaves $line at the next line.
elsif (my $closingSymbol = $self->StripOpeningBlockSymbols(\$line, $self->BlockCommentSymbols()))
{
# Note that it is possible for a multiline comment to start correctly but not end so. We want those comments to stay in
# the code. For example, look at this prototype with this splint annotation:
#
# int get_array(integer_t id,
# /*@out@*/ array_t array);
#
# The annotation starts correctly but doesn't end so because it is followed by code on the same line.
my $lineRemainder;
for (;;)
{
$lineRemainder = $self->StripClosingSymbol(\$line, $closingSymbol);
push @commentLines, $line;
# If we found an end comment symbol...
if (defined $lineRemainder)
{ last; };
$line = <SOURCEFILEHANDLE>;
if (!defined $line)
{ last; };
::XChomp(\$line);
};
if ($lineRemainder !~ /^[ \t]*$/)
{
# If there was something past the closing symbol this wasn't an acceptable comment, so move the lines to code.
push @codeLines, @commentLines;
@commentLines = ( );
};
$line = <SOURCEFILEHANDLE>;
}
# Otherwise just add it to the code.
else
{
push @codeLines, $line;
$line = <SOURCEFILEHANDLE>;
};
# If there were comments, send them to Parser->OnComment().
if (scalar @commentLines)
{
# First process any code lines before the comment.
if (scalar @codeLines)
{
$self->OnCode(\@codeLines, $lineNumber, $topicsList, $lastCommentTopicCount);
$lineNumber += scalar @codeLines;
@codeLines = ( );
};
$lastCommentTopicCount = NaturalDocs::Parser->OnComment(\@commentLines, $lineNumber);
$lineNumber += scalar @commentLines;
@commentLines = ( );
};
}; # while (defined $line)
# Clean up any remaining code.
if (scalar @codeLines)
{
$self->OnCode(\@codeLines, $lineNumber, $topicsList, $lastCommentTopicCount);
@codeLines = ( );
};
};
close(SOURCEFILEHANDLE);
return ( undef, undef );
};
#
# Function: OnCode
#
# Called whenever a section of code is encountered by the parser. Is used to find the prototype of the last topic created.
#
# Parameters:
#
# codeLines - The source code as an arrayref of lines.
# codeLineNumber - The line number of the first line of code.
# topicList - A reference to the list of <NaturalDocs::Parser::ParsedTopics> being built by the file.
# lastCommentTopicCount - The number of Natural Docs topics that were created by the last comment.
#
sub OnCode #(codeLines, codeLineNumber, topicList, lastCommentTopicCount)
{
my ($self, $codeLines, $codeLineNumber, $topicList, $lastCommentTopicCount) = @_;
if ($lastCommentTopicCount && defined $self->PrototypeEndersFor($topicList->[-1]->Type()))
{
my $lineIndex = 0;
my $prototype;
# Skip all blank lines before a prototype.
while ($lineIndex < scalar @$codeLines && $codeLines->[$lineIndex] =~ /^[ \t]*$/)
{ $lineIndex++; };
my @tokens;
my $tokenIndex = 0;
my @brackets;
my $enders = $self->PrototypeEndersFor($topicList->[-1]->Type());
# Add prototype lines until we reach the end of the prototype or the end of the code lines.
while ($lineIndex < scalar @$codeLines)
{
my $line = $self->RemoveLineExtender($codeLines->[$lineIndex] . "\n");
push @tokens, $line =~ /([^\(\)\[\]\{\}\<\>]+|.)/g;
while ($tokenIndex < scalar @tokens)
{
# If we're not inside brackets, check for ender symbols.
if (!scalar @brackets)
{
my $startingIndex = 0;
my $testPrototype;
for (;;)
{
my ($enderIndex, $ender) = ::FindFirstSymbol($tokens[$tokenIndex], $enders, $startingIndex);
if ($enderIndex == -1)
{ last; }
else
{
# We do this here so we don't duplicate prototype for every single token. Just the first time an ender symbol
# is found in one.
if (!defined $testPrototype)
{ $testPrototype = $prototype; };
$testPrototype .= substr($tokens[$tokenIndex], $startingIndex, $enderIndex - $startingIndex);
my $enderResult;
# If the ender is all text and the character preceding or following it is as well, ignore it.
if ($ender =~ /^[a-z0-9]+$/i &&
( ($enderIndex > 0 && substr($tokens[$tokenIndex], $enderIndex - 1, 1) =~ /^[a-z0-9_]$/i) ||
substr($tokens[$tokenIndex], $enderIndex + length($ender), 1) =~ /^[a-z0-9_]$/i ) )
{ $enderResult = ENDER_IGNORE(); }
else
{ $enderResult = $self->OnPrototypeEnd($topicList->[-1]->Type(), \$testPrototype, $ender); }
if ($enderResult == ENDER_IGNORE())
{
$testPrototype .= $ender;
$startingIndex = $enderIndex + length($ender);
}
elsif ($enderResult == ENDER_REVERT_TO_ACCEPTED())
{
return;
}
else # ENDER_ACCEPT || ENDER_ACCEPT_AND_CONTINUE
{
my $titleInPrototype = $topicList->[-1]->Title();
# Strip parenthesis so Function(2) and Function(int, int) will still match Function(anything).
$titleInPrototype =~ s/[\t ]*\([^\(]*$//;
if (index($testPrototype, $titleInPrototype) != -1)
{
$topicList->[-1]->SetPrototype( $self->NormalizePrototype($testPrototype) );
};
if ($enderResult == ENDER_ACCEPT())
{ return; }
else # ENDER_ACCEPT_AND_CONTINUE
{
$testPrototype .= $ender;
$startingIndex = $enderIndex + length($ender);
};
};
};
};
}
# If we are inside brackets, check for closing symbols.
elsif ( ($tokens[$tokenIndex] eq ')' && $brackets[-1] eq '(') ||
($tokens[$tokenIndex] eq ']' && $brackets[-1] eq '[') ||
($tokens[$tokenIndex] eq '}' && $brackets[-1] eq '{') ||
($tokens[$tokenIndex] eq '>' && $brackets[-1] eq '<') )
{
pop @brackets;
};
# Check for opening brackets.
if ($tokens[$tokenIndex] =~ /^[\(\[\{\<]$/)
{
push @brackets, $tokens[$tokenIndex];
};
$prototype .= $tokens[$tokenIndex];
$tokenIndex++;
};
$lineIndex++;
};
# If we got out of that while loop by running out of lines, there was no prototype.
};
};
use constant ENDER_ACCEPT => 1;
use constant ENDER_IGNORE => 2;
use constant ENDER_ACCEPT_AND_CONTINUE => 3;
use constant ENDER_REVERT_TO_ACCEPTED => 4;
#
# Function: OnPrototypeEnd
#
# Called whenever the end of a prototype is found so that there's a chance for derived classes to mark false positives.
#
# Parameters:
#
# type - The <TopicType> of the prototype.
# prototypeRef - A reference to the prototype so far, minus the ender in dispute.
# ender - The ender symbol.
#
# Returns:
#
# ENDER_ACCEPT - The ender is accepted and the prototype is finished.
# ENDER_IGNORE - The ender is rejected and parsing should continue. Note that the prototype will be rejected as a whole
# if all enders are ignored before reaching the end of the code.
# ENDER_ACCEPT_AND_CONTINUE - The ender is accepted so the prototype may stand as is. However, the prototype might
# also continue on so continue parsing. If there is no accepted ender between here and
# the end of the code this version will be accepted instead.
# ENDER_REVERT_TO_ACCEPTED - The expedition from ENDER_ACCEPT_AND_CONTINUE failed. Use the last accepted
# version and end parsing.
#
sub OnPrototypeEnd #(type, prototypeRef, ender)
{
return ENDER_ACCEPT();
};
#
# Function: RemoveLineExtender
#
# If the passed line has a line extender, returns it without the extender or the line break that follows. If it doesn't, or there are
# no line extenders defined, returns the passed line unchanged.
#
sub RemoveLineExtender #(line)
{
my ($self, $line) = @_;
if (defined $self->LineExtender())
{
my $lineExtenderIndex = rindex($line, $self->LineExtender());
if ($lineExtenderIndex != -1 &&
substr($line, $lineExtenderIndex + length($self->LineExtender())) =~ /^[ \t]*\n$/)
{
$line = substr($line, 0, $lineExtenderIndex) . ' ';
};
};
return $line;
};
1;

View file

@ -1,219 +0,0 @@
###############################################################################
#
# Class: NaturalDocs::Languages::Tcl
#
###############################################################################
#
# A subclass to handle the language variations of Tcl.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
package NaturalDocs::Languages::Tcl;
use base 'NaturalDocs::Languages::Simple';
#
# bool: pastFirstBrace
#
# Whether we've past the first brace in a function prototype or not.
#
my $pastFirstBrace;
#
# Function: OnCode
#
# This is just overridden to reset <pastFirstBrace>.
#
sub OnCode #(...)
{
my ($self, @params) = @_;
$pastFirstBrace = 0;
return $self->SUPER::OnCode(@params);
};
#
# Function: OnPrototypeEnd
#
# Tcl's function syntax is shown below.
#
# > proc [name] { [params] } { [code] }
#
# The opening brace is one of the prototype enders. We need to allow the first opening brace because it contains the
# parameters.
#
# Also, the parameters may have braces within them. I've seen one that used { seconds 20 } as a parameter.
#
# Parameters:
#
# type - The <TopicType> of the prototype.
# prototypeRef - A reference to the prototype so far, minus the ender in dispute.
# ender - The ender symbol.
#
# Returns:
#
# ENDER_ACCEPT - The ender is accepted and the prototype is finished.
# ENDER_IGNORE - The ender is rejected and parsing should continue. Note that the prototype will be rejected as a whole
# if all enders are ignored before reaching the end of the code.
# ENDER_ACCEPT_AND_CONTINUE - The ender is accepted so the prototype may stand as is. However, the prototype might
# also continue on so continue parsing. If there is no accepted ender between here and
# the end of the code this version will be accepted instead.
# ENDER_REVERT_TO_ACCEPTED - The expedition from ENDER_ACCEPT_AND_CONTINUE failed. Use the last accepted
# version and end parsing.
#
sub OnPrototypeEnd #(type, prototypeRef, ender)
{
my ($self, $type, $prototypeRef, $ender) = @_;
if ($type eq ::TOPIC_FUNCTION() && $ender eq '{' && !$pastFirstBrace)
{
$pastFirstBrace = 1;
return ::ENDER_IGNORE();
}
else
{ return ::ENDER_ACCEPT(); };
};
#
# Function: ParsePrototype
#
# Parses the prototype and returns it as a <NaturalDocs::Languages::Prototype> object.
#
# Parameters:
#
# type - The <TopicType>.
# prototype - The text prototype.
#
# Returns:
#
# A <NaturalDocs::Languages::Prototype> object.
#
sub ParsePrototype #(type, prototype)
{
my ($self, $type, $prototype) = @_;
if ($type ne ::TOPIC_FUNCTION())
{
my $object = NaturalDocs::Languages::Prototype->New($prototype);
return $object;
};
# Parse the parameters out of the prototype.
my @tokens = $prototype =~ /([^\{\}\ ]+|.)/g;
my $parameter;
my @parameterLines;
my $braceLevel = 0;
my ($beforeParameters, $afterParameters, $finishedParameters);
foreach my $token (@tokens)
{
if ($finishedParameters)
{ $afterParameters .= $token; }
elsif ($token eq '{')
{
if ($braceLevel == 0)
{ $beforeParameters .= $token; }
else # braceLevel > 0
{ $parameter .= $token; };
$braceLevel++;
}
elsif ($token eq '}')
{
if ($braceLevel == 1)
{
if ($parameter && $parameter ne ' ')
{ push @parameterLines, $parameter; };
$finishedParameters = 1;
$afterParameters .= $token;
$braceLevel--;
}
elsif ($braceLevel > 1)
{
$parameter .= $token;
$braceLevel--;
};
}
elsif ($token eq ' ')
{
if ($braceLevel == 1)
{
if ($parameter)
{ push @parameterLines, $parameter; };
$parameter = undef;
}
elsif ($braceLevel > 1)
{
$parameter .= $token;
}
else
{
$beforeParameters .= $token;
};
}
else
{
if ($braceLevel > 0)
{ $parameter .= $token; }
else
{ $beforeParameters .= $token; };
};
};
foreach my $part (\$beforeParameters, \$afterParameters)
{
$$part =~ s/^ //;
$$part =~ s/ $//;
};
my $prototypeObject = NaturalDocs::Languages::Prototype->New($beforeParameters, $afterParameters);
# Parse the actual parameters.
foreach my $parameterLine (@parameterLines)
{
$prototypeObject->AddParameter( $self->ParseParameterLine($parameterLine) );
};
return $prototypeObject;
};
#
# Function: ParseParameterLine
#
# Parses a prototype parameter line and returns it as a <NaturalDocs::Languages::Prototype::Parameter> object.
#
sub ParseParameterLine #(line)
{
my ($self, $line) = @_;
return NaturalDocs::Languages::Prototype::Parameter->New(undef, undef, $line, undef, undef, undef);
};
1;

File diff suppressed because it is too large Load diff

View file

@ -1,201 +0,0 @@
###############################################################################
#
# Package: NaturalDocs::Menu::Entry
#
###############################################################################
#
# A class representing an entry in the menu.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
package NaturalDocs::Menu::Entry;
###############################################################################
# Group: Implementation
#
# Constants: Members
#
# The object is implemented as a blessed arrayref with the indexes below.
#
# TYPE - The <MenuEntryType>
# TITLE - The title of the entry.
# TARGET - The target of the entry. If the type is <MENU_FILE>, it will be the source <FileName>. If the type is
# <MENU_LINK>, it will be the URL. If the type is <MENU_GROUP>, it will be an arrayref of
# <NaturalDocs::Menu::Entry> objects representing the group's content. If the type is <MENU_INDEX>, it will be
# a <TopicType>.
# FLAGS - Any <Menu Entry Flags> that apply.
#
use constant TYPE => 0;
use constant TITLE => 1;
use constant TARGET => 2;
use constant FLAGS => 3;
# DEPENDENCY: New() depends on the order of these constants.
###############################################################################
# Group: Functions
#
# Function: New
#
# Creates and returns a new object.
#
# Parameters:
#
# type - The <MenuEntryType>.
# title - The title of the entry.
# target - The target of the entry, if applicable. If the type is <MENU_FILE>, use the source <FileName>. If the type is
# <MENU_LINK>, use the URL. If the type is <MENU_INDEX>, use the <TopicType>. Otherwise set it to undef.
# flags - Any <Menu Entry Flags> that apply.
#
sub New #(type, title, target, flags)
{
# DEPENDENCY: This gode depends on the order of the constants.
my $package = shift;
my $object = [ @_ ];
bless $object, $package;
if ($object->[TYPE] == ::MENU_GROUP())
{ $object->[TARGET] = [ ]; };
if (!defined $object->[FLAGS])
{ $object->[FLAGS] = 0; };
return $object;
};
# Function: Type
# Returns the <MenuEntryType>.
sub Type
{ return $_[0]->[TYPE]; };
# Function: Title
# Returns the title of the entry.
sub Title
{ return $_[0]->[TITLE]; };
# Function: SetTitle
# Replaces the entry's title.
sub SetTitle #(title)
{ $_[0]->[TITLE] = $_[1]; };
#
# Function: Target
#
# Returns the target of the entry, if applicable. If the type is <MENU_FILE>, it returns the source <FileName>. If the type is
# <MENU_LINK>, it returns the URL. If the type is <MENU_INDEX>, it returns the <TopicType>. Otherwise it returns undef.
#
sub Target
{
my $self = shift;
# Group entries are the only time when target won't be undef when it should be.
if ($self->Type() == ::MENU_GROUP())
{ return undef; }
else
{ return $self->[TARGET]; };
};
# Function: SetTarget
# Replaces the entry's target.
sub SetTarget #(target)
{ $_[0]->[TARGET] = $_[1]; };
# Function: Flags
# Returns the <Menu Entry Flags>.
sub Flags
{ return $_[0]->[FLAGS]; };
# Function: SetFlags
# Replaces the <Menu Entry Flags>.
sub SetFlags #(flags)
{ $_[0]->[FLAGS] = $_[1]; };
###############################################################################
# Group: Group Functions
#
# All of these functions assume the type is <MENU_GROUP>. Do *not* call any of these without checking <Type()> first.
#
# Function: GroupContent
#
# Returns an arrayref of <NaturalDocs::Menu::Entry> objects representing the contents of the
# group, or undef otherwise. This arrayref will always exist for <MENU_GROUP>'s and can be changed.
#
sub GroupContent
{
return $_[0]->[TARGET];
};
#
# Function: GroupIsEmpty
#
# If the type is <MENU_GROUP>, returns whether the group is empty.
#
sub GroupIsEmpty
{
my $self = shift;
return (scalar @{$self->GroupContent()} > 0);
};
#
# Function: PushToGroup
#
# Pushes the entry to the end of the group content.
#
sub PushToGroup #(entry)
{
my ($self, $entry) = @_;
push @{$self->GroupContent()}, $entry;
};
#
# Function: DeleteFromGroup
#
# Deletes an entry from the group content by index.
#
sub DeleteFromGroup #(index)
{
my ($self, $index) = @_;
my $groupContent = $self->GroupContent();
splice( @$groupContent, $index, 1 );
};
#
# Function: MarkEndOfOriginal
#
# If the group doesn't already have one, adds a <MENU_ENDOFORIGINAL> entry to the end and sets the
# <MENU_GROUP_HASENDOFORIGINAL> flag.
#
sub MarkEndOfOriginal
{
my $self = shift;
if (($self->Flags() & ::MENU_GROUP_HASENDOFORIGINAL()) == 0)
{
$self->PushToGroup( NaturalDocs::Menu::Entry->New(::MENU_ENDOFORIGINAL(), undef, undef, undef) );
$self->SetFlags( $self->Flags() | ::MENU_GROUP_HASENDOFORIGINAL() );
};
};
1;

View file

@ -1,76 +0,0 @@
###############################################################################
#
# Package: NaturalDocs::NDMarkup
#
###############################################################################
#
# A package of support functions for dealing with <NDMarkup>.
#
# Usage and Dependencies:
#
# The package doesn't depend on any Natural Docs packages and is ready to use right away.
#
###############################################################################
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
# Natural Docs is licensed under the GPL
use strict;
use integer;
package NaturalDocs::NDMarkup;
#
# Function: ConvertAmpChars
#
# Substitutes certain characters with their <NDMarkup> amp chars.
#
# Parameters:
#
# text - The block of text to convert.
#
# Returns:
#
# The converted text block.
#
sub ConvertAmpChars #(text)
{
my ($self, $text) = @_;
$text =~ s/&/&amp;/g;
$text =~ s/</&lt;/g;
$text =~ s/>/&gt;/g;
$text =~ s/\"/&quot;/g;
return $text;
};
#
# Function: RestoreAmpChars
#
# Replaces <NDMarkup> amp chars with their original symbols.
#
# Parameters:
#
# text - The text to restore.
#
# Returns:
#
# The restored text.
#
sub RestoreAmpChars #(text)
{
my ($self, $text) = @_;
$text =~ s/&quot;/\"/g;
$text =~ s/&gt;/>/g;
$text =~ s/&lt;/</g;
$text =~ s/&amp;/&/g;
return $text;
};
1;

Some files were not shown because too many files have changed in this diff Show more