From a93fd928812d8ac28b39a39b3a1e80b6b9e967f8 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Sun, 1 Feb 2015 13:57:30 -0500 Subject: [PATCH] Import code. --- Jamfile | 6 + Jamrules | 55 + bepodder_podcasts.opml | 2862 ++++++++++++ build/BuildSettings | 127 + build/ConfigRules | 146 + build/HelperRules | 51 + build/MainBuildRules | 427 ++ build/OverriddenJamRules | 214 + build/UserBuildConfig | 61 + build/UserBuildConfig.sample | 61 + documents/ChangeLog.txt | 52 + documents/Difference_between_version.txt | 124 + documents/Releases | 22 + documents/comunicati_comunity.txt | 80 + documents/elenco_clienti.txt | 233 + documents/email_betatester.txt | 49 + documents/email_user.txt | 16 + ...feeds_per_prove_su_formati_particolari.txt | 7 + documents/license.txt | 20 + ...y_internazionali_di_podcast_e_RSS_feed.txt | 25 + documents/lista_siti_di_news.txt | 26 + gfx/100/add-channel-button.png | Bin 0 -> 3104 bytes gfx/100/add-channel-file.png | Bin 0 -> 2786 bytes gfx/100/add-item-button.png | Bin 0 -> 2769 bytes gfx/100/add-item-file.png | Bin 0 -> 2571 bytes gfx/100/bepodder-logo1.png | Bin 0 -> 3931 bytes gfx/100/bepodder-logo2.png | Bin 0 -> 4575 bytes gfx/100/channel-button.png | Bin 0 -> 2224 bytes gfx/100/channel-file.png | Bin 0 -> 2118 bytes gfx/100/delete-channel-button.png | Bin 0 -> 3695 bytes gfx/100/delete-channel-file.png | Bin 0 -> 3467 bytes gfx/100/delete-item-button.png | Bin 0 -> 3413 bytes gfx/100/delete-item-file.png | Bin 0 -> 3238 bytes gfx/100/done-channel-button.png | Bin 0 -> 3437 bytes gfx/100/done-channel-file.png | Bin 0 -> 3257 bytes gfx/100/done-item-button.png | Bin 0 -> 3190 bytes gfx/100/done-item-file.png | Bin 0 -> 3036 bytes gfx/100/download-channel-button.png | Bin 0 -> 3031 bytes gfx/100/download-channel-file.png | Bin 0 -> 2764 bytes gfx/100/download-item-button.png | Bin 0 -> 2749 bytes gfx/100/download-item-file.png | Bin 0 -> 2550 bytes gfx/100/emblem-add.png | Bin 0 -> 794 bytes gfx/100/emblem-delete.png | Bin 0 -> 1366 bytes gfx/100/emblem-done.png | Bin 0 -> 1138 bytes gfx/100/emblem-download.png | Bin 0 -> 835 bytes gfx/100/emblem-enqueued.png | Bin 0 -> 1218 bytes gfx/100/emblem-error.png | Bin 0 -> 792 bytes gfx/100/emblem-kill.png | Bin 0 -> 1589 bytes gfx/100/emblem-play.png | Bin 0 -> 1179 bytes gfx/100/emblem-refresh.png | Bin 0 -> 1523 bytes gfx/100/emblem-remove.png | Bin 0 -> 475 bytes gfx/100/emblem-stop.png | Bin 0 -> 1293 bytes gfx/100/emblem-www.png | Bin 0 -> 1345 bytes gfx/100/enqueued-channel-button.png | Bin 0 -> 3498 bytes gfx/100/enqueued-channel-file.png | Bin 0 -> 3249 bytes gfx/100/enqueued-item-button.png | Bin 0 -> 3289 bytes gfx/100/enqueued-item-file.png | Bin 0 -> 3022 bytes gfx/100/error-channel-button.png | Bin 0 -> 2968 bytes gfx/100/error-channel-file.png | Bin 0 -> 2752 bytes gfx/100/error-item-button.png | Bin 0 -> 2730 bytes gfx/100/error-item-file.png | Bin 0 -> 2533 bytes gfx/100/index.html | 89 + gfx/100/item-button.png | Bin 0 -> 1936 bytes gfx/100/item-file.png | Bin 0 -> 1892 bytes gfx/100/kill-channel-button.png | Bin 0 -> 3909 bytes gfx/100/kill-channel-file.png | Bin 0 -> 3562 bytes gfx/100/kill-item-button.png | Bin 0 -> 3660 bytes gfx/100/kill-item-file.png | Bin 0 -> 3372 bytes gfx/100/play-channel-button.png | Bin 0 -> 3555 bytes gfx/100/play-channel-file.png | Bin 0 -> 3300 bytes gfx/100/play-item-button.png | Bin 0 -> 3350 bytes gfx/100/play-item-file.png | Bin 0 -> 3080 bytes gfx/100/refresh-channel-button.png | Bin 0 -> 3808 bytes gfx/100/refresh-channel-file.png | Bin 0 -> 3620 bytes gfx/100/refresh-item-button.png | Bin 0 -> 3591 bytes gfx/100/refresh-item-file.png | Bin 0 -> 3391 bytes gfx/100/remove-channel-button.png | Bin 0 -> 2688 bytes gfx/100/remove-channel-file.png | Bin 0 -> 2497 bytes gfx/100/remove-item-button.png | Bin 0 -> 2348 bytes gfx/100/remove-item-file.png | Bin 0 -> 2270 bytes gfx/100/stop-channel-button.png | Bin 0 -> 3468 bytes gfx/100/stop-channel-file.png | Bin 0 -> 3173 bytes gfx/100/stop-item-button.png | Bin 0 -> 3170 bytes gfx/100/stop-item-file.png | Bin 0 -> 2952 bytes gfx/100/www-channel-button.png | Bin 0 -> 3655 bytes gfx/100/www-channel-file.png | Bin 0 -> 3424 bytes gfx/100/www-item-button.png | Bin 0 -> 3379 bytes gfx/100/www-item-file.png | Bin 0 -> 3207 bytes gfx/50/Thumbs.db | Bin 0 -> 81408 bytes gfx/50/add-channel-button.png | Bin 0 -> 2286 bytes gfx/50/add-channel-file.png | Bin 0 -> 2124 bytes gfx/50/add-item-button.png | Bin 0 -> 2105 bytes gfx/50/add-item-file.png | Bin 0 -> 1962 bytes gfx/50/bepodder-logo1.png | Bin 0 -> 2560 bytes gfx/50/bepodder-logo2.png | Bin 0 -> 2631 bytes gfx/50/channel-button.png | Bin 0 -> 1490 bytes gfx/50/channel-file.png | Bin 0 -> 1345 bytes gfx/50/delete-channel-button.png | Bin 0 -> 2455 bytes gfx/50/delete-channel-file.png | Bin 0 -> 2191 bytes gfx/50/delete-item-button.png | Bin 0 -> 2264 bytes gfx/50/delete-item-file.png | Bin 0 -> 2032 bytes gfx/50/done-channel-button.png | Bin 0 -> 2215 bytes gfx/50/done-channel-file.png | Bin 0 -> 2020 bytes gfx/50/done-item-button.png | Bin 0 -> 2044 bytes gfx/50/done-item-file.png | Bin 0 -> 1869 bytes gfx/50/download-channel-button.png | Bin 0 -> 2168 bytes gfx/50/download-channel-file.png | Bin 0 -> 1981 bytes gfx/50/download-item-button.png | Bin 0 -> 2006 bytes gfx/50/download-item-file.png | Bin 0 -> 1821 bytes gfx/50/emblem-add.png | Bin 0 -> 785 bytes gfx/50/emblem-delete.png | Bin 0 -> 816 bytes gfx/50/emblem-done.png | Bin 0 -> 681 bytes gfx/50/emblem-download.png | Bin 0 -> 707 bytes gfx/50/emblem-enqueued.png | Bin 0 -> 831 bytes gfx/50/emblem-error.png | Bin 0 -> 609 bytes gfx/50/emblem-kill.png | Bin 0 -> 848 bytes gfx/50/emblem-play.png | Bin 0 -> 860 bytes gfx/50/emblem-refresh.png | Bin 0 -> 868 bytes gfx/50/emblem-remove.png | Bin 0 -> 384 bytes gfx/50/emblem-stop.png | Bin 0 -> 858 bytes gfx/50/emblem-www.png | Bin 0 -> 809 bytes gfx/50/enqueued-channel-button.png | Bin 0 -> 2355 bytes gfx/50/enqueued-channel-file.png | Bin 0 -> 2140 bytes gfx/50/enqueued-item-button.png | Bin 0 -> 2179 bytes gfx/50/enqueued-item-file.png | Bin 0 -> 1983 bytes gfx/50/error-channel-button.png | Bin 0 -> 2137 bytes gfx/50/error-channel-file.png | Bin 0 -> 1878 bytes gfx/50/error-item-button.png | Bin 0 -> 1951 bytes gfx/50/error-item-file.png | Bin 0 -> 1725 bytes gfx/50/index.html | 89 + gfx/50/item-button.png | Bin 0 -> 1291 bytes gfx/50/item-file.png | Bin 0 -> 1252 bytes gfx/50/kill-channel-button.png | Bin 0 -> 2204 bytes gfx/50/kill-channel-file.png | Bin 0 -> 2023 bytes gfx/50/kill-item-button.png | Bin 0 -> 2054 bytes gfx/50/kill-item-file.png | Bin 0 -> 1903 bytes gfx/50/play-channel-button.png | Bin 0 -> 2383 bytes gfx/50/play-channel-file.png | Bin 0 -> 2184 bytes gfx/50/play-item-button.png | Bin 0 -> 2208 bytes gfx/50/play-item-file.png | Bin 0 -> 2058 bytes gfx/50/refresh-channel-button.png | Bin 0 -> 2328 bytes gfx/50/refresh-channel-file.png | Bin 0 -> 2126 bytes gfx/50/refresh-item-button.png | Bin 0 -> 2158 bytes gfx/50/refresh-item-file.png | Bin 0 -> 1967 bytes gfx/50/remove-channel-button.png | Bin 0 -> 1798 bytes gfx/50/remove-channel-file.png | Bin 0 -> 1798 bytes gfx/50/remove-item-button.png | Bin 0 -> 1627 bytes gfx/50/remove-item-file.png | Bin 0 -> 1634 bytes gfx/50/stop-channel-button.png | Bin 0 -> 2214 bytes gfx/50/stop-channel-file.png | Bin 0 -> 2103 bytes gfx/50/stop-item-button.png | Bin 0 -> 2037 bytes gfx/50/stop-item-file.png | Bin 0 -> 1933 bytes gfx/50/www-channel-button.png | Bin 0 -> 2321 bytes gfx/50/www-channel-file.png | Bin 0 -> 2137 bytes gfx/50/www-item-button.png | Bin 0 -> 2175 bytes gfx/50/www-item-file.png | Bin 0 -> 1991 bytes gfx/75/Thumbs.db | Bin 0 -> 126976 bytes gfx/75/add-channel-button.png | Bin 0 -> 3720 bytes gfx/75/add-channel-file.png | Bin 0 -> 3412 bytes gfx/75/add-item-button.png | Bin 0 -> 3399 bytes gfx/75/add-item-file.png | Bin 0 -> 3125 bytes gfx/75/bepodder-logo1.png | Bin 0 -> 4480 bytes gfx/75/bepodder-logo2.png | Bin 0 -> 4870 bytes gfx/75/channel-button.png | Bin 0 -> 2468 bytes gfx/75/channel-file.png | Bin 0 -> 2185 bytes gfx/75/delete-channel-button.png | Bin 0 -> 4218 bytes gfx/75/delete-channel-file.png | Bin 0 -> 3705 bytes gfx/75/delete-item-button.png | Bin 0 -> 3843 bytes gfx/75/delete-item-file.png | Bin 0 -> 3424 bytes gfx/75/done-channel-button.png | Bin 0 -> 3762 bytes gfx/75/done-channel-file.png | Bin 0 -> 3346 bytes gfx/75/done-item-button.png | Bin 0 -> 3448 bytes gfx/75/done-item-file.png | Bin 0 -> 3031 bytes gfx/75/download-channel-button.png | Bin 0 -> 3582 bytes gfx/75/download-channel-file.png | Bin 0 -> 3108 bytes gfx/75/download-item-button.png | Bin 0 -> 3271 bytes gfx/75/download-item-file.png | Bin 0 -> 2811 bytes gfx/75/emblem-add.png | Bin 0 -> 1232 bytes gfx/75/emblem-delete.png | Bin 0 -> 1455 bytes gfx/75/emblem-done.png | Bin 0 -> 1239 bytes gfx/75/emblem-download.png | Bin 0 -> 1019 bytes gfx/75/emblem-enqueued.png | Bin 0 -> 1407 bytes gfx/75/emblem-error.png | Bin 0 -> 978 bytes gfx/75/emblem-kill.png | Bin 0 -> 1413 bytes gfx/75/emblem-play.png | Bin 0 -> 1415 bytes gfx/75/emblem-refresh.png | Bin 0 -> 1556 bytes gfx/75/emblem-remove.png | Bin 0 -> 588 bytes gfx/75/emblem-stop.png | Bin 0 -> 1508 bytes gfx/75/emblem-www.png | Bin 0 -> 1537 bytes gfx/75/enqueued-channel-button.png | Bin 0 -> 4022 bytes gfx/75/enqueued-channel-file.png | Bin 0 -> 3537 bytes gfx/75/enqueued-item-button.png | Bin 0 -> 3691 bytes gfx/75/enqueued-item-file.png | Bin 0 -> 3255 bytes gfx/75/error-channel-button.png | Bin 0 -> 3483 bytes gfx/75/error-channel-file.png | Bin 0 -> 3115 bytes gfx/75/error-item-button.png | Bin 0 -> 3159 bytes gfx/75/error-item-file.png | Bin 0 -> 2793 bytes gfx/75/index.html | 89 + gfx/75/item-button.png | Bin 0 -> 2146 bytes gfx/75/item-file.png | Bin 0 -> 1964 bytes gfx/75/kill-channel-button.png | Bin 0 -> 3721 bytes gfx/75/kill-channel-file.png | Bin 0 -> 3387 bytes gfx/75/kill-item-button.png | Bin 0 -> 3470 bytes gfx/75/kill-item-file.png | Bin 0 -> 3177 bytes gfx/75/play-channel-button.png | Bin 0 -> 4020 bytes gfx/75/play-channel-file.png | Bin 0 -> 3614 bytes gfx/75/play-item-button.png | Bin 0 -> 3714 bytes gfx/75/play-item-file.png | Bin 0 -> 3347 bytes gfx/75/refresh-channel-button.png | Bin 0 -> 4079 bytes gfx/75/refresh-channel-file.png | Bin 0 -> 3689 bytes gfx/75/refresh-item-button.png | Bin 0 -> 3760 bytes gfx/75/refresh-item-file.png | Bin 0 -> 3348 bytes gfx/75/remove-channel-button.png | Bin 0 -> 2961 bytes gfx/75/remove-channel-file.png | Bin 0 -> 2897 bytes gfx/75/remove-item-button.png | Bin 0 -> 2649 bytes gfx/75/remove-item-file.png | Bin 0 -> 2566 bytes gfx/75/stop-channel-button.png | Bin 0 -> 3767 bytes gfx/75/stop-channel-file.png | Bin 0 -> 3500 bytes gfx/75/stop-item-button.png | Bin 0 -> 3450 bytes gfx/75/stop-item-file.png | Bin 0 -> 3191 bytes gfx/75/www-channel-button.png | Bin 0 -> 4047 bytes gfx/75/www-channel-file.png | Bin 0 -> 3643 bytes gfx/75/www-item-button.png | Bin 0 -> 3737 bytes gfx/75/www-item-file.png | Bin 0 -> 3362 bytes gfx/AppIcon.svg | 64 + .../bepodder-logo1.svg | 62 + .../bepodder-logo2.svg | 184 + gfx/Icone_source_misterytrain/emblem-add.svg | 30 + .../emblem-delete.svg | 37 + gfx/Icone_source_misterytrain/emblem-done.svg | 30 + .../emblem-download.svg | 30 + .../emblem-enqueued.svg | 30 + .../emblem-error.svg | 34 + gfx/Icone_source_misterytrain/emblem-kill.svg | 60 + gfx/Icone_source_misterytrain/emblem-play.svg | 33 + .../emblem-refresh.svg | 38 + .../emblem-remove.svg | 27 + gfx/Icone_source_misterytrain/emblem-stop.svg | 66 + gfx/Icone_source_misterytrain/emblem-www.svg | 42 + gfx/Icone_source_misterytrain/kind-button.svg | 24 + gfx/Icone_source_misterytrain/kind-file.svg | 37 + .../logo-channel.svg | 106 + gfx/Icone_source_misterytrain/logo-item.svg | 11 + gfx/Icone_source_misterytrain/make.sh | 43 + gfx/bebits_logo.gif | Bin 0 -> 1473 bytes gfx/bepodder_ban1.png | Bin 0 -> 26035 bytes gfx/bepodder_splashscreen_prova1.jpg | Bin 0 -> 35491 bytes gfx/bepodder_splashscreen_prova2.jpg | Bin 0 -> 42365 bytes gfx/bepodder_splashscreen_prova3.jpg | Bin 0 -> 45923 bytes gfx/bp_icon.bmp | Bin 0 -> 3126 bytes gfx/item.png | Bin 0 -> 1915 bytes gfx/logo2.svg | 185 + icons/Application/bebits_logo.gif | Bin 0 -> 1473 bytes icons/Application/bepodder-logo1.png | Bin 0 -> 4480 bytes icons/Application/bepodder-logo2.png | Bin 0 -> 4870 bytes icons/Application/bepodder_bianco.png | Bin 0 -> 2970 bytes icons/Application/bp_icon.bmp | Bin 0 -> 3126 bytes icons/Application/logo1.svg | 64 + icons/Application/logo2.svg | 185 + icons/Application/podder.hkv | Bin 0 -> 20033 bytes icons/Application/podder.png | Bin 0 -> 4666 bytes icons/Application/podder.svg | 68 + include/curl/curl.h | 968 ++++ include/curl/easy.h | 68 + include/curl/mprintf.h | 83 + include/curl/multi.h | 190 + include/curl/stdcheaders.h | 36 + include/curl/types.h | 28 + include/libclv/ColorTools.h | 69 + include/libclv/ColumnListView.h | 343 ++ include/libclv/ColumnTypes.h | 254 + include/libfish/HelpViewer.h | 60 + include/libfunky/Colors.h | 53 + include/libfunky/ImageCache.h | 52 + include/libfunky/KeyMap.h | 207 + include/libfunky/ObjectList.h | 866 ++++ include/libfunky/PBox.h | 59 + include/libfunky/Setting.h | 24 + include/libfunky/SettingsTextView.h | 25 + include/libfunky/Utils.h | 39 + include/libxml/DOCBparser.h | 96 + include/libxml/HTMLparser.h | 298 ++ include/libxml/HTMLtree.h | 142 + include/libxml/Makefile | 556 +++ include/libxml/Makefile.am | 56 + include/libxml/Makefile.in | 556 +++ include/libxml/SAX.h | 173 + include/libxml/SAX2.h | 176 + include/libxml/c14n.h | 105 + include/libxml/catalog.h | 182 + include/libxml/chvalid.h | 230 + include/libxml/debugXML.h | 217 + include/libxml/dict.h | 69 + include/libxml/encoding.h | 226 + include/libxml/entities.h | 139 + include/libxml/globals.h | 455 ++ include/libxml/hash.h | 233 + include/libxml/list.h | 137 + include/libxml/nanoftp.h | 143 + include/libxml/nanohttp.h | 81 + include/libxml/parser.h | 1169 +++++ include/libxml/parserInternals.h | 602 +++ include/libxml/pattern.h | 91 + include/libxml/relaxng.h | 188 + include/libxml/schemasInternals.h | 905 ++++ include/libxml/threads.h | 81 + include/libxml/tree.h | 1154 +++++ include/libxml/uri.h | 84 + include/libxml/valid.h | 458 ++ include/libxml/xinclude.h | 121 + include/libxml/xlink.h | 189 + include/libxml/xmlIO.h | 356 ++ include/libxml/xmlautomata.h | 138 + include/libxml/xmlerror.h | 918 ++++ include/libxml/xmlexports.h | 138 + include/libxml/xmlmemory.h | 222 + include/libxml/xmlmodule.h | 57 + include/libxml/xmlreader.h | 399 ++ include/libxml/xmlregexp.h | 108 + include/libxml/xmlsave.h | 83 + include/libxml/xmlschemas.h | 190 + include/libxml/xmlschemastypes.h | 151 + include/libxml/xmlstring.h | 141 + include/libxml/xmlunicode.h | 202 + include/libxml/xmlversion.h | 373 ++ include/libxml/xmlversion.h.in | 373 ++ include/libxml/xmlwriter.h | 459 ++ include/libxml/xpath.h | 513 ++ include/libxml/xpathInternals.h | 630 +++ include/libxml/xpointer.h | 114 + include/r5-only/BePodder_R5.h | 14 + include/r5-only/ObjectList.h | 866 ++++ include/r5-only/R5Locale.h | 9 + include/r5-only/iconv.h | 120 + include/runview/RVAction.h | 15 + include/runview/RunView.h | 249 + include/runview/TextRender.h | 25 + include/runview/Theme.h | 109 + library/Jamfile | 8 + library/Jamrules | 67 + library/build/BuildSettings | 127 + library/build/ConfigRules | 146 + library/build/HelperRules | 51 + library/build/MainBuildRules | 428 ++ library/build/OverriddenJamRules | 214 + library/build/UserBuildConfig | 63 + library/build/UserBuildConfig.sample | 61 + library/libclv/ColorTools.cpp | 76 + library/libclv/ColumnListView.cpp | 4128 +++++++++++++++++ library/libclv/ColumnTypes.cpp | 667 +++ library/libclv/Jamfile | 27 + library/libclv/ObjectList.h | 866 ++++ library/libclv/include/ColorTools.h | 69 + library/libclv/include/ColumnListView.h | 343 ++ library/libclv/include/ColumnTypes.h | 254 + library/libfish/BoxRenderer.cpp | 44 + library/libfish/BoxRenderer.h | 33 + library/libfish/CompositeRenderer.cpp | 78 + library/libfish/CompositeRenderer.h | 22 + library/libfish/ContainerBox.h | 50 + library/libfish/HDoc.h | 31 + library/libfish/HelpViewer.cpp | 239 + library/libfish/HorizontalContainerBox.h | 59 + library/libfish/ImageRenderer.cpp | 67 + library/libfish/ImageRenderer.h | 19 + library/libfish/InstanceBox.h | 36 + library/libfish/Jamfile | 37 + library/libfish/MultiLineBoxRenderer.h | 143 + library/libfish/OneSView.cpp | 402 ++ library/libfish/OneSView.h | 65 + library/libfish/ParBoxRenderer.cpp | 238 + library/libfish/ParBoxRenderer.h | 28 + library/libfish/RVAction.h | 15 + library/libfish/RVActionGoto.h | 31 + library/libfish/RVActionOpenURL.h | 31 + library/libfish/SView.cpp | 69 + library/libfish/SView.h | 40 + library/libfish/TextInstanceBox.h | 23 + library/libfish/TitleBoxRenderer.cpp | 23 + library/libfish/TitleBoxRenderer.h | 16 + library/libfish/VerticalCompositeRenderer.h | 17 + library/libfish/VerticalContainerBox.h | 61 + library/libfish/include/HelpViewer.h | 60 + library/libfunky/ImageCache.cpp | 100 + library/libfunky/Jamfile | 27 + library/libfunky/PBox.cpp | 428 ++ library/libfunky/Setting.cpp | 64 + library/libfunky/SettingsTextView.cpp | 27 + library/libfunky/Utils.cpp | 347 ++ library/libfunky/extra/Action.h | 26 + library/libfunky/extra/ActionAsync.cpp | 8 + library/libfunky/extra/ActionAsync.h | 15 + library/libfunky/extra/ActionDownload.cpp | 285 ++ library/libfunky/extra/ActionDownload.h | 86 + library/libfunky/extra/Colors.h | 53 + library/libfunky/extra/Hashtable.h | 1609 +++++++ library/libfunky/extra/Queue.h | 1058 +++++ library/libfunky/extra/ReflowingTextView.cpp | 255 + library/libfunky/extra/ReflowingTextView.h | 83 + library/libfunky/extra/String.cpp | 674 +++ library/libfunky/extra/String.h | 672 +++ library/libfunky/include/Colors.h | 53 + library/libfunky/include/ImageCache.h | 52 + library/libfunky/include/KeyMap.h | 207 + library/libfunky/include/ObjectList.h | 866 ++++ library/libfunky/include/PBox.h | 59 + library/libfunky/include/Setting.h | 24 + library/libfunky/include/SettingsTextView.h | 25 + library/libfunky/include/Utils.h | 39 + library/librunview/Jamfile | 30 + library/librunview/NormalTextRender.h | 42 + library/librunview/ObjectList.h | 866 ++++ library/librunview/RunView.cpp | 2842 ++++++++++++ library/librunview/SmileTextRender.h | 66 + library/librunview/Theme.cpp | 249 + library/librunview/URLCrunch.cpp | 99 + library/librunview/URLCrunch.h | 40 + library/librunview/Utilities.cpp | 378 ++ library/librunview/Utilities.h | 70 + library/librunview/include/RVAction.h | 15 + library/librunview/include/RunView.h | 249 + library/librunview/include/TextRender.h | 25 + library/librunview/include/Theme.h | 109 + release/Language/Dictionaries/BePodder.blBY | 604 +++ release/Language/Dictionaries/BePodder.czCZ | 604 +++ release/Language/Dictionaries/BePodder.daDK | 604 +++ release/Language/Dictionaries/BePodder.deDE | 603 +++ release/Language/Dictionaries/BePodder.enUK | 604 +++ release/Language/Dictionaries/BePodder.enUS | 605 +++ release/Language/Dictionaries/BePodder.esAR | 603 +++ release/Language/Dictionaries/BePodder.esES | 603 +++ release/Language/Dictionaries/BePodder.etEE | 603 +++ release/Language/Dictionaries/BePodder.fiFI | 603 +++ release/Language/Dictionaries/BePodder.frBE | 601 +++ release/Language/Dictionaries/BePodder.frFR | 601 +++ release/Language/Dictionaries/BePodder.hrHR | 604 +++ release/Language/Dictionaries/BePodder.huHU | 604 +++ release/Language/Dictionaries/BePodder.itIT | 601 +++ release/Language/Dictionaries/BePodder.jaJP | 789 ++++ release/Language/Dictionaries/BePodder.nlBE | 1192 +++++ release/Language/Dictionaries/BePodder.nlNL | 1192 +++++ release/Language/Dictionaries/BePodder.noNO | 598 +++ release/Language/Dictionaries/BePodder.plPL | 599 +++ release/Language/Dictionaries/BePodder.ptBR | 603 +++ release/Language/Dictionaries/BePodder.ptPT | 603 +++ release/Language/Dictionaries/BePodder.ruRU | 604 +++ release/Language/Dictionaries/BePodder.svSE | 604 +++ release/Language/Dictionaries/BePodder.trTR | 604 +++ release/Language/Dictionaries/BePodder.zhCN | 604 +++ release/helpR5.xml | 433 ++ release/tutorial/bittorrent.html | Bin 0 -> 3990 bytes release/tutorial/gmail.html | Bin 0 -> 2971 bytes .../tutorial/images/add-channel-button.png | Bin 0 -> 2286 bytes release/tutorial/images/bittorrent_off.png | Bin 0 -> 1936 bytes release/tutorial/images/bittorrent_on.png | Bin 0 -> 2220 bytes release/tutorial/images/bp_main_page.png | Bin 0 -> 9720 bytes release/tutorial/images/enjoy.jpg | Bin 0 -> 84286 bytes release/tutorial/images/gmail_off.png | Bin 0 -> 2191 bytes release/tutorial/images/gmail_on.png | Bin 0 -> 2449 bytes release/tutorial/images/gui1.png | Bin 0 -> 83247 bytes release/tutorial/images/gui5.png | Bin 0 -> 21944 bytes release/tutorial/images/gui6.png | Bin 0 -> 11340 bytes release/tutorial/images/gui7.png | Bin 0 -> 19104 bytes release/tutorial/images/introduction_off.png | Bin 0 -> 2080 bytes release/tutorial/images/introduction_on.png | Bin 0 -> 2308 bytes release/tutorial/images/next.png | Bin 0 -> 1409 bytes release/tutorial/images/photocasting_off.png | Bin 0 -> 2260 bytes release/tutorial/images/photocasting_on.png | Bin 0 -> 2568 bytes release/tutorial/images/play-item-button.png | Bin 0 -> 2208 bytes release/tutorial/images/prev.png | Bin 0 -> 1404 bytes release/tutorial/images/rss-icon.gif | Bin 0 -> 1540 bytes release/tutorial/images/rss.gif | Bin 0 -> 1105 bytes release/tutorial/images/screen1.png | Bin 0 -> 276666 bytes release/tutorial/images/screen2.png | Bin 0 -> 18245 bytes release/tutorial/images/screen3.png | Bin 0 -> 19131 bytes release/tutorial/images/screen4.png | Bin 0 -> 18802 bytes release/tutorial/images/screen5.png | Bin 0 -> 106721 bytes release/tutorial/images/screen6.png | Bin 0 -> 4552 bytes release/tutorial/images/videocasting_off.png | Bin 0 -> 2319 bytes release/tutorial/images/videocasting_on.png | Bin 0 -> 2600 bytes release/tutorial/images/xml.png | Bin 0 -> 373 bytes release/tutorial/introduction.html | Bin 0 -> 4743 bytes release/tutorial/photocasting.html | Bin 0 -> 4476 bytes release/tutorial/videocasting.html | Bin 0 -> 5284 bytes resources/AppIcon.svg | 64 + resources/BePodder.rsrc | Bin 0 -> 3775 bytes resources/Icons.rsrc | Bin 0 -> 66994 bytes sources-experimental/Action.h | 26 + sources-experimental/ActionAsync.cpp | 13 + sources-experimental/ActionAsync.h | 15 + sources-experimental/ActionAsyncWrapper.cpp | 15 + sources-experimental/ActionAsyncWrapper.h | 19 + sources-experimental/ActionDelete.cpp | 27 + sources-experimental/ActionDelete.h | 22 + sources-experimental/ActionDownload.cpp | 335 ++ sources-experimental/ActionDownload.h | 88 + sources-experimental/ActionHTTPContent.cpp | 88 + sources-experimental/ActionHTTPContent.h | 42 + sources-experimental/AddWindow.cpp | 141 + sources-experimental/AddWindow.cpp_OR | 146 + sources-experimental/AddWindow.h | 25 + sources-experimental/Archive.h | 37 + sources-experimental/AttributeDumper.cpp | 201 + sources-experimental/AttributeDumper.h | 40 + sources-experimental/AttributeExtractor.cpp | 138 + sources-experimental/AttributeExtractor.h | 24 + sources-experimental/AttributeMap.h | 38 + sources-experimental/AutoFiletypeMap.h | 50 + sources-experimental/BPAlert.cpp | 708 +++ sources-experimental/BPAlert.h | 119 + sources-experimental/BPEpisode.cpp | 37 + sources-experimental/BPEpisode.h | 30 + sources-experimental/BPLocale.h | 19 + sources-experimental/BPSettingsWindow.cpp | 275 ++ sources-experimental/BPSettingsWindow.h | 58 + sources-experimental/BitmapTextRender.h | 92 + sources-experimental/BitmapView.h | 31 + sources-experimental/BitmapWindow.cpp | 24 + sources-experimental/BitmapWindow.h | 13 + .../ChannelSettingsWindow.cpp | 83 + sources-experimental/ChannelSettingsWindow.h | 39 + sources-experimental/Cursors.cpp | 167 + sources-experimental/Cursors.h | 20 + sources-experimental/DirectoryItem.h | 24 + sources-experimental/DirectoryWindow.cpp | 460 ++ sources-experimental/DirectoryWindow.h | 59 + sources-experimental/DownloadListItem.cpp | 151 + sources-experimental/DownloadListItem.h | 61 + sources-experimental/DownloadListView.cpp | 123 + sources-experimental/DownloadListView.h | 31 + sources-experimental/DownloadManager.cpp | 161 + sources-experimental/DownloadManager.h | 62 + sources-experimental/ElementListener.h | 17 + sources-experimental/ElementNotifier.cpp | 20 + sources-experimental/ElementNotifier.h | 37 + sources-experimental/EntryIterator.cpp | 457 ++ sources-experimental/EntryIterator.h | 157 + sources-experimental/EpisodeListItem.cpp | 148 + sources-experimental/EpisodeListItem.h | 49 + sources-experimental/EpisodeListView.cpp | 128 + sources-experimental/EpisodeListView.h | 27 + sources-experimental/Extractor.cpp | 30 + sources-experimental/Extractor.h | 31 + sources-experimental/FileStatus.h | 23 + sources-experimental/FileStatusColumn.cpp | 318 ++ sources-experimental/FileStatusColumn.h | 77 + sources-experimental/GreenBoxTextRender.cpp | 57 + sources-experimental/GreenBoxTextRender.h | 36 + sources-experimental/GroupItem.cpp | 24 + sources-experimental/GroupItem.h | 23 + sources-experimental/HelpTextView.h | 58 + sources-experimental/HelpWindow.cpp | 168 + sources-experimental/HelpWindow.h | 31 + sources-experimental/IABPChannel.cpp | 294 ++ sources-experimental/IABPChannel.h | 128 + sources-experimental/IABPDownload.cpp | 202 + sources-experimental/IABPDownload.h | 106 + sources-experimental/IABPGroup.cpp | 186 + sources-experimental/IABPGroup.h | 76 + sources-experimental/IABPItem.cpp | 258 ++ sources-experimental/IABPItem.h | 106 + sources-experimental/IAction.h | 49 + sources-experimental/IActionBP.h | 33 + sources-experimental/IActionManager.h | 67 + sources-experimental/IActionManagerBP.cpp | 70 + sources-experimental/IActionManagerBP.h | 67 + sources-experimental/IActionMenuItem.cpp | 23 + sources-experimental/IActionMenuItem.h | 20 + sources-experimental/IconMenuItem.cpp | 107 + sources-experimental/IconMenuItem.h | 48 + sources-experimental/IconTextItem.cpp | 77 + sources-experimental/IconTextItem.h | 34 + sources-experimental/IconTextRender.h | 73 + sources-experimental/ImageButton.cpp | 129 + sources-experimental/ImageButton.h | 37 + sources-experimental/ItemProperty.h | 54 + sources-experimental/ItemRunView.h | 100 + sources-experimental/Jamfile | 117 + sources-experimental/Logger.cpp | 153 + sources-experimental/Logger.h | 41 + sources-experimental/Main.cpp | 19 + sources-experimental/MainController.cpp | 1907 ++++++++ sources-experimental/MainController.h | 136 + sources-experimental/MainModel.h | 63 + sources-experimental/MainWindow.cpp | 1504 ++++++ sources-experimental/MainWindow.h | 169 + sources-experimental/MemoryArchive.cpp | 156 + sources-experimental/MemoryArchive.h | 50 + sources-experimental/MyColumnTypes.cpp | 208 + sources-experimental/MyColumnTypes.h | 99 + sources-experimental/NodeWalker.cpp | 695 +++ sources-experimental/NodeWalker.h | 143 + sources-experimental/Notifier.cpp | 59 + sources-experimental/Notifier.h | 40 + sources-experimental/OPMLParser.cpp | 240 + sources-experimental/OPMLParser.h | 45 + sources-experimental/PercentageView.cpp | 75 + sources-experimental/PercentageView.h | 29 + sources-experimental/PercentageWindow.cpp | 96 + sources-experimental/PercentageWindow.h | 29 + sources-experimental/QueueActions.cpp | 153 + sources-experimental/QueueActions.h | 54 + sources-experimental/QueueFileDownload.cpp | 40 + sources-experimental/QueueFileDownload.h | 27 + sources-experimental/QueueMultiActions.cpp | 238 + sources-experimental/QueueMultiActions.h | 67 + sources-experimental/R5Locale.cpp | 26 + sources-experimental/RVActionBP.h | 29 + sources-experimental/RVActionBPOpenURL.h | 28 + sources-experimental/Retriver.h | 26 + sources-experimental/RssChannel.cpp | 12 + sources-experimental/RssChannel.h | 22 + sources-experimental/RssItem.cpp | 42 + sources-experimental/RssItem.h | 47 + sources-experimental/SectionSelector.cpp | 243 + sources-experimental/SectionSelector.h | 47 + sources-experimental/SettingsWindow.cpp | 176 + sources-experimental/SettingsWindow.h | 53 + sources-experimental/SplitPane.cpp | 747 +++ sources-experimental/SplitPane.h | 137 + sources-experimental/StackedView.cpp | 63 + sources-experimental/StackedView.h | 57 + sources-experimental/Store.h | 26 + sources-experimental/StripeView.cpp | 55 + sources-experimental/StripeView.h | 29 + sources-experimental/SubscriptionColumn.cpp | 321 ++ sources-experimental/SubscriptionColumn.h | 114 + sources-experimental/SubscriptionListItem.cpp | 324 ++ sources-experimental/SubscriptionListItem.h | 99 + sources-experimental/SubscriptionListView.cpp | 276 ++ sources-experimental/SubscriptionListView.h | 48 + sources-experimental/TextControlFloater.cpp | 157 + sources-experimental/TextControlFloater.h | 64 + sources-experimental/TheApp.cpp | 483 ++ sources-experimental/TheApp.h | 31 + sources-experimental/TitleTextRender.cpp | 45 + sources-experimental/TitleTextRender.h | 32 + sources-experimental/XMLChannelExtractor.cpp | 286 ++ sources-experimental/XMLChannelExtractor.h | 27 + sources-experimental/XMLItemExtractor.cpp | 202 + sources-experimental/XMLItemExtractor.h | 33 + sources-experimental/htmlparse.cpp | 216 + sources-experimental/htmlparse.h | 12 + sources-experimental/owner.h | 3 + xres.output.rsrc | Bin 0 -> 66472 bytes 645 files changed, 85386 insertions(+) create mode 100644 Jamfile create mode 100644 Jamrules create mode 100644 bepodder_podcasts.opml create mode 100644 build/BuildSettings create mode 100644 build/ConfigRules create mode 100644 build/HelperRules create mode 100644 build/MainBuildRules create mode 100644 build/OverriddenJamRules create mode 100644 build/UserBuildConfig create mode 100644 build/UserBuildConfig.sample create mode 100644 documents/ChangeLog.txt create mode 100644 documents/Difference_between_version.txt create mode 100644 documents/Releases create mode 100644 documents/comunicati_comunity.txt create mode 100644 documents/elenco_clienti.txt create mode 100644 documents/email_betatester.txt create mode 100644 documents/email_user.txt create mode 100644 documents/feeds_per_prove_su_formati_particolari.txt create mode 100644 documents/license.txt create mode 100644 documents/link_a_directory_internazionali_di_podcast_e_RSS_feed.txt create mode 100644 documents/lista_siti_di_news.txt create mode 100644 gfx/100/add-channel-button.png create mode 100644 gfx/100/add-channel-file.png create mode 100644 gfx/100/add-item-button.png create mode 100644 gfx/100/add-item-file.png create mode 100644 gfx/100/bepodder-logo1.png create mode 100644 gfx/100/bepodder-logo2.png create mode 100644 gfx/100/channel-button.png create mode 100644 gfx/100/channel-file.png create mode 100644 gfx/100/delete-channel-button.png create mode 100644 gfx/100/delete-channel-file.png create mode 100644 gfx/100/delete-item-button.png create mode 100644 gfx/100/delete-item-file.png create mode 100644 gfx/100/done-channel-button.png create mode 100644 gfx/100/done-channel-file.png create mode 100644 gfx/100/done-item-button.png create mode 100644 gfx/100/done-item-file.png create mode 100644 gfx/100/download-channel-button.png create mode 100644 gfx/100/download-channel-file.png create mode 100644 gfx/100/download-item-button.png create mode 100644 gfx/100/download-item-file.png create mode 100644 gfx/100/emblem-add.png create mode 100644 gfx/100/emblem-delete.png create mode 100644 gfx/100/emblem-done.png create mode 100644 gfx/100/emblem-download.png create mode 100644 gfx/100/emblem-enqueued.png create mode 100644 gfx/100/emblem-error.png create mode 100644 gfx/100/emblem-kill.png create mode 100644 gfx/100/emblem-play.png create mode 100644 gfx/100/emblem-refresh.png create mode 100644 gfx/100/emblem-remove.png create mode 100644 gfx/100/emblem-stop.png create mode 100644 gfx/100/emblem-www.png create mode 100644 gfx/100/enqueued-channel-button.png create mode 100644 gfx/100/enqueued-channel-file.png create mode 100644 gfx/100/enqueued-item-button.png create mode 100644 gfx/100/enqueued-item-file.png create mode 100644 gfx/100/error-channel-button.png create mode 100644 gfx/100/error-channel-file.png create mode 100644 gfx/100/error-item-button.png create mode 100644 gfx/100/error-item-file.png create mode 100644 gfx/100/index.html create mode 100644 gfx/100/item-button.png create mode 100644 gfx/100/item-file.png create mode 100644 gfx/100/kill-channel-button.png create mode 100644 gfx/100/kill-channel-file.png create mode 100644 gfx/100/kill-item-button.png create mode 100644 gfx/100/kill-item-file.png create mode 100644 gfx/100/play-channel-button.png create mode 100644 gfx/100/play-channel-file.png create mode 100644 gfx/100/play-item-button.png create mode 100644 gfx/100/play-item-file.png create mode 100644 gfx/100/refresh-channel-button.png create mode 100644 gfx/100/refresh-channel-file.png create mode 100644 gfx/100/refresh-item-button.png create mode 100644 gfx/100/refresh-item-file.png create mode 100644 gfx/100/remove-channel-button.png create mode 100644 gfx/100/remove-channel-file.png create mode 100644 gfx/100/remove-item-button.png create mode 100644 gfx/100/remove-item-file.png create mode 100644 gfx/100/stop-channel-button.png create mode 100644 gfx/100/stop-channel-file.png create mode 100644 gfx/100/stop-item-button.png create mode 100644 gfx/100/stop-item-file.png create mode 100644 gfx/100/www-channel-button.png create mode 100644 gfx/100/www-channel-file.png create mode 100644 gfx/100/www-item-button.png create mode 100644 gfx/100/www-item-file.png create mode 100644 gfx/50/Thumbs.db create mode 100644 gfx/50/add-channel-button.png create mode 100644 gfx/50/add-channel-file.png create mode 100644 gfx/50/add-item-button.png create mode 100644 gfx/50/add-item-file.png create mode 100644 gfx/50/bepodder-logo1.png create mode 100644 gfx/50/bepodder-logo2.png create mode 100644 gfx/50/channel-button.png create mode 100644 gfx/50/channel-file.png create mode 100644 gfx/50/delete-channel-button.png create mode 100644 gfx/50/delete-channel-file.png create mode 100644 gfx/50/delete-item-button.png create mode 100644 gfx/50/delete-item-file.png create mode 100644 gfx/50/done-channel-button.png create mode 100644 gfx/50/done-channel-file.png create mode 100644 gfx/50/done-item-button.png create mode 100644 gfx/50/done-item-file.png create mode 100644 gfx/50/download-channel-button.png create mode 100644 gfx/50/download-channel-file.png create mode 100644 gfx/50/download-item-button.png create mode 100644 gfx/50/download-item-file.png create mode 100644 gfx/50/emblem-add.png create mode 100644 gfx/50/emblem-delete.png create mode 100644 gfx/50/emblem-done.png create mode 100644 gfx/50/emblem-download.png create mode 100644 gfx/50/emblem-enqueued.png create mode 100644 gfx/50/emblem-error.png create mode 100644 gfx/50/emblem-kill.png create mode 100644 gfx/50/emblem-play.png create mode 100644 gfx/50/emblem-refresh.png create mode 100644 gfx/50/emblem-remove.png create mode 100644 gfx/50/emblem-stop.png create mode 100644 gfx/50/emblem-www.png create mode 100644 gfx/50/enqueued-channel-button.png create mode 100644 gfx/50/enqueued-channel-file.png create mode 100644 gfx/50/enqueued-item-button.png create mode 100644 gfx/50/enqueued-item-file.png create mode 100644 gfx/50/error-channel-button.png create mode 100644 gfx/50/error-channel-file.png create mode 100644 gfx/50/error-item-button.png create mode 100644 gfx/50/error-item-file.png create mode 100644 gfx/50/index.html create mode 100644 gfx/50/item-button.png create mode 100644 gfx/50/item-file.png create mode 100644 gfx/50/kill-channel-button.png create mode 100644 gfx/50/kill-channel-file.png create mode 100644 gfx/50/kill-item-button.png create mode 100644 gfx/50/kill-item-file.png create mode 100644 gfx/50/play-channel-button.png create mode 100644 gfx/50/play-channel-file.png create mode 100644 gfx/50/play-item-button.png create mode 100644 gfx/50/play-item-file.png create mode 100644 gfx/50/refresh-channel-button.png create mode 100644 gfx/50/refresh-channel-file.png create mode 100644 gfx/50/refresh-item-button.png create mode 100644 gfx/50/refresh-item-file.png create mode 100644 gfx/50/remove-channel-button.png create mode 100644 gfx/50/remove-channel-file.png create mode 100644 gfx/50/remove-item-button.png create mode 100644 gfx/50/remove-item-file.png create mode 100644 gfx/50/stop-channel-button.png create mode 100644 gfx/50/stop-channel-file.png create mode 100644 gfx/50/stop-item-button.png create mode 100644 gfx/50/stop-item-file.png create mode 100644 gfx/50/www-channel-button.png create mode 100644 gfx/50/www-channel-file.png create mode 100644 gfx/50/www-item-button.png create mode 100644 gfx/50/www-item-file.png create mode 100644 gfx/75/Thumbs.db create mode 100644 gfx/75/add-channel-button.png create mode 100644 gfx/75/add-channel-file.png create mode 100644 gfx/75/add-item-button.png create mode 100644 gfx/75/add-item-file.png create mode 100644 gfx/75/bepodder-logo1.png create mode 100644 gfx/75/bepodder-logo2.png create mode 100644 gfx/75/channel-button.png create mode 100644 gfx/75/channel-file.png create mode 100644 gfx/75/delete-channel-button.png create mode 100644 gfx/75/delete-channel-file.png create mode 100644 gfx/75/delete-item-button.png create mode 100644 gfx/75/delete-item-file.png create mode 100644 gfx/75/done-channel-button.png create mode 100644 gfx/75/done-channel-file.png create mode 100644 gfx/75/done-item-button.png create mode 100644 gfx/75/done-item-file.png create mode 100644 gfx/75/download-channel-button.png create mode 100644 gfx/75/download-channel-file.png create mode 100644 gfx/75/download-item-button.png create mode 100644 gfx/75/download-item-file.png create mode 100644 gfx/75/emblem-add.png create mode 100644 gfx/75/emblem-delete.png create mode 100644 gfx/75/emblem-done.png create mode 100644 gfx/75/emblem-download.png create mode 100644 gfx/75/emblem-enqueued.png create mode 100644 gfx/75/emblem-error.png create mode 100644 gfx/75/emblem-kill.png create mode 100644 gfx/75/emblem-play.png create mode 100644 gfx/75/emblem-refresh.png create mode 100644 gfx/75/emblem-remove.png create mode 100644 gfx/75/emblem-stop.png create mode 100644 gfx/75/emblem-www.png create mode 100644 gfx/75/enqueued-channel-button.png create mode 100644 gfx/75/enqueued-channel-file.png create mode 100644 gfx/75/enqueued-item-button.png create mode 100644 gfx/75/enqueued-item-file.png create mode 100644 gfx/75/error-channel-button.png create mode 100644 gfx/75/error-channel-file.png create mode 100644 gfx/75/error-item-button.png create mode 100644 gfx/75/error-item-file.png create mode 100644 gfx/75/index.html create mode 100644 gfx/75/item-button.png create mode 100644 gfx/75/item-file.png create mode 100644 gfx/75/kill-channel-button.png create mode 100644 gfx/75/kill-channel-file.png create mode 100644 gfx/75/kill-item-button.png create mode 100644 gfx/75/kill-item-file.png create mode 100644 gfx/75/play-channel-button.png create mode 100644 gfx/75/play-channel-file.png create mode 100644 gfx/75/play-item-button.png create mode 100644 gfx/75/play-item-file.png create mode 100644 gfx/75/refresh-channel-button.png create mode 100644 gfx/75/refresh-channel-file.png create mode 100644 gfx/75/refresh-item-button.png create mode 100644 gfx/75/refresh-item-file.png create mode 100644 gfx/75/remove-channel-button.png create mode 100644 gfx/75/remove-channel-file.png create mode 100644 gfx/75/remove-item-button.png create mode 100644 gfx/75/remove-item-file.png create mode 100644 gfx/75/stop-channel-button.png create mode 100644 gfx/75/stop-channel-file.png create mode 100644 gfx/75/stop-item-button.png create mode 100644 gfx/75/stop-item-file.png create mode 100644 gfx/75/www-channel-button.png create mode 100644 gfx/75/www-channel-file.png create mode 100644 gfx/75/www-item-button.png create mode 100644 gfx/75/www-item-file.png create mode 100644 gfx/AppIcon.svg create mode 100644 gfx/Icone_source_misterytrain/bepodder-logo1.svg create mode 100644 gfx/Icone_source_misterytrain/bepodder-logo2.svg create mode 100644 gfx/Icone_source_misterytrain/emblem-add.svg create mode 100644 gfx/Icone_source_misterytrain/emblem-delete.svg create mode 100644 gfx/Icone_source_misterytrain/emblem-done.svg create mode 100644 gfx/Icone_source_misterytrain/emblem-download.svg create mode 100644 gfx/Icone_source_misterytrain/emblem-enqueued.svg create mode 100644 gfx/Icone_source_misterytrain/emblem-error.svg create mode 100644 gfx/Icone_source_misterytrain/emblem-kill.svg create mode 100644 gfx/Icone_source_misterytrain/emblem-play.svg create mode 100644 gfx/Icone_source_misterytrain/emblem-refresh.svg create mode 100644 gfx/Icone_source_misterytrain/emblem-remove.svg create mode 100644 gfx/Icone_source_misterytrain/emblem-stop.svg create mode 100644 gfx/Icone_source_misterytrain/emblem-www.svg create mode 100644 gfx/Icone_source_misterytrain/kind-button.svg create mode 100644 gfx/Icone_source_misterytrain/kind-file.svg create mode 100644 gfx/Icone_source_misterytrain/logo-channel.svg create mode 100644 gfx/Icone_source_misterytrain/logo-item.svg create mode 100644 gfx/Icone_source_misterytrain/make.sh create mode 100644 gfx/bebits_logo.gif create mode 100644 gfx/bepodder_ban1.png create mode 100644 gfx/bepodder_splashscreen_prova1.jpg create mode 100644 gfx/bepodder_splashscreen_prova2.jpg create mode 100644 gfx/bepodder_splashscreen_prova3.jpg create mode 100644 gfx/bp_icon.bmp create mode 100644 gfx/item.png create mode 100644 gfx/logo2.svg create mode 100644 icons/Application/bebits_logo.gif create mode 100644 icons/Application/bepodder-logo1.png create mode 100644 icons/Application/bepodder-logo2.png create mode 100644 icons/Application/bepodder_bianco.png create mode 100644 icons/Application/bp_icon.bmp create mode 100644 icons/Application/logo1.svg create mode 100644 icons/Application/logo2.svg create mode 100644 icons/Application/podder.hkv create mode 100644 icons/Application/podder.png create mode 100644 icons/Application/podder.svg create mode 100644 include/curl/curl.h create mode 100644 include/curl/easy.h create mode 100644 include/curl/mprintf.h create mode 100644 include/curl/multi.h create mode 100644 include/curl/stdcheaders.h create mode 100644 include/curl/types.h create mode 100644 include/libclv/ColorTools.h create mode 100644 include/libclv/ColumnListView.h create mode 100644 include/libclv/ColumnTypes.h create mode 100644 include/libfish/HelpViewer.h create mode 100644 include/libfunky/Colors.h create mode 100644 include/libfunky/ImageCache.h create mode 100644 include/libfunky/KeyMap.h create mode 100644 include/libfunky/ObjectList.h create mode 100644 include/libfunky/PBox.h create mode 100644 include/libfunky/Setting.h create mode 100644 include/libfunky/SettingsTextView.h create mode 100644 include/libfunky/Utils.h create mode 100644 include/libxml/DOCBparser.h create mode 100644 include/libxml/HTMLparser.h create mode 100644 include/libxml/HTMLtree.h create mode 100644 include/libxml/Makefile create mode 100644 include/libxml/Makefile.am create mode 100644 include/libxml/Makefile.in create mode 100644 include/libxml/SAX.h create mode 100644 include/libxml/SAX2.h create mode 100644 include/libxml/c14n.h create mode 100644 include/libxml/catalog.h create mode 100644 include/libxml/chvalid.h create mode 100644 include/libxml/debugXML.h create mode 100644 include/libxml/dict.h create mode 100644 include/libxml/encoding.h create mode 100644 include/libxml/entities.h create mode 100644 include/libxml/globals.h create mode 100644 include/libxml/hash.h create mode 100644 include/libxml/list.h create mode 100644 include/libxml/nanoftp.h create mode 100644 include/libxml/nanohttp.h create mode 100644 include/libxml/parser.h create mode 100644 include/libxml/parserInternals.h create mode 100644 include/libxml/pattern.h create mode 100644 include/libxml/relaxng.h create mode 100644 include/libxml/schemasInternals.h create mode 100644 include/libxml/threads.h create mode 100644 include/libxml/tree.h create mode 100644 include/libxml/uri.h create mode 100644 include/libxml/valid.h create mode 100644 include/libxml/xinclude.h create mode 100644 include/libxml/xlink.h create mode 100644 include/libxml/xmlIO.h create mode 100644 include/libxml/xmlautomata.h create mode 100644 include/libxml/xmlerror.h create mode 100644 include/libxml/xmlexports.h create mode 100644 include/libxml/xmlmemory.h create mode 100644 include/libxml/xmlmodule.h create mode 100644 include/libxml/xmlreader.h create mode 100644 include/libxml/xmlregexp.h create mode 100644 include/libxml/xmlsave.h create mode 100644 include/libxml/xmlschemas.h create mode 100644 include/libxml/xmlschemastypes.h create mode 100644 include/libxml/xmlstring.h create mode 100644 include/libxml/xmlunicode.h create mode 100644 include/libxml/xmlversion.h create mode 100644 include/libxml/xmlversion.h.in create mode 100644 include/libxml/xmlwriter.h create mode 100644 include/libxml/xpath.h create mode 100644 include/libxml/xpathInternals.h create mode 100644 include/libxml/xpointer.h create mode 100644 include/r5-only/BePodder_R5.h create mode 100644 include/r5-only/ObjectList.h create mode 100644 include/r5-only/R5Locale.h create mode 100644 include/r5-only/iconv.h create mode 100644 include/runview/RVAction.h create mode 100644 include/runview/RunView.h create mode 100644 include/runview/TextRender.h create mode 100644 include/runview/Theme.h create mode 100644 library/Jamfile create mode 100644 library/Jamrules create mode 100644 library/build/BuildSettings create mode 100644 library/build/ConfigRules create mode 100644 library/build/HelperRules create mode 100644 library/build/MainBuildRules create mode 100644 library/build/OverriddenJamRules create mode 100644 library/build/UserBuildConfig create mode 100644 library/build/UserBuildConfig.sample create mode 100644 library/libclv/ColorTools.cpp create mode 100644 library/libclv/ColumnListView.cpp create mode 100644 library/libclv/ColumnTypes.cpp create mode 100644 library/libclv/Jamfile create mode 100644 library/libclv/ObjectList.h create mode 100644 library/libclv/include/ColorTools.h create mode 100644 library/libclv/include/ColumnListView.h create mode 100644 library/libclv/include/ColumnTypes.h create mode 100644 library/libfish/BoxRenderer.cpp create mode 100644 library/libfish/BoxRenderer.h create mode 100644 library/libfish/CompositeRenderer.cpp create mode 100644 library/libfish/CompositeRenderer.h create mode 100644 library/libfish/ContainerBox.h create mode 100644 library/libfish/HDoc.h create mode 100644 library/libfish/HelpViewer.cpp create mode 100644 library/libfish/HorizontalContainerBox.h create mode 100644 library/libfish/ImageRenderer.cpp create mode 100644 library/libfish/ImageRenderer.h create mode 100644 library/libfish/InstanceBox.h create mode 100644 library/libfish/Jamfile create mode 100644 library/libfish/MultiLineBoxRenderer.h create mode 100644 library/libfish/OneSView.cpp create mode 100644 library/libfish/OneSView.h create mode 100644 library/libfish/ParBoxRenderer.cpp create mode 100644 library/libfish/ParBoxRenderer.h create mode 100644 library/libfish/RVAction.h create mode 100644 library/libfish/RVActionGoto.h create mode 100644 library/libfish/RVActionOpenURL.h create mode 100644 library/libfish/SView.cpp create mode 100644 library/libfish/SView.h create mode 100644 library/libfish/TextInstanceBox.h create mode 100644 library/libfish/TitleBoxRenderer.cpp create mode 100644 library/libfish/TitleBoxRenderer.h create mode 100644 library/libfish/VerticalCompositeRenderer.h create mode 100644 library/libfish/VerticalContainerBox.h create mode 100644 library/libfish/include/HelpViewer.h create mode 100644 library/libfunky/ImageCache.cpp create mode 100644 library/libfunky/Jamfile create mode 100644 library/libfunky/PBox.cpp create mode 100644 library/libfunky/Setting.cpp create mode 100644 library/libfunky/SettingsTextView.cpp create mode 100644 library/libfunky/Utils.cpp create mode 100644 library/libfunky/extra/Action.h create mode 100644 library/libfunky/extra/ActionAsync.cpp create mode 100644 library/libfunky/extra/ActionAsync.h create mode 100644 library/libfunky/extra/ActionDownload.cpp create mode 100644 library/libfunky/extra/ActionDownload.h create mode 100644 library/libfunky/extra/Colors.h create mode 100644 library/libfunky/extra/Hashtable.h create mode 100644 library/libfunky/extra/Queue.h create mode 100644 library/libfunky/extra/ReflowingTextView.cpp create mode 100644 library/libfunky/extra/ReflowingTextView.h create mode 100644 library/libfunky/extra/String.cpp create mode 100644 library/libfunky/extra/String.h create mode 100644 library/libfunky/include/Colors.h create mode 100644 library/libfunky/include/ImageCache.h create mode 100644 library/libfunky/include/KeyMap.h create mode 100644 library/libfunky/include/ObjectList.h create mode 100644 library/libfunky/include/PBox.h create mode 100644 library/libfunky/include/Setting.h create mode 100644 library/libfunky/include/SettingsTextView.h create mode 100644 library/libfunky/include/Utils.h create mode 100644 library/librunview/Jamfile create mode 100644 library/librunview/NormalTextRender.h create mode 100644 library/librunview/ObjectList.h create mode 100644 library/librunview/RunView.cpp create mode 100644 library/librunview/SmileTextRender.h create mode 100644 library/librunview/Theme.cpp create mode 100644 library/librunview/URLCrunch.cpp create mode 100644 library/librunview/URLCrunch.h create mode 100644 library/librunview/Utilities.cpp create mode 100644 library/librunview/Utilities.h create mode 100644 library/librunview/include/RVAction.h create mode 100644 library/librunview/include/RunView.h create mode 100644 library/librunview/include/TextRender.h create mode 100644 library/librunview/include/Theme.h create mode 100644 release/Language/Dictionaries/BePodder.blBY create mode 100644 release/Language/Dictionaries/BePodder.czCZ create mode 100644 release/Language/Dictionaries/BePodder.daDK create mode 100644 release/Language/Dictionaries/BePodder.deDE create mode 100644 release/Language/Dictionaries/BePodder.enUK create mode 100644 release/Language/Dictionaries/BePodder.enUS create mode 100644 release/Language/Dictionaries/BePodder.esAR create mode 100644 release/Language/Dictionaries/BePodder.esES create mode 100644 release/Language/Dictionaries/BePodder.etEE create mode 100644 release/Language/Dictionaries/BePodder.fiFI create mode 100644 release/Language/Dictionaries/BePodder.frBE create mode 100644 release/Language/Dictionaries/BePodder.frFR create mode 100644 release/Language/Dictionaries/BePodder.hrHR create mode 100644 release/Language/Dictionaries/BePodder.huHU create mode 100644 release/Language/Dictionaries/BePodder.itIT create mode 100644 release/Language/Dictionaries/BePodder.jaJP create mode 100644 release/Language/Dictionaries/BePodder.nlBE create mode 100644 release/Language/Dictionaries/BePodder.nlNL create mode 100644 release/Language/Dictionaries/BePodder.noNO create mode 100644 release/Language/Dictionaries/BePodder.plPL create mode 100644 release/Language/Dictionaries/BePodder.ptBR create mode 100644 release/Language/Dictionaries/BePodder.ptPT create mode 100644 release/Language/Dictionaries/BePodder.ruRU create mode 100644 release/Language/Dictionaries/BePodder.svSE create mode 100644 release/Language/Dictionaries/BePodder.trTR create mode 100644 release/Language/Dictionaries/BePodder.zhCN create mode 100644 release/helpR5.xml create mode 100644 release/tutorial/bittorrent.html create mode 100644 release/tutorial/gmail.html create mode 100644 release/tutorial/images/add-channel-button.png create mode 100644 release/tutorial/images/bittorrent_off.png create mode 100644 release/tutorial/images/bittorrent_on.png create mode 100644 release/tutorial/images/bp_main_page.png create mode 100644 release/tutorial/images/enjoy.jpg create mode 100644 release/tutorial/images/gmail_off.png create mode 100644 release/tutorial/images/gmail_on.png create mode 100644 release/tutorial/images/gui1.png create mode 100644 release/tutorial/images/gui5.png create mode 100644 release/tutorial/images/gui6.png create mode 100644 release/tutorial/images/gui7.png create mode 100644 release/tutorial/images/introduction_off.png create mode 100644 release/tutorial/images/introduction_on.png create mode 100644 release/tutorial/images/next.png create mode 100644 release/tutorial/images/photocasting_off.png create mode 100644 release/tutorial/images/photocasting_on.png create mode 100644 release/tutorial/images/play-item-button.png create mode 100644 release/tutorial/images/prev.png create mode 100644 release/tutorial/images/rss-icon.gif create mode 100644 release/tutorial/images/rss.gif create mode 100644 release/tutorial/images/screen1.png create mode 100644 release/tutorial/images/screen2.png create mode 100644 release/tutorial/images/screen3.png create mode 100644 release/tutorial/images/screen4.png create mode 100644 release/tutorial/images/screen5.png create mode 100644 release/tutorial/images/screen6.png create mode 100644 release/tutorial/images/videocasting_off.png create mode 100644 release/tutorial/images/videocasting_on.png create mode 100644 release/tutorial/images/xml.png create mode 100644 release/tutorial/introduction.html create mode 100644 release/tutorial/photocasting.html create mode 100644 release/tutorial/videocasting.html create mode 100644 resources/AppIcon.svg create mode 100644 resources/BePodder.rsrc create mode 100644 resources/Icons.rsrc create mode 100644 sources-experimental/Action.h create mode 100644 sources-experimental/ActionAsync.cpp create mode 100644 sources-experimental/ActionAsync.h create mode 100644 sources-experimental/ActionAsyncWrapper.cpp create mode 100644 sources-experimental/ActionAsyncWrapper.h create mode 100644 sources-experimental/ActionDelete.cpp create mode 100644 sources-experimental/ActionDelete.h create mode 100644 sources-experimental/ActionDownload.cpp create mode 100644 sources-experimental/ActionDownload.h create mode 100644 sources-experimental/ActionHTTPContent.cpp create mode 100644 sources-experimental/ActionHTTPContent.h create mode 100644 sources-experimental/AddWindow.cpp create mode 100644 sources-experimental/AddWindow.cpp_OR create mode 100644 sources-experimental/AddWindow.h create mode 100644 sources-experimental/Archive.h create mode 100644 sources-experimental/AttributeDumper.cpp create mode 100644 sources-experimental/AttributeDumper.h create mode 100644 sources-experimental/AttributeExtractor.cpp create mode 100644 sources-experimental/AttributeExtractor.h create mode 100644 sources-experimental/AttributeMap.h create mode 100644 sources-experimental/AutoFiletypeMap.h create mode 100644 sources-experimental/BPAlert.cpp create mode 100644 sources-experimental/BPAlert.h create mode 100644 sources-experimental/BPEpisode.cpp create mode 100644 sources-experimental/BPEpisode.h create mode 100644 sources-experimental/BPLocale.h create mode 100644 sources-experimental/BPSettingsWindow.cpp create mode 100644 sources-experimental/BPSettingsWindow.h create mode 100644 sources-experimental/BitmapTextRender.h create mode 100644 sources-experimental/BitmapView.h create mode 100644 sources-experimental/BitmapWindow.cpp create mode 100644 sources-experimental/BitmapWindow.h create mode 100644 sources-experimental/ChannelSettingsWindow.cpp create mode 100644 sources-experimental/ChannelSettingsWindow.h create mode 100644 sources-experimental/Cursors.cpp create mode 100644 sources-experimental/Cursors.h create mode 100644 sources-experimental/DirectoryItem.h create mode 100644 sources-experimental/DirectoryWindow.cpp create mode 100644 sources-experimental/DirectoryWindow.h create mode 100644 sources-experimental/DownloadListItem.cpp create mode 100644 sources-experimental/DownloadListItem.h create mode 100644 sources-experimental/DownloadListView.cpp create mode 100644 sources-experimental/DownloadListView.h create mode 100644 sources-experimental/DownloadManager.cpp create mode 100644 sources-experimental/DownloadManager.h create mode 100644 sources-experimental/ElementListener.h create mode 100644 sources-experimental/ElementNotifier.cpp create mode 100644 sources-experimental/ElementNotifier.h create mode 100644 sources-experimental/EntryIterator.cpp create mode 100644 sources-experimental/EntryIterator.h create mode 100644 sources-experimental/EpisodeListItem.cpp create mode 100644 sources-experimental/EpisodeListItem.h create mode 100644 sources-experimental/EpisodeListView.cpp create mode 100644 sources-experimental/EpisodeListView.h create mode 100644 sources-experimental/Extractor.cpp create mode 100644 sources-experimental/Extractor.h create mode 100644 sources-experimental/FileStatus.h create mode 100644 sources-experimental/FileStatusColumn.cpp create mode 100644 sources-experimental/FileStatusColumn.h create mode 100644 sources-experimental/GreenBoxTextRender.cpp create mode 100644 sources-experimental/GreenBoxTextRender.h create mode 100644 sources-experimental/GroupItem.cpp create mode 100644 sources-experimental/GroupItem.h create mode 100644 sources-experimental/HelpTextView.h create mode 100644 sources-experimental/HelpWindow.cpp create mode 100644 sources-experimental/HelpWindow.h create mode 100644 sources-experimental/IABPChannel.cpp create mode 100644 sources-experimental/IABPChannel.h create mode 100644 sources-experimental/IABPDownload.cpp create mode 100644 sources-experimental/IABPDownload.h create mode 100644 sources-experimental/IABPGroup.cpp create mode 100644 sources-experimental/IABPGroup.h create mode 100644 sources-experimental/IABPItem.cpp create mode 100644 sources-experimental/IABPItem.h create mode 100644 sources-experimental/IAction.h create mode 100644 sources-experimental/IActionBP.h create mode 100644 sources-experimental/IActionManager.h create mode 100644 sources-experimental/IActionManagerBP.cpp create mode 100644 sources-experimental/IActionManagerBP.h create mode 100644 sources-experimental/IActionMenuItem.cpp create mode 100644 sources-experimental/IActionMenuItem.h create mode 100644 sources-experimental/IconMenuItem.cpp create mode 100644 sources-experimental/IconMenuItem.h create mode 100644 sources-experimental/IconTextItem.cpp create mode 100644 sources-experimental/IconTextItem.h create mode 100644 sources-experimental/IconTextRender.h create mode 100644 sources-experimental/ImageButton.cpp create mode 100644 sources-experimental/ImageButton.h create mode 100644 sources-experimental/ItemProperty.h create mode 100644 sources-experimental/ItemRunView.h create mode 100644 sources-experimental/Jamfile create mode 100644 sources-experimental/Logger.cpp create mode 100644 sources-experimental/Logger.h create mode 100644 sources-experimental/Main.cpp create mode 100644 sources-experimental/MainController.cpp create mode 100644 sources-experimental/MainController.h create mode 100644 sources-experimental/MainModel.h create mode 100644 sources-experimental/MainWindow.cpp create mode 100644 sources-experimental/MainWindow.h create mode 100644 sources-experimental/MemoryArchive.cpp create mode 100644 sources-experimental/MemoryArchive.h create mode 100644 sources-experimental/MyColumnTypes.cpp create mode 100644 sources-experimental/MyColumnTypes.h create mode 100644 sources-experimental/NodeWalker.cpp create mode 100644 sources-experimental/NodeWalker.h create mode 100644 sources-experimental/Notifier.cpp create mode 100644 sources-experimental/Notifier.h create mode 100644 sources-experimental/OPMLParser.cpp create mode 100644 sources-experimental/OPMLParser.h create mode 100644 sources-experimental/PercentageView.cpp create mode 100644 sources-experimental/PercentageView.h create mode 100644 sources-experimental/PercentageWindow.cpp create mode 100644 sources-experimental/PercentageWindow.h create mode 100644 sources-experimental/QueueActions.cpp create mode 100644 sources-experimental/QueueActions.h create mode 100644 sources-experimental/QueueFileDownload.cpp create mode 100644 sources-experimental/QueueFileDownload.h create mode 100644 sources-experimental/QueueMultiActions.cpp create mode 100644 sources-experimental/QueueMultiActions.h create mode 100644 sources-experimental/R5Locale.cpp create mode 100644 sources-experimental/RVActionBP.h create mode 100644 sources-experimental/RVActionBPOpenURL.h create mode 100644 sources-experimental/Retriver.h create mode 100644 sources-experimental/RssChannel.cpp create mode 100644 sources-experimental/RssChannel.h create mode 100644 sources-experimental/RssItem.cpp create mode 100644 sources-experimental/RssItem.h create mode 100644 sources-experimental/SectionSelector.cpp create mode 100644 sources-experimental/SectionSelector.h create mode 100644 sources-experimental/SettingsWindow.cpp create mode 100644 sources-experimental/SettingsWindow.h create mode 100644 sources-experimental/SplitPane.cpp create mode 100644 sources-experimental/SplitPane.h create mode 100644 sources-experimental/StackedView.cpp create mode 100644 sources-experimental/StackedView.h create mode 100644 sources-experimental/Store.h create mode 100644 sources-experimental/StripeView.cpp create mode 100644 sources-experimental/StripeView.h create mode 100644 sources-experimental/SubscriptionColumn.cpp create mode 100644 sources-experimental/SubscriptionColumn.h create mode 100644 sources-experimental/SubscriptionListItem.cpp create mode 100644 sources-experimental/SubscriptionListItem.h create mode 100644 sources-experimental/SubscriptionListView.cpp create mode 100644 sources-experimental/SubscriptionListView.h create mode 100644 sources-experimental/TextControlFloater.cpp create mode 100644 sources-experimental/TextControlFloater.h create mode 100644 sources-experimental/TheApp.cpp create mode 100644 sources-experimental/TheApp.h create mode 100644 sources-experimental/TitleTextRender.cpp create mode 100644 sources-experimental/TitleTextRender.h create mode 100644 sources-experimental/XMLChannelExtractor.cpp create mode 100644 sources-experimental/XMLChannelExtractor.h create mode 100644 sources-experimental/XMLItemExtractor.cpp create mode 100644 sources-experimental/XMLItemExtractor.h create mode 100644 sources-experimental/htmlparse.cpp create mode 100644 sources-experimental/htmlparse.h create mode 100644 sources-experimental/owner.h create mode 100644 xres.output.rsrc diff --git a/Jamfile b/Jamfile new file mode 100644 index 0000000..461a3e3 --- /dev/null +++ b/Jamfile @@ -0,0 +1,6 @@ +SubDir TOP ; +#SubInclude TOP sources ; +SubInclude TOP sources-experimental ; +MakeDistro distro ; + + diff --git a/Jamrules b/Jamrules new file mode 100644 index 0000000..098624d --- /dev/null +++ b/Jamrules @@ -0,0 +1,55 @@ +BUILD_DIR = [ FDirName $(TOP) build ] ; +GENERATED_DIR = [ FDirName $(TOP) generated ] ; +DISTRO_DIR = [ FDirName $(TOP) generated distro ] ; + +include [ FDirName $(BUILD_DIR) HelperRules ] ; +include [ FDirName $(BUILD_DIR) ConfigRules ] ; +include [ FDirName $(BUILD_DIR) OverriddenJamRules ] ; +include [ FDirName $(BUILD_DIR) MainBuildRules ] ; +include [ FDirName $(BUILD_DIR) BuildSettings ] ; + + +# Include UserBuildConfig. +{ + local userBuildConfig = [ GLOB $(BUILD_DIR) : UserBuildConfig ] ; + if $(userBuildConfig) + { + LOCATE on UserBuildConfig = $(BUILD_DIR) ; + include UserBuildConfig ; + } +} + +# default to strip generated apps if not specified otherwise: +STRIP_APPS ?= 1 ; + +# Cache files for header scanning and jamfile caching. +HCACHEFILE = header_cache ; +JCACHEFILE = jamfile_cache ; +LOCATE on $(HCACHEFILE) $(JCACHEFILE) = $(GENERATED_DIR) ; + + +rule MakeDistro +{ + # MakeDistro + + local target = $1 ; + + NotFile $(target) ; + Always $(target) ; +} + +actions MakeDistro +{ + #jam + cp $(DISTRO_DIR)/BePodder $(TOP)/release + xres -o $(TOP)/release/BePodder $(TOP)/resources/Icons.rsrc $(TOP)/resources/BePodder.rsrc + + if [ -f /boot/beos/bin/IconTool ] ; then + echo "Adding SVG Icon" + IconTool $(TOP)/release/BePodder Build STD_ICON 1 -1 SVG $(TOP)/resources/AppIcon.svg + fi + + mimeset -f $(TOP)/release/BePodder + +} + diff --git a/bepodder_podcasts.opml b/bepodder_podcasts.opml new file mode 100644 index 0000000..44b7222 --- /dev/null +++ b/bepodder_podcasts.opml @@ -0,0 +1,2862 @@ + +BePodder Podcast Directory +Wed, 28 Dec 2005 03:18:34 GMT +Sunday, 4 November 2006 13:45:00 GMT +Funky Idea Software +bepodder.team@gmail.com + + +############## + +---------------- + + + + + --------------------- + + + +--------------------- + + + +--------------------- + + + + + +############## + +--------------------- + + + +--------------------- + + + + + + + + + + + + + + + + + + + + + + + + + + + +--------------------- + + + + + + + + +--------------------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--------------------- + + + + +----------------------------------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +----------------------------------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--------------------- + + + + +--------------------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + +############## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +############## + +--------------------- + + + +--------------------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--------------------- + + + + + + + + + + +--------------------- + + + + + + + + + +--------------------- + + + + + +--------------------- + + + + +--------------------- + + + +--------------------- + + + +--------------------- + + + + + +############## + + + + + + + + + + + + + + + + + + + + + +############## + +--------------------- + + + + +--------------------- + + + + + +--------------------- + + + + + + +--------------------- + + + + + +############## + + + + + + + + + + + + + + + +############## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +ndweavers"/> + + + +---------------------------------------------------------------------------------------------- + + + + + +############## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +------------------------------------------------------------------------------------------------------ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +############## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +############## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +############## + +--------------------- + + + + + + + + + + + + + + + +------------------------------------------------------------------------------------------------------------ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--------------------- + + + + + + + + + +############## + +----------------------------------- + + + + + + + + + + + + + + + + + + + + + + +----------------------------------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--------------------- + + + + + +--------------------- + + + + + +--------------------- + + + +--------------------- + + + + + + + +---------------------------------------------------------------------------------------------------------------------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--------------------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--------------------- + + + + + + + + + + + + +----------------------------------------------------------------------------------------------------------------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--------------------- + + + +--------------------- + + + + + + + + + + + +--------------------- + + + + +--------------------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--------------------- + + + + + + + + + + + + + + + + +--------------------- + + + +--------------------- + + + + + +--------------------- + + + +--------------------- + + + + + + + + + + + + + + + + + + + + + +--------------------- + + + + + + + + + + + + + + + + + +--------------------- + + + + + + + + + + +------------------------------------------------------------------------------------------------------------------- + + + + + + + + + + + + +--------------------- + + + + + + + + + + + + + + + + +--------------------- + + + + + + + + + + + + + + + + + + + + + +--------------------- + + + + + + + + + + + +############## + +--------------------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-------------------------------------------------------------------------------------------------- + + + + + + + + + + + + + + + + + + + + +--------------------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--------------------- + + + + + + + + + + + +--------------------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +############## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +############## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +############## + +--------------------- + + + + +--------------------- + + + + +--------------------- + + + + +--------------------- + + + + + + + + + + + +############## + +--------------------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--------------------- + + + + + + + + +--------------------- + + + + + + + +--------------------- + + + + + + + + + + + + + + + +--------------------- + + + + + + + + + + + + + + + + +--------------------------------------------------------------------------------------------------------- + + + + + + + + + + + + + + +--------------------- + + + + + + +--------------------- + + + + + + + + + +--------------------- + + + + +--------------------- + + + +--------------------- + + + +--------------------- + + + + + + + + +--------------------- + + + + + +############## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +############## + + + + + + + + + + + + + + + + + + + + diff --git a/build/BuildSettings b/build/BuildSettings new file mode 100644 index 0000000..efbe698 --- /dev/null +++ b/build/BuildSettings @@ -0,0 +1,127 @@ +# BuildSettings +# +# Setup global variables. + +# C and C++ flags +if $(OSPLAT) = PPC { + # filter out -nosyspath + CFLAGS = [ FFilter $(CFLAGS) : -nosyspath ] ; + C++FLAGS = [ FFilter $(C++FLAGS) : -nosyspath ] ; + LINKFLAGS += -warn -export pragma ; + + # set file containing preprocessed headers: + PREFIX_FILE ?= [ FDirName $(LOCATE_TARGET) pe.headers ] ; +} + +if $(OSPLAT) = X86 { + # check for BONE... + local haveBone = [ GLOB /boot/develop/headers/be/bone/arpa : inet.h ] ; + if $(haveBone) { + CCFLAGS += -DBONE_BUILD ; + C++FLAGS += -DBONE_BUILD ; + SYSHDRS += /boot/develop/headers/be/bone /boot/develop/headers/be/bone/sys ; + LINKLIBS += -lsocket -lbind ; + } else { + LINKLIBS += -lnet ; + } + # check for Zeta... + local haveZeta = [ GLOB /boot/beos/system/lib : libzeta.so ] ; + if $(haveZeta) { + LINKLIBS += -lzeta ; + DEFINES += ZETA ; + } +} + +# Use copyattr for copying. +CP = copyattr --data ; + +# Default paths for bison and flex: +BISON = bison ; +LEX = flex ; + +# mkdir shall not fail, if the directory already exists. +MKDIR = mkdir -p ; + +# Modify the main target dirs for languages and extensions. +SetConfigVar LOCATE_MAIN_TARGET : TOP Languages + : [ FDirName $(DISTRO_DIR) Languages ] ; +SetConfigVar LOCATE_MAIN_TARGET : TOP Extensions + : [ FDirName $(DISTRO_DIR) Extensions ] ; + +rule SetUpSubDirBuildSettings { + # SetUpSubDirBuildSettings ; + # + # Sets up the compiler flags and defines based on the WARNINGS, DEBUG, and + # OPTIMIZE variables. Also sets the locations for the targets (objects, + # libraries and executables). + # + # : Parameters as passed to the SubDir rule, i.e. the name of the + # TOP variable and the subdir tokens. + # + local dir = $(1) ; + + # warnings settings + if $(WARNINGS) != 0 { + if $(OSPLAT) = X86 { + CCFLAGS += -Wall -Wno-multichar -Wmissing-prototypes ; + CCFLAGS += -Wpointer-arith -Wcast-align -Wsign-compare ; + C++FLAGS += -Wall -Wno-multichar ; + C++FLAGS += -Wno-ctor-dtor-privacy -Woverloaded-virtual ; + C++FLAGS += -Wpointer-arith -Wcast-align -Wsign-compare ; + C++FLAGS += -Wno-unknown-pragmas ; + } else { + CCFLAGS += -w on -requireprotos ; + } + } + + # set the objects-folder according to debugging settings: + if $(DEBUG) && $(DEBUG) != 0 + { + OBJECTS_DIR = [ FDirName $(TOP) generated objects-debug ] ; + } + else + { + OBJECTS_DIR = [ FDirName $(TOP) generated objects-nodebug ] ; + } + + # debugging settings + if $(DEBUG) > 0 { + OPTIMIZE = 0 ; + STRIP_APPS = 0 ; + DEFINES += DEBUG=$(DEBUG) ; + CCFLAGS += -g ; + C++FLAGS += -g ; + LINKFLAGS += -g ; + } + + # optimization settings + if $(OPTIMIZE) = 0 { + if $(OSPLAT) = X86 { + OPTIM = -O0 ; + } else { + OPTIM = -O0 ; + } + } else { + if $(OSPLAT) = X86 { + OPTIM ?= -O2 ; + } else { + OPTIM ?= -O7 ; + } + } + + # setup objects location + local objdir = [ FDirName $(OBJECTS_DIR) $(dir[2-]) ] ; + SEARCH_SOURCE += $(objdir) ; + LOCATE_SOURCE = $(objdir) ; + LOCATE_TARGET = $(objdir) ; + + # setup main targets location + LOCATE_MAIN_TARGET ?= [ FDirName $(DISTRO_DIR) ] ; +} + +# The LOCATE_MAIN_TARGET variable shall be reset for each subdirectory. +AUTO_SET_UP_CONFIG_VARIABLES += LOCATE_MAIN_TARGET ; + +# Add the rules setting up the build settings for a subdirectory to the +# rules invoked by SubDir. +SUBDIRRULES += SetUpSubDirBuildSettings ; diff --git a/build/ConfigRules b/build/ConfigRules new file mode 100644 index 0000000..082ec46 --- /dev/null +++ b/build/ConfigRules @@ -0,0 +1,146 @@ +# ConfigRules +# +# Contains rules providing the config variable feature. It allows to set the +# values for certain variables for subdirectories in a central place. That is +# one can, for instance, specify in a file like UserBuildConfig for which +# directories to enable debugging, warnings, set special defines, compiler +# flags and the like without needing to edit the Jamfiles for the respective +# dirs. + +rule ConfigObject +{ + # ConfigObject ; + # + # Private rule. Returns the dummy object on which the config variables are + # set for a given subdir. + # + # : Parameters as passed to the SubDir rule, i.e. the name of the + # TOP variable and the subdir tokens. + # + local config = __config__ ; + local grist = [ FGrist root $(1) ] ; + return $(config:G=$(grist)) ; +} + +rule SetConfigVar +{ + # SetConfigVar : : [ : ] ; + # + # Sets a config variable for a specified directory to the given value. + # + # : The name of the variable to be set. + # : Parameters as passed to the SubDir rule, i.e. the name of the + # TOP variable and the subdir tokens. + # : The value to which the variable shall be set. + # : Either "global" or "local". The former implies that the variable + # value shall also be used for subdirectories (recursively), if + # for them the variable has not been set. The latter has the same + # effect regarding subdirs as if the variable for the directory + # is not set. Defaults to "global". + # + local var = $(1[1]) ; + local config = [ ConfigObject $(2) ] ; + local scope = $(4) ; + if ! $(scope) { + scope = global ; + } + $(var) on $(config) = $(3) ; + __set_$(var) on $(config) = $(scope) ; +} + +rule AppendToConfigVar +{ + # AppendToConfigVar : : [ : ] ; + # + # Appends a value to a config variable for a specified directory. Shortcut + # for + # SetConfigVar : : [ ConfigVar : ] ; + # + # : The name of the variable to be set. + # : Parameters as passed to the SubDir rule, i.e. the name of the + # TOP variable and the subdir tokens. + # : The value which to append to the variables current value. + # : Either "global" or "local". The former implies that the variable + # value shall also be used for subdirectories (recursively), if + # for them the variable has not been set. The latter has the same + # effect regarding subdirs as if the variable for the directory + # is not set. Defaults to "global". + # + SetConfigVar $(1) : $(2) : [ ConfigVar $(1) : $(2) ] $(3) : $(4) ; +} + +rule ConfigVar +{ + # ConfigVar : [ : ] ; + # + # Returns the value of a configuration variable for a given subdir. + # If the variable is not set for the subdir, the rule is invoked + # recursively for the parent directory with the scope "global". When + # the root is reached without yielding a value, the value of the global + # variable is returned. + # + # : The name of the variable whose value shall be returned. + # : Parameters as passed to the SubDir rule, i.e. the name of the + # TOP variable and the subdir tokens. + # : If not given any scope passed to SetConfigVar for the given + # directory will be accepted, otherwise it must match the scope + # passed to SetConfigVar. + # + local var = $(1[1]) ; + local dir = $(2) ; + local config = [ ConfigObject $(dir) ] ; + local scope = $(3) ; + local varScope = [ on $(config) return $(__set_$(var)) ] ; + if ( ! $(scope) && $(varScope) ) + || ( $(scope) && $(scope) = $(varScope) ) + || ! $(dir) { + on $(config) return $($(var)) ; + } else { + dir = [ FReverse $(dir) ] ; + return [ ConfigVar $(var) : [ FReverse $(dir[2-]) ] : global ] ; + } +} + +rule SetUpConfigVars { + # SetUpConfigVars ; + # + # Sets the global variables defined in AUTO_SET_UP_CONFIG_VARIABLES to the + # values specified for the subdirectory . + # + # : Parameters as passed to the SubDir rule, i.e. the name of the + # TOP variable and the subdir tokens. + # + local dir = $(1) ; + + # Backup the global variable value on first invocation, otherwise restore + # them, so that ConfigVar returns the right values for not explicity set + # local variables. + local var ; + if ! $(__config_var_backup__) { + __config_var_backup__ = true ; + for var in $(AUTO_SET_UP_CONFIG_VARIABLES) { + __config_var_backup_$(var)__ = $($(var)) ; + } + } else { + for var in $(AUTO_SET_UP_CONFIG_VARIABLES) { + $(var) = $(__config_var_backup_$(var)__) ; + } + } + + # Set the variables to their configured values. + for var in $(AUTO_SET_UP_CONFIG_VARIABLES) { + $(var) = [ ConfigVar $(var) : $(dir) ] ; + } +} + +# Add the SetUpConfigVars rule to the rules that are invoked at the end of the +# SubDir rule. Prepend it, so that the variables are set up before any other +# rule is invoked. +SUBDIRRULES = SetUpConfigVars $(SUBDIRRULES) ; + +# Some config variables that should be set up automatically for subdirs. +AUTO_SET_UP_CONFIG_VARIABLES += + CCFLAGS C++FLAGS DEBUG DEFINES HDRS LINKFLAGS OPTIM OPTIMIZE + SYSHDRS WARNINGS +; diff --git a/build/HelperRules b/build/HelperRules new file mode 100644 index 0000000..dda3e89 --- /dev/null +++ b/build/HelperRules @@ -0,0 +1,51 @@ +# HelperRules +# +# Helper rules without side effects. + +rule FFilter +{ + # FFilter : ; + # + # Removes all occurrences of in . + + local list = $(1) ; + local excludes = $(2) ; + local newList ; + local item ; + for item in $(list) { + local skip ; + local exclude ; + for exclude in $(excludes) { + if $(item) = $(exclude) { + skip = true ; + } + } + if ! $(skip) { + newList += $(item) ; + } + } + return $(newList) ; +} + +rule FSplitPath +{ + # FSplitPath ; + # + # Decomposes a path into its components. + # + # : The path to be decomposed. + # + local path = $(1:G=) ; + + local components ; + # $(path:D) for "/" is "/". Therefore the second condition. + while $(path:D) && $(path:D) != $(path) + { + # Note: $(path:B) returns "." for "..", but $(path:D=) is fine. + components = $(path:D=) $(components) ; + path = $(path:D) ; + } + components = $(path) $(components) ; + return $(components) ; +} + diff --git a/build/MainBuildRules b/build/MainBuildRules new file mode 100644 index 0000000..8ceb8a5 --- /dev/null +++ b/build/MainBuildRules @@ -0,0 +1,427 @@ +# MainBuildRules +# +# Rules that specify what to build and how to do it. + +rule Application +{ + # Application : : ; + # + # Creates an application from sources. + # + # : Name of the application. Grist is allowed. + # : List of source files. Grist will be set. + # : List of libraries to link against. + # + local app = $(1) ; + local sources = $(2) ; + local libs = $(3) ; + + Main $(app) : $(sources) ; + MakeLocate $(app) : $(LOCATE_MAIN_TARGET) ; + LinkAgainst $(app) : $(libs) ; +} + +actions Strip +{ + strip "$(1)" ; +} + +rule AddOn +{ + # AddOn : : ; + # + # Creates an add-on from sources. + # + # : Name of the add-on. Grist is allowed. + # : List of source files. Grist will be set. + # : List of libraries to link against. + # + SharedLibrary $(1) : $(2) : $(3) ; +} + +rule SharedLibrary +{ + # SharedLibrary : : ; + # + # Creates a shared library from sources. + # + # : Name of the shared library. Grist is allowed. + # : List of source files. Grist will be set. + # : List of libraries to link against. + # + local lib = $(1) ; + local sources = $(2) ; + local libs = $(3) ; + + Main $(lib) : $(sources) ; + MakeLocate $(lib) : $(LOCATE_MAIN_TARGET) ; + local linkFlags ; + if $(OSPLAT) = X86 { + linkFlags = -nostart -Xlinker -soname=\"$(lib)\" ; + } else { + linkFlags = -xms ; + } + LINKFLAGS on $(lib) = [ on $(lib) return $(LINKFLAGS) ] $(linkFlags) ; + LinkAgainst $(lib) : $(libs) ; +} + +rule StaticLibrary +{ + # StaticLibrary : ; + # + # Creates a static library from sources. + # + # : Name of the static library. Grist is allowed. + # : List of source files. Grist will be set. + # + local lib = $(1) ; + Library $(lib) : $(2) ; + MakeLocate $(lib) : $(LOCATE_MAIN_TARGET) ; + + # If KEEPOBJS is set, Library doesn't make the library depend on `lib'. + if $(KEEPOBJS) { + Depends lib : $(lib) ; + } +} + +rule LinkAgainst +{ + # LinkAgainst : ; + # + # Adds libraries to the list of libraries a (Main) target shall be linked + # against. + # + # : The name of the target for which to add libraries. + # : The libraries (actually arbitrary shared objects and static + # libraries) to be added. Valid elements are e.g. "be" or + # "libopenbeos.so" or "/boot/.../libfoo.so". If the basename starts + # with "lib" or the thingy has a dirname or grist, it is added to + # the NEEDLIBS variable (i.e. the file will be bound!), otherwise + # it is prefixed "-l" and added to LINKLIBS. If you want to specify + # a target that isn't a library and also has neither grist nor a + # dirname, you can prepend "" as grist; it will be + # stripped by this rule. + # + for i in $(>) + { + local isfile = ; + if $(i:D) || $(i:G) { + isfile = true ; + if $(i:G) = { + i = $(i:G=) ; + } + } else { + switch $(i:B) + { + # XXX: _APP_ and _KERNEL_ should not be needed for ELF. + case _APP_ : isfile = true ; + case _KERNEL_ : isfile = true ; + case lib* : isfile = true ; + case * : isfile = ; + } + if ! $(isfile) && ( $(i:S) = .so || $(i:S) = .a ) { + isfile = true ; + } + } + if $(isfile) { + NEEDLIBS on $(1) = [ on $(1) return $(NEEDLIBS) ] $(i) ; + Depends $(1) : $(i) ; + } else { + LINKLIBS on $(1) = [ on $(1) return $(LINKLIBS) ] -l$(i) ; + } + } +} + +rule XRes +{ + # XRes : ; + # + # Adds resources to a file. + # + # : The files to which resources shall be added. + # : The resource files. + # + if $(2) + { + Depends $(1) : $(2) ; + XRes1 $(1) : $(2) ; + } +} + +actions XRes1 +{ + xres -o "$(1)" "$(2)" ; +} + +actions MimeSet +{ + mimeset -f "$(1)" ; +} + +rule LexC++ +{ + Depends $(1) : $(2) ; + MakeLocate $(1) : $(LOCATE_SOURCE) ; + Clean clean : $(1) ; +} + +actions LexC++ +{ + $(LEX) -i -o$(1) $(2) +} + +rule Bison +{ + local _h ; + + _h = $(1).h ; + + MakeLocate $(<) $(_h) : $(LOCATE_SOURCE) ; + + Depends $(<) $(_h) : $(>) ; + BisonC++ $(<) $(_h) : $(>) ; + Clean clean : $(<) $(_h) ; + + # make sure someone includes $(_h) else it will be + # a deadly independent target + + Includes $(<) : $(_h) ; +} + +actions BisonC++ +{ + $(BISON) $(YACCFLAGS) -o $(1[1]) $(2) +} + +rule Rez +{ + # Rez : [ : ] ; + # + local output = $(1) ; + local rezFile = $(2) ; + local flags = $(3) ; + + REZHDRS on $(output) = [ on $(output) FIncludes $(HDRS) ] ; + REZFLAGS on $(output) = [ on $(output) return $(REZFLAGS) ] $(flags) ; + Depends $(output) : rez $(rezFile) ; + Rez1 $(output) : rez $(rezFile) ; +} + +actions Rez1 +{ + $(2[1]) $(REZFLAGS) $(REZHDRS) -o "$(1)" "$(2[2-])" ; +} + +rule RezObjects +{ + local rezFiles = $(1) ; + local rezFile ; + for rezFile in $(rezFiles) { + local rsrcFile = $(rezFile:BS=.rsrc) ; + RezObject $(rsrcFile) : [ FGristFiles $(rezFile) ] ; + } +} + +rule RezObject +{ + # RezObject : ; + # + local _rsrc = $(1) ; + local _r = $(2) ; + + local tmp = [ FGristFiles $(_rsrc)_tmp ] ; + + SEARCH on $(_r) = $(SEARCH_SOURCE) ; + + # include directories to by used + HDRS on $(_rsrc) $(tmp) = $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ; + + # preprocess the rez file + PreProcess $(tmp) : $(_r) ; + + # generate the resource file from the preprocessed rez file + MakeLocate $(_rsrc) : $(LOCATE_TARGET) ; + Rez $(_rsrc) : $(tmp) : -t ; + + RmTemps $(_rsrc) : $(tmp) ; + Clean clean : $(_rsrc) ; +} + +rule PreProcess +{ + # PreProcess : ; + # + local target = $(1) ; + local source = $(2) ; + + Depends $(target) : $(source) ; + + CPPHDRS on $(target) = [ on $(target) FIncludes $(HDRS) ] ; + + MakeLocate $(target) : $(LOCATE_SOURCE) ; +} + +if $(OSPLAT) = PPC { + actions PreProcess + { + mwcc -preprocess $(CPPHDRS) -o "$(1)" $(2) + } +} else { + actions PreProcess + { + gcc -E -x c $(CPPHDRS) -o "$(1)" $(2) + } +} + +rule RezHeader +{ + # RezHeader : : + # + # generates a header from a given resource file. + # + local _hdr = $(1) ; + local _rsrc = $(2) ; + + SEARCH on $(_rsrc) = $(SEARCH_SOURCE) ; + HDRS on $(_hdr) = $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ; + MakeLocate $(_hdr) : $(LOCATE_SOURCE) ; + Clean clean : $(_hdr) ; + + Rez $(_hdr) : $(_rsrc) : -h ; +} + +rule PreCompile +{ + # PreCompile : + # + # precompiles the given src (a headerfile) into the specified header. + # + local _hdr = $(1) ; + local _src = $(2) ; + MakeLocate $(_hdr) : $(LOCATE_TARGET) ; + PreComp $(_hdr) : $(_src) ; + Clean clean : $(_hdr) ; +} + +rule PreComp +{ + Depends $(<) : $(>) ; +} + +actions PreComp +{ + mwcc -precompile $(<) -lang cplus "$(>)" ; +} + +rule PeLanguage +{ + # PeLanguage : : : + # + # generates a SharedLib which extends Pe with syntax-highlighting for + # that specific language. + # + local lang = $(1) ; + local srcs = $(2) ; + local libs = $(3) ; + local rsrc = $(4) ; # contains keywords + + SharedLibrary $(lang) : $(srcs) : $(libs) ; + XRes $(lang) : $(rsrc) ; +} + +rule PeExtension +{ + # PeExtension : : : + # + # generates a SharedLib which extends Pe with a specific feature. + # + local ext = $(1) ; + local srcs = [ FGristFiles $(2) ] ; + local libs = $(3) ; + local rsrc = [ FGristFiles $(4) ] ; # optional resource file + + if $(rsrc) { + local header = $(rsrc:BS=.r.h) ; + + Includes $(srcs) : $(header) ; + RezHeader $(header) : $(rsrc) ; + } + SharedLibrary $(ext) : $(srcs) : $(libs) ; + + SymlinkDistroExtensionsLibDir $(ext) ; +} + +rule SymlinkDistroExtensionsLibDir +{ + # SymlinkDistroExtensionsLibDir ; + # + local extension = $(1) ; + + Depends $(extension) : lib ; + NoUpdate lib ; + MakeLocate lib : $(DISTRO_DIR)/Extensions ; + + SymlinkDistroExtensionsLibDir1 lib ; +} + +actions together SymlinkDistroExtensionsLibDir1 +{ # create a link to the folder where libhekkel.so lives + ln -sfn ../lib $(1) ; +} + +rule SubDirSysHdrs +{ + # SubDirSysHdrs ; + # + # Adds directories to the system include search paths for the current + # subdirectory. Counterpart of SubDirHdrs which adds non-system include + # search paths. + # + # : The directories to be added to the current subdir's system + # include search paths. + # + SUBDIRSYSHDRS += [ FDirName $(1) ] ; +} + +rule ObjectSysHdrs +{ + # SubDirSysHdrs : ; + # + # Adds directories to the system include search paths for the given + # sources or objects. Counterpart of ObjectHdrs which adds non-system + # include search paths. + # + # NOTE: This rule must be invoked *after* the rule that generates the + # objects. + # + # : The targets for which to add system include + # search paths. + # : The directories to be added to the given objects' system + # include search paths. + # + + local s ; + for s in [ FGristFiles $(<:S=$(SUFOBJ)) ] { + SYSHDRS on $(s) += $(>) ; + CCHDRS on $(s) = [ on $(s) FIncludes $(HDRS) ] + $(HDRS_INCLUDES_SEPARATOR) [ on $(s) FSysIncludes $(SYSHDRS) ] ; + } +} + + +# FSysIncludes ; +# +# Counterpart of FIncludes for system include search paths. +# +if $(OSPLAT) = X86 { + rule FSysIncludes { return -I$(<) ; } +} else { + rule FSysIncludes { return "-i "$(<) ; } +} + +# Variable referring to the STL. +if $(OSPLAT) = X86 { + STDC++LIB = stdc++.r4 ; +} else { + STDC++LIB = mslcpp_4_0 ; +} diff --git a/build/OverriddenJamRules b/build/OverriddenJamRules new file mode 100644 index 0000000..c0fef0c --- /dev/null +++ b/build/OverriddenJamRules @@ -0,0 +1,214 @@ +# OverriddenJamRules +# +# Jam rules that need to be overridden for good reasons. + +# Overridden to allow for spaces in file names and to support resources. +# Also set the on target LINKFLAGS variable to prevent later changes to +# the global variable from having an effect on the setting for the target. +rule Link +{ + local dbg = [ on $(1) return $(DEBUG) ] ; + if $(STRIP_APPS) && $(STRIP_APPS) != 0 && (!$(dbg) || $(dbg) = 0) { + # strip app if requested so and if not in debug mode! + Strip $(1) ; + } + # Note: RESFILES must be set before invocation. + MODE on $(1) = $(EXEMODE) ; + on $(1) XRes $(1) : $(RESFILES) ; + Chmod $(1) ; + MimeSet $(1) ; + LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ] ; +} + +actions Link bind NEEDLIBS +{ + $(LINK) $(LINKFLAGS) -o "$(1)" $(UNDEFS) "$(2)" "$(NEEDLIBS)" $(LINKLIBS) +} + + +# Overridden to allow for spaces in file names. +actions Chmod1 +{ + $(CHMOD) "$(MODE)" "$(1)" +} + +# Overridden to allow for spaces in file names. +actions piecemeal together existing Clean +{ + $(RM) "$(>)" +} + +# Changes to rules for sake of discrimination between system and non-system +# headers. + +if $(OSPLAT) = X86 { + HDRS_INCLUDES_SEPARATOR = -I- ; +} else { + HDRS_INCLUDES_SEPARATOR = -i- ; +} + +rule Cc +{ + Depends $(<) : $(>) ; + + # If the compiler's -o flag doesn't work, relocate the .o + + if $(RELOCATE) + { + CcMv $(<) : $(>) ; + } + + # Just to clarify here: this sets the per-target CCFLAGS to + # be the current value of (global) CCFLAGS and SUBDIRCCFLAGS. + # CCHDRS and CCDEFS must be reformatted each time for some + # compiles (VMS, NT) that malign multiple -D or -I flags. + + CCFLAGS on $(<) += $(CCFLAGS) $(SUBDIRCCFLAGS) $(OPTIM) ; + + CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] + $(HDRS_INCLUDES_SEPARATOR) [ on $(<) FSysIncludes $(SYSHDRS) ] ; + CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ; +} + +rule C++ +{ + Depends $(<) : $(>) ; + + if $(RELOCATE) + { + CcMv $(<) : $(>) ; + } + + C++FLAGS on $(<) += $(C++FLAGS) $(SUBDIRC++FLAGS) $(OPTIM) ; + + CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] + $(HDRS_INCLUDES_SEPARATOR) [ on $(<) FSysIncludes $(SYSHDRS) ] ; + CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ; +} + +rule Object +{ + # locate object and search for source, if wanted + + Clean clean : $(<) ; + + MakeLocate $(<) : $(LOCATE_TARGET) ; + SEARCH on $(>) = $(SEARCH_SOURCE) ; + + # Save HDRS for -I$(HDRS) on compile. + # We shouldn't need -I$(SEARCH_SOURCE) as cc can find headers + # in the .c file's directory, but generated .c files (from + # yacc, lex, etc) are located in $(LOCATE_TARGET), possibly + # different from $(SEARCH_SOURCE). + + HDRS on $(<) = $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ; + SYSHDRS on $(<) = $(SUBDIRSYSHDRS) $(SYSHDRS) ; + + # handle #includes for source: Jam scans for headers with + # the regexp pattern $(HDRSCAN) and then invokes $(HDRRULE) + # with the scanned file as the target and the found headers + # as the sources. HDRSEARCH is the value of SEARCH used for + # the found header files. Finally, if jam must deal with + # header files of the same name in different directories, + # they can be distinguished with HDRGRIST. + + # $(SEARCH_SOURCE:E) is where cc first looks for #include + # "foo.h" files. If the source file is in a distant directory, + # look there. Else, look in "" (the current directory). + + HDRRULE on $(>) = HdrRule ; + HDRSCAN on $(>) = $(HDRPATTERN) ; + HDRSEARCH on $(>) = + $(SEARCH_SOURCE:E) $(SUBDIRHDRS) $(HDRS) $(SYSHDRS) $(STDHDRS) ; + + HDRGRIST on $(>) = $(HDRGRIST) ; + + # propagate target specific-defines + + DEFINES on $(<) += $(DEFINES) ; + + # if source is not .c, generate .c with specific rule + + switch $(>:S) + { + case .asm : As $(<) : $(>) ; + case .c : Cc $(<) : $(>) ; + case .C : C++ $(<) : $(>) ; + case .cc : C++ $(<) : $(>) ; + case .cpp : C++ $(<) : $(>) ; + case .f : Fortran $(<) : $(>) ; + case .l : C++ $(<) : $(<:S=.cpp) ; + LexC++ $(<:S=.cpp) : $(>) ; + case .s : As $(<) : $(>) ; + case .y : C++ $(<) : $(<:S=.cpp) ; + Bison $(<:S=.cpp) : $(>) ; + case * : UserObject $(<) : $(>) ; + } +} + +rule ObjectHdrs +{ + local s ; + for s in [ FGristFiles $(<:S=$(SUFOBJ)) ] { + HDRS on $(s) += $(>) ; + CCHDRS on $(s) = [ on $(s) FIncludes $(HDRS) ] + $(HDRS_INCLUDES_SEPARATOR) [ on $(s) FSysIncludes $(SYSHDRS) ] ; + } +} + +# Override Jam 2.5rc3 MakeLocate and MkDir to deal more intelligently +# with grist set on the supplied directory name. +rule MakeLocate +{ + if $(2[1]) + { + local dir = $(2[1]) ; + if ! $(dir:G) { + dir = $(dir:G=dir) ; + } + LOCATE on $(1) = $(dir:G=) ; + Depends $(1) : $(dir) ; + MkDir $(dir) ; + } +} + +rule MkDir +{ + # If dir exists, don't update it + # Do this even for $(DOT). + + local dir = $(<) ; + if ! $(dir:G) { + dir = $(dir:G=dir) ; + } + + NoUpdate $(dir) ; + + if $(dir:G=) != $(DOT) && ! $($(dir:G=)-mkdir) { + local s ; + + # Cheesy gate to prevent multiple invocations on same dir + # MkDir1 has the actions + # Arrange for jam dirs + + $(dir:G=)-mkdir = true ; + MkDir1 $(dir) ; + Depends dirs : $(dir) ; + + # Recursively make parent directories. + # $(dir:P) = $(dir)'s parent, & we recurse until root + + s = $(dir:P) ; # parent keeps grist + + if $(s:G=) && $(s) != $(dir) { + Depends $(dir) : $(s) ; + MkDir $(s) ; + } else if $(s) { + NotFile $(s) ; + } + } +} + +# Add SUBDIRSYSHDRS to the variables that shall be reset automatically by the +# SubDir rule. +SUBDIRRESET += SYSHDRS ; diff --git a/build/UserBuildConfig b/build/UserBuildConfig new file mode 100644 index 0000000..67cf7c7 --- /dev/null +++ b/build/UserBuildConfig @@ -0,0 +1,61 @@ +# UserBuildConfig +# +# Sample of a UserBuildConfig file. It is a central place where the user can +# set variables affecting certain aspects of the build, such as debug, +# warnings and optimization settings. The file is ignored by CVS. +# +# The following variables can be set: +# +# CCFLAGS, C++FLAGS - Flags passed to the C/C++ compiler. +# DEBUG - If not empty, will turn on debugging, i.e. will +# add respective C/C++ compiler and linker flags and +# the CPP DEBUG macro. +# DEFINES - CPP macros to be defined, e.g. something like +# `SPECIAL_FEATURE' or `CACHE_SIZE=1024'. +# HDRS - List of directories to be added to the local include +# search paths. +# LINKFLAGS - Flags passed to the linker. +# LOCATE_MAIN_TARGET - Directory where the main targets (i.e. applications, +# libraries shall be placed). Should usually not be +# tampered with by the user. +# OPTIM - Optimization specific flags passed to the C/C++ +# compiler. Usually you want to use OPTIMIZE instead. +# OPTIMIZE - If not set to `0', will turn on optimization, i.e. +# will set the respective C/C++ compiler flags +# (i.e. the OPTIM variable). +# STRIP_APPS - if not set to '0', will cause all generated apps to +# be stripped. Default is '0', i.e. no stripping +# SYSHDRS - List of directories to be added to the system include +# search paths. +# WARNINGS - If not set to `0', will turn on warnings, i.e. will +# set the respective C/C++ compiler flags. + +# Examples: + +# Globally turn off debugging: +# +# DEBUG = 0 ; + +# Globally activate debugging: +# +# DEBUG = 1 ; + +# ... e.g. like this, for the `add-ons/catalogs' directory and all its +# subdirectories. +# +# SetConfigVar WARNINGS : TOP add-ons catalogs : 1 ; + +# Turn on debugging for the the directory `Languages' and all its subdirectories. +# +# SetConfigVar DEBUG : TOP Languages : 1 ; + +# Turn off optimization for the `rez' directory and all its subdirectories. +# +# SetConfigVar OPTIMIZE : TOP rez : 0 ; + +# Define the CPP macro INSANE_DEBUGGING_LEVEL to the value `100' in the +# `lpe' directory, but NOT in its subdirectories (note the use of the +# optional fourth parameter `local', which works for both SetConfigVar and +# AppendToConfigVar). +# +# AppendToConfigVar DEFINES : TOP lpe : INSANE_DEBUGGING_LEVEL=100 : local ; diff --git a/build/UserBuildConfig.sample b/build/UserBuildConfig.sample new file mode 100644 index 0000000..67cf7c7 --- /dev/null +++ b/build/UserBuildConfig.sample @@ -0,0 +1,61 @@ +# UserBuildConfig +# +# Sample of a UserBuildConfig file. It is a central place where the user can +# set variables affecting certain aspects of the build, such as debug, +# warnings and optimization settings. The file is ignored by CVS. +# +# The following variables can be set: +# +# CCFLAGS, C++FLAGS - Flags passed to the C/C++ compiler. +# DEBUG - If not empty, will turn on debugging, i.e. will +# add respective C/C++ compiler and linker flags and +# the CPP DEBUG macro. +# DEFINES - CPP macros to be defined, e.g. something like +# `SPECIAL_FEATURE' or `CACHE_SIZE=1024'. +# HDRS - List of directories to be added to the local include +# search paths. +# LINKFLAGS - Flags passed to the linker. +# LOCATE_MAIN_TARGET - Directory where the main targets (i.e. applications, +# libraries shall be placed). Should usually not be +# tampered with by the user. +# OPTIM - Optimization specific flags passed to the C/C++ +# compiler. Usually you want to use OPTIMIZE instead. +# OPTIMIZE - If not set to `0', will turn on optimization, i.e. +# will set the respective C/C++ compiler flags +# (i.e. the OPTIM variable). +# STRIP_APPS - if not set to '0', will cause all generated apps to +# be stripped. Default is '0', i.e. no stripping +# SYSHDRS - List of directories to be added to the system include +# search paths. +# WARNINGS - If not set to `0', will turn on warnings, i.e. will +# set the respective C/C++ compiler flags. + +# Examples: + +# Globally turn off debugging: +# +# DEBUG = 0 ; + +# Globally activate debugging: +# +# DEBUG = 1 ; + +# ... e.g. like this, for the `add-ons/catalogs' directory and all its +# subdirectories. +# +# SetConfigVar WARNINGS : TOP add-ons catalogs : 1 ; + +# Turn on debugging for the the directory `Languages' and all its subdirectories. +# +# SetConfigVar DEBUG : TOP Languages : 1 ; + +# Turn off optimization for the `rez' directory and all its subdirectories. +# +# SetConfigVar OPTIMIZE : TOP rez : 0 ; + +# Define the CPP macro INSANE_DEBUGGING_LEVEL to the value `100' in the +# `lpe' directory, but NOT in its subdirectories (note the use of the +# optional fourth parameter `local', which works for both SetConfigVar and +# AppendToConfigVar). +# +# AppendToConfigVar DEFINES : TOP lpe : INSANE_DEBUGGING_LEVEL=100 : local ; diff --git a/documents/ChangeLog.txt b/documents/ChangeLog.txt new file mode 100644 index 0000000..2a8bc00 --- /dev/null +++ b/documents/ChangeLog.txt @@ -0,0 +1,52 @@ +since 1.2.5 + - prima implementazione di una metodo visivo per vedere il drag di un canale. + - fixed big/small view per i canali e i gruppi + - le info di cache e dei gruppi sono salvate come attributi della + 'archive' directory.. questo rende possibile più usi di BP. + - se l'archive directory non esiste, viene creata! + - groups : + - add + - rename [ICONA??] + - check channel + - remove group + - da fixare il riordino. + - fast browsing (da testare e finire) + - multi selection (da finire) + - per channel settings. [DA RIPENSARE] + + +since 1.2 bebits release: + + +-release 1.2.5 (riassunto dei cambiamenti per gli utenti) + + - better MimeType recognition (after downloading a file). + - Fixed some drawing issues. Less useless re-drawing (less flickering while checking channels). + - the 'archive' folder can now be a symlink. + - Fixed a bug that prevent to load preferences in the Light version. + - Added a paperclip icon for episodes with enclosure. + - Added a "Check for updates" feature + + + +- added "check for update" + - engine + - setting + - menu + +- added 'paperclip' icon. + +- fixed the light-preference bug + +- archive can now be replaced with a link to a folder. + +- removed useless printfs (Committed revision 57.) + +- speeded up the redrawing function in MainController: now the Subscription view in not always redrawen. (added main_win->RefreshSubscription(SubscriptionListItem* row);) Also the EpisodeList gains a LOT of drawing speed.. with the function ( fView->RefreshEpisode(dx_list,sel);) + + +- introduced ActionSync (later should be moved to a libfunky, and maybe do a libcurlaction.a with action based on curl) + +- fileType fix: se non viene scoperto e settato il filetype dal downloader, si chiede a beos di identificarlo. + +- fixed CLV color drawing. diff --git a/documents/Difference_between_version.txt b/documents/Difference_between_version.txt new file mode 100644 index 0000000..cb5d805 --- /dev/null +++ b/documents/Difference_between_version.txt @@ -0,0 +1,124 @@ + + +Difference between version 1.0 and 1.2 --------------------------------------- +- Added RDF and Atom support +- Better multilanguage support +- Added bittorrentfeeds built-in OPML directories +- Extended podcat OPML list from 3000 podcast to more than 10000 podcast +- Zeta (multilanguage) and BeOS R5 (english only) +- better players integration with a new Auto option +- online opml directory + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +BePodder Light is the basic version (free download and no time-limited). +The registered version adds some nice features + +- Easy to use yet powerful Graphical User Interface +- Handles all news/podcast feeds in RSS 0.9, 2.0, Atom, RDF and iTunes +- Fully integrated with BFS (BeOS/Zeta file system) +- Integrated podcast, videoblog, imagefeeds, BitTorrentfeeds, newsfeeds and Iternationalfeeds built-in OPML directories with thousands of feeds +- Advanced channels/lists management with drag and drop support +- Support for more than 10 languages +- Easy to integrate with other applications like BitTorrent/ Installer / Unzip / etc. +- players integration with a new Auto option +- BePodder is 100% adwares/spywares free +- Support for multithreading podcast download (available only in registered version) +- Small Channel view (available only in registered version) +- Support for Proxy (available only in registered version) +- No limited number in channel subscription (available only in registered version) +- Automatic channel control (available only in registered version) +- Low price 15€ only +- Zeta (multilanguage) and BeOS R5 (english only) +- You don't need an iPod or any kind of MP3 player to use and enjoy BePodder +- The same licence-keyfile can be use on to unlock BeOS R5 and Zeta version + + + + + + + + + + + + + + + +BePodder will be shareware, and in a very altruistic move by the team, they will donate 20% of the sales to Haiku, to support their development. Like BePodder's quality wasn't a good enough reason to buy it, you now have the added incentive of supporting Haiku through your purchase. The next beta stage will begin next week and a final version is expected around spring time. The main features include: + + * Easy to use yet powerful Graphical User Interface + * Full integration with BFS + * Integrated OPML Podcasts and Videoblog Directories + * Built-in support for RSS 0.9, RSS 2.0 and iTunes + + + + 1. Easy to use yet powerful Graphical User Interface + 2. Handles all news/podcast feeds in RSS 0.9, 2.0 and iTunes + 3. Fully integrated with BFS (BeOS/Zeta file system) + 4. Integrated podcast, videoblog, imagefeeds and newsfeeds built-in OPML directories with thousands of feeds + 5. Advanced channels/lists management with drag and drop support + 6. Support for more than 10 languages + 7. Easy to integrate with other applications like BitTorrent/ Installer / Unzip / etc. + 8. Support for multithreading podcast download + 9. BePodder is 100% adwares/spywares free + 10. Low price + 11. You don't need an iPod or any kind of MP3 player to use and enjoy BePodder + 12. The same licence-keyfile can be use on to unlock BeOS R5 and Zeta version + + + + diff --git a/documents/Releases b/documents/Releases new file mode 100644 index 0000000..1152ccd --- /dev/null +++ b/documents/Releases @@ -0,0 +1,22 @@ +- Added Icons to splitPane. +- Replaced the application icon with the old new by zuMi (Haiku only format :) + +1.3.0 ALPHA 2 + +- Better OPML Parser: works also with ITunes exported files. +- Fixed VLC loading + +1.3.0 ALPHA 1 + +- Redrawed Add Subscription panel +- Adding Import OPML +- Fixed bugs when removing a channel + - if it was the last channel the right list is cleaned. + - it actually fire a new channel selection. + +OPEN BUG: adding a channel fuck the selection of the current selected. + +1.3.0 +- Fixed open directory bug +- Fixed setting filetype' enclosure bug +- DISABLED check version \ No newline at end of file diff --git a/documents/comunicati_comunity.txt b/documents/comunicati_comunity.txt new file mode 100644 index 0000000..e7d4f07 --- /dev/null +++ b/documents/comunicati_comunity.txt @@ -0,0 +1,80 @@ +During the next BeGeistert (8-9 Dec, Milan - Italy) , Funky Idea Software will show the new version of BePodder mediafeeds agreggator for BeOS, Haiku and Zeta. A tool that brings news, journals, broadcasts and images from all around the world direct to your desktop. + +BePodder Light is the basic version (free download and no time limited) that includes many cool features: + +- Easy to use yet powerful Graphical User Interface +- Handles all news/podcast feeds in RSS 0.9, 2.0, Atom, RDF and iTunes (up to 10 feeds in the Light version) +- Fully integrated with BFS (BeOS/Haiku/Zeta file system) +- Integrated podcast, videoblog, imagefeeds, BitTorrentfeeds, newsfeeds and Iternationalfeeds built-in OPML directories with thousands of feeds +- Advanced channels/lists management with drag and drop support +- Support for more than 10 languages +- Easy to integrate with other applications like BitTorrent/ Installer / Unzip / etc. +- players integration with a new Auto option +- BePodder is 100% adwares/spywares free +- Zeta (multilanguage) and BeOS R5/Haiku (english only) +- You don't need an iPod or any kind of MP3 player to use and enjoy BePodder +- The same licence-keyfile can be use on to unlock BeOS R5, Haiku and Zeta version + +The registered version adds some more nice features: + +- Unlimited number of channels +- Small Channel view +- Proxy support +- Automatic channels check +- Up to 5 enclosure downloads at the same time. (multithreading) +- Low price, only 15€ (BePodder team will support the Haiku project donating 20% of the cost for every copy sold) + + + + +------------------------------------------------------------------------------------------------------------------ +Funky Idea Software (http://www.funkyideasoft.com) proudly presents BePodder 1.0 a new Mediafeed aggregator (Podcaster) developed for the BeOS/Zeta platform. +It helps you to find, subscribe to, and download multimedia contents. It +allows you to easily enjoy audio, video, images and news published around the web in RSS format. Screenshots can be found here (http://www.funkyideasoft.com/screenshots3_bp.html). +BePodder has a cheap shareware licence (15 euros + VAT); this allows the authors to provide support and updates. They will also provide support to the Haiku project by donating 20% of the revenue of every sold copy. + +Main Features : + +- Easy to use yet powerful Graphical User Interface +- Handles all news/podcast feeds in RSS 0.9, 2.0, and iTunes +- Fully integrated with BFS (BeOS/Zeta file system) +- Integrated podcast, videoblog, imagefeeds and newsfeeds built-in OPML directories + with thousands of feeds +- Advanced channels/lists management with drag and drop support +- Multilanguage support +- Easy to integrate with other applications like BitTorrent/ Installer / Unzip / etc. +- Supports multiple downloads at the same time. +- BePodder is 100% adwares/spywares free +- Low price +- You don't need an iPod or any kind of MP3 player to use and enjoy BePodder. +- The same licence-keyfile can be use on to unlock R5 and Zeta version. + +The demo version can be unlocked by purchasing a licence-keyfile. + +Right now, only Zeta version is available. The team is also working on a BeOS R5 version that will be released soon. + +banner url: +http://www.funkyideasoft.com/logos/bepodder_ban1.png + +---italiano + +Funky Idea Software (http://www.funkyideasoft.com) è orgogliosa di presentare BePodder 1.0 un nuovo Mediafeed aggregator (Podcaster) sviluppato per la piattaforma BeOS/Zeta. Questo software ti aiuta nel trovare e scaricando contenuti multimediali. Ti potrai godere audio, video, immagini e notizie pubblicate per tutti il web attraverso il formato RSS. Immagini del programma possono essere trovate qui (http://www.funkyideasoft.com/screenshots3_bp.html). +BePodder ha una licenza shareware molto economica: solo 15 euro (piu IVA). Questo per permettere agli autori di provvedere in futuro a supporto e nuovi aggiornamenti. Inoltre per ogni copia venduta il 20% verrà donato al progetto Haiku. + +Caratteristiche principali: +- Semplice e potente Interfaccia Grafica +- Supporta tutti i feeds nei formati RSS 0.9, 2.0 e iTunes. +- Integrato con BFS (il file system di BeOS/Zeta) +- Supporto multilingua +- Facile da integrare con altre applicazioni come BitTorrent/Installer/Unzio/etc.. +- Supporta multipli download contemporanei +- BePodder è al 100% libero da adwares/spywares +- Prezzo basso. +- Non serve un iPod o un player mp3 per usare e goderti BePodder. +- Lo stesso file di licenza può essere usato sia per sbloccare la versione per R5 sia quella per Zeta. + +Al momento è disponibile solo la versione per Zeta. Il team sta attivamente lavorando alla versione per BeOS R5 che verrà rilasciata a breve. + +banner url: +http://www.funkyideasoft.com/logos/bepodder_ban1.png + diff --git a/documents/elenco_clienti.txt b/documents/elenco_clienti.txt new file mode 100644 index 0000000..b5a2711 --- /dev/null +++ b/documents/elenco_clienti.txt @@ -0,0 +1,233 @@ +LISTA CHIAVI INVIATE GRATUITAMENTE (BETATESTER E SPONSOR) + +Dane Scott ( dane@tunetrackersystems.com ) + Rémi Grumeau ( remi@beosfrance.com ) +Bernd Korz ( btk@yellowtab.com ) +Jorge G.Mare ( koki@aequus.net ) +Frank Paul Silye ( frankps@gmail.com ) +Maurice Kalinowski ( maurice.kalinowski@yellowtab.com ) +Daniel Texeira ( daat@iscomputeron.com ) +Begasus ( Begasus@skynet.be) +Kim ( bem@jcom.home.ne.jp) +Alan Westbrook ( alan.westbrook@yellowtab.com ) +Steven D. Blackford ( kb7sqi@yahoo.com ) + +######################################################### + +LISTA CLIENTI CHE HANNO PAGATO DIRETTAMENTE + +Christian Celona ( christian@celona.it ) (pagata a Giuseppe) + + + +########################################################## + +LISTA CLIENTI A CUI E' GIA' STATA INVIATA LA CHIAVE +--------------------------------------------------- + +United States 7 +Germany 4 +Japan 2 +Brasil 1 +Sweden 1 +Italy 1 +Portugal 1 +-------------------------------------------- +totale 17 + + +17)Registered-To: Paul Artz +Email: paulartz@mac.com +Postal: 15 Channel Center St 310, Boston MA 02210, United States +Total Amount Paid: USD 18.22 +Date: 2006-09-27 +Processed: 2006-09-27 +PaymentMethod: card +Invoice: I530387774 +TransactionID: CHQ9PQZJG688 +Comment: Though I don't have a Be up at the moment, I wanted to help ASAP. Even at that, I waited too long. +Note: SSL from 66.171.79.179 via KOOP 5.6.4aen for supplier 6FCQZ. + +16)Registered-To: Armin Hald +Email: a-hald@ti.com +Postal: Freisinger Str, Langenbach , Germany +Total Amount Paid: EUR 17.4 +Date: 2006-09-16 +Processed: 2006-09-16 +PaymentMethod: card +Invoice: I529452879 +TransactionID: CHQQ1YSTHAW7 +Note: SSL from 212.144.156.73 via KOOP 5.6.4aen for supplier 6FCQZ. + + +15)Registered-To: john skinner +Email: olivero604@comcast.net +Postal: 604 olivero rd # 13, modesto CA 95358, United States +Total Amount Paid: EUR 15 +Date: 2006-06-08 +Processed: 2006-06-08 +PaymentMethod: card +Invoice: I520840924 +TransactionID: CHCNWD7S3D3K +Note: SSL from 67.187.147.82 via KOOP 5.6.2en for supplier 6FCQZ. + + +14)Registered-To: Liz Holt +Email: lizholt@mac.com +Postal: 7510 W. 57th Ave, Suite B, Arvada Colorado 80002, United States +Total Amount Paid: USD 18.32 +Date: 2006-06-08 +Processed: 2006-06-08 +PaymentMethod: card +Invoice: I520782913 +TransactionID: CHC5HK3K1WH5 +Note: SSL from 71.56.221.226 via KOOP 5.6.2en for supplier 6FCQZ. + +13)Registered-To: Edward Falis +Email: falis@verizon.net +Postal: 26 Topsfield Rd, Ipswich MA 01938, United States +Total Amount Paid: USD 18.3 +Date: 2006-06-01 +Processed: 2006-06-01 +PaymentMethod: card +Invoice: I520198475 +TransactionID: CHCTXFZ5T7Q6 +Note: SSL from 70.19.195.67 via KOOP 5.6.2en for supplier 6FCQZ. + +12)Registered-To: Kristof Doebner +Email: kristof.doebner@arcor.de +Postal: Kristof Doebner / Kattowitzer Str. 27, Muenchen Bavaria D-81929, Germany +Total Amount Paid: EUR 17.4 +Date: 2006-05-27 +Processed: 2006-05-27 +PaymentMethod: card +Invoice: I519740154 +TransactionID: CHQYRXYY2TYN +Note: SSL from 84.56.50.122 via KOOP 5.6.2en for supplier 6FCQZ. + +11)Registered-To: Mats Borg +Email: mats_borg@bredband.net +Postal: Värmlandsv 8D, Karlskoga Värmland 69132, Sweden +Total Amount Paid: EUR 18.75 +Date: 2006-05-20 +Processed: 2006-05-20 +PaymentMethod: card +Invoice: I519142904 +TransactionID: CHCE5FANUXAY +Note: SSL from 83.226.1.6 via KOOP 5.6.1en for supplier 6FCQZ. + +10)Registered-To: Christian Winkler +Email: bestellungen@cwinkler.net +Postal: Bothestr. 23, Leipzig 04155, Germany +Total Amount Paid: EUR 17.4 +Date: 2006-05-17 +Processed: 2006-05-17 +PaymentMethod: card +Invoice: I518882946 +TransactionID: CHCUQRSJSA22 +Note: SSL from 194.138.39.54 via KOOP 5.6.1en for supplier 6FCQZ. + +9)Registered-To: Adam McNutt +Email: kancept@nylonoxygen.com +Postal: PO Box 4018, Hailey ID 83333, United States +Total Amount Paid: USD 17.82 +Date: 2006-04-27 +Processed: 2006-04-27 +PaymentMethod: card +Invoice: I517196426 +TransactionID: CHCQVMDFQE7T +Comment: Sweet! +Note: SSL from 204.134.212.146 via KOOP 5.6.0en for supplier 6FCQZ. + +8)Registered-To: Daniel Alexandre Arsénio Teixeira +Email: daat.teixeira@gmail.com +Postal: Av. Sto. António, 63 - 2 Dto, Tercena Oeiras 2730-164 Barcarena, Portugal +Total Amount Paid: EUR 18.15 +Date: 2006-04-27 +Processed: 2006-04-27 +PaymentMethod: card +Invoice: I517178335 +TransactionID: CHCX0W731C28 +Note: SSL from 85.138.152.213 via KOOP 5.6.0en for supplier 6FCQZ. + +7)Registered-To: Andrea Bernardi +Email: bernardi.andrea@gmail.com +Postal: Via N.Tommaseo, 3, Scaltenigo di Mirano Venezia 30035, Italy +Total Amount Paid: EUR 18 +Date: 2006-04-27 +Processed: 2006-04-27 +PaymentMethod: card +Invoice: I517147269 +TransactionID: CHCNNS316S18 +Note: SSL from 87.5.240.235 via KOOP 5.6.0it for supplier 6FCQZ. + +6)Registered-To: Bruno Gonçalves de Albuquerque +Email: bga@bug-br.org.br +Postal: R. Voluntarios da Patria, 41/603A - Botafogo, Rio de Janeiro RJ 22270-000, Brazil +Total Amount Paid: EUR 15 +Date: 2006-04-25 +Processed: 2006-04-25 +PaymentMethod: card +Invoice: I517015790 +TransactionID: CHCJUPFUHNFK +Comment: Thansk for this great program. +Note: SSL from 200.165.235.197 via KOOP 5.6.0en for supplier 6FCQZ. + +5) Registered-To: Joseph Allen +Email: josallen@newsguy.com +Postal: 715 Hidden Creek Lane, North Aurora IL 60542, United States +Total Amount Paid: USD 17.68 +Date: 2006-04-23 +Processed: 2006-04-23 +PaymentMethod: card +Invoice: 1081312031 +TransactionID: CHCG0X8ACH8E +Note: SSL from 67.184.27.203 via KOOP 5.5.2en for supplier 6FCQZ. + + +4) Registered-To: Gregory North +Email: gregnorth@sbcglobal.net +Postal: 11355 Richmond Ave #1507, Houston TX 77082, United States +Total Amount Paid: USD 17.68 +Date: 2006-04-23 +Processed: 2006-04-23 +PaymentMethod: card +Invoice: I516810978 +TransactionID: CHC8ZE2V8F5S +Note: SSL from 67.65.166.129 via KOOP 5.5.2en for supplier 6FCQZ. + +3) Registered-To: Toshihiro Kodera +Email: mizki@gem.bekkoame.ne.jp +Postal: 3701-6 fukami, yamato kanagawa 242-0011, Japan +Total Amount Paid: EUR 15 +Date: 2006-04-23 +Processed: 2006-04-23 +PaymentMethod: card +Invoice: I516805500 +TransactionID: CHCKWPRXU4T1 +Note: SSL from 210.79.164.82 via KOOP 5.5.2ja for supplier 6FCQZ. + +2) Registered-To: Koichi Kimura +Email: bem@jcom.home.ne.jp +Postal: Igusa 1-15-4, Suginami-ku Tokyo 167-0021, Japan +Total Amount Paid: JPY 2168 +Date: 2006-04-11 +Processed: 2006-04-11 +PaymentMethod: card +Invoice: I515798726 +TransactionID: CHCX17JHTQ12 +Note: SSL from 203.165.232.114 via KOOP 5.5.1ja for supplier 6FCQZ. + +1) Registered-To: Sebastian Bernstein +Email: sebe@blue-cable.de +Postal: Moltkestr. 19, Plauen Sachsen 08523, Germany +Total Amount Paid: EUR 17.4 +Date: 2006-04-11 +Processed: 2006-04-11 +PaymentMethod: card +Invoice: I515787525 +TransactionID: CHCSM2XQPRDD +Note: SSL from 62.117.2.174 via KOOP 5.5.1en for supplier 6FCQZ. + + + diff --git a/documents/email_betatester.txt b/documents/email_betatester.txt new file mode 100644 index 0000000..4d11464 --- /dev/null +++ b/documents/email_betatester.txt @@ -0,0 +1,49 @@ +subject: BePodder testing + +body: + +Hi, +The BePodder Team is looking for beta testers for its new application: BePodder. +You can find information about this incoming application for Zeta here: +http://www.iltuosistema.it/news_sing.php?id=282 + +If you are not interested in this kind of activity please DON'T reply to this email. Discard it and sorry for boring you. + +The software is developed and compiled under Zeta 1.1 (build 13538) +We can't garantee that it will works on different (newer or older) O.S. versions. +(Please notify us if you are going to test our application with a different OS version) + +What we expect from you collaboration: +- Your ideas and suggestion for new features and for getting better the one already implemented. +- Your help in adding support for your language. +- Your help for finding the best podcast and videocast in your language. +- Your reports for bug or strange behaviours of the application. + +Before we can send you the first beta you must have a look at the following EULA (end user license agreement). +Please read it carefully (it takes 20 seconds) and replay to this email by confirming that you read the license and you agree with it. + + +Beta Test / End User License Agreement (EULA) + + PLEASE READ CAREFULLY: This EULA is a legal Agreement between BePodder Team (BPT) and you (either an individual or a single entity). This Agreement covers all software, data, documentation, written materials, files and information ("Software") which it accompanies. This Agreement takes precedence over any other agreement embedded within the software. + + Confidentiality: The enclosed Software is Confidential Information. You will not disclose Software or any comments regarding Software to any third party without the prior written approval of BPT. You will maintain the confidentiality of Softwae with at least the same degree of care that you use to protect your own confidential and proprietary information, but not less than a reasonable degree of care under the circumstances. You will not be liable for the disclosure of any Confidential Information which is: (a) in the public domain other than by a breach of this Agreement on your part; or (b) rightfully received from a third party without any obligation of confidentiality; or (c) rightfully known to you without any limitation on use or disclosure prior to its receipt from BPT; or (d) independently developed by your employees; or (e) generally made available to third parties by BPT without restriction on disclosure. + + License: BPT grants you the right to copy the software onto a single computer for your internal use. You will not use, copy, modify, sell or transfer any part of the Software except as provided in this Agreement. + + Restrictions: Except as specifically permitted in writing, you may not: (a) Copy the Software except as provided in this Agreement or elsewhere by BPT. (b) Sublicense or permit simultaneous use of the Software by more than one user. (c) Reverse engineer, decompile, or disassemble the Software. (d) rent, lease, or lend the Software. You may NOT transfer the Software under any circumstances. + + Ownership And Copyright Of Software: Title to the Software and all copies thereof remain with BPT or its suppliers. You agree to prevent any unauthorized copying of the Software. Except as expressly provided herein, BPT does not grant any express or implied right to you under BPT patents, copyrights, trademarks, or trade secret information. + + Term Of This Agreement: If not terminated sooner by BPT, this license to use Software expires one year after the date of delivery of Software from BPT to you, after which you shall either return all Software to BPT or shall certify that the Software has been destroyed, with no copies of any kind remaining. BPT may terminate this license at any time without any liability. + + No Obligation Created: Provision of any Software under this Agreement is experimental and shall not create any obligation for BPT to continue to develop, productize, support, repair, offer for sale or in any other way continue to provide or develop Software either to you or to any other party. + + THE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. IN NO EVENT SHALL BPT OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, LOSS OF INFORMATION) ARISING OUT OF THE USE OF OR INABILITY TO USE THE SOFTWARE, EVEN IF BPT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + SOFTWARE IS BELIEVED TO CONTAIN DEFECTS AND ONE PURPOSE OF THIS BETA TEST LICENSE IS TO IDENTIFY DEFECTS. YOU ARE ADVISED TO SAFEGUARD IMPORTANT DATA, TO USE CAUTION AND TO NOT RELY IN ANY WAY ON THE CORRECT FUNCTIONING OR PERFORMANCE OF SOFTWARE. + +------------- + +Best Regards, +BePodder Team. diff --git a/documents/email_user.txt b/documents/email_user.txt new file mode 100644 index 0000000..5ea7b1c --- /dev/null +++ b/documents/email_user.txt @@ -0,0 +1,16 @@ +Dear BeOS/Zeta user, + +Here is your purchased licence-keyfile for BePodder 1.0. +We would like to thank you for supporting us and we hope you will enjoy our product. + +For support and updates please visit our website (http://www.funkyideasoft.com) or write us and email (bepodder.team@gmail.com) + +Please unzip the attached file and read the file README.txt in order to install your keyfile. + +NOTE: If this email doesn't contains an attachment or if it's corruped please contact us! + +Best Regards, +BePodder Team + +Funky Idea Soft +http://www.funkyideasoft.com \ No newline at end of file diff --git a/documents/feeds_per_prove_su_formati_particolari.txt b/documents/feeds_per_prove_su_formati_particolari.txt new file mode 100644 index 0000000..9e75899 --- /dev/null +++ b/documents/feeds_per_prove_su_formati_particolari.txt @@ -0,0 +1,7 @@ + +Formato feed +------------------------------------------------------------- + +.3gp http://spreeblick.com/category/toni-mahoni/feed/rss2 + +.swf http://dok.info/rss/podcast.php?feed=videocast \ No newline at end of file diff --git a/documents/license.txt b/documents/license.txt new file mode 100644 index 0000000..b45ecf3 --- /dev/null +++ b/documents/license.txt @@ -0,0 +1,20 @@ +BePodder for BeOS/ZETA +End-user License Agreement + +NO WARRANTY + +BEPODDER IS DISTRIBUTED "AS IS" AND WITHOUT ANY WARRANTY AS TO MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE OR ANY OTHER WARRANTIES EITHER EXPRESSED OR IMPLIED. THE AUTHOR WILL NOT BE LIABLE FOR DATA LOSS, DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING OR MISUSING THIS SOFTWARE. + +Any attempts at reverse-engineering or thwarting the license protection scheme of this software is prohibited. Any evidence of tampering will be investigated and may lead to prosecution according to all applicable laws. + + +Distribution of the Demo version + +You may copy the Demo version of this software and documentation as you wish, and give exact copies of the original Demo version to anyone, and distribute the Demo version of the software and documentation in its unmodified form via electronic means. But you should not charge or request donations for any such copies however made, or from distributing the software and/or documentation with other products without the author's written permission. + +Registered Edition + +One registered copy of BePodder may either be used by a single person who uses the software personally on one or more computers. + +You should have received a license key which is necessary to enable the registered edition of the software. This code must be kept in the strictest confidence and must not be given or revealed to anyone but the registered owner. Failure to abide by these provisions may result in severe legal penalties and will result in revocation of the license which will cause the program to no longer work. + diff --git a/documents/link_a_directory_internazionali_di_podcast_e_RSS_feed.txt b/documents/link_a_directory_internazionali_di_podcast_e_RSS_feed.txt new file mode 100644 index 0000000..48815b0 --- /dev/null +++ b/documents/link_a_directory_internazionali_di_podcast_e_RSS_feed.txt @@ -0,0 +1,25 @@ +Link a directory internazionali di podcast e RSS feed +############################# + +Argentina---------------------------------------------- +http://www.podcast.com.ar/ + +Australia----------------------------------------------- +http://www.digitalpodcast.com/browse-australia-8-1.html +http://www.podcastingnews.com/forum/links.php?id=27&sid=6901b11f54b75a5ce93df08ffff28cad + +Danimarca-------------------------------------------- +http://www.overskrift.dk/ +http://www.overskrift.dk/feedsearchresult.php?q=podcast +http://www.podcastdirectory.com/search/keyword.php?page=1&search=Denmark +http://www.podcastingnews.com/forum/links.php?id=301&sid=c4d2a069267a5609d039c0fac51c137b +http://www.podcastingnews.com/forum/links.php?id=300&sid=1717a8e0b8c65056f640549f8343dfcf +http://rss.spontek.dk/ (Newsfeed) +http://www.djh.dk/ejour/arkiv/RSS.html (Danmark, Finland, Island, Norge, Sverige ecc.) +http://www.syndic8.com/feedlist.php?ShowGeoIPLocation=dk%3BDenmark + +Ungheria----------------------------------------------- +http://podcasting.lap.hu/ + +Russia-------------------------------------------------- +http://podstars.ru/ \ No newline at end of file diff --git a/documents/lista_siti_di_news.txt b/documents/lista_siti_di_news.txt new file mode 100644 index 0000000..97dbe8e --- /dev/null +++ b/documents/lista_siti_di_news.txt @@ -0,0 +1,26 @@ + +NOME LINK CONTACT +------------------------------------------------------------------------------------------------------------------------------------------- + +IsComputerOn http://www.iscomputeron.com/ daat@iscomputeron.com + frankps@gmail.com + +BeOSNews http://www.beosnews.com/ stephenb@beosnews.com + +Haiku Podcast http://haikupodcast.com/ sikosis@haikupodcast.com + +Haiku News http://haikunews.org/ kianduffy@iol.ie + +lebuzz's Xanga Site http://www.xanga.com/home.aspx?user=lebuzz dane@tunetrackersystems.com + + Haiku OS Il Nuovo... http://latere.blogspot.com/ agenio@gmail.com + +BeGroovy http://www.begroovy.com/ news@begroovy.com. + +ItBug http://www.itbug.org/ andrea@itbug.org + +BeBug http://www.bebug.be/index.php Begasus@skynet.be + +JPBE http://www.jpbe.net/ webmaster@jpbe.net + + \ No newline at end of file diff --git a/gfx/100/add-channel-button.png b/gfx/100/add-channel-button.png new file mode 100644 index 0000000000000000000000000000000000000000..4ecda99da1fd17e1365d237a39ef20feee622c39 GIT binary patch literal 3104 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 literal 0 HcmV?d00001 diff --git a/gfx/100/bepodder-logo1.png b/gfx/100/bepodder-logo1.png new file mode 100644 index 0000000000000000000000000000000000000000..a16cb83dc6e5207ef0b18367b88f50bf6d5f8a47 GIT binary patch literal 3931 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 literal 0 HcmV?d00001 diff --git a/gfx/100/delete-channel-button.png b/gfx/100/delete-channel-button.png new file mode 100644 index 0000000000000000000000000000000000000000..2b1f063be7fe54f9aee8c654726356ebfbedbd29 GIT binary patch literal 3695 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 literal 0 HcmV?d00001 diff --git a/gfx/100/delete-item-button.png b/gfx/100/delete-item-button.png new file mode 100644 index 0000000000000000000000000000000000000000..96de244eff75e68d4bbd2b705879b0236bc4f8c4 GIT binary patch literal 3413 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 literal 0 HcmV?d00001 diff --git a/gfx/100/delete-item-file.png b/gfx/100/delete-item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..305beecb0df26a10976ba8f0bd5cb83c8e9b3706 GIT binary patch literal 3238 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 P00000NkvXXu0mjfyE%*G literal 0 HcmV?d00001 diff --git a/gfx/100/done-channel-file.png b/gfx/100/done-channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..5e52db118a44392e06e39033e41cd44bd6d74ec6 GIT binary patch literal 3257 zcmV;q3`X;bP)VOKfmm&kDnm;=9_O0S1Ofv0QBCYj`sybw9U+u zen{};0o7{t&xoj3QIzlZ_V)gprfH>nSF`NtIsGW+p1B=#sfzSNabN#pSH`NbRtw@Qd z|Lbq%%$@rA4T47iAQ%i*RaK1xs6I?`-FlCI?;Fn!Zre9iT?dXGtBI}y%oq^@-<|qR zdgM-q`I-VmRR1falvQ7p-6venT@8NjZ=N06w%0{C3?xr>;hD+b2LQbF&Yxp;&PJht zL1ujSiQlEC{{1g+_k@-R5JE6&tlt;poh|<6TVLsaZ~5&m02m+rDf{Eky!0a@6!8FH zdF^WO5B~1i;az84>Fy>Z$8?-ee;$L8+Qa_&sV_nBS1~(ZK%pQ9fe(}5dl>|39#E}T zz4n=SIIid3RloGgFOF{J*8=Zfdnfev)qm}N`8Qr)B4WJw&F7Bp*y~DnH{;}(fhSYH z1tSzg-rWEI7+ODm=JfA?#b0A~E{{UN8)U|J9{)5=)B|Hn9)McR=(q=5U%R4y;gz5J z$d0|C=sF`Fuc^7VR>7@8F7U-yp8p5{Y}@OB?rz4|2?IZQ{8teQcB9~~-!@h#*p0`> zejP;L!p!V09LF2c7+(bNhrr#%fR1{=qBX7k(LcU$EMMGEy1NBVj)igZ$TAS3mv6kY{AT}-y{;}SY~bX{fx9N5X8cXqb_vADDFRRZ^XKnv zGX$Wv3^KFV2{A&w<bv1kv}D^ZOtY5IFmp=+0H(PP+jha!*m&Or5D|z7%q%?5 zL#Je<@3j5d=PyjxNGQTIZ-R&*gzzOq1k=0;+b+UTdqLdT_?8LSYwvYZj`mOHKXd*< z#@Htz2cS6#0KqhK`^Nv$_}9_Qc;5sZAVNqf(P1BHB@3HnlnhYI)Rskm24lh2Q?!3zrS8PQnjyCr_w7`5)Gd*CM5l z|MWk6FB%#>n7p-*006?*sBOYX-=zJik6pNIgd(Lv!G>wxfRyihf|P)1-aw&X!w5x6 zpZeH^%SZdt_5ppHqU9Lid7iwVl8BxzeDcX}|3KFwr9z>A+1W*GZS7)fYZtS#izpNd z(6vbElTUv82Z`wE0swA10SAZ>QcAktG88%OeBz_8UheLS6^lg&i;GKGTwFr2=%BkR zR{X?AU%fmOIqgU(X>Y^k8!cyoMD#%3rVjT`7C!gP_x|HM?|pUj#>V%f0C2SLCvH7G z{)OdGAhMsH@9F4!+*WskLP~jWIqE$?Q+m7?Cjaz0fa?dZe?TYE3IQ!m0j{q(4>4NR z@ovrp+k%aa4dv?9t6cz)N~P?+zP?JEhHhyJw44ezlEuYE-84ADVG*D*0MQL-#cV`lE@=>ZXmd_Es& zRBj@jNrZ@q8%a1EmPEwc+uMPI<*lu)01@%%=xCXUcx7cpi$4h#%bJzwRT)TFy%kw-D zi^Zg>s@%>P(CV3BQ^HcIRQb}SOUmZvX27y6Z)j+!GBq{jZf$LGC=?_>-=Wr9AK7n-JV zDwV1*Gn=LvDwRr#VHh+#JS>Swj!% z(=WV`@pxRuVli2%RJd3yiu!daB`+^82c?wE%p|4cga6m->g|igqNr3V z9E-(dJRbKG{X4S?9GC*W**$aSOl5a>*E0-*>iu%LoKh?nmD*v3gs$rn0363*W=64C z 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 literal 0 HcmV?d00001 diff --git a/gfx/100/done-item-file.png b/gfx/100/done-item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..e91ec58912ae580f0f08531540813b9b3818da46 GIT binary patch literal 3036 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 Z`9HEvB`nN;650R&002ovPDHLkV1ia9!G{0< literal 0 HcmV?d00001 diff --git a/gfx/100/download-channel-file.png b/gfx/100/download-channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..eaf98dcddde0e9b4595d32acd6a7f957f817e92d GIT binary patch literal 2764 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 SDaaH600009?#}&uFZ)TUfBv+2u^ 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 DloB}E literal 0 HcmV?d00001 diff --git a/gfx/100/download-item-file.png b/gfx/100/download-item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..cb8c3debc7e27e051c06eda1dc12534070919c26 GIT binary patch literal 2550 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 Eg299P)Bpeg literal 0 HcmV?d00001 diff --git a/gfx/100/emblem-download.png b/gfx/100/emblem-download.png new file mode 100644 index 0000000000000000000000000000000000000000..9d1c25aacb6283d64bbb152c8111f55ad3af78f9 GIT binary patch literal 835 zcmV-J1HAl+P)oJ0CF}IGcN)_kDi%Ip=cE6;-94!_?Is@Ocr< zO-NhDVH~9gXmyb<3QX@9Zl1WNzubC@+Y-!8NSiv$0}(HvQ3d-bgxViKxT~Z-6raU5xA?vQBAj;X z@1B6rDgvPITMsGzP|0FeR!x2G=v*sZG; zU~d9zo&jo>z#agt!xH>I30MFg6R`eO0$u?sO&~fYEg86-fj)sw*!LEw_a(^J{g@I3 zP*^bV+Q5DLlCB;IfMG(Q&nnWi$^<%r8>(~w7xNbjK1L$3H*5j^mJVoa_U7evY;VBo zHvp1t7YIYvxPVjDSbQ}GQk%IuHJqu-6gT$-0I)eD zmj#{zmfwbkA`m+XIk>DwB=4Ar_q&`bOFbVjq9DtKE2ZsG8^;J3j$_4;% zzDU1n79w{kEyA#Mygc)Y0RYmoa$evbfWlp0m%go}PsISW8g>6W{sWoc18*ynmx%xX N002ovPDHLkV1kRHVjchh literal 0 HcmV?d00001 diff --git a/gfx/100/emblem-enqueued.png b/gfx/100/emblem-enqueued.png new file mode 100644 index 0000000000000000000000000000000000000000..774b3e3d7b5932c261d8cc7e54a3efc9f2b079db GIT binary patch literal 1218 zcmV;z1U>tSP)VMXd9Ro&?pd{-im?5Ku>|`fPLMnaNU^@XGrT_ z)qMlY79a&jS`j?~R3HLRK0&B@H5=Cksjn`kc1;m=Yl_+45XMeTaES94GgB`%mF8R@OQ!kw zt6>g)bP*jIp3a1|O`Sd0=i{=U0?Rv!N(G@H!41{C{YnL8VZ%r=os-D*a+k0qXlU6I z=F|EroI5roopQuG1~kpbWxNMu#pmsaX~wdkzJ{HRD^LRo+gs45(&Y3ry$(Htlk99< z0rfRtSzt_~lpfo?a0bL2Km@8+Q(YS&T3Nt|z4&A5rnC2d?R7ZUp8_CSSwQtO5eCPi zFnAl_1K>oK0ErxLz*uz@1_-Q+vUy!G3ENwg9KgK?^3x@oQ&*jgwax2_xj7oe9g4$U zw^ky@8+7#5?#v8Wfi_Txl(I5Xh?5qa+-1+Osd@i_?|U3hUUG7vgq4v(;*nAq9s{He zxJQ67Exv#-g++#u)Y9Ytt|tI|bKd6Lo?PU<6&4wYgds5jNXyLnoB$yT0;|HPWk{s* zyCvPUa-z%O>n?jyoLUA}g<(Ko?heVwfWNpZOiG2x$-Maa?01_l&MtiNSpn)F4r3M+ zFuh_Jy_+97z`@R?$!9HK=6G@lhyk_SNkOCPy7+kys(64{*nC+}Gb1mjwjDg-En3&GQ!|*#PxH{yY-kA3?D6{&3x?ehhW+Fj& zX#Zt60Lyy~V}==@g!BJ^B~W1Q&n5_N~7j8rME&n^jf!%ufh5Vb++0FI8RS}T6wmet>l_i-D@Lv*!lm6$wNpPlSLYzUY zy?SBW^4szZ(3W%Upa+2b2NQI^_B1`%V3GyidcFbAYXe$<==6AoKb8>#P9a_g-Hi`- gG<%fx*r((F0iq$oZqi`yhyVZp07*qoM6N<$f>Et7FaQ7m literal 0 HcmV?d00001 diff --git a/gfx/100/emblem-error.png b/gfx/100/emblem-error.png new file mode 100644 index 0000000000000000000000000000000000000000..30e1758927e107697b790c73cc61e91912f92129 GIT binary patch literal 792 zcmV+z1LypSP)#9Tx(A~}I6 zfpK6kL|(G+J`PVGT3ZV9matbaBa$=1642`cdn`7^GV;jULMKsZ1>%NhKyP<9ISgeI07h#`a1wDs={_T=x&$X zE(ZW=Sc(n+^CI9Cg3`LAR|viWh55(;`zdBs@ftg@R}UJjQ|{HFu>-1ju{bXy1KeM; zbya3n!CP~9`n90^MtM6?w6(|p0HVB71#i^>V71wR!W$QFCxD59&8t$VSD?D}@8+v+ zLA?U16eo&y@xlNAMED>A-#@@ z`PXM^Qa$d2$hiSpyCMo*J!fm`+ef?L4`*Ljp%Ff+!p1l7eMn_brtb&WRKfg@|G?)F zxrUG@{D88FWn?tp`9RVN=L(GGZNZ0OHO#3}Qf=<}?JTKb&WB;w#o-(k_+N49r{h1^ WZ_$t^7E*Em0000lMd;=h1j%Nn=@-WF?Yf#}J|rZ-N{{xXB{Wg~MGGZ<=!9Zu$wbEcYXXW_Rf) zXz40}RCXXFiwl9qmtKOELTN~xKx$*jLVl4fX=IJ8nJ(m+Dzf~dv{Njp!-6<+{tsZhZ|PsaH;apl`v3}HX=y1eB2PtR)-Vh*nGBgs2E#BAk#P}u zIE-@u5qT&g;{)u?ipbNYrKK={w!FMNEh5j|ou|`jE?>Uv8T$C~BXmPJEP%TJsZ@%Y znHl#RYinx&zXE<}1=GBQFsokm31+}y-8%~{}qJbU)+J&?J2^(yIf8eP``XfztE zudlPQu>sJrZTknuaef2bI%D&H7m+7QsfU1XYHEt<>1jft5CE-Ki$bB`M&g4eB4aL6 z+qSVR3(KZcki%mo0*vzVzC&JNCcnHH!${{PKQdR!p_bPpFe*_DaG~c*V*0OrBo{QtM39g z#Bm&6ym&DM{DJOi7huwH9G|9XwA*ds@i^1d(?lYXGt%FcN~Oa3`a0X&+l-8iaCmr# zh#UetfK8X+et+-Yy$$JQLRVhCeEGfOIDc{+N9nrGwQJXiL?S4q&IQ1>Z7P)t@87@2 zvMfZTBO>1|EG#_f*BxkaVPWAfz*D6Zu~^JIY_@Hm>j4M^0z{)x7xa@s&H=QOcA=Eg z0Yae=N-59qc||FOVHlLlWke)+lHQ2`L}VTy7z}zPI*f>j_b>k?tn&jCZ;yk616-C12D_;>P17Tn(a}*RCMF03 z0{&;>wjPOiWCiS-R&+K{y;Hl}cfn zCQ2#B$H$4sX=TgR`UQP5(yHC#EEu> z2H=M7Gy~;w8Gy;j$rE+XO2I%Xe*OCO_agFV5fNS2F$@F4Fc=#f^KQVC#Ih`EwHoz$ zoqD~FWmz~~`R$!McaE{4IF7^0%F40J2=Hl|cB}-m+3cwR^7;H1?@B2S4-Wy3T}HQW z-`lnq1K=LMei<1V@c<-~Nesgv5C~8#7TMa`>Q~-Pzf34Rw@KpMfiH-@YB_+}+vHssCi#_Drc%^7;LKFPg6O_^K)qSr!or zg#xB&dW#~`OQ&VWaegNvzx1x3@ceS5Tkf-gh+vu~g+jr7|EneS9M4H}Jx+m0h5{{;T1=I7_vMdTY1`AI}57K@ms`Naiu z)Hx3&BJ%1Kdq0WDo%#9sO^=9HS65FRPUq(4h8j*+S65FRPUq(4_Mwjn^ZES1@jRQ& ne${xM&*uk@=hAn~=vx&9 zDTN|}Kj@Rs5i9sqh!o#yl12?#F|C`~O)~py=K8Rm$xL=O-Lyg<95^g9_uTn@=6lZE zoh#N_9^|19R2@h~Pevys=e77qU<}xQ=W@xyRqHW1bJ6}D&41=S+0)nJxEdC&eQtlb z7XS%L@ZuRc=ozj9LtSzmFU66WPumcq6O!{={0!s(EAXw?8$}7*EC7Hs2l02)p#R5ctACz>{ZF@{>x;lQ4! z7<>9Og$RVzyF+wwpd5=N2aIeuP;XUOYusjd@Nq`-uTjYF3?U@7HAEsnt?9%f2|%Lx zttxI~1-G%nQ1(%dJa&>oK0_v>s4`;uyF=W24@gh~rO~R!92?9$OfmN|#X>fO=-bKk zv8hgo4gg~e^;RVo#+XhAOw@r&N7*tvc5~>FXDJp2$YczvjO_54KD7xVxdg3BEE0Pl zl3#CCJ6v;{EA*$*9N7B=#lm0+;Sq-j7owoU+c$LLHr;s(;@5&-q2aCK+eT7}Q8nz{ zeSl&?x$)ZywVF5L!)4%9R|htiV5@b&7(>%vrS3Uh1M$f28lX_vLni~Acfx8{n!qU}rW)rkPfR&F{MKmxd}KP#+-g@u1`oEoZ> z5l#nV_YM%rH^yu!K0kj8$8k}mtjhS6sf}-k#3oESI-0Nt2duT+yt$0ytYeh2h4Cv> zb|#wB;Xt>i*{opA~8Rx7yf zI;t$06eliC^ezsOjmeo$;OW>9C;xcd);XL(f%WUb7-FLQ zxSZqdsfT6izXF&(AaP@OOcl~;A)OXfL4>1IkBD;>09A-YlQ=5 z7^t#c4S%}xknH`;0JR=@-jOcO8}J^(heLpejknQHE1#1``tuCMFn8rEwfZ zh5qUahgU05T3K9Uk)9ZLPCUryCWlx|QRUXK@S{%!Set!>vB4=ke*w>5U~F)TOeWG& zVYLFYAO4Pymgic&p1(jX@EISPVr;AzV?dQ}i->#@V9hxY>f<1gjK@O^ZA=pHP2&1F z0OGw#hBhY2=P%>Bwe`S7V0doMd%q@Q)`8vSFGZ*(oe-Y1zT#aJ5! zYf1nR751t!uL{0j#~9OQi9~O+2NGXDA-9CWIF0QnBofh%F^#w=#xzdUP#CAJ2LNV{ zTUV4BRVbIMsA`*yjPw%@E2?ZW!n?pPR4LZ$bzFC)V~ncex+~P{byQjExtZCH001V$ z?^U5vsdmgH8V$2;+c3%GIwBE+8tzc#iYjEY#jXluv&E)zr)D0o^{xOf9plf&aLIMc zT~+Aq4Kpz@#O=3_Vhk9=urYjGE?4k8zs=wCe9Gkt#_+K*{A~4lZ2%T)Rrsxl<-&y= zBHA@8V@&I#q{>elDik_oUugNvJYkow2>=lE@B>xe@%C!f`DgKDR^EP z*R8CoeFe`eqe>wNc;=I9bp)7s)Rx8YO*Is9xg{=M%y(6y2{7}7T{fnv!osTT7p{J^ z+OzKp0Px}wd(OajRS9yrMds$tQZBdGw+R4XO;d#uu3N@+%XnT1RSMR$XMarqfL|Z6 zF9Uap@{aHOy!YN&KKS56ve`UWu6P7Num<3TL$;{O$%YC!ve{g7{^SdX8h6Rh1OV`x z!}g7vme^?wkBeBZSS)hsQkMDobIi{Et#MUT-fa5U;FKy$uIu8uE~+fm;8eHwcfA#N z8sGc54257%0Fxq20+YZ6YkBPXhwW=kzlWZcFI&sA03z&rZr^{d^ZygT|6|w} literal 0 HcmV?d00001 diff --git a/gfx/100/emblem-remove.png b/gfx/100/emblem-remove.png new file mode 100644 index 0000000000000000000000000000000000000000..d2e9219f46f6511a319a518e8a70665676ec8f83 GIT binary patch literal 475 zcmV<10VMv3P)Z#_d@y9(U`dxFBQ(aC$yVIXvnppz#9gH|CS zgvBjZoes95S)E3_%>T4AhxvV&nf>nyr4;KdYpv-9U;qYS0Dv<;*e?rzJfbR~1Qax9 zbrsarn95^Kb&^SuwBmy^vCV`h6gkboKWktMb{jWS#B2wo;9A+_G8xF{A)VHn8b#3S z!Enf?fGgl+0bo0n0DNC^a(Kzk)}B^Cr{Co6{(^QphUpQr0FZKe=GknDvHIlst)Uf= ztSw~>bN6coaK4{XsT42o58A_%wH+s1m|Ft4uFLD7xe|cuy0e^r0jsP(0aDTh3URFP zyp5HFhv5fO0?=IoI1Y8-I0*U_iv>JS?|T@A5kb&TcA&lluw2fq2}e;h%(Yr=t>N<} zC4-SoB^itPpVHG?;R{7|q9_TWw-qZz*AmnPRBGj4TJgGS?O#I!FaQHEfG_yEXnxcZ R?$7`L002ovPDHLkV1iGU%B27R literal 0 HcmV?d00001 diff --git a/gfx/100/emblem-stop.png b/gfx/100/emblem-stop.png new file mode 100644 index 0000000000000000000000000000000000000000..cef341bc3f168e77301ceaac2cbefe5c4808e448 GIT binary patch literal 1293 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 literal 0 HcmV?d00001 diff --git a/gfx/100/index.html b/gfx/100/index.html new file mode 100644 index 0000000..8dee7b2 --- /dev/null +++ b/gfx/100/index.html @@ -0,0 +1,89 @@ + + +Index of /mushaspot/50/ + + +


+
+

Index of /mushaspot/50/

+
+
+

Thumbnails

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+
+ + diff --git a/gfx/100/item-button.png b/gfx/100/item-button.png new file mode 100644 index 0000000000000000000000000000000000000000..f1610af4eb5ceb38baf3ddee769fabe5c5671b89 GIT binary patch literal 1936 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 efSV?8)A$djl9kwyE>{Bp0000L2`%aNu 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 literal 0 HcmV?d00001 diff --git a/gfx/100/kill-channel-file.png b/gfx/100/kill-channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..f84a450716259249349b640bb65e53f9fe468c50 GIT binary patch literal 3562 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 literal 0 HcmV?d00001 diff --git a/gfx/100/kill-item-button.png b/gfx/100/kill-item-button.png new file mode 100644 index 0000000000000000000000000000000000000000..32e64368e9c8f1ec70b97e8ee45bea109695eabf GIT binary patch literal 3660 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 Pbr8_gGSaNpu#5UX#k2k$ literal 0 HcmV?d00001 diff --git a/gfx/100/kill-item-file.png b/gfx/100/kill-item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..5113e25deb3935abdcf9b7b8f839a56fc64d1c52 GIT binary patch literal 3372 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 literal 0 HcmV?d00001 diff --git a/gfx/100/play-item-file.png b/gfx/100/play-item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..0b45a30b6b13eb444fa2a23c4b2f56f157533de4 GIT binary patch literal 3080 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 N002ovPDHLkV1f~K(RCt{2 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%0DxpN zsfWYiW={qlFkTPiT=^?R1Vn5{cz#yN<#Ni##)jgizPh@qGRBZGhO4WqDkAcYjSVH2 z%bm18ul^*Kb{6E;3cR|Yt`@Mfvm+aZL1M9(rK+matquUtIhL;LWOH+qQc9ia>1l&8 z*0t_N?!x}2^83HNJ-xBB9K6q}vYS3`38>FmS7I+7{P?@S-i%+m(kYLp7~shQ0Dw4- z!_O+3rZqX|yjrc2ZuRZ$ZE0p^rcNofDW&$z%uIcIdt2h1b4}Blj^prZwMx3x&nr8X zP5CE(c>P-D?kAU6qbiFcKrahxROQUwPcHrRkFQ_bzL!nIi`R z0jE-_V69dY$HvB*?fSvNfiyNY)|{N2v?`T~oX_X!<;$0Ae!t%V00@Obb|#bY0{~7= zPFetf2L}fd0AL^xZ~y>nwVK#jKTp;_efaj3hJ7TBi~x*{0jR2%m7Wh{0Oc}(uIu8T zKmOJ9FMsft6@Wfp$h2d?S?z+sU=slN;o+fxh&&t)H}2lOtK{=}`T6IcHzJWpV{UHl zh%qJD#-)YO!rs;V7{L>l#ao#gX*831@V9Bv>YKRi4X0DuRB!DcrZ z+HBoh4vHc`JTAeTul@!m!;5Z~>Y6VqpTqnA_&IEDHel=CaY`st@5(0Y>Z+_|H^^2#fRgb?7I zV@n{a3EpKg}wiC|CxNos&; zSLF_w`u8T>Itw}zN~sfxL>ha0d(z6vin_3{P@kQhWz}j`s?}J$nEnK4FG zRdoOW7-OVRD9G`6+%gP<)M_asYsF}@nkZ|TraG(GFg_P zQ2X3%H&4j2d@@f5{c}NXjv{(q@whcLHDv<;GRCA_E~gPfaCUZ9_xXGX0Iq^urvmy(d!Ej{>Fa%fn?~c~ARqipO(x%Gb~P0M}X;1OYBwxWJ+HWH^ok*=$zD4(UwO zBo7Ll&1ThDEY>81fGCQm#_+=Tzxi(dcQ?NsWbD4UwzlcDyK6M+v%h!!ot@6T>FZ&f zm-d~MN+rqdWksn}qOn-4@u+hF07OP!uzz;r@2h`Z`bF%E%6|g7^*`xx#(NN-9BNF4 z7w*6D;yXK$k;_eR8JixY=UI?xnz**Mrf8bxT)A?^0yy#g6aX+9jW!Mr4g_7-PmSgC z`J7-dXcvn`X=`hXMx#-?9Sb%#HspG}P7;ZPsVIu;$e7{VaNx58B z5K*9%lEuZvhNfxA7!%X!v}ReBc$PeaE?)MuCs|N7n^hQNg5U3VQmK@sC<;RBoTpeU z%7{o3iG>-D-LisGp`+vB&Uay{NxP0tn3 zG4MkzAdyJe>2zAqbzN9mTB0p0-~a&A)6?x=(s_D^n30&pVl$mi%et-$%gf8Bl<>HirishT%d%k@==b}1DwS$>y16F} zFBahSN>VthD2hT-sg$j08tS?(WV2bNTYE1ho6Rb^t_zx`VJelf6-6Pv8oM9GOBU1< z7u1GQ3aM1e&StZs&*#Hlxd=_u5E0?()vNZC{Nz6ho^Qm?YpW;<%+1ZUFHL$9B&VmR zIUN5e_^I&u{mg=%iVYYvUwIljteWl-#s;>w<0pzz<8M5=5iX>`)00$F}XYQt4#h zZ@KB?>Z5(RTyFT$K5x`G=ktj~;@pq+xl#ZCz~<&=ywPa9hsWQK8-BL(;gmS%w>al- ux!HUG4+p_5bpwbQz>;mL7q+wB60xS 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 LNkvXXu0mjf2!HUx literal 0 HcmV?d00001 diff --git a/gfx/100/stop-item-button.png b/gfx/100/stop-item-button.png new file mode 100644 index 0000000000000000000000000000000000000000..12d10de67dc65a7761c4e4002e8b7c73fe7f83d7 GIT binary patch literal 3170 zcmV-o44w0dP){QUFJCphQ70`Q4aYP5@O`hN=% zWdYn~jQ#Sn&pvz7Qk_8|{q6q#{s#a)X{Ao9Ibak3Ow$yGVI-AOqSHpc$ry%_G)=Rvo0jrqs~%AQ zErN)6JLTK*002D?IG>C6fFI?6 zo(G&kS8_m;aMm-x*$`1%%R4;}xL~?E3PLpp^bBw|UC#l%9h@`hY7W2~J__vu08oAf_SXGT zFTd3{`m?`X=7trtB8M^73qhTb|MuVCf%LUlEQYbMF#y2M&JN1u!|2Yh|KS6sg@RE3 zSfT&@&mQZsLHA{Hdc)8T35wY`V+>>C z#2Cy-1YkMXSLqkLU+}vE{ zr#8e119-)H8v!L6Q%$7=Akj$5N(Kl;tcDCD5~<3Oeh4+aytX-DW@e^x_3Bl(P$=+1 zp`g`2_xAR*yLaze@4ox4ol2$Jnex99Cq1A5psHXfRlSCq9h3lMwOQ4W6aqO1jk$=|cMAP_9 zM1ZVLY#Ym5%?4;Xmr4OL0IR$(KwVCgUfRk5ZOz(PquaEP>$oKwUpEu>x-%lvd))`~f-b>Utq*B!| zR6AFw8KHiz6qN7*QK=p^4`^0PyEnFkLZMDzK)R+l$0FyPP4%~itTupA#B z_XY+Ag0H^%DwfOT^lUb(kB*LBNH|jYhY9uQ_8duHZ(PeQzjGo4)vq@x{{%03`3r;8 zI7Q#x3qh~46fr+P?>>6;2&GbqA0Hp{d_Hg7yLT@%Jw5GAOiXyuXcTjEbKdgua(HcR z%^DaOD4C}DN}))($02O}ZjK;yJraQ#jlwCH;X96oCIcubA%uYMd5}`V^E`+kK;TuM zz^vFdxTZl00nRzNrh#(~YU=&Xy6NhEK%3`w0o0Ccc6L`vv-IE*XrOaajpqIMSL+z!h5 ze60|HIEThLVu|*jJ#O-Vj&#%Za&#v*`7wrJ;MT2M?$*|pT3uZ=H#RmRgM))A91hF* z`FZcoojalZ{e8oAUGJ5=z%52W1S1v$BEvu=37A(9ttHQLK3@wb1oTY;kr99!XUp_T zKzRqK>;g(PC-d%kK$8L5wzBX0^z`Xd{n@i;Apl6FQr^VGgsNjOws@NFBYJO?xrAPum_5rG6ThV0|V zV2nYxis%~`(4sAPL39LAKHwZQJU}(+rrQ&-GjUy)R#sNbNF*XBCnvpo_wGep*KIWJ zhaY~>c6N5;haY}u>$o z&dxf9VYKWKYH+$hd&`0JJ(bX>e;u}Mn+**O1>4)(hU>aK5{byEsVNTtHa0dwwr%t6?QLUn za?%ThLa;1Ll}aU6DwXv9{(cdU#}xoNK0ej}__l5Hy}doHTrTrWCR1tE2o$n}y86)* zwsrfuTPP4Q2IGnZm{|=yOmD0MaZMr?GU2;rNIM6nofC?xig{sxCf!{4Jb-F3v$oxK z>fw2wwzRZlIgX=SmPK=ObHVfH&ke>HpPrr;$z)O`lSwr_JuMhxJe$oL^}6wR9E>qu zE|+y8;{E;o^>dAg_}tuFU|AM9j-xLvEm@xDX=k(bKFl3A%#STq`yi;Ih{VHh+#JS>F} zGMP-uy0Pg6tS;}`wQIt09G*-jB@wZ3IE=~3$$*Fy5i!#=k;!D-Z@&4)v~8O&EiFYB z7Z+O&M`~cYBpG|EZQq&ji$x;FpvU7cEzh*pBC`?#j4>!~1k_;;Xe+6{te35=t%WO< ziWZGVDU-?grfD)F;+0B8%jffw?E(Aj7Ec3!kGrB?Oe~LKF%hDWRgn6*>4`iGYsg0WJMa zb!lly0l?JM)aJ{|)bc>cwrv)PL}WUh_SzXTo<%og^TLy;p1nIv((ib7FTz6=f9#{2 z3Y~mtYhz>M1^}ef>2od7$&+!X5)Oxv$z+0>qWJpyy0NgZa3OzZU0+`hIgZ0D%Tnod zIxq~QHht|Jb!D>RM~Akx{AwSSvtberC*gBa;!L@U8$y~1S6Jh=7-IW@bhhhH+u9S5P4f{z#?>pxB{^Q-5DKXTs!V+p8vXWp&rnq%4@Y4_crpA4?}yL2W%5_0!Sa zqL%|MnM>V}>CqlN59k8j2tio@qf*Ls&iQPo4SO39LaY$c9|6d=Qohv?bQ{25WwTkN zQmM6`5l%-4v69U;^nSaQIxVe+K79DF_tL)hC@7^CW@l%goL8_V0|3D0=H`U&`@f>< z`{R1AtvsEqQtGx+>X)r3A85k>J-S10RCCGn3~Px# literal 0 HcmV?d00001 diff --git a/gfx/100/stop-item-file.png b/gfx/100/stop-item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..c3bc0dc13ab98a772f3b3b3c81327f1eaf29ad8e GIT binary patch literal 2952 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 Z_&-7=U!n^eKKlRw002ovPDHLkV1k1e-a!BW literal 0 HcmV?d00001 diff --git a/gfx/100/www-channel-file.png b/gfx/100/www-channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..c3f2f89ea6a7961b0292e1f9ef48e8bcb7c8db42 GIT binary patch literal 3424 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 literal 0 HcmV?d00001 diff --git a/gfx/100/www-item-file.png b/gfx/100/www-item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..6985fdf2ed3e4158ee44fe50ab84130305ecb4ab GIT binary patch literal 3207 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 literal 0 HcmV?d00001 diff --git a/gfx/50/Thumbs.db b/gfx/50/Thumbs.db new file mode 100644 index 0000000000000000000000000000000000000000..b6c6b72206e541fe7dd7d628b62eb37be2c03c13 GIT binary patch literal 81408 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

*-j~Q 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 IM6N<$f))=NasU7T literal 0 HcmV?d00001 diff --git a/gfx/50/add-channel-file.png b/gfx/50/add-channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..2ee36e0beb559069318e43016f03e609fd034a9f GIT binary patch literal 2124 zcmX9%hy*qMOw5gI;77kEO`0(q z_~BT%lj0}rQF$6b;uHv|>sEDj_0ZludxFu;<+%@T7K_XC%EejNC$-NaR7l~zrR%=W z&+^nabn&eCcn*I~=cwqbt(`OTbIGiiy?pdx=D`Mhl8W#TfRKy;S65f(loZ{L=;-L1 z!eyg=uR1Y2oUjbf8Mg3jc?0m&Ysyp|qzDlR+om;d{G}K1A#etdb%LAVXW-oVYku+? zY1zj(!eVn45r0_`puyXsRmATLWP+v7^L9Agk*D%mpWWHp@>^P>S91ceK0em%eWeZj znZo?+~_K`eDRS`A98| z=M9f)E|>R^T{{)i)4lfJ5}e4Q#xMlMOn~~>el*g!gjFTM@Di8HWi9Hp)`}sS6XEpE zt#ME<`i|)$+vT0+BPcV%Lju@}JhEIWMVaJXx_avxyk$&y19l3|Lsu~tcmA`)IA;jVx?MIB5qD=a2iwq7EKp1r z>UxG`1(YOV*)KoeZ7D*K7M2X2m+f~P_X3}6sN?W*_jIKWO^t!j>rkfY3y~+c88>MF zBLj5~ktO@~S!TkUf-Mw!60H5*uRCy(Aw~FDSVSTQ5e4)R;^LqSaaOs}e&OxpB;f93 zL81rFCX&?%0tiF6eK~vq(Xj@m{W->JEk)HyWxrO!zx!O#-4p24 zUpz^ln77G3*i+dgx-HH*W_(b6_93wF!S?mYoJjp)$4DA8ddo_X4tf9=cDNg+<|L2h z24}ez!qoL8%_Q0f<~Z!_fAU?3?}37gI)m1;G1+gBFUa68Je%o$RjQ)P1IC8nA$&z$ z2FtL*vysD-@U1u-6}NUIAJXgfu;BA-UU_Nhg7#7JP#KNeugtf5%;9hZd3kwD?}mpL zv1{LJG{yy8-TT>xsiL zm^NV&8NV%ul<4b_wc>w2aOB@jNH2S7S6gdqD`s|k-}8nze~CmwjC+!%{KC@{wwgG> z3l0u;O-)VZvAS2CHV3En$B--0yHIl?_t;daKSO1<-M)whOj*bVZpRO^egx-1er_&q zZ1Q=7zsS~06e`Ne!P=}-LG5Qmq2W%T92q}-C9vE2eQ7X~qsW(j0pUu$EpdDV5^BqG3s#PVZN#=nA zOP=oT=80c7I@h|K?_yi7U|$e8ZaBrBP-#3%>I2RpQH?*gV(_O~w085EULm;~(D@X( znk~I{4V8_Iv~c?{JdRRRT**997{c2`kmM}Ko%6?`vVNFTNY{cfG#j^zvJ{7 z@G7rrl*B;qWM67Zb8z~6!G_w@i%8tt>xBTKEN<^00 z$b)*2_|LGryE|U~M;rc19G5#Tn<&Brl&s=-Q45XF`ujOS>GPEP5{a2Lbq}PQb{gPk z>m4vAAD`NdTkXqu(Fy3^;7z7Tc>JB#@j+ePl#tD4A7U0Fp~E(VCD>|g&8tVrKBzv0 zkVd010+4pkI+!B734e5>(JD$ZJP#Vn(AW*siNm5BMieFxRbR8wZRD$qGmEkgLY;@z4#lSLAAsFq`*zibvM&7(fFZg# literal 0 HcmV?d00001 diff --git a/gfx/50/add-item-button.png b/gfx/50/add-item-button.png new file mode 100644 index 0000000000000000000000000000000000000000..ad04ac5e1bf2fca389d1600bde4050daf805d318 GIT binary patch literal 2105 zcmW+%dpy)xA3ifb2F)-sa!HtS%_YXjir!{Wa?ND1s@-NpBb!27Erppe*re8!yi6(6 zr%jSvYAan$#<=7%T3)tjr+qKhh)!J16 z0K?Fb?a>H&B8#YxLH3wI)j9-pk^>?G0BHI(TeZ9NYcVk-Iud|W4gj#Z04&1@$^kfm z9GqeR;8zZSd0P2x{vZH)ZK2x(Vlpcas9~5QqG154&AZ=7ULHeK75~28G^xnq5|)kxHb}iWeGXD>{Ry zVC5dYPDd_zP$!|nk9S%SsxN~6?L@r>QdWYx!;ECg!}uu0e0}fktofByPP8)@%J}0| zk5XP0CrO^{?1`wOexv4QfoVtHNI!}SKJ-A;NLI>6R4`GEKlj%b|I0}&>ZiS>a$7Mt zzEz|tALhr|UfYmZGd9~7JfeEHM5pr;Y#71|dH}6|*aXdC8BuFekZ$oUL8t=vqK5c7jpN5?*H3{ItIp(kIrDK(C&_4+KH+ z1T5A!hKeaQ33uz6hF`$y9<^fWXC`lFMTM5EUS2Bw(4{KIA@n6@!hfS6tNtC7To&^b zyu7))L`vspZP8_Mz5HnYt`9AMJ~5R9j+v7CGb}>&?UxjjQSG;)s_tc^r>hCZ#>#Gy zNMSx@S$C}f6(<;%NZ+~prbY4JcFcJA2K>6B)?n|iyR$(w;<03@McS`R|y$Wbz>iBSwNh!WO7g0th4`hMNGW9J&^EzGA`3dj3r&UB`o zII&w!5p4ae^Vxxa!R+ssv@Y~)-t_N6xenQ8e~ZVm{O<62-1!}EUw zI_>RrCT*0Z`cn4c{l}YLm%ZX|mJg}!z9%iXgdR8VuE(McoU zE9Jj%IaTmR(XE-ZH++74MPpeYA}Ch^Ip_vfOd>+LniX-TYVk4g@{xdhy*(p~& zI6U0UuIOlMlVL*)ga3d6h>U{?IzDMEQueYY4;3e7gjc6`Xp%7#-!S%_F^ING3=jJH z{Tz4@yJC$sMBY>}A(JJMyuH;&4jx=kbeDTfmv8!EY9g9EM8=*+GiDd5SQ2>rwgKe5b}+w z@nn*7BfH`%Dta;RY--_m4f~sbbw~PSpY_8TX$yIyi;LEqOjhO0%Xj}%VoTBL`Mk7b zdv~aoX86>pf`Wp8^LuD1m>-FrjrWgfu#akUo~RFP{QTVC<4wTwn5w}eVrpva+_Ptu z?=2EAn1#FhB*+*mOC{&atSj~Y-h4oMxppOYd12DZ>0t!!-)W4wChJ_G-vXhVKP{$7 zUyz#a-SYzBSK+X*FjoEk=dTQVgi^6sY`HC4DcodlKW{G2d}vF_^&D-^;Qp|0pGuEr zG;P3p%z|NNf7#EPdY3HaL<2?2r`pKhOy6Eyf)DR9GuxJa0XHXxnycAU@cBXaTqXt&$CS@!TYIGr27rh_E1 zs6!%9zibnBICLtPq_!soVUD~j0XO{!ziklCezkA+;DG;fJv(C<(MminvKni?Dc#D# zLXAGl{a&PBd!9oA!+5WCF>UD6kv+of*4jIFR95o!jtn_>Ye@pBUkP)V4{YPEWr|PD z4CTbpvN}42t?#SL;Lz})Ps8*=da7p*uka ziT4}RJ!kKww+6|iaElv`=Up;};$5M3t$v3?{Gz;Qx2fo@tPMmD<^><+jT6E(Mbp() z@+T<7!6R{Zv$d~lDO4A>nHv$W4lGA(IW<&H@h0G1@KiFXkc$|-2%;90aLQI&H72w} zuiEA_HU!Mt%BwwykFJL!;ajN3z8STqF>(N!cRysDLc`qwsG6)foseO{*K#n)ZxA8H eaQSr#8$ci)qU~L{idjOkAB67MwY@%&k@tVfMa{+l literal 0 HcmV?d00001 diff --git a/gfx/50/add-item-file.png b/gfx/50/add-item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..33a78db308f6f8451cdc982161aa078e9c138ada GIT binary patch literal 1962 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 literal 0 HcmV?d00001 diff --git a/gfx/50/bepodder-logo2.png b/gfx/50/bepodder-logo2.png new file mode 100644 index 0000000000000000000000000000000000000000..1e317469eb00dab4e8c8419b7926ce125b434c27 GIT binary patch literal 2631 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 literal 0 HcmV?d00001 diff --git a/gfx/50/channel-file.png b/gfx/50/channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..83ad18a8bf4a434590992577f4fb6436c2890b69 GIT binary patch literal 1345 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 NuXmu=T~Aid{{e?YYIy(v literal 0 HcmV?d00001 diff --git a/gfx/50/delete-channel-file.png b/gfx/50/delete-channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..cc311384876698148072bf7df0709352c400233e GIT binary patch literal 2191 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 literal 0 HcmV?d00001 diff --git a/gfx/50/delete-item-file.png b/gfx/50/delete-item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..1f248476f926be06f362bc6df692d3056043c032 GIT binary patch literal 2032 zcmWkvX;f3!7Cy<%1cW4vCIS*fks?SSXmO~yK^qVeK~YgrLMTQHOIiWZ04CR9z?ot# zNU6j^pA%?M7ScL!859CMf-@E|@DLG=1q?L_gxnX-TKjxI&idBc`}@w``*=)rxV`OM zTL6Ilx`?%#tjL}X3dwqBNFAjU=2ld33v!klLq7o9Y zBkn7|jBLrvbL2v6x_KnUi0;V~7g5H$1apRANlRyWIYaq%r!2A&8ueS|s_0LH1-c51 z3UK*@Kp+r|Nij1cpH+Q|!dRFk#gsKMKagh!-BC1trN3ODiSta5-o;)%U#vZ% zz2Dic?m{d7xup3#-IuM{Ih|fJZK&{ay^;Y%tb{>QDA;@Wc3s_M&boE#%kVO%-JL8J zt2BN)w(IKkpTxbY=)XgsBYYp9g29*9!>QH%9=hyni(kdFFb*?+ZjfJ<3)hTU&LgL5 z&W${>++B}hNfc6<3S!GR?r3Z4f(1*KSOk%gk$O!9Pdf2R)7AVL>mOdPt9apG98&ls zg^@iWG)_z|gPgdFaNm*m$Xlj52E5yG@Lee`=uODDp>G>$wMW0kc02Lr z{^-%-o;_1m{jM~FtuujX1$eh8{Q?XhPH4_ajlNv>*U%zTbnI#chB28%+)z$U@V!5$FAiF+CMF_|O(@!H z<4C5k(_(=gqJ^hzTpi()$c>q4I`clZ{S}KD&uk3h%orcZcHaY#9C0ZP=kw_&d}s#? zL#-y-;flOrukjKkB>TX;z{L8~Z~h`}tlB2%JC7j0&3QXd*YWKZgf<`=c#u<`71YYLt}tqSR9G8>K|qyMAFl)L!RgJ*cxOcZu!10w}u02Ls4ys5I7RcuiX)BHW4!>i{ZGIcoIVYzCK~5JS$Ts|Y&XrKRm2m;w zd^!VW6778nFmNWugb%bzr5549vuD@>MzO{C<_Jll)gnLI`SX?&n9Mi*$-)L{*@$K) zStpg|<`*L4Z6j3bSq&#QIVJzCwWFF{@j^NXFs@hqj#p!*7T=4Tr6Uh3wAAeS4O?O| zg+k+0F)}#nF_?HOPainbkavEhyWG!y;jb7~igb9orx@{3`L$?OJ@lP5qrpfhN=b-_ z+hEgm^%NCjJ^WlYmdkK8Wl8&1v3!oyRyfxDH#>BLj`ssD$Zk=aHs|BzR4mUt`K2*1 zkt-t(uNKBqNdVVcxL-Xn)Rx$xR`(|-C7DPaXYzM}Y?D;rS}&FIq{0+Y3f9)HHW@ID zXBWzz(KI*xt2aFrAN0&#k}llw|?g12b!ttUD4vuq}G+@K!a^;R} z-|NBXH{gJ7tRkxG^(qY2CGxf_AFGX+VdGZe{uGhw^OQ!J4n^Lfs#?ibmpXCmJ;bC* z24ES7+USqOnv1nR;`)HuY?ksv+8rWj2rHlC6xRfvx;Syp22YGv_Ri9rycoCfL2eR? z>@B>H5FdH#o4l!?N4tMp8HJYV&z?BZu~B%%Ojb}{_(HGf577ZQpdW{)q|PUZT+_S& zJ}oVciqT5(Cl}hO zrc&-^kIgf@x-B+c5;0w zP<#A+V!E4LiPlNH)Gcfm&Cd@VZawYxbv*wU8P&nr*&N7bkJI00(7e1ZX`7pyqbgSC ziO9zrb4|sjX~S3-+N!2f|KPF1W$yHlkDgs^oVg@`r)*nI_zsNX{zH%9SmX+SNJ0Sw#)C8? z{R4YXk$^$k(QbbK*t>{$$~t&4nWE)id06DywFDirDvo|5{!%GU;0;-|oI@0n_ok+D z!R@)+p73gkL?TVHp_I-mMQBNagQ4x&8!xU(B8Xy~&BH@O(0SHCLz~NN@d37$HBMd) z`4G$Y0D$dw(&0vz@;;o z@pP#-6`nce2^R$7%l@3V%h9@Ft|d!m>(Cl1Awc1P)9zovze*ftS2$SrZS>k3VZx*T E2jT^P)c^nh literal 0 HcmV?d00001 diff --git a/gfx/50/done-channel-button.png b/gfx/50/done-channel-button.png new file mode 100644 index 0000000000000000000000000000000000000000..45add87624932e17fd147218be9a9e41e354921e GIT binary patch literal 2215 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 literal 0 HcmV?d00001 diff --git a/gfx/50/done-item-button.png b/gfx/50/done-item-button.png new file mode 100644 index 0000000000000000000000000000000000000000..cf1cf325cd4c921f5c712b7de9d5643f8defe2b8 GIT binary patch literal 2044 zcmW-ie>~Is9>+g3wqf#nn;&U%(8;ekJ9MxZNq&r$+r`xn^P_Pd?Ickl$9_a2MJLWS zxtV)zA}�JK~xQ1834v6vbj8x26dGXR{k0Ib0} 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 literal 0 HcmV?d00001 diff --git a/gfx/50/download-channel-file.png b/gfx/50/download-channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..fb12b1eb3afc10c663321480b23029c9341d4c8e GIT binary patch literal 1981 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 aDIj#)s3N1Elx#6(5WX#P>zxqEss95XRei|- literal 0 HcmV?d00001 diff --git a/gfx/50/download-item-file.png b/gfx/50/download-item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..7b9befd4a20aadc246eeb47e329c85943df19a1b GIT binary patch literal 1821 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 P00000NkvXXu0mjfP8%Dj literal 0 HcmV?d00001 diff --git a/gfx/50/emblem-download.png b/gfx/50/emblem-download.png new file mode 100644 index 0000000000000000000000000000000000000000..8cbb101e19b47fbcc3a0f56729e8432eb5df9dca GIT binary patch literal 707 zcmV;!0zCbRP)004R=004l4008;_004mK004C`008P>0026d000+nm#LZ50006` zNkl*6RSU|-2d5j2={|sLL|1xwjGcw2^EByPP;ptyyhH?fbhAl8L z)5QM_009IxfQb>VnS+s$VWO;-nhKwcEd#^9zYuXIW`<8s4)Z_0b!!69!Fzyee!vU? z2q3Tl%uEanKtTqeBs&Weg9N{fAp?_m4A9!I5LL|F4EzjV7+&7LCI06h13Sn7n9l(M z2y6fs2Lr=zpk@F5fi3&X@b5JP!?&|Qfp1V3a4~?ym{=J8G6U5y0WD-@hDZSf5ZC|? zcAy|o;`eWcKg?i>cR<^30X6-EdW{_{#=-)2=^s{B1_m~$0RRC6HsIeMu+6NjEDXXx znvsDKXu!YQK#jj4s{R3WFoF$W1csL|&;`GMdccwZ0mKA$fdqpEFbIyburpj@WoO`J zUh2l2q3Tv*hLxa8GkYu3u%I50%*+_AOnbzVwVZ% z2nl_V>lpaoU1u<66Jf9f3ZDQ7Ag~L5-e*|&_ZP$2?{9#5IDrDJP@|DCD?|>Y2B`MT z&j$>PL3#lK2y6f_;k*F)E#UiehI2p+3?Zl?$QURFk^`v$stp9{c>~f55I|r9z)odk zcmj+8|KBed&i#4;H3VimkPQ+8$$`{>)WW<65I{@}sNe}OuKj*LV>tU8+o>H+_sGc1C} pK-|CIn3_QVAb=Pt&CUP;1^_BYvh~37Q=$L>002ovPDHLkV1ns63Qzz5 literal 0 HcmV?d00001 diff --git a/gfx/50/emblem-enqueued.png b/gfx/50/emblem-enqueued.png new file mode 100644 index 0000000000000000000000000000000000000000..550145a710f0ab84d12ba52bfb84f3a2aba06664 GIT binary patch literal 831 zcmV-F1Hk-=P)004R=004l4008;_004mK004C`008P>0026d000+nm#LZ50008Y zNkl*6RSU?0L=Q1Gqmx1B;Zy@zoo`K;{5>V8Ifq_X0NCV}5-eX{p z+RMQ3WgY|buLlgQ96&K9hX3EA7ytr@1;x1k|094JdRe5Ur8IO!88kHo7)-T!81CNw zAhBo9Bdfb--=r}7V=4x!Tn^I$5I_h6{{0VUVCPt-XsgN?8>z^kAwKLZof3XnE{0Ahj|^Iw*Mk!iA&od#n}f+_2>E^_St^+rJFoftLOL$H1`W*cXNk$3HR{+DbDpD@%v~y_y2j3J^dL zFR-$?aVv>3eEHABa2==-6fggPns_-Gz?zpI|H`oO^fv|;W(EdkHWmhu+E33vxB`{c z0R#}l01h^VKZ3jrw}CeP|N9>rBn%7!zZe*%?f=TK`TP$CMv%jSn34G}14u1M4@ezA z06|^A!tjleiQ(H%MsRGxz$>5uw@&D004R=004l4008;_004mK004C`008P>0026d000+nm#LZ50005( zNkl*6RSkMJ#GBJ8H{AcK7VqlO#76)4Mgo%-%Jmug2t;pg40mO*z zg1JnLw>2EpRHPkj8UFqK3l?KyW@dPD@G!&8{kQHW|NF0ktR5hMFkHaK%pf6crNtoX z?#uA^`&Y0SGbc9#!|%5Y_Yd6?M^_IJKo|zFurvJq|LFn4xAWT>{{8v^aRD0#!~c&D zz;fv70Rjla09JMeMyBtN8U8%@$?zZQg?~UVFnxaomP1z$5I`6PFflQ_`ThAVA1C`; z2B>}ppnitmpTTl((bWS45EHt<-+v4{zPx8(;1FP7VCRKk5c~6ckR-!SboBrMgkb

pO>re*gQ=u#3tuzBGJFn8p?yu#4= v<|ZUV{rwHeNQ}&w1^@&QMrI-v00bBS)vc8*lc1u200000NkvXXu0mjff$sp? literal 0 HcmV?d00001 diff --git a/gfx/50/emblem-kill.png b/gfx/50/emblem-kill.png new file mode 100644 index 0000000000000000000000000000000000000000..4892b9df4e12173526e714780e69525dffee796b GIT binary patch literal 848 zcmV-W1F!svP)004R=004l4008;_004mK004C`008P>0026d000+nm#LZ50008p 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 FngEiNijM#Q literal 0 HcmV?d00001 diff --git a/gfx/50/emblem-stop.png b/gfx/50/emblem-stop.png new file mode 100644 index 0000000000000000000000000000000000000000..5aaf28e7c06df6ac916599a70675c2604cd51d27 GIT binary patch literal 858 zcmV-g1Eu_lP)004R=004l4008;_004mK004C`008P>0026d000+nm#LZ50008z zNkl*6RSU|+3rFkfVjK6*}{Qvuh;m=>DY6ixC`TrRhuQ4$HD`I9~ zJNKV~iGh)kk%66qok26IhXEjfn6R13$jHp_pOMv$gNvhH)67LwMp50K-TNCWxPb?q+6YU}t9s8o~-P1ZeYPhQB{QGyMPe z6NrI<`tu#oeLopEMP(ScMZ_7{*jS}OdI16m9tQva|I=jr_g{#Gkwq9}7z5C@e}8{6 zFtM-z<^D1-GW=)w2eRzb6JW&r1&XtQ^#KGB*Z{`=3_%<$Y)hCqSvY@v{q~KCi5cvy zzkhxL4f)0J=l5^03xR?RtZZyRHY?Dj5W4{a2x0)!|71RCB~A_*ZH8|T&U5|#{Ep$@ ze#NGcBla$+kh$Y{~vH*g8)DP!BXN&CT5nPzhA!Y{q^<*(3W37p??gF ztRVk_^!^0mUr-E*6(*+tuR$6C0thK7Grk4}ROr8N-?#sM_nzTDFyI(K84VQ2NcjJs zzYKrhzh+<)Qd|kr1rR_;Ng3?K_smSpk<34S*8KhTCJ>lp1)*wSSr!yEub4Q57BdU0 kc7g-|0*H~)>004R=004l4008;_004mK004C`008P>0026d000+nm#LZ50008C zNkl*6RSU?1$z-k7De}5Smm_QsL2AK&m`14l?4H3;`W@S!eVrEqM z{p;@ohJXKO{r{gj4IqFRK`y{B;2)I!4P^ZM0WysPD0WTSR9VqCNQvR?ef;{1;oOs73^y;l09x>GEl3GK0I|Ro|7T!_ zxSjDQ(An%zul!_SW&*NV*cn(D;Tf9U;|kGZ)5nw;K9Ji^q+y1k^Rfjn+y!H!VC=7Y77j|-r9q-0t65X)b=J7 zD@AQ~P8No%haPDg`zU~g&+dMprR^fe@bl|$hC64UGB9`5zId#`^2x{R0M+pi-G z%*=%#H2?twF@Tln;jL%COt_^P7(}&28ScLQ3l;{kAAMn90Ln2iurcpv`1vOm7(Oh( zaQVpa7m|Je0to5?md9_t{$;rRg_%J>ikso^Lx=$&Hb@L4$H2t&2pE`O8UFo-r429u z2q1_7%*;>z{QJ*v=PM&Hc97dwz-j;j z2x0&`%M*tGK!x0_4F5rjUVemxt*ih8!{2|9*kxyX4D>40T4n}@KYzeXfB=FRz{2vF z;SW$DA22Df0wtj?U=RQ%qTfL0gZ#@1RKpB2fCZXV85jTp2x0&m^G$}&zuz#t{VD=B z;PrQi32(o$gAM-l>kUx+CIgmq3lKoigv9(7NMtY^c+d)T?{{EAss@Yiz60blass_q n&A_Cl3=m)da=hd{&J|#000000NkvXXu0mjf$6i-= literal 0 HcmV?d00001 diff --git a/gfx/50/enqueued-channel-button.png b/gfx/50/enqueued-channel-button.png new file mode 100644 index 0000000000000000000000000000000000000000..8ad51afbbba30d76e9d3bef5b68630fb01ff1ff1 GIT binary patch literal 2355 zcmW+&X;@R&7ClMehLA7@At=LDFrrL}K`M$QP^CZuM2ZEqLKwsWD_U9vg$#s2)E3Ja zENUDoVpSqMtF}Ob0htL(KgoMVV$=c;qs)y!lKaB@anAa&zw@2F*WT-_Q^Jn=!oqyD zIRL;SJZxu-5h=z6n?c4s_RnP}BbXctjtmCi!H>DiyUSOCDPb{@0GwVA0AC2eB4We| z0KPXKoa6wotr`G_jOzNDKLIdn4c{3Yn_Zi%LlC;04FOcU-=L+~4wzWuf0wNi{&SGZhOWSdtz;u2?TH4sR85vXFUA6#Kpce2D!xko!DXp%k$VI2phWbmg0g*VQ z8dqG+q@VfcF0O0W3}AqyY;Ze1jK$LYP*6}{Pazv#^jBsB%DWmt)RUPv9r(T91@OVs zY2fDOMx>e2X;_GpSrvfj^olNdzwWQTuxVyU^P6;E-+C<%p>Eb0ETRz3XM&L; zOMo^zy>CsCWud1iTPfSxJ==3$7&OQ)zZCa64;zLr^ zvFvB;pLk!t`KHIQ>X-9<_ZypNh%mt7Rf~~!n++;FC)uK4Y+QKc6kx4mbFtv?fo=0lUnImJnW=?$^Ny5JH(tdoE@&^wI^7NP&xFkQ$ zo>{k{>p8smC_}Yb)pDlVdEy9LV<Uw_grypJO% zBqW^J2vLPWEDT22z_5}CoV?xL z=dq+0fw{T4ynFZV(GRqou4Kl>&TAD{>A?@Ty0M)qibe2)9@#W8{!$=!x%7N+S*hAk z%p=G)TOQwV+ew){gO%Hev7=n*nLSOC@M*SM?LhOyU^Y0&=c=V!_lg{)$)1JA-o%m9 zib5S8>rDMWaxu;WhH3TZQJI-@4e*2X;rk~Af#wn0N?qw=v0r|qg9>?INW`f>G`?RwrJ|HG@%2`+ozqMi#xg3q*P-j&M3T>87hLY{$Cr~K7 zB>UagQy-mNDc>}qm<~Q-;ojhDR*^^hYHMpRL|+a18{N|+oan9gokKe-%;%j(YE?W( zr5w{9bZ1&`Xgi_bf)N6&`^^9eC&3>&aeAA!Vr@X|{Jpz=ojeY)WYvB$WCq{u@bH6V z;n?`mOhEInl9Yl?!+Tu=vt_si7(Yntg9*0S9CH%w>zJ6B3$kVz)aTYL3zR|35T1b| z>5gcmW$o#fzHY{P<@>ankk@c_;(*(wVvDj=h9x#fvzh(tl`IRryO-&0EWlF@dXJKlzB?bKq z+}0p?J4Bd-UJX{=kh!;;_l*$t?b`=uQvSmnsbwKoT6O)6*+bh$KXlSFU*#;8E(|9^ zp-IP!q~sorbX|*S&>7`)9_ITxE+X)YE2MySBBd&C$NuaZc_y@LPl&=e2vF-ck2zCcvyPJFqBnjfc^QTwc zIMD%@2VY~dh8!zWIj2tqxH$4zx>Ai-=;43=@G6r2d;w!(-ReGX^{TCX>shCV?IP32 z5b5CGD~hp2Kb#7FxTy#WnKSlxiH%MQ|KH%*>bI_Rt^}2y;KC-~Dkb9b5yoeEs3#T& z&@i782w3tx#y4pSwPf#i*3YA84<9Jo5Uokru$XBqFLVdxPh$fu7M~yC0}QzEu=D=E T3_4rmuLp$hirRTUgp>b2!V@cs literal 0 HcmV?d00001 diff --git a/gfx/50/enqueued-channel-file.png b/gfx/50/enqueued-channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..7ec5730efae9eae77014f99b7a35514731dfcc4d GIT binary patch literal 2140 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 F{{lNyhn@fc literal 0 HcmV?d00001 diff --git a/gfx/50/error-channel-button.png b/gfx/50/error-channel-button.png new file mode 100644 index 0000000000000000000000000000000000000000..576888f919476902e0d72e199d382d39e40b21c7 GIT binary patch literal 2137 zcmW+&dpwle8eTKsn2Y%|lk1=up6+)Cv6fH(p(rKWGCfXhIY|y zN1aMi2FchGJBm7IM>V0+#-pqVf9qXqz3=m^+~A-sTAD_h001pt zAMb5Aa`3^XlJPlYU~w4^r2V`=9smtz(ii`E?r$UCXImfuX_f$pG67IxIF18w6c7A@ z0N_>vfI&jZwXy*KC<#a)i zJn`cuO}=Rwa6xnms0;N82$(34NF@54mFUZ!^C^I%C=&-goc_>34@+Jr0&P>k+}vD; z!*@ba^`dQXztm@=tQZ{Ak^eM)1mDe`%o6LG2lpqiO>|8}Zk0>Fxaa~Vw{e3Ed3_vAHGePH<{gh$IN`Dv_Zcc;np-uYfMD+~d;S8Q9DI=QT=*n?leHDA ztPH(Nr>RlKa{(7V#*w@CSxDX!@ND!U_Eymvb@dL*PExY!2EQ|_r( z_qCTE9h4U6ZlA1t6Ge=m^G>yBrcT~-TzQJQdBvlCud}z#1sJ_}*tNTYpAXS&tSvhf zv`z;Nm$U3*QS;7$*v^Dvy&f z`b_3Lbn`{nCxt>lSl&gveobtKZuRz7m|7W%W2jbhGhYX92gpX{TZ65$?F&Wu`wete z-@kTy#y@jd%VG)5Rpjf781%8^{3*I3m0U-VvJkvH@JBv-tNIGlHJ8IZcd5R9Y7bI( zH#aX2Ly6Br*jwl{nwoHb>kzkE3sz5Z3mbAzpGHyT%&I#5{iJLUD@JRNm>+x);V(KU zMixdt`Xklt?K0U5dTS*ShCN$|J7|9B$lBHD?Bp0@pT%)bv~3n3QoTs!yJWv>^w6b! zs-D)?)~TuYUO`DoGq)!uCi0I@zWYQpT$uj2Whe6TL&)~+i?o0!Vf-IW9a^(}4$=jT z`mqo6@nhb}w6g=}2Z#5-a6}snFO%JOsAWR!oweM#^%~6|igu~GK$m}h@BXXP$-vOd-m0m7CO6aGn$Jjw)m2gmFE{=cA<0 zl|R0P??Z~B`v(WH>4ooc`qIoWvDuRR_nwG*Wo0EMwq%wxH*bJAd+M7{%$*4f4_~Cn zlN!Gek@#5UzlE1`q{LO3r6;WFmy96u(^GEk-R-9ywnVP8l_iWRKM&8{4&X4je@LSB zaRTgy>RDjb#ktAhq=?69=P98ZGFC7Bnn_`}R%bT=_g1)#o%nOD$g$nh(z1hUxBJbn zk&m9y?S2_Tx|k4#^)8HcBpq9t)dCY&^s-V?O*uI>g6I)I{#>WJBmXbId-kNB zY3XY#^ZG;k!38di-{OAAS&wU$f1?Vz!wfa$K(9E28CgQGw&c|>tdYqCvPtA!;cs`B zG%qZEa^kod${N~Mu;&>=L;P6qhVV_qGGY(!WW>FV zf!OzCxU2-YjHFAp+Ot$jExUptR;k2$=__YWl2b;}$|8>g)}+&f{GTBzJH5jy!clG} z?X$f48MaA9(x%)@qFtGn3zlv^X;WtI5vJk6Tt|AjL{QyLATjS- z%$k zt@r^>(v7^0blYvXGLjwp68LPCOcQ~aWp-VX2we2M1j$Bh8BkM#458O)Yw^DU@ZA*T J{p&^~~fTsJLCn!%o?&8=CHlqvJEnyhU!y`Y&6 znc9@8Wl4^|ax590CT*KQK{KUtns&9e%~&#B$0jKXG~h1oAK&->anARA&wI}Mp7V|9 z(@k#FWmEuw+vddhZBAq@916*KAI{A+JHh44xUF#j{7`=UWAfRB;GV>7TLH)o06q(GhE@3wj zrpS$jpmFyG2Kw%4IoDq|-seapL$hxzewA`Ws23s?79Y{ykIb$b-0ejMF0_-d?0iI0 zQj)s*+_~e_^l;Dpg7B52;})UbR$X8}bNM4LI z{#Eb>@RA~;*aDW~b0&Me?8fU7Kcr7RE+7QND&d_>#`9+xVrwtEU*lV)Fl0N~EF~&M z)(x3~bC%IC($RfSI-ccv`>neEENEx|_Qc;+83g+qiT?g8>HfETo$1SnBYUlz+F(XX ziooABLox}w!lK=3UrVly1QEQ54){*kaNwtHS)&v@85rJ zrQt`Tkngt6A6J|K?O+)~2m#c}?+avnc()r=%#4YKua?4ukj3^26w0e@ph z+q%gaal_%j3Gu6?p;_z`OPaH`+#CJNwbIC+J1*^$W>#Fe$`t0Y*SsIiBhvmEPtmob zdJ;8T>CceekUaQ74Vs5|5e8 z%uHOyh7|56-;Arfip;X%FACwWU2DHj z%9@MLHJ7^X^$h1_j@1jW2UnY#-qXj*#kVj#mOdD#oFXi{t4Q}=5@O;k*l`-Xq=9`T zf|7{$^z_uqWA}WGJ7UPZP!(ax3YAY^pUrC8BUT=kZYfC-!1+3vG z@5qil|eUUnt<)c+e1w!CoH22FfFgv{e@ZEeaBO4i>LyuiRfd%}ZltRlI4 z2Gs1f&e!*{T4U}zHgDdyLrm!ZBq)gb_C40x!*B;q_5tiQgJ?!@kwQV$zW;4BMOKWQ zYHyzrh*CgkTQcCfLZL2AymPI5l-a z-cVHYf#7|FbpUsXk`PDq6I0U!sPvFB?=B$3=ZshE04xn4Z+TvRW_Q71=VAn#6F!Z< J{wHza{{UAoKzRTF literal 0 HcmV?d00001 diff --git a/gfx/50/error-item-button.png b/gfx/50/error-item-button.png new file mode 100644 index 0000000000000000000000000000000000000000..2082a488bc48cef0c037ace6c59b12433daff849 GIT binary patch literal 1951 zcmW+%X;>3k7JZdUDnJqz*#g=miUIo_v=BB0SrrtwZlFN{H#QX^m8vQH@!t7y-}~djijR6RNnpSlis?7k^m{F~HdSlN$0@uCN zmrucy!Z~++CqVmTuTZ>+iH;s$(Xs$Q>4RtrfxB+qy0xyTurQG#7xZ-GBmh&>p8k=p zvLA*2_;OvpWz!@Ofsh1nMd~e)yjP{Cr(5vs@W&me698|x1ogW+`ByVzcdVNdG)w?n zTU%3Jm;lFhTBm>>wf6>1A&56^i5iU|yRAUjsF`g*Pc+xY%tpEHoXOkOX24if<)Hze zfp42seFBG9c$rfz-VuZ@OfGW#Q!GC9ezlx@^Q^$w)}a~)&z3^VJ5DH}aB%-GJpUCis}xW|;0 zdmEG7+|T+SP$p%=MAo=me1p>~T+z_HanZq}6bVslDGs;_Ot0{tw^F zMmN^0do}mJ1h>?G?s!n7*^rfmqUSAB-Dqrfax(3g1%+6Bv>Y4j@8Y!ck^+omRD>Md zY|*sA+G_SA&^@W1L&v^+c=>nHmg)5g6Uv^JmQi<}1-`c?UPT`j+evL27)oE5A1%{w zw8P$wuSAf)g&>Hb>}644Haa*IsMemR>^s`(gv-GTT3b!PnvkaX)lflP#ij?EJjQ?A z+}w6ES*(;jyLaoTnd`Kdw-$YMb#+BeCQHqGL*-#%Vd&N73@aQ{jBMMcZM?W2A8U^D zE(i$?mwlZ&gAT&RC)U;^QIWN)@3H3%lnVI9l@z`^eCfT;==&2l_uUJH)}0*eJntUa zUzZZTJtzn}piq3#jz0SLD~>Q3Gm1+O=5!b=NVOWb|Ot>ou$J)(NdW-MLAev830R{bqh@CCn!0f&A1~#(e~IOdfYq-;=JQe@N=_J4cBcf zEgyJcEIrECH!#5A{ql2GrV$X2qil~ zqLT`B9EiA#mdql0B8EjiJ^5lA>HeLipEzf8=%?xG5_Y3_KAj+S!voF3Y*lIL!rnWJ zUB2sHgwd;})?U_TjgBI4@PY^Q*!5ev@`g(gxt^@qM+cMu Z27Z4K32y#%WWWO8v&qlve;Z_}{|EgeR89Z@ literal 0 HcmV?d00001 diff --git a/gfx/50/error-item-file.png b/gfx/50/error-item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..51de387538266de424b74aa067c3b8dcb1931f79 GIT binary patch literal 1725 zcmW+%YgAKL7CyFbXI-3j;Ud zC2GWKd5E zbKoohMO*-0ApnFo06^c@aJlg*08R;svBI7IIw!Vb7{5<|mjkhoK7K9B85-Sjjx9PS zRK9*qQSY0wF9wE%oj;{$K6X^0Uh&|azK!OQFH(!gAgFE@a&+kWr8pXny zDK2b^KzM&}@Xr0d^&M|6K3Fdn4=v0aSl=orBCUvW(%_wPt7swk-tIL-0Mn`#O3XwZA@todGt{da~!t(mBc8za&L z3|B-fUcH)5NBuaQOQxBTCUt+fyt497es?u#vojIuYx-i0+4BQ7vVa*vsvGlOQ?RJW zY$WsUQ%Cmr1^Ft*S*5zvW`0K}RTpXap7khNirGiV2Y|ly?-Z1EJKKm+SC?arjm$G> zj|ALrh8$!)@k%xkys;Dd`&$)!6yp_K!z4PL)nL&l`PZN!x{s^fq{E#ff^H^r@yWl0|FIK{%SArsBC(x%5f95OTwo>va6wiv&Nv4RpU>d>r9x38PYDd>h2rwaadk z9cWmdsf6&4U4Nt8E>6?*FP_x(J@Qu02YZW=l@q;O8e85~1xWI;HMO1zg}_fg#cxt` zd6;!5u*LkHqHf-8lS@~dHPa}wLVapJ%3X1^#D8dDhgL9*onDK_?Dj0l^S`Wp+CGED zpx@k{r=F7!pnT%lPcGs+LPl`{pxX+GROaJZ`!B zedpAJ9<}VDvV*{u=X0X7;}Uiwo4`j}N>GNd847Ies(L*Cl~yAK9^&aTCG*AQ?M;o$ zt487n!nE!(Zt;3}mtB9CI+!zZ{%S#Cq1~NEGY$_75FUQYa5bF_h*dl*KfN*3Jv6i` z7l$Y1u7|~G?CcmS?x%U-rH{Nu-9(4xC$m<2c-VeyYcsp=^uou$xwVQ5YmV_=IHZ0b z@0sTd@a^sG6iu61T~>zwNhQ8rY74hChUSc)P%3-&=jS6uush5xkEVOS_ZlgcgdnQ< zUGjgz&kh^r3YsDh*Uy`lXU_Ti`=dsasd3*QzYqcqU9ZZ;DI_G;QQgcU5CkI(DQ{HY z9>iYDm}xhg&6rlJwfCUdd2a@OA|oRM>nXJjy)(bf-FEQcLCf zUMrhI7E1^E7yf$S<&Q*!f|8M?<(chqTeb}FTUuJM8W#Vd-DWuyhq%}1mS;xtSWz-S zzodc9)Mw{$X9wWq35F|hc<5K!D{;!rRc-E!y%RTj$s*gdk?3SVeSMoz0narvQ#YlF zy|?o6$%c(WVK275DJsjUZBI{$Wn*_o#~e!)G43YlwhM>p$^gf2y9sX20h0n(kkOA{ zYHn`UHEljL$Ho1AT$M*$;y4FLYHMo+zWo%68OzJd6A6-pvX*~;(OJk~FswSg9wO-Z z(x>7I;OM{MDsHk?RYuG(a`~lJh6EQtwl6L%-FaIcy)`x#UiVx?0v+kijIJAIwleD$%5An2TA(=T8tYvT z!iRxik8$_CQ2{aAuUv82TA>sqH40vWv?WC}A#&x$&6~nUZ&_#3(gpQ>(bS5oTi)xp z2}l?AAb~m1H`BO3@#${P%ES44HDjs7%LM;8u7#TV2UUU+HZG$$?}c?=Qa@zO4hJH< z-=Uq9ys^`xf9rD*Oxjl+=qIZhhaYip`07(H!kdNwTV6e9c|-;<1MJtd-sY7oE;#lN NNZhh5wj&xT`#(!M0Qvv` literal 0 HcmV?d00001 diff --git a/gfx/50/index.html b/gfx/50/index.html new file mode 100644 index 0000000..8dee7b2 --- /dev/null +++ b/gfx/50/index.html @@ -0,0 +1,89 @@ + + +Index of /mushaspot/50/ + + +


+
+

Index of /mushaspot/50/

+
+
+

Thumbnails

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+
+ + diff --git a/gfx/50/item-button.png b/gfx/50/item-button.png new file mode 100644 index 0000000000000000000000000000000000000000..ebeece63aa58f098132975633f253977372eb330 GIT binary patch literal 1291 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 dAJ75G11OfreS& zUYYqYs3OU}V&%`0(51 z6W$qLZ;)kvGk^>Brvgb7KPc$azw+|(Oxd=YS1&750b5lo-f@3M*-eQ)=?;TO)4;~Y z#)uu~qS36aY!db%d>?5AIBg{RQJsvcIS}Y#V;f=LF=j(0k?Ut|V{n8E#*_Rd!$MSI zY!*QMP`E>!Sa*q79APUgXl-rP5YE^ShU!bccnfJZdsNX#7NwcAQ@okn8UgU^^J`W;CgZ{R8$z} zR#llo?514L9s>0z404qo9v)8rp(DK;oHH-oTDqs@7bXF{D+@@T39doSRmRd%uz@4= zPhc7gm}#PZEumrQ!Ol9*5KJWB%G1-6#XS2_t!9I6b5Q_P(@uv?>>zd{$1`(LUzIBS zv_?q(dPgErTOw!i@|Q#sGm!&YE6mky#p`hwR+i>AzU#ZX^NpLEn}$pxt>Qh#o%&te ziu{C)kDoqW@DB@{^AdWmd>+1gN?fAEyPK-H1Q7$ij_)q1umAROcaa&7(FWZRUdDPY z5+&zpdtfY1|0W$oSZR;vJIZ}}hHl0DiV^6<8yJ)+q@hZpT$#OSe^gjT4y;8^>dt%G zg+JsJ)CKY4laiC2f!7NVzCfc7cX7?>s>sA{JG7p20J@>%E^u7k*?;N(T)RmncO{LMY_e4jp z;UZl>RXgre5*t1%kZ0unSlk&FCCI^%IuC5@2;5#$RIRw2+B_QzD)~yKaHmn1G&NSV8axOfF`m9AR)Hl)bWF;m zFqd__x#dKxG(vuwS$VM*`b->*AE6*K9vGwaQy3|}rn(_Zsv%p{Iqx@g2|Q`h797^be(-8dbGds(Gp z%py1#A1`_(8Wqc3a=CB)2kZG+pA0RtOfV`Ot|i@7s<< zTfKHhvl+W4`H(AtTFCxpKd51&#hlRxy3`UYRi{lR=0@T7gQGl%q3j>SUpZfrY Z04QS*%5Efe4xk@72=LqCd(%gh^MCE`aBctq literal 0 HcmV?d00001 diff --git a/gfx/50/kill-item-file.png b/gfx/50/kill-item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..37d5fb25f64f45decac438225b5a3d274fae3fd6 GIT binary patch literal 1903 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 literal 0 HcmV?d00001 diff --git a/gfx/50/play-channel-file.png b/gfx/50/play-channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..12d0331f2217cc095f5ed98a7737d701cc78b1f2 GIT binary patch literal 2184 zcmX9=eK^zWAAa_}n2^PH9WgPjP-951+q^~SM@La98<|d=xJD;w*@mX2yquJwGWwO$ zD%JJt9Gzm!iIX`>I!GFM&2d6uUbcOI>pFitpZkyJx<1!^-Jj=k-;X48_f8X|RYm{+ zlfVGqJq9FyJ9w<2rlhCO7yup53Sj~8Fps|!cIn$?Y`~rn0MaP{2(tiKfDJeXzzG@v z<7@!76a!$DRD7qT69BwLpf4*t?P`n`h8apGQV3#LR^5-{j8U(`u9AZT=yVGw<>+Km zMleG`m;CV#I1(QYe!S0diq4(vKSGg^f z3(#g_6htCDhjmL`h$BW|nxWl250^_MmnGM(g{XD~iTeDzt_{5Z=LRo+W8d}07foR< zP3syqZg`>44B~v=U(##}N{yS?lc8PUjlhEJhX9d10A#~$9UUFE6bhvr*`u15$H#GD z&EnwqdC|@4!0|g?wC=zE>qeu~U9UdlpY_`xGClozEn{;hhC(X3=|S?ejjDn_4-H=L zDo=W<<;?4HvdRiYCP%SM!0{4FB!L0J!4nsYii$?c8G

Fg9)#_~%7CPsruL>Wt^H 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 Tvb3NpF@XQ>eY+m+U}XLQWUBzT literal 0 HcmV?d00001 diff --git a/gfx/50/play-item-file.png b/gfx/50/play-item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..3be6193078ce881bb3421a36cbbdfed665bde3d5 GIT binary patch literal 2058 zcmW+%eK^y58~^ToY*-~W(I!#nq>Ry_(r;e#GS2i$Imb+_o_0mjIXE8s4TpA;<2;8D zWu;ObCwjRm&rw^Zcxn!X2T9u!NnQ&Zw*8)Y{SU^lT3cx8Q z0AoA=wv_>3n_PCIq8k80X=tF|-t;QI9zh@l8w~@#pKafrL=vVms*1r0VX;;FI-SFXLxsf$qbob`L_&W9chu&)X z#w38Hf??GPd0&F|W8!qXDRcW3JtQb!O`-fe)&(*Wsk`>R*4=+4g0)#!euu1=7c zglHFs_7ugnszS$Zcr*JxUGZSDSngF#Sw9EGM9j>*+yMD>9MuQJOjDq57>S;STWNv$z# z@OV^>WmAclN4#BdXuc!obB5_| zG$2}49Dct|Qa*&pm`zLBR-?sMY6=Ke(OrUhcKk)f^vDYbX+i~UecmwD_3UH!sz<4; zFJEdQd-kO?7&MOoE*mBTev_q6tEDr24GH}C_(kNCN|3Kru`PAPG|DQ43_*-c7RJ{w zWu+*XvZ6AA-91uLZ@W`R!&tG6M$eh90;mj_rn83afw@@4CaBMfMGS!vX~o_z)@)Gp zs_LmmCJ4Y%o!MoEL_FTbsVgo&S@f1E*Ej2{C7Le}su@Nro2~h4OgrCMr9kjQPb*<{U=sERJhu|-f z!HDZ7E7!>Zp2!e7g3IN8jWEv|oLRZwW?mL6%z;$@On>3*=<=UwqhdSW#$_@tc05Z| z(h>n3Z*2OGlNY{ttUOeEY!W(;IR3y;0wN=}zxX44qZmV4uea1al|OaSzi5>%{#~>w z;_C-*ck%^^?-wU-99m?roP+bxTSx}!yix2h(4S#<@@mIv$oTA*G(JnvW3F} ziUTfDt#lpJAEv%d!ZfOT?N)A?g1sDAn^*%-3vPc zDQ=mw8bmF3#+I{Bxl(F&p+de)sbn-dl&v%mOVR7~qKx!(V~zq{^*!TgzFGSOhayL} z$T}SWg&n=hk#ZO9zVQp+8yw``ev~=)%YxCc#L3Fa67}@-h*D3SFksGIj1C}=oh+`P zTAGxqlTgMEZWZ=ZN_xdTUYLeQ(}b4CKWVoNeC(=Sn4O)?CXz_V(-ERH29YN5ub@n) zVvDXLA2|xv6NFC89htMICk#tkrN6(w$ji%1gsu^5M%pWPxVX5e{I0IeTw!T}vJpxs z448R`=2;%Y`v~&H5=-k3t_*Mw-WMMJNmg3A`g#@5S7h8#-_*1N!!$3a@62k$?Ituc zeA|*>Wu6b9Vg4^>H`xQmS>qT%QtbRl`x=+xskJ-O<)4RN*aq{?e5}88NkivN--SfR zD%5)-_nlt9z*2NnL$sj4K;sjCv>i^_cNs9?l*E9BKjNbR`TKLf(jku%si{W7ws*2y zw+W^!=*R%tQ~w&dYm*hySZxEojqaNFRR$jG7P#Pd2My| z^;XYs+RN`XqYAzDA34t#C!Me+Q`owd8v2nVOjJ#-*?B|xMc<$BD>1`pu40vt=&BLx z*mCkFrF8Y0kReg*vZT{NsE06W`ki7739{ra^u zP)G0H3sw(w=C#9{SD=?o4L-jX(aq#usI06c^%qE+3D!z!;Ljwu8{K7w;kx~@joV|X zq^ZQ`Apal1vatZ_y?t_Fk44&__LwUvwfD5eV*s@c|Xtl{eF%IZ28&5Xuc5u zz{GFE+CVHauwg?YVsp?79SsY5`#769092fe*KIxfV^Odna5DhM>;QnI08F7+901@j zmN>`*z%v(sc@eoKc`pDUUGiJY35vN8GJ~S52LVKYd+5?`T4VwA%#CZ6oi}#fM-lj~ zVd!_l2y5EQa0SpGTPhTOj*N)VtW?bgxa1y*7)4w+ZrrHI&CZU;hcY`_j>iBBrK7vQ ztuTreH&JG&S~mjNfFA>{1#j52Y3M|9a`Ifp66ATyxfsAu=SjBIjC^V|-VyBqfrepV zYimnk2$%>0>sADG6m9TTW`iRX)$aq5*l8eL zxU$Gzz~PwvRS^qpAi3Sb^#Rc^4*w<=nw5PMCA1j489#-yP_iF8L4%9U>Gu!fYYg&} z8QxfWR|rrWW?g07Dpkw!WT;q&0wZq!j#iS>q{-(dS<+#XCS}MkPoHuy8#mvL(B}i9 zT2ZJ_I61uSUZJ}`$~f9&nmW$ey6B#(qw$HZP7IME-MBE9%K_2gdnmfDGdpk=}wE*h57 zM-B8oMzy9E^1DRgOLn1;qD^oIPZ!o2b<)upoqptO=4~q0WVjRfC92sbgFpGX?L)iY1TWw7h!I zT*wv2hrEf||3}$9nxnL$k}l0VY51Vz?sYqBMNR8yulDEEU2R&Xyi&xB*|F9seIvr( zbE|yomsc7(dkrE5%p4LAtEDU!?97wk>|GBF0(plugYe+Oe-+8~l9=%%5-X2#bNIe59At z7fZ8LVz(uq6`5_^c=SFpuqkzy;{+ofo;u0#|Mh&&_??XSQy<=`L-<0SaU|tmV636- zG;+JcLI;PLdBG>Dj%Q?`$oD>Drs|omudf*TN^#?5%1cX26Ag}KZVn0>(_&Z1`JcNj zV+uO6>IIG0j_bLfyFKQ$J9L=bF)wu~z18`i4uK>YI+is5)`xzVSC-rN-k(O$Z%>WM zj*8u3yioXwvU%cSSbvITr5Hhoo(t58&4DBvNE8+#isp>sDe^;FD{3X#jP9d$`ROOr zh@7yV=iGyjwU9*z(^-klC0DObP^e7t!S}U|CS&c6Mbjv$7jo61;!Qd83pDQ3DKRSn zhI*cAipku>)q=^%FDnT2;$aO-tf&x;&g@h7gz+b5MlBy`#D!D~wLW!~_q$~ipGPUC zbLYC1+C zw3HP6ArG4tyu-OJPJy|FMJPTNsCik%r^g;toIa!LFE2zTO~LXt`g$?c=;$ld9o2P} zBNZ8Fyl%p(E2_wI48BVzADqr}tntvxlh`q=Zf_$0Lss)DrLQR|*e8BcdFb0a4T1RO`y=V$mYSzgCQ5#1Bh!<1ArfG2Uu z(3%m9iL~wId;4%X+M-Plr$5#cwp`;ou>BcQ#s->t8LwI7=jZ2y&)9bRz^j`h`18Ht z@=#KPGE~|0u(@GA|NZzc{)^NP#;uN03%tdu;qkXiQ@LWXv;9UH?ED`iok&~1nl~U8 zh+efNJbv=%Dc&Su8zv2y3eS%s%cEBNEZHx!w7K!?`hc&khM5U&2?+^XL!&T^4@Aw+7jkZFUC(>n3LGR<$koy6 zS_v@X?}ll-GXl_QP~=^I`Nj>{DqD}UzaoW3nwioPf>tv`m7|j7#=I0=?kty+%12Em z`?oXkXHB~<*_g4db%(8^Qq%adlO$?qUJ}eW14x#s37CyG86!=WO^%|ZHe)wan{vzqL`h6DOB2(= zmOI&Ua$zRDrs7tbW;!jV*GXJTvkhDk5q_8E+&{ke`QttBbH4X^-uHZ;D2y3wgtNl| z0E~8q1ntoy@$12&^)WR)eL)Y%1jcR#0JY~bG^~qXlbnz}y8%dd0e~j}Kn>~fJpjLw z0r`kkPU4v36l2d_d$y44@tyee*%9QplOa zi;lUFS)%D0L(Jr}#MCsVT;5Z0_|5E3;)5%yEQ|1_Bw0YL_4L)x zD?N|Vf2H12&=7PG<1;3gar>S>f39$Gago4>gK|v$zL}Pl7xpJh3hcC6*>^ygpr|Ih=arKiA{xlKxs;$L|9;cV7+7b3p3@qhPsD&1 zZ6uXvLzI7gACsl=>Vs<4Ep1+eT_Ftz~FY7m`iYg;?JJC%zXH{mG~DFtV6%&SS0DH(_A zF?g=6j8c=j%E8uGWvncG{@2p!*9jq5Y#sGj-7G~pSLdaiqad~Mhr|Y(CJ1^l&%z_H zt3qG6n{Hm!@3`6ee)PGU5`>X!V!{W60eNqm8@|U35|9z9*ve~HpiP;aN?JH zl{w=t3UA>foACGx=KlUiAVL;n35GO%U<$UvE#X|gn7v_fy1yD?Hj4TS|Ne3Pl1Aai zWU_lWadB~B`*dA36G5Wq3JD%+K=}}ch9Ych;HrRxtUsGao zA@g<_q+99gchPPC>G_9_kM)j(q2Xcvf3iv#QOsfnqpZBFgTgFSUxm7Ab2c?NM#wnu)|pNl(zB&61mLvR~(HG9rx zEX^(Y9qVp6tucGQOK5C;k`4&D7aU|De9arfEDnwuq{?9F69r z&401#sFu@sJ7$u;T~m;Kt0Lb#+QC1)Q#skC;vBKZ-yQaG`oB1=r3j^dA;gOM=w{l*CkYbcK&u|9qZ|`@=ITR5|^Oc0+$XtMl8Xx#K__E z2F1YORdHCCSL;jd@?wriPy!W}Mt#;wxHt#xil)F;yi2D=`Z9w(^P%!~)urv_$?JkJ)A?f)vd}Pu9&B`aevm{+SaYIu@B6L zc(HPEII=mjcXkBaaAY+Bq^S^5`SbZQvx%VdyYWe*O)>ALryJ-Gxn+!aD!2mcq61TUgoTr-6i%rcj7MBq zXak7^nY`!32LuGTvQKc(gB6wTF{r_-_vitJx#$lu=nn~)GQ^|MFzGk}3E zUPgshw%3C3aFRkv?zPpvF$aQ7wfjN>pfFkj=hK&%)R z6US(qvfKV)iN^9M*6aBLs3m>ZMSdSn71JW zhMG9|kL}sNAHo#JGB#uOWA)PS!w}Da5GwX?Vj_gG{&yui;Wy3F#;#IQbZeVY-TT?e zt_u3r8i(-kSJ3tA*DE)p)};IxSZ_ZC^uvGIh#|}(yZ5%)qwpzcHj@oD?;YZ`^`Vbj zbO%EWD-&{CE!cjB!DJd+;)ok7s|2Mcbg7sphFPP!^^Zc$ASz@-sTE=2o?}1;TXt+5 zZbOz!TQbxaw0e7pazUL(_iN8eq``4Z47o9a&+172IJlAdHWF#H^R2t^4A5KLCnO3O z3==O9fv%A^BnuEjOr%vm(QxP*s}r6F58H>V<%=#Z4oee0wPyF=4@vpF$#nOEM8HlKQ0S62t+Vh8b2c}pK&KcFZSiZO$Y-0K_+^U~KJ5h-b#%(8xQMzbk~#=h(UDcGpS+?h`H zwqh74o?LXxCkDf%>#B~$3VnggauH15xDTirr;v+kVctq!3an-?2dren2!F7DV+VHr zvK7mFnT2yc??Mc2*C!iv@Tc2o{0Y*)cD?Lmd$6#>icDDqR=r-tU;F5GqM7bk7RJLO x6Rd5)9-c}+z6fBQJ_F4h97pY6?D6)e#yoSNXM%nt7-Jk zSap_?`nldvw0i+iK~xI3&G0{PV6GrLJKK`vsC_n2oB~L)GHy`o!rN|iSdte9bj||@ z2M0VU#$Bt`th&&Lc>cbEB5)or`hNP1uG(fKfotwSA4;^hGq>ZAD@@;engbJRi?;wQ z3wWDiXf#}P(*9gXb>T?UPzx_CE{LQi?}M~mYn0?IFwlpN0S-(lpOPnH`aiGqWyGcRKb-i4nF&Am*;zVuwXl?&wP%`NyJHCMQ^Z`HWhp3Of$!@yo7Ql}A0HuoPDemlC#FggK za-)lTbG#U>8AN`^uKAv&_DD(<|oaNWI*zU@U!|e+2Tc1^J<`NF| zBo&}nj2D`kPN`wE#srNKh3V-cv6VQvEHvo(oOU(fvGA)aBR`_G6Ip3AwIt-3%HqY<#tA+ zR^o4CYb{C4qmznM)#vk4C*nbanYx*6ZQ8UdTCm?$n!k*)4!;!HGv(F+MX-|`yBe%g z2_4$BUS92Q1M{jEyF2zKo;=e;dZ5Yi11yZLnkP=+Vw{9=?&Adf2pbbCZq?SVyz1n?J43aWSm>qa&g37(?zLhb)bkxy7ecp5YR8?EY`mvx2ZCQFEURg`n8eOib?Xj zzPeBeBuT%(l}?n@VJ_EGtV^GFJeX@E?fN_@kx*;hw??_-0JuS@BXX~mgAE|tg-}SZ zI?~J0)5l(;aCWC`tgX|nOih)^AI3fGc&IYw1p^Ck;xh!5x_Wp^PLmd)43!GjRU$cP z-J$-WXMSNQ6zLNrm9VuLG15upps1_Ab6z>+o-2WTwr&!kNrzKf{xdf)zak_AFGiC-ZjJSpB_-_P6SJDPpSi?398VANl6hpUJi? z7K=~2sZcC9I5iqR0l#{^=Cg6Zy+R{BDw-zD%`7N-NnvZ$g;FE{Y|^k`{j_4zME0so#jErbgA#M7{NPb4srTlz%uwJ}n(ixz6v`Qsz4mC%EIVb7AEB731O^TG$ez#ZGU+khwu^ZfU9gar%%tjv39;5Tjl#zaRWLu|D)KE@ZGBRQ-mCCYTmO+b9|IhG=+l5Hi z(MZJl6*OU0616CJ8mmz)yIkXPg>G~gvkk^YP~qz%z@kYIfp;hU)pR^QUW0UWtEeQ? z1F-e$s14_P68S#deE&nNpi_=o&C0q)VXsk0ml(u1Y|D%;!!zDD&CJf`|EnBfLS>W> zJ>8BzUXVG45o{lvS1q47B?i~@+gkG@oH@Q1v$C>G8T&L=W@gcFvfYX2SOinEy=hXL6~Z=|721JT!y?=NpM&d}bR4)`O&D=>LSCu9PT004R=004l4008;_004mK004C`008P>0026d000+nm#LZ5000L% zNkl_@T0AV=b z-@kv&($doJB_$=F0@*}`5IZa9znhQGai8C_$&`uvC)@cKTR+D*RXuvW|E86-i7Lap zk1rXv-EL3*{hd{cjhP{ak&)pY10zH)KmcJlfQgAoNL*a}jg*v>=AS=*{u1K=78aKO zv-hkL6%l1*GuN?Z*njef)Pr{yxHvf&{+nxhGpb71Fr2!xiecN)^`0+YGfe&Siy`vg zZ-`!i0K)JgBO@adFkv$O`t|GE@87=(V#fb0U$5Oe^Y6fwMO@}O<_spPehd=g?2M}p z_Hi)*efjXsS%zotuP`Wzn=rUoxG;!_F+{vP&k%lL0mMFl0Kygmj35U9)4?wwCYT2P zG5!6w{`f=*A(1~!;zHsKZ$3X@&{k1r*!SinJ1?impF?MkF~4~Cm{D8ajDeS%pFv(i zoZ+L{OD`F7hLs@w00D&60bqmw{rdyNcpbpR$i(pV`zMBbFE4Tm32-vJ`+lF{|F;JW ze;L0quyg!l2)C$w`t_I=l9NC*hBGjOu;G4S%TGVt;-1pQ`Ymt$F+hc|=zn?OE`1*q3_b&zp9uD4L-+sMj5ffu( z_{;Ex;nR<&3|zbn43ZK&JZ%3Mfkrv3!H10e}F)8U@g3_(v@M{r4w>k8$Y(j=xgho;-gFb_5u6 zurNppDgLlhi+uL-^*eCLzJ2=<=u3tP4F4H^f$ReaAgmz(0-z`$+5vxl{uk#{`IcZm z`zpgXiLWsw>2F3GjfAJ1j1pfSJbJ|N!od&{9G-Mjw&V}f~<0U&^I|G?Z2G6Cox zaMA*%hyTD3LQw?}Kv+Wnh*?1xR3M>S{^Q3F#%Ir-u>rHxKYo7xzaScx4sZdG?Lf>7 zGMj-BwQvOpAZ#H3!mL2dh8_YSIgnw%Qj+cI)2B>#?%ZJl)|`J-R8)QfL*+j(M6gB~ zC`zFi9``T+5I|THArP}*3jq*d1GXlBZH4~|3JRctit*aDYwTyvoMAUIGWrh8`&b>p zgaH4+p@0Mc0tjn1goXeH2Ktf(SOv4)yLXTK?Afz?&!0c%G&ME-!^6YFeCyUNZe04H z7#;%1ApsCTSRDWh0T>2a3@qMRSwJ)}&RGl$4E_Nv{`>CTJNBD5Z*uGC==}Tq`7`_5 zw{JOsp}+!Ci>@Eta+m`E0tjm&1o;$%K|u_ym>Ax?dBX&3`7qqQdzS^+SYcFFR{jHY z#J>|KPO$&{`IA9HLV^+G2o4U8KcHv?CeVMtv;sC0XciMF=U|HhfB?dp4WTao!vLw2 z7;fCS!3wejWQd@k;C}%Dfqy`sa|j6u{T3D$X8QE$6FW%!<;$1M-@kun1}08sU?}|o zIRfN(pjrQ5K1NT300D%nAYuW<8%X{2>(^O;hB6u&8vcQ%dSFA~4=6raK!yWD0_;g( zu>S}8o(bq62B6QGE?>UP0n!6ZAE03T2Mt*U^bi0DAbi>IAJjq2AdMglw2=7`utEV^ zz^J68^bcq_Tt6tJL_|cujzLQG;EENB8DKOr00>*YCdX-|zZ8#k_<2 zOiebM002xQBf|JtWMPM41Y>v9u-+aEgcFv*NlmJe|9;+r z8rEMJ$La8M?A1NSu3*!GbA0@p^pq5ho7w_Eg%dIfYVh8_e}8LrMMVxS&TFW@I15-> z4voJZP<+Wg_u-DQdhZ+v2BIu*QxL)B&i<>gu#nDjGCb+8%mS>b8ri`g=O(*Ihco=7 zpj`_b9UU!MVlRVXUGK^pLLx#`6(G}6eQG)#Lvw>|WHd+KPzqx!ZL8G3&V0s)2B^V5 z1gOBG3ULv0IF#%6&H{#1$=nvs%UFl<+a@9TIV94k1OKr+_!>C5>Lu9WC*KpCjQi1a z3pVI40bqEcT24f^{--uH4Z68SFu&37fe?n4f>Xt+__J)esVCqT@NFaP1$+-#r%)#! zUUJw)u?Y25)D+v&>cX1rrkrZkB~nL@lAO(#pCl==a%QhnTS{dxzgwf zwFJM~iOH^#y4$yJv#$l^_QDH;8tkPq-=5Mb5#Cevwi`4H?*sD>`B>j-F)Yh1Z&)i{ z%eD=uI@P*yj`P~_rZX>2IXTgj%vBppjs;O^QZQOJHZ~?<=dO0{WH7Wu!PW12A3a*f z`Im2sI)o2hQ(U;9X7fC8T~ywmZ-2detVY^jra<`QB-n8tRkZ%(v1@b)>2uT8^o(!6 z1WgACP1@cQ=#OiM}L!nq`m4bV@wrCNxj^tSf)c8TWY!=7ZJ zP-`^}`N-?f7Zw`ETFzAyX-`H*MidQSwDdA}>{!)fxY+x1N?Pvw9qL& zPd8<3hd~B|%ufdKV>+Dag~;>k^qrRpbT(oKd0^92?DuKOwCOK|+kLP;8{Oiw?>{5x$#1A(2QfRR;V? zSa^$|>ttJ5RVt7hc#{BmkN`GNW}}t&($`6iH*=dlWZ1rI+2j6-NRC|_)SGY_(3mWU|n4u zDq~WuS#%re`^>5{npYl)iHRsUYxbrXxTg6>2IgDOEHX9<5{uysr z)H{#F(il>07Z7ylmozm}+lnoMrZwp7Oj`lbo=a7MPeXni#AVZ_x5L7|)a@=V((=uA ztWqT|aL&>OXrHfY&|~DJq@(DwXIV!6TXE8~CDg&r#Ro}l=Rwq9K_DoBsMa>R+2-bE z)Z5z|ZOK_F{|ApJx4lv(kp+M+Z7!JVT$Jr%d{@!6Yp+`C_m!rDk|W{5JkUrgOM?CW zxtwRA?nn4njrrz6HJ(5n;gZSTbSnIN_UY4$sLDpzlB@TzWM!bBWI!^yP+U?{pl!uu zq@R?jbeHHv5Wid@4nK4SL5Cb_8=I6ojL^8kq=Wwv05ZU=5v zmY2r@C%e?zu5YTMDAF-PhF!QCB2a(gl4Ho}M(OdL#9$_cOYycZee<>AquII}uZNyt zZ8y7K^;#6qxl9e$<2Q`;D|C>1aY81;4bnYH|D*5x%i6UbH$QfXb3r zap`tVgpb)PMc+yrPf`XSAedg1fbnh`@Vs2Wbj<^ WG<%s=>xF$}Aad`)u!ay}{{I0lTnwoI literal 0 HcmV?d00001 diff --git a/gfx/50/remove-channel-file.png b/gfx/50/remove-channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..f5a5bd875a2775cb595521eae361b6750d578341 GIT binary patch literal 1798 zcmV+h2l@DkP)004R=004l4008;_004mK004C`008P>0026d000+nm#LZ5000J& zNkldj!mgJC^WzRWT^Ph$WY9}%7=#iaMH^F)B-HGyM7c2bXIZm>HQkm|0jj&fGZ2 zd-m$>c8~)A0tl-EKs3jMA&CP(bV1uL=U~XYzc>DG< z0~`ClryyZ~0KydopiuZjsFeKm`#Xc8n9)Zc!=i^r@63^Y&F~Iv4Hf`Q_zW!H{{WLA z!|&ff_6s%+hDwkGKmcKl0%$b+BjkYpKnU`cr+(FaJN1kw|Nj5QW;@8ZZ_l2*GQRY9 zQ~%+ooz1}T}L2&347<^qs7 zBMdV$GlRnsDhHz(fLRrsWpT(eBAEe-S0-q&4XojQGjOu-f$akbAY6%%8D;>;cW>Uj zVddxN|NH6FCuUw=-oM|zePafdQ5P>>sJmTAtAJ=%gY0+GY)1xK0YRPc6Mf9%?U~`tialn7071+(Lg<* z`k5VM4iv+q0ER&TAb_xi04TiRE(iHSL_~z~_3PIhK#LeaA;81K1Bwb}pkp{dA)}_I z_V4M_r=aLy06LT%qzC9YkON@8XM-lf|L7qA5J31s0E~fg%?50sFaYC}85HbhW@f)Z z7Cd_Nhzl4+%s>aQy?F70Q%6VVFEE6d9z1x!rLM024=BZgY!0pv00PKsSMW^dCqw023SwFmxE?Zw8Rbf$p3;+TMTL>^BrCe5E(6fH{@PYlpg$rE3e9!vw%t-Gmy;&as((OU}*pvvKZMAAb_ye1yD`kk^-3LS%5+R zUqwZQ0hrjBLGi1sto#?<(LjeXfh-25k-wUnnv7@9o@JGgkYEBv2`C=^!y2zJpTht^ z0AVc&p~3bKq!^f}7_MKx&T{YGJ!V;1+5f`A!my$m1%R?Buqh8p4@|dj-)07;hyQ|t zf}nH+^7(({C_n}P0fa3P{)Z+)a4`xjX2C%R40;xzCI5iI&VZ|_2ugTQo;+a$ITDx^ zL4^}D)Bz~Lj|>0;2*UwD4Ud6|j18!P2b2qdr5Xd!Ck()#1f#NUFLjWLvFdP8%MHMhH^#B#iG9Y!$KpKf@A7D`jDieMH9li)?=6ZDX o00G1}(7j`T02=V#F+hL;04Y|F#CiPT+yDRo07*qoM6N<$f(UpXoB#j- literal 0 HcmV?d00001 diff --git a/gfx/50/remove-item-button.png b/gfx/50/remove-item-button.png new file mode 100644 index 0000000000000000000000000000000000000000..2bdb80348d6aab5c9e0b243e056c2f0b1acc9f37 GIT binary patch literal 1627 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 Ee=)1E@&Et; literal 0 HcmV?d00001 diff --git a/gfx/50/www-item-button.png b/gfx/50/www-item-button.png new file mode 100644 index 0000000000000000000000000000000000000000..f06917fb94632ad7bf412594b2b62b8a18f17e71 GIT binary patch literal 2175 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 NZvJ}HwGG08{{i+TflL4Z literal 0 HcmV?d00001 diff --git a/gfx/75/Thumbs.db b/gfx/75/Thumbs.db new file mode 100644 index 0000000000000000000000000000000000000000..e40142e5342168b96041db48c4c950ad9671dcb5 GIT binary patch literal 126976 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 literal 0 HcmV?d00001 diff --git a/gfx/75/add-channel-button.png b/gfx/75/add-channel-button.png new file mode 100644 index 0000000000000000000000000000000000000000..18bcb7a4778cc6788dc2c799bb533d30d5daa5fb GIT binary patch literal 3720 zcmW+(c|4TQAAg>`tzEXro!yd1WYIw@yDOEu4Y71sS13g%mF%-_B4>26^`$R5EF$#{ z8yk|V(xt_^O^S~v7Gl1@fvsl0El+BHZC%2D=SnS zMpl>Kviv18s6eI@69CGtL@w{klJzNmwk}Qpa6uOUpcnvHgk^RF0M1eY;3o$Fw&wzX zYG`ip^)3KVP_naOx<%ab6~i#SL0?D&5Q)M3)znWQ14zY?K!C(BtX@}j;#-Ske!OQb z#Z3Jgv5;Tipi4K6mfPJJ*xK4U4V}r)&Hbnvf(H?}KmcS~u>6c@wB-OwEp|}xN!Q%? za7X@H#@A+%NQ58!=hA&(!Ur!gGhdAPiS)tY38zB_Yo-k-C=+v0ji@op4C&J087}hZRuoY)JybVAixW2RsZ&UA2kM_#Y2Z~-+?Iuvkig(Ek>u|TpH#|fm)d0l*BI}V7V!= z3k7b!J~=!-?pP-ki#%%?5|nR0kpcm0O9%+}$(Tn3U&K%p2R#E1rhbd`(7rW@L}QxU zD0@$zo{*UAKOI?W@DTnz-{bB0Y5QPjq8=LqqDbFOahXfP8!&T{5Ag4<`1E$UZd9Z- zseYhjm3P!aSaO2DRGTt#=htS5IJ_C-;6i?1Uxgka@R4Ppcli^K-Fv?GE9ub` z1-GX(cU*_WB8EO%2B#f}4vsH}Gh8t*GA%1XC7tP>G;i;U=SvIOuCA$ZYrfveWO@mq zK4XE=>-yIAusNxHJho$5E${i$cBJ8DHH**ZnY&OQrf@m9Fc1Rj)fvKj=GC!*Q1+b6 zDQR?b)qez3Q`5`&(=Nh~?L8NBBx2(*>Oe|Tx z**E*|GJy+$qV{^E!C7_oXUOP!9DuYe>t~OmDI#P%R<1<49KKjqI>0BE!MPW-zU!G=>(G37xA{aTK8kh^c-z>>Tv((PPui&s=< zW~CTMAP;e2nCD7b_YVjA|NFqOK;Agp3!?CbtcUR8bl}jF&>mByYcrXZ95FpaG!uM; zhrc`tP2mekN=nO%qwn-~@7wpLM+o^|Se(+`$Qn~+rHp?2FT6E6I=YTI#V}(-8~&(v zYNtOfIsx3%;>@;HFR>Hq8?&-j)k?*RPH%*Xh#|bQGi%>Oe&6zVxG;NCll>EcOiW7c z!&0G7Ja8s|RPSBOKUsr5qsZ)%*oX+Jh*tUiOjl|Y*k0KCHH{`qK#8n1#8aedt>~l} z1VN1ipO?*wTA1MNvbOG5C6jx+StTxRZsOvCf*B=c#?;gl%>3-kVDuVOC)lyEu~J)m zdui0n$O>9Bo4-Kj06a4~oeqZXB*|{7`_u=SyZv=B z71%s$4GM%KhErossh<%L6l4+0y?pr>nW`%QUMpbuP25AZk=K7s4m6G7@pwA)8Jk^b z4i(3&%0AxJ)m4i`j?jvpKjp$!G-Km&Z8W3f%Jv3D&sMv#)yYRu^k6E99D?AxkgfU z{YLBKmeyCB_T&#KUqaYNt39`hY z*pQkI#P|%dbEp7v2&+HGJPIAx8Txl`{wc)$bMCB**z8rzm#VB=a@ST{6ciLlqw!}b zN2n$yi=d+u%;BZAW$?Z1Vm+2r>8kVNdL7@(%gd6G_e0&YKUh%3f?tw(a!Q7{VPbM1 zJYKcb%ET65968WOLOmNJZ*(!kYy@zW=nXgx2KznFOC+o!>R*HqS?X@@V-UD*Q&|9V zm_OBcZ3q>P0irTI3PPw{GlF@o*sFHcUnizJwy8L&FPG-+4lX@+D_{Stbn0~W(Y)1( z``vWaVq+s%E$dZO*2nKr>@l@GKbP0{(c8uV89X#RC{g0LFIcB|k9PFb(Ldt~|30y7 z+Zf9$Mra-ZeMB!z1yL0&^xG%|dVw5TZ_ehT#^{vw)aau%Twx=ni1$jt@Lwsf3n?GG zo-^l<`EY{EYy%%Buf#*V*P@W47N8Y1M)cM?G&iIns^yNnbSV zwM;B(WSm%%KdNL>E}f>fN4B*iLiDA`Ey_=&C3aqy+%p7Xe8|}{#Ft%MHJtKW0JL#* z(9nhW8!m(FiSqBy&u6V>ACq9V0?bM^`Jyr2+*6@0x%p1#8(>1PUcVFa{7t8_qQv6G ztRLN#$F%s_D8pVZgpjMbgOj_?hS1w4FjUy(~R&>2zn4PD|i;P=gxyk|%LGo=h2coIUs~P^& zQtW`XLL(nB%hfk6UblKf-y3O;w7tN`6CO9#B9=E3qv&;9vQk#$4*;DL*0G~)}4n}`M=oaKig=2 zb82$o_lClyX^X5{G^N!s6F~V;g6{TuFTlql@NxDD4=t;2J&k?jZ;IshSe@$eb;mhJ zTsFC&HM7FH+5G68jprQy*%^C0a_9j;e>xL&5O|1DGP3tCQ!?qmB%N@f6e^6~f8d1$ zx(XgGmj^f|+tQxoOg*Zxbu)_?-P!&wL*+2I3bZLQj(5TEZvM)*;(0Z-3UemBIlaOb z^&>1F;*6}lKka=CrG{^aYPIJ}SKE@!n*D@haxIS>h1R#^K4~prLk>!HHpkDvu=nmL z=Q4O@^r^bMn#lUbwl>gkxVm@6lvHvcKAc=jElTc|a{PXv;#3SN)UPNfl=*Lj?8Yc1 zjDV=IVi_}WXaUQ@j0_l$$bhaY;$FdT!Qr8{z^QeSkEpS)HPjS&ET zFAn^h;#sJ0)lMRaUMYxq1*9x;JCk;O^~+%ckFgz`pdj2I`}7jBI&lB^P|x7ecn|+- z9gOS&4KP_hV;GN;HgsDMP#Om!4$hOe{;~1;c}D@5o#jV~uD_H?1CE163FiK<4Y$kG zP-b?h1lr#*m6)oS5pvBLfSboCK-BT^J~yQ7h+Rm?$0`k9y0z{? zE4pvjYcgc|s5Cta9##x8l)!o%A4|hr5Gk1>jO?-Ed((SeaDP8exKGy(5JE)n5zC%1 z;~Vmz>yw?Upl$}8D;)&4ve6K@c~$OqnOfd9`&BL^Uo4&I+i8g`FhU_34A9^U8i(P8 zcw1AgEJO6&;?6#yP!{Y4gD;&30M!`;tN;KI1N1LmHQCaf_(JxT1nhP>+dQ)7ME?(X CWv%T1 literal 0 HcmV?d00001 diff --git a/gfx/75/add-channel-file.png b/gfx/75/add-channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..e4b9bc5df1a9f24852a464109860a999cc7094a5 GIT binary patch literal 3412 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 literal 0 HcmV?d00001 diff --git a/gfx/75/add-item-button.png b/gfx/75/add-item-button.png new file mode 100644 index 0000000000000000000000000000000000000000..2290c76caffa924aa9ef6015ccc2e093706038e8 GIT binary patch literal 3399 zcmX9>dpMM78-L$98#9cEnOFunl{8ETh2|YeR9ll&Gu37sq9e9erDWb2B}AzxmCaLkoHJ?2TLB&9Vkwe6I`V{d<0ZPZKLk&KR3Vg73Od&Z zVTWTBg0k<;LaYE*u{th!8&E4rba7xjpgRvs>6;Q>ev`ZXZ3Gn8;V&8!+;I++I{8{?qU%& zUUF0yxo@AQA*}-guD&roG&;ITs@E!b&mkQqqMuBM0f)OJ)Q<6#2c!tpKgoRT6f%(2 zleE(|e*lfeHNK*6Id*JJ=ehk@QpKYC$jEGO*rv|a1FzFuxHu3)`RGNsqL$r6*yCbA zTxiz$MkD>AuoB8EQ4^^+@5!f-Cdglef@wpd) z4yOgP#o78<0VV5#r244#nQqFrz2DEzOF)xWp6qI2rV)rtXpgEusjPM(#XRth39EXv zGjRRKesdQeQ^~Ir)_yl&tpakz8p>${Lzf!QyVoW z9~+s)$qH0C#gPip z{pd9e4U~&1RuVJA_)FC1#~Y^;98AN08q}bpswy8 z1FTvQ(_A3KIkYxl&YYV4{?p8f(T|lA#%$Q`@9Qh*|8-Z~>aT%PU??Oo(2$=3oh2T~PLT~#?AxJkdS(Gj5Up2@J5G-F zO6%UwpFdx)$kkOl(ATHJX9jZ33tVMw&AQRno+JLAW@E4`cx&cxA1nm3dz1A#f`V{Hh9jn&6?iVSj94>W4+U@B zh+MgRdCtkhL$7&Xb0|NiEnm4}*)lC|06~>3EDSMId>3TOB5>Tro}Nj_v@Q2tcK3T= z1(Bx*t8JOyK5(-gA2M(K0RRI^tD6Z&jFrnV?-YWG0i%Xb4VStgTXPCUh2FHhcW_`J z8I2z9ZMy1`82hod30zbF555sNppD+_kH&ez=R6q2fRA6m{(2LxtjC<5nuqt_6!Z*R z4$xu3!yOkZWTZYneLpOUd(Es=j=^UJWcqjy|p#lD?Rs|lEo~ViE!?? zf+NuVKe6dDl!A*U>`>SHHp}I5S0|_GOIcYX73Jl_(#1O;!~@k5sSSK&fyl|)z0{e|+yx(fvtG_zM@;&@%13gKTX7iXN}t33IW^wQF`9^avZ zYm&8XWBq@*;DYUQ<9uyI&@H6WVR@tkW#HL7kr+IC$Ansq2nWfJGcc=EfBv?3Y5)C`c>NYgd^|N+O4p$~m1*bHdrfg6umH!MB1p!nJQpOXta=33gf-c3AC-?259Pnp-xcDu#p=230^l3K*z*3_*7(gO{66PJjEmOSs(puF9ME2yD zFZ1w?;kC832s}u%mYhO%BC>>6fCIJjuz6`Y!O+$OdF0x=|; z9rNesvSgxsFy|@sQiL+vy#W<%5g&Y{&}OPDWXXj2YagVmlcwMMQ~>pjWzCn1k77e^ z-wC8k(v63&#A{7!_9wk;cN){ohK=>vIhNiV|2BHUGH95Ixcob9P+HeQdydY9{w?&7%9;{9GRVvfg9; z_T0U@1E%xCxu{GW6>oWaqg!k=c$3aXM+whZMfe}qIXyakE6jFg?9lFa-4qQG{&;?F zq<+fJ-lskLi@R6UA$54ObJ=adaipjKMTz!s15y~2nqA-6dmc~gAB`^%{V}P9?qGk4 zHfvODa&G!Qe603A)Qc~e><`MLZQEILIu1*z8IFo8&bjL0JhrIr>MLp_i*4rZd)7|& zHqOhf*jYE=WF{hfWE2iB1YiQtLb=$!HDdASF5f7rwliqzY|qT6V;8p_YM;^A8rWlL zY6woKfVyyy#YL^zfkhir82azBJP~wp}wDNBek2 zB^NI`s7cAnHMiI$fg$j9Mw(feC7M7NnV)Y2F-HN30bPe3pQcDw%CXUWzP3stQIRte zO4lK<5c9RyE9Gwd;oI1Bq59y;*bl&8N$xTW+@exMG+bAVr)l-GDZC9qLzgPHHZ>%~ zEIPMz@3WNtwVYjMpK|9uMTY7xU-%I=%X=oltu8N#hCGyi8q9>**9$`5S0dj9_z6JL z91TQQN+Hv#+Qi9Jaz_IyAs`&sk=mC*<9r2+{rL&)28TLh#SPS*$C^Cv44Cc_;C8>7 zs+cFbDHwg``*QqS`-zj(_$nj)+nnP%=OsnP!|$}H6=GVQj_IBpbv7cOM>6p0_DRWc zO2$35E%-2xmYJ1Rmu1TD6X&h6tdCUCK%(Sz*-fpTBruV{J>&_wSf)?RtJ=${BbGN& z$7+hwLD|7ub1S=^hQDzCp7!s3UZ#=X1$(qVFP#DxFL)DTG7Xeg;HMqis3=22mK-R( zDI5n!z`D!CfBEr+ctjjdgTy&&T`w3U{?0fZx8KtGA&5CLstiRNls1Hd{=>4q`@Kye zZ1(67}<=7>G3i>eS$Me;AO{Albo_o{}xwHQKpJ zfy~6s{K3t`r6`Uyp|kRzIra2CfB~2M-=vq^_7NV*>9t#vlokWelu=W8M3m@+48Dme zI{mX7hCt7VS##cCfW+asNA`mNYX36B=)(XScyj!P*SL7$62ngj2wt~2;DJA1^j}>a BFZ=)i literal 0 HcmV?d00001 diff --git a/gfx/75/add-item-file.png b/gfx/75/add-item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..2a5e38834a31b2b9a0bd5c94188afc833b3dd65d GIT binary patch literal 3125 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 literal 0 HcmV?d00001 diff --git a/gfx/75/bepodder-logo1.png b/gfx/75/bepodder-logo1.png new file mode 100644 index 0000000000000000000000000000000000000000..470a2399b9772bdbb56f4441b30089aad85d9d03 GIT binary patch literal 4480 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 literal 0 HcmV?d00001 diff --git a/gfx/75/channel-button.png b/gfx/75/channel-button.png new file mode 100644 index 0000000000000000000000000000000000000000..c15b7fddb13aed893ff02bfe83055983f9e673ae GIT binary patch literal 2468 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 literal 0 HcmV?d00001 diff --git a/gfx/75/channel-file.png b/gfx/75/channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..d638c173fe331502fe1f63384d6015a7fc6b139e GIT binary patch literal 2185 zcmZuzdpwl+8vniXj(27ZX58;HZ)i9rMnouP#=RsQTj-=Qii&dS;?8SEqLn75nAK`H z8&aE*YP+3GMQg)pj#N6WMT_H7E~Uk~%)WO2J%9Xu&*%Akp4;#HJfH9LD+&(s(^NN6 z2LNaW_Axp9UiUYIRa-$@BnGDV_ry&@@omd*_Jh zyQ%(`?G+Ujp{nIYYfZhH)W{g3u&%SS^B8vgTzUDMoe5_Efm}zz(&3@`UCz#TI?T+> z{4m~Z$@jUQIZO0~FB7||N^>-4y|WL1@?XM=V0)r#)ZV?z`Et2@qtYw)&~Ru1FdElL z?0>X1`SZvQgul&(uNZ_d@MH`^>Cw^A_v}yNTR z0m6$8D1^EV1o=MJ`hC87*nP7^9Re8@29Qk%`%ih;4z+iw1~fP*1&6XaP(up}-pDH# z-TAC&f)9wyo|9ulx8TfBezqcrvY8?*h7HIAfGZHi@1>i5ty?i&%S3Tt1SZGi#Tq1( zl%rbtw&=nI{hml-Gq;2&K=_^pwkyLOhPBsrH>TwE#K*_y{yI3gK>9>?cVAR_=B}`X z>_W|iQQ`gKK*i)luISR-4gTP)@wl(!%1oA%ZFU;K< zn5{0I&IhhUqngg{?rzy^SJvWhM}pR@S%bvKPcU0@mIdiE@6|};|M$@3HUL+-kx?uu z14vw}8GNpbo+Ql2+nZyF1g1{?GE697i5eQl`~Uai@-a{bueY|gemU``@olvaTA`@} z|CHB*^$2INS&Pb3Z8NsYtU^Z#K6m`T;ZVPW98H>AgC$%nx8Ju?CKk`fCnPLU>*uDL<6iXUNu}lokwV(x#HJc+eJhuN zS)6JHzaN%8^0PNqRKt>3Byxo&$(ibV@FPVBW>Lk?Bi1{sl0X@;zJ!lN(@m|AQur!# zRc#C!QZFGV!eGUO!%YC;N_%0Hpl z0-oD5h`T@2hJ`s<+E|L#IVND*hZ5AwEg=FqkyY?JBfdw- z)6(l!-0DKMu@uT!L8F7ND+T6LF-NA&wFoqs>Wgy=;(GhB%Gv z(IK2d*{;|(>em$()0gkwou9&)(E*tMh-}-gpsTrf%8sB(m84Z18lnlYu?Rml4vbJ= z)0iG?sM4e*PoPr95F*vzch#+uheZr_E00sPzaToe9(>Jv-BE5Y;+0Y=DBLeG$nty?d&I&*|6 znX^fgj~<#77>f0^MJ|IMRG#yftXM6bVavMYvjw~An3Rvt)_pl3Bi!X}QKMJqZ3x%E zymW@x>FMbRKO>HK$BrwVx?EH9-qX&`4$02WPO5_LtedHg2yTWN3@$ZJ{(SE#(TOUt zUxB)iH|BEs>0Lu=0CM-J?Z}VdiKL=)g zc}PG&5jP@Y!SlE?`3lb~1r9of@6mm%9L>WIVCg=rV0+B@IHgjFzUs39;beN~C%sXG zA=|sT?uWnj?SEX2dp9JgT{O~=ojDy1Y9sP|*fe>*E|eid$}Rp}p8WbbteYvX2_U9K z7$f`|(?U=1EnC}vZXlFM=M<|>&kJZ6F!>a}77z}$X983KGJK`)4nDju#Qzc?z$eK2 I29GcN15A2yH2?qr literal 0 HcmV?d00001 diff --git a/gfx/75/delete-channel-button.png b/gfx/75/delete-channel-button.png new file mode 100644 index 0000000000000000000000000000000000000000..0aaeba82dc4c438dd86bcf4bddc7ecc0fdefd657 GIT binary patch literal 4218 zcmW+)c{r5a8-Cvzvor=HV(f#`VB%#;WSJRR(=wq_sRmh+FTPZ0G4GHipDmFkF)FQO zQla{ou_h^fE|p4I%D!Z0Fy7zv`{SJFI{%z=KhJev_w(H63VXM+96_A`0DzpUi-Wr~ zx=0s<$4d9|e49~ekO^e%VgbOD)Qih|uSw4oKNt610C0W-0Kl;TAV#Ed2msDP05HM< zfNj|TpcZu|*0F`)xuLX62OdthI0s#_}R<*w3)b|$2 z!tZW93SBKnu9#m}zky*Mv&N|@u(h>y20l}mo&8xggaD%OfdI&|V*72fwqEw9)Zl(8 zRCdh&9&9VrV|Fz+G&B%?efIT`Au%n{L)}8Is|bE^>+aoiha4Onz-Ht%l* znSt5T!%#yFe~hr!-_P#?jY6R`zIpRNuJx2KsILP=iAox=v)@elIzqtX zs=CQp0K80xnYzRV8b5PJ`feFB*b74vcuVA_HJZ~X!ajE#iMi-bx=%u9StBeTnFj8I zi54D)3okM{(k!J}_Yx_5r!YX001GKQ&u)~b086;Bt?4?f=tj&RAV96X>hbr5K4d1J z&BKu1)379Fqz6ff8jgCU#~<55d`i}D4y7>q+*ndDTVWW`WPYH{r(sjq%R=F&SN(hg z5nQrW6QjGv3_&Cszc|WUc7}u?yb;mWrG@2)0j@B*hzc*QDN#NKfHI`L{v<(?j

V ziB3oB8;=TAaSBs4*4%=Gtn7ud%vawon4B2y7BK;50|5_BWTtX;Opf$kj9L`nT?(s8 z$DKjjo4>h2gtLSwtZn;{xX}wMz4eDVK4VFghp?t#kewu6m{I*XS8#6l#2-Rlqa*8TY@!=5?Qivs7j_As^ztq`{JOyv za?K>jOoC#cW0+Z8Vi^&Ir{wR`bSI$VW`zhEPd@0iDv^k1kgSS;FUFfT5%L)f!SJCS z5cR>Nd9>w)>&Wroq@_pt&XHs*E3U0qh3Bu3=z^~dPEU|}A_PN;mkb!k##h@N^^#j# zxjgM-stkaKjU03q z`1XBwGR2N6xBX-6qXYNVA&pN-aU(2QEhn~cxqEy~^>ihVr*F_I;;V(!Qbv^CibQoy zqQ`gY`T02wq6YIDy%S$XZ9bnbo54>)(Ea5%beDvC5G0!vn{qW}H|F{=I{EQ~Q^QY4JQ2!{VG&t69gKLBD@-#jXx| zcAHwBQ$X*ICUrnJ%oX=v63)L4$JRHh=S{EK*HpBBO^3T^^c?nmQa2oM-?wjlafsr2Mf*q@$1Hb`s&tM)xrk6xxolTYzG!on4Kv?3geBa~Fl(u%Wn+pNVlt zx12+vP+ZnUUELx^Mn;B^^+5JGjlH5k-4HX@H#mqp>rcKq4)zMWYo1JM9KM*b%O!Gt zSPNZWEm=^jIl^cbO%ChUBcWyFRc;j6*rvA1#kL>g`4$%FUl9V2{35wGdh1`r5+f9< zeHQCmB+k0V%Vr7By4tux_#MhAEGwQaZ3&4V!fNkNgmAXPwR20kYbkr1e)Dm{COAZbW?&g8BTAn|;gxtcLs+}VALvi@eCb`}0 zhai?@X~j9228^_H0@c{BTA5ezJcm zJpRJ#8nYGOfu-9&I-)&VjeEA-xA2p>pfu*39}h@%wpSkO0yg1OjzB=11ysC(^WVhI zo$jecpW{3fgFDptB^yjl5v5Ff*f1$BHufh2nuB5m$;qvzoSv{1@RR1YZQHt;zIzI6 zd~n4On^PamIs=4sm_evla)jc!h+JOWQoW&V3o+2noSG})aC!%@XSYsWZaWrVRwjhH ztmhJXH=+l1QXU%~aFo~|l`K!)#B|)kI@+P1>D5U)8p+qh3W$M7aU%Qb7@xMJJiuyB}}iDSS74Ey}|0*1uIo=-3#w^%$P9S=YF=vPf>M z{NYzR)MYiBB4&BSsmm%T+!h2jYczEWbA8^Cz0ZTFL=GVaOWIG|q21TlM`W((G+;jk zhwuSZv3mLpk5`W(0)lOvr?6a3k|k>i2H)ao*H*!|)Rlqozv-8%&*ULG|f z4M^`+gAd|tDx?p|b6%iNxpEVT40vWMv@H2KFtDmXtNOz0?_i{#XMa=(_C}qo6!Hgv zLyl{%*zULBoLp2JMAA$<9ZJdM&M2PY;MOWyZJ)bKEowKxs~xSsIsI}LnS7K{{Z{;Y zW}^kiV)+e|pN_>-d=Is^Hj~@W`UFJJ4k_XU{C+S>-BZ4rixkLtR=~5cyS&RL=pUYP zEQ-*I^S5R1M?c}NuDm%v{&kB9$1P98(+LFWFOLwph(O@hvf`t9bx|^<+wij_KgeGW ziW7iuZ=e=P zI~+qqnf3S(?G-c@`u6eBffu~s+JlN#|45Ljn<>uS)7f60?XS}INWo|a0-q02+G5J( zEyG~m)UX;9mTCt5TSfFl-{Dm&V)vhNQ1RDLi_Y4-m(J7_`%7k-=J?|(&^)WuFM#8=XbOdK`iWHn?D<7g z!M^0@HsCPkc^;y!OiWS-^eoUNNrKoES0D1cKF^8d6lnQ2 z#L(-zl&h*Go9JlzPp_?6f#DxOaK^_fwv&Vd<=! z-7E1;zH>vRbkr`7nK8U`JzkE`rx}X-e*xJ;F%N?yNwHt;MEhriZrLVJyoJ$P%2NLA zpFTDOkmu)#hbTOEc|q|zJW|qn?iJFlVNdT~=xY6U0-AtbK>PqxD z&6=)&Ftpt&f7A5VauH+^yL+9~uN)^$CN9=Kc)Tz&`enN&rL?Q*9HVpH^JoMSqwf#s zSoSj|&G<&kr(~&!JRI;DSB?aDD3q5!eQ0zP!JVU%S#jp*Tf@6WmJSqNi#{i+US{*4 zsX(?)3Q8qriFLb1G=WJg_^6|;e}lm(Dio5Xle~OL1>OE$G#o7v-{fsSDq-A9n%^qO z>*n%<$?Urc@I0>t^{+?UAJP7b>pH^RDx>Tok~cs@1GW7a>fxRRH6wVwM~x^ahwzL{ z+~<(xx!7EA!$v>s7}6~i+GWO+_8DB`$K;MDkE& zAd@i-N|wNEdl;xwV~U!(d^!4$RXW?2a3k71_us_Rfaknuso0@I1OxybWb}XM8#?kr zsnbp@>8($Q#5Qz(7wlj$C*{fPYw#IUlQ^jxjo2Ne{D;dQ1T7ZN007*q&XfU|FbFVG XGlTVLl?Bqz1HjdBx5Hz5PR#!R5TAK0 literal 0 HcmV?d00001 diff --git a/gfx/75/delete-channel-file.png b/gfx/75/delete-channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..ed1f4ec38f0a8debca6210f63dd1b905bcca8766 GIT binary patch literal 3705 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 literal 0 HcmV?d00001 diff --git a/gfx/75/delete-item-button.png b/gfx/75/delete-item-button.png new file mode 100644 index 0000000000000000000000000000000000000000..22dcb5310703f589a9a43aeb2c454cbd7a049b6b GIT binary patch literal 3843 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 S-l+c~0YTgM1l-xm%=$lWP$LBZ literal 0 HcmV?d00001 diff --git a/gfx/75/done-channel-button.png b/gfx/75/done-channel-button.png new file mode 100644 index 0000000000000000000000000000000000000000..f9162ac690580d527bb7630d527e59c3fdf31558 GIT binary patch literal 3762 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 XnsV>?iYK~85`ZlmgEw6F<%$0f?D3<| literal 0 HcmV?d00001 diff --git a/gfx/75/done-channel-file.png b/gfx/75/done-channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..03afad8b0981866393b432877c6c73074163257d GIT binary patch literal 3346 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 literal 0 HcmV?d00001 diff --git a/gfx/75/done-item-file.png b/gfx/75/done-item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..12893a20baa07185821a1a9f5adcdf749ce3879d GIT binary patch literal 3031 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 literal 0 HcmV?d00001 diff --git a/gfx/75/download-channel-button.png b/gfx/75/download-channel-button.png new file mode 100644 index 0000000000000000000000000000000000000000..725167351076aad92e91ec4b1775decc6169755f GIT binary patch literal 3582 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 Uk#$R|6mWpg)}3DWJ-EsL55v1Q6aWAK literal 0 HcmV?d00001 diff --git a/gfx/75/download-channel-file.png b/gfx/75/download-channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..ed934ffc4a3bdd7bbed4dc7833fd98e4e5d092e0 GIT binary patch literal 3108 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 DvPVwL literal 0 HcmV?d00001 diff --git a/gfx/75/download-item-button.png b/gfx/75/download-item-button.png new file mode 100644 index 0000000000000000000000000000000000000000..f4c1f160bb466c037b1d9d1e9eaa458dfafcd189 GIT binary patch literal 3271 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 KJZ`xQ(*6(pji%fH literal 0 HcmV?d00001 diff --git a/gfx/75/download-item-file.png b/gfx/75/download-item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..e698b5f74997f939442c301972af8cf1a4f36223 GIT binary patch literal 2811 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 a0U&@Vt)E)5D^58AwE1q^<#pGCFa94bv+e-^ literal 0 HcmV?d00001 diff --git a/gfx/75/emblem-add.png b/gfx/75/emblem-add.png new file mode 100644 index 0000000000000000000000000000000000000000..e17fabec9b2be506328d1a47c2bf46c4e137c298 GIT binary patch literal 1232 zcmV;>1TXuEP)004R=004l4008;_004mK004C`008P>0026d000+nm#LZ5000DA zNklE#$ z$i#4w;Xgwy13SYmWaWQ>?&V=)VBiFryr=s=13&8fu3gh{e!{m?;nO8Km%=nLdO`O2C*Iz+$2+&ER2{z`)MJ2^ReM=R3oWQwtbQUwX<2)RqIc0BAS|&>_r>5HmplAb?n4 zCV>Q)fT}sT7#M#2gj*oR0CbI#tOA3Uq!+`F-(SFj9IQMHw`316oV)gvf#Dy6G)yrY z(1A=02*W`DAb?mHkimbjBN*6#VfgniL?JM&8UFqM!|?9=6NVqZK0z#C;{%H^GeLqE z6m-B~1nd0|@dz9M1Q4nPPyo{awB#4aSO5P1X88R56~j-c4}Sms0TzSEG5i7>j-EK6 z03d*nEwBROT%fC^kSx(>0=n`q!ykq(KVAS0{tmU^3s?-~17IYW0@WUb1q+Z33^#_U zKztO$2M8dr1;C`~0(8x0pkW-WNGSj;2UPLz-%o}wzuqwX`3p$_EX*8WF?L{t{`qH{pvR;V=@2)5X1+djKsps z@aO+`hF{;GGoW~ZB)|v^(!UHKvzVEGgUtpAAV?g5axpOb{rUfm;n&}PWEu_uY{2ja znZ*PRIe-9y`QQ)Gd(2EsAe(WdHzENO&}2|hfy@N)0RjjX$rrzT`C<0)<4*uckjO9K-L7Zh>eYfK~GN> z!xE6XOP3xq{QC6=C6j^F{r&g<2hay~AU;3?%%(ErC^2wf&SmW zjQk*Pqx%XZ22=~eAA#J9FiU{cQ(y@^_1|wuMgs^SuEQ?rK!M-{x(HOhAc3dW+n%)KKl6`)h7S}1h3IR-UKN?%LS8xWl`9J2alQGz54)mF$nwvmeHR+ zeFm}q13fYY#l^r1>&q`lkbwX|0Kt9046T#@p?dK+u$p)O_3KyLt5e% uwbU{oB@CE3;5dQu0Ro7T*3A}x00RKo@oWNF7X8ow0000>q literal 0 HcmV?d00001 diff --git a/gfx/75/emblem-delete.png b/gfx/75/emblem-delete.png new file mode 100644 index 0000000000000000000000000000000000000000..9f9506e30bb12e2ae742a5a7711808fcbce4253e GIT binary patch literal 1455 zcmWlZc~BE~6vuzrg(Z+hQqW|V!>j@U1u+Kz9kt4$*#E&sEcyM8MdKE+N|7y>0Z?@~ck-8`mYPV6UbP&698Ulk4FKQG799X! zy9j_!6aXP50Pr`LT-LP#U>y<@C5z2IMNgT{;qU?$396Vv&t(VE{0O!)tZxAA?F?__HX;PUHmi_tdaP*8`qTAgm}q2uba_z zj`Z zQYE8_V6C%uop!c%gBC}l&(7eI4Po9$PgdA$1X;c|0QuOLiSSq%h~LI}$c2s5s6+bn zY6$7_(?+b}A)eN&mB`Jjxk!4X7b0_6OI6lLbbkpf$SQZF3dLX5ZIBh$sZB6M z4u2c@A{K4BGhY}tT~DLA%TQ`{F+x5L!M#tH6qKCgN#i@s#ohfY3#O~OOrb0*F2|pK5)_PKx05|_ zllgn&$gokW*TS2WNi@YroGcOHv%> zhpd4~2V^j?zeQR(S|t|QJ`=e&_3iVrPhZ=5Y=KG{9k*&;G-)-(a-eH+nE20-fx zcBZ%Jt%>C{m{0X6lm#Ak^|fan<=*F2l5Og*3@ChIjmG)SU<(LFn^z8@|17xr8NISp zh@y`rhTE*T`k#nB47tqq+|WB5X|Jutv%ub5at>5vIaA)H@CsG7m*|eq1-t~mW_si<7HWpA$Fd(!-@>9{jc$jsJ&b}jERpiMP41K$_7ORWlWv{Sd3dh z9=dMIO=(4r8GV0jT?N@QkH-fWvDae*FKcT>?abWqVJ|9X%#9XCqn6P!E8kb4`MF9e zdkd5rRQXb&T=Ffcf}D`9m}%Rl2cQXl-a7{ zbwkh-SCdp6yE_-XdO(M7fcD;Fa(0~eT4-TczrEU;Fo3bs$H3>004R=004l4008;_004mK004C`008P>0026d000+nm#LZ5000DH zNkl{iQ41fLrIgAVp zKYuYWumEXT?ED3?*_nY1p#1m0Kt7OWW@eBCs;~b4kHHZr^OBW~p%W;+lL_c#Ru+h! z6O;Zk00a;VIj&-4WKjP1hhZx-6N5S{C)h%*Kff6qf#Rh==^kXY00Bf&5J7#U1T=U% zD=UM#vI+}BymuIbgM}IcH!lMN(DmIwT!fr10Rjk@57dFFw-l&Q9O$b3K>lPP{tfiC z0y87SCMISERe5=4h9H}41`R1!23-YL1}5fChEo^rFns^c&;?Zc1Bj=A3<3xs3?Bdu z31nenILFM&kj%!;-~)6~FEBnf0xdKA2Q(b$a&1K=HU@8tSOy6JZH9MW9y9#=_n*N* zCyBwrNQr@mmw_3mXDSf8fXo93AQT?}UF-kvAHy{r3~_N>*qJ!XLAQzoFdj8y^{e*Ia^aPIPBhCja;%7DUq00M{w z$#6d)UdqkQz@e!o!l0vQ$H2)d!XU`c&v2Ic9K(wjzZvA^*%=JfEE)JXB^lm-dxVG; zC}3t{VGtLTX5i#}%<%OugEUACAb?n)k!JuTR&aAOajL5cF(``bG5r1epW*Z0mkiwO z;tbj<>I}jn_ZehGG#J=f_!&NZe+E>JUc@jm{QUEd;okG>48MMYlkqW-C_n&#E%^7F zp_ZM4kyBMwkU>I3mf_dmZ$SJNu91z6gF#AI85j&q3}1de$C@hs{Qt)Aq-yc;u`=-UaROcO9vo??j$;HxKEqFtIF_=J37E9ry!{9^ z92hB2ftk)5m>(a4W}*M>-Wz)cb)?+`2#i(+2yRjtPFAa3!uyY zz5;Rsftm9xt~de+Ak3nIkzqa1%+TMze|^7u_X*e%kf8{de+Rn!3CQr*Kp%SpwVcFd zI0yg)5Z2NZXvt=vS+PHV{``LL-XmZ{{s4+GGJO2_1#CDlSY83;{eePf2vz9-0fe(Y z0BT+f3i6*nelEOo=RP|Z7Z=0l&tE}?zX66+Fi^>H{6<3nKmZY{4^}dBG1&b5`)B=! zkDsnFGW=b@%)wv-%oj(9F&qQ{0*H~;%@%+F0{}_paxAC!*Yf}X002ovPDHLkV1lCj B8kGP5 literal 0 HcmV?d00001 diff --git a/gfx/75/emblem-download.png b/gfx/75/emblem-download.png new file mode 100644 index 0000000000000000000000000000000000000000..6db19d585bfde94366334c74558088986f791ca1 GIT binary patch literal 1019 zcmV004R=004l4008;_004mK004C`008P>0026d000+nm#LZ5000Aq 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 literal 0 HcmV?d00001 diff --git a/gfx/75/emblem-kill.png b/gfx/75/emblem-kill.png new file mode 100644 index 0000000000000000000000000000000000000000..fa310ccf8ec1dd6aff323101a250403e1a241466 GIT binary patch literal 1413 zcmWlZc~BE~6vuy?>~0`O34|jsAloP=LKwM04%r~ugrdd_j=+F!B#Hu+Lo*<9z0bUv_vX#_`^T%6Z}^JC z^k4!2I5KIx!bbk*v_oxmv@mAY1~^l)UIM^R$4VA9)!KS2L#kL0K(P-1WElW+RvRY) zPzM0;f&d`04gj~@x(f|v01&P$UXoOFdizNGZeDL^sg+N5S*%uT3x3Uq$9tq+x9-<4 zYFL7flQHsK7kTS)`Rjb@@g8c}9XkbKWHQBUCz<+!ygb93>FI!yPxG5U+&S)@isy$@ z=U!sv!@#7(SFOkP+6#r}+2P^gy>%t+AFlYN|X5s#K8l9Lz%}nY)*;2bN=^PN3Za(93_!I+Ecw?kLer^Ypz}L z6Nv&${r!P$SFe^ilj(M5F>Jm}Q=w3LHao-&d=EiYgS3f1G-mP}#tWzd4CiCh(_?Gi zpN%bbrNdm7ycY5H_AYC0523SIEc*Qe?3|n&Hbu>UoZA~M&k)Gd94GDCCNN+&eE765 z(-vF0r~>b;PbVgjm(bJ>Tj*+PlttFXnBGfUTE&1?h3x7Y$bE9FKl;E2wzHT(;^N}i zt=l?x&d$F1(MVC)Z~>QNgkiFxj8ioK?t-8SO#zSoTbRks8vz6G+>7Nn&>OrELiFvb zj!8?JXi58X=jMnbjJ)E_kwQxpy0P%dt3w>Js@C%&GagQIsoyW0?HpclF4R%e;2$o) zg0~cD4~-PI9|zkpg5tJSDdscdTu=v4v(BeC<~f`07T zz^Q<;T&T~DULFfgrQF@wNn_Pvg_W_vS*Cf%bk zGj%(;XnzJvQ12=Am$Urt$AxmeRrX@*=RwgB2`iOMXBB+~Zsh74bwgyJ`3~_j7RJ5W zZSL{}T%2GL9@J=T;!;s)w*nQnl0YOYoquP4dK@2fcnc*BmewNy!8R2+P(gf88rp-g z@F`DAoGvnXRy#~hGx{|_-X=kPYmGlpk|3^{Zty9Ul<2-R8jb9xrY2&)PJ+=Tz{1nr zl^oObxrEqRd&U836I%}1lgmhbp4M4Y;3s;nEm$G8)2xM)y-b1B310IT^|J1)M%O&* zynqDS6fn38_oN**cND(X`hy>23Wb8WD_N~YmYS|pH-PIP!NQA4j4zrw1D$+8zT=R9 zmO`*@A0e+Oz;4)`8N_WKo48vy`WCre>CR*+xS+o~L9S~hT`$u8v(bL~&}!gYO}E2z z$a{Q^3+{tOC`cb)Q6DMbH*=E`w6`T!;!&)UwBT8IH^NMiM|TH3s}*i^CR?&&aG*Jy zt=4I%Acj6kQW0A;4U#@CqFLLKIoNeE00gmBfl`j#-_NibLWK7!DHVI)_a3&bgh#wC z-ylnGrNih$M~?>tUGvWl{Oi9o6TdLT$)gR(B%gZhg@@uTu}>R^gvl#SVyXd~%K#8; zq}&X++ayyhS2KKPl=~s+S=z}^mZ72&ikhXhM{ug1DrGK~0^Ms(ei2UUv9AqJ~d-uI`4gJ)ywpedxqmrA)#?c8cJB)RD(>Rg3Z zJohDjD`K-d((&&CDOJT*QzL^X|IO7ihssUh`aN;BY zCtv{H$pQGZ0sybfio3c20B9e_MMdtLjLn%N3V6hrsZk>5Q zCDJY-_9@FII`?ql8lIG*@v6F9blw;nl5gzpx*kbB;_~9aj|e-6(U4Q01UN_*D=|^X zRpGN2Mm#tKZY#rdv@}wOgd-TAwzRyFPIjD;HeU;u#_rUd`-gRLsLaqjy1fYqQ3DrE zW;YDKGWS8|+$ZT)*R~cSQe}YJIj=P5T4$Cgc4~uVUr7TmB!vumzYdA*hOxE?U82$0 zt~u&lsjtdFZ5ZBYsz}X5xsT{8!{JI!NUJ!FY8#&W-U~9LN`Go7KmJ5KPf?YGlsAKY zBg*J?m4M1&4KeP=Lu#}JUz`e}z!E-=6Quc7qJ;Od!C^JhV`Yz1qP4XxX1LD&H_&#d z<({yFnbj?s{3dU}tjJlJzQce|{6Y$FF!e7jfLuuP=|rZ~4qNMtWs^r@zlAWPTFT?+ z^Il?h_9~Ms!4n)K7N^#}h|xoo^)w!K)zBHxp}%<_JQxo#mEJKYV@fY_kSl{JY^I5k zOw@02$(#yZc{Ixs(;GoLC-4@ZpKCwOK1p>2pG!!;Z|o`tx=g;0Z228!|1CBLVG2Ns zjlmPQV4WV+L>*F-kyj8g_*rzJzl_LL7{18I2Gq92;*qgumC$`L)Q2uFgdo5;hU)m9 zZ^RIRJHAE>L$S7w5SpEhc?iJ1*(;K%?R#jg4DUhGV=#_diencq6B27f1%LZH?6ysJWCRZ z{B-!Cd@H1I=^=A$a}$|}DV3ChFGavl9B6BdyqrSiyxa-Zr-9#p&szkYKBd^w7TEWHCFNa${TP3Pv^`ewZ$I9#b7nZjo*iTWw2% zA#!vyeKVcjAADpU>|+J?2q-D|gj+(A5N@vXb|*WpW|qV z2=_a1my)y4rGiGoMcd5m*q#5>xShtwp-FziwXx7OROdX7l2%K%o0~Gt0e?L{D>y>( z8p?C#k<``0^O#l5=YQKMkv<^s1*r$Gkj>Na@1gC_!cPq|6j5|Fv^|VX8?b zFVP%WF+>eevKRbvN-`AJT;@BKas>|PpF literal 0 HcmV?d00001 diff --git a/gfx/75/emblem-refresh.png b/gfx/75/emblem-refresh.png new file mode 100644 index 0000000000000000000000000000000000000000..080cdc33d7ede63404115529cd2680ffddeec853 GIT binary patch literal 1556 zcmXApe^gUt7{}l3ZkNF>L4vT!l6BNUA#t~*`J>pT1Er2Q(MZwaj*U$Xbsa0q2HTik zML{tYhMas)tOb$s z*}_Fh)i3^(E^<4OGKv(RWTfdE4QMY#-5h=9O@Wi)bo`cyk|atb;&pKQ`}w|`hGJ`_ zI$j#$s?3e&^UND9i#UdQuMCm{OR^_zO29>Uh>i}G%l(3uQlHWJx(vGy98kwfxr>?I zss!;zFurAgA8n#^qmzE?AT=OEs!5Z6eMnBxlXzI)WuxdA`XpDkYZ z{dnnv+j{&Jx%30cCA2`J+hq%30tV|TqirWa=rvkhn{F7x`c`FY?W#;Y=n>Q)!X;YB zDlgs1Kk1dZc5Uh6ImiGZbf0ea=xjHz3k~f=YbVj#(SkmhOoFfcyq3>w!>KYdyl16YyscDpxWk@ilyS%xSgjlTx|bZ#mh z8=qp`5J`=Ex6nA?ASc^eT1FpCoZnWkJhxuoy(&wiikt%`jvcmCm6Rz~yj?QbSItFC zedLjQQzZsa7=W~MpL<*`%|m@uWph@}zP*YaxqAlxxVj6e6Sz4ae}k5%%o;Bp{O#A2 z05N*hH`!$(-)kV3kdvnBqh)0~E&Jb@65WQ(o?U=2jWtMZsJ#TWXL1=NCSh(`SPGiQUgvMdb0eOQRnmdXSklp8u*SN?(sUEXp_;;J~{SM z6xRib(qT5H3cc0-SYqFbLVb>W-`KO4TwTt1zRy3O7ai?aRP~kr8E<8`tv3VaS|apv zNl>;p6jeH?fWOwlww=RlkgZ;s_N}5_u8fl=EuNRy_mROav0q}k;?KavRTc;9>tRfd zu|zAfLt%sMKaU(-^Ws6?ljZnc+K$Uu{!~yAUcLj_6T)Vz>(m_&y#uCYzVRnrDKY8z z{*>IJq1c!q#P&Y01hh*-I(u{75YDY z@)W|~*pg~aX11~uvn(*Q0iKTic8{&C4f@8ST)QHO-jI_DqbM71B?RGNB9vxcOu;OV zNrd~2Cf)@yNPhR2v?h@2Y95x>)I9WD!*pcCs|y^(T&WJfPB%2tw9PAS8%K!aryj{> zE^MaZslE!%n1^FsXLAL}Mduoxz(fW%jQw$Q`KG$&>jYW^UN<)9(qV||{6KVyI#2(; z&AwhV*PeH8@8%eqy?3tP38B&3e+w{_Te*OVfE`b}g!P9PHqlrI8EKiy3yZMge*rBS BwuJxy literal 0 HcmV?d00001 diff --git a/gfx/75/emblem-remove.png b/gfx/75/emblem-remove.png new file mode 100644 index 0000000000000000000000000000000000000000..14b8a1fd738301ca9d06696ae22755b133f17b8e GIT binary patch literal 588 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjEa{HEjtmSN`)Ym%P6qN7l0AZa z85pWm85kOx85n;42huMX7)lKo7+xhXFj!4zU=YurzH;Uj1_s9Ko-U3d6?2mQ{Qqyy ztjp-YV0iILi2?(M!mMZp0SA-q3+VW*j@mmtq|J?9u;v$&mkl z6K8Old^Vq8Ev?XSKx~77k;vvELxURb^p&7d_AbyruRHMV5IT+gQ3BTl@W$3yeka;uv#_BaL004R=004l4008;_004mK004C`008P>0026d000+nm#LZ5000GV zNklQbv0yb7!xmN z%)-Q?&d1He@cq|s+wVVqZ({iWw;X8na|Q;+Z9tXZ(6s^t5K$H|F|#uKXJWAb_xG>5 zw46MHu%;cukC%5C?p{90`RfX0u16A82_tF$SE)g$m=kCd~}_GkqM~o#|L20 z|7Kw3;AUX>_m_czjh%som5t%w*YC273`}Q$QMLu>{xqQe=Kui&w}78Vkl_#WABLYl zegj?i2WE*Z(60;vqEZaNfM?+Q`GtY;*Cz&sUmt-M`~bR#iGlh1Tc9Q18CW^F7^M05 z827Va`mi_{#4q&7M9nT09{Rg(_A5iQc&^Ih!olkiU*4Lo* zo1!(7g#pWwiU=hzI4^+!!o{s^PN7+(eFl#JLgWLc|KUIvM{@}YFmMQoG5q}SitXD6 zU~&XSBrvu72L=TrFfRW8|IP60+aIvuAm9A@1{7xkdK6p^0pp614IG4^%mxAg0fY!5 zrvL72z_iROqr$)_qRGG}@`8co(M5*OZ-B`V7*dQZ{0!_O+CVlt)J4#|0t+%=fynR; zn9}}y0tXw+2LJ&Cw}6?60NCY5&n6UVB1uzvP z{r~mr*Uz`_fSDBN1(0h%zF>qVSte#EWV&KFD!e=mXz0|+2o^}$j`7GS~j z>*t)`@7{5;3J3sG9~;yX90fZlHG%TOmoE(ee|%?P5mQ+R5(Wq$oD~kxm}S6}1+?VX zoIh{ga4~UkKzxD=04?|r${XLmF|hpoF`q@*4Qv5G0O76CfR-$0W?;Dq)SCbQ#}6Bz zkO&ZS;ZXjC>HpvJ3}Whwnf@^?WBBp$4+A?713&;V(z@9K5MTh{s@)X=e)SOm0000< KMNUMnLSTX_G@>#9 literal 0 HcmV?d00001 diff --git a/gfx/75/emblem-www.png b/gfx/75/emblem-www.png new file mode 100644 index 0000000000000000000000000000000000000000..1bf61e93bb7ddd521dea41088f8606166edffd11 GIT binary patch literal 1537 zcmW-hdr%X15XXOcT|(}FpcpPtN))Xqf|tY&QWY+M3LTAssg?S`14OVx3%0eO0=Xni zKxLE~l|)fer?%;oN_^GoP!gJ`2uRRsMXO*mK1N3Yqmr1%HTuWyXZDZX`F>|-cZXcI zG?W|71ptKRWM}0CiM|UC6wLRk7P*69mP(gP0XVU{#+$1R*23cKyyXCFn*ji+2EaoF z`2>J17ywTR06u8}AgZF}SN(MWSWP)u($A_}i+mK7&Pbx+-~`E8(tQI#6jHvwm>^WW zm?*=BO1Y%%W(9(n6%w3zk7PGaM$tgM81tPaz_X2=HjAYb%C`Hd^w(2@BY2O)42#>_ zahL-79=>n1nAq^?Lv3Vf^FHSWx4%W{xY0MdWPL#`R^)cw(-*U}N0AwFNfO1%#-dET~u!{8=E zB?M1Y8T~6}yxl76MPFhsq4+Cy_vvZ|NZ*#Lhq{U8;1}ex=78HMk`S z&$I~wqKxYpHBmx%sU41VZKND26Usy5tqV*Qbph4<@ib5X4^?o&D(@4!s$IkS@MN3$3Js5-qN<0n9nz0O->vz9Glx)`RrPv zrejY*h={Y9@vSPBp^hAU(5Cb_eesZ{B~E$3^a2uu@^CqtnVCP&v07J|1<~Zek-K$Qh_a*$@(&XSg6#ZB% zv}ub}Q`KRXaCVu*YioUQ*}v)XJm00UXVeT0yuz&%CByyx3PHZ^tQeDQ0ovDJHD3iZ z=Bazh3EFfo`0hp`G5;HeHFs~DBQ8;5y}L?5KElK%7wtk83k_fr(b~E<4Gvd|p--R%7ZXkm~biLa@`;}jlOczgZf zU3zIoCh17QwhnKdXmdOsRT!LaW6;hCGK_i5s~F0A=Tq)fI_=>#0We8uNsS&re_1F8an0iDCY zZ1282+4v;FX!OA2(;9u$^OS@HREM97T78;g&#+KJSeM4QFr2wFVo4)35AbjvJcM@9 z{DF}Cg)V<7>-=ukYMpZ4Uv40qN-@uoKYF7!Bp933=*9k5r1G$!@V3Gb-&L!2vJ(JD zSoVRbhVf-JG7mqbJj{B!&P21koPZf>4)(jtB;7k5`&)o_(fibs*m>ijCtDk0ei$c# zkTjgz=ZV1@k6=FfYRg4L#B^?x)2MN_sge;L#xEr!Lq-(pXCE1?FAVuW1RD>84zM`F z{KARYvL_Nv93G|W?7z(2Eb6J0vs|%Hj*cjV`W?Hb++QR=S_u7|*39bBMcl}Ee@gT@ z1-En^k{V|8D+uko)80(bAFVY(L~i%k*rLHAzC0(Ssl{%%!!2rKd-+iiodiYFlclM0 ztij+$`S!K|2s6979)Ocam}=WV%f!o0yB4ssUDvW{mEs{a9fdz@nc literal 0 HcmV?d00001 diff --git a/gfx/75/enqueued-channel-button.png b/gfx/75/enqueued-channel-button.png new file mode 100644 index 0000000000000000000000000000000000000000..b63ead7fae013799fb7801cb388a753a68da9562 GIT binary patch literal 4022 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 Nlke8`cfC1+{{xNQIGO+e literal 0 HcmV?d00001 diff --git a/gfx/75/enqueued-item-button.png b/gfx/75/enqueued-item-button.png new file mode 100644 index 0000000000000000000000000000000000000000..fe287b3c84ba147fbeb49fca148518d8aa43a954 GIT binary patch literal 3691 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 R^=h>U?B220tJZ^&{{M86m3#mI literal 0 HcmV?d00001 diff --git a/gfx/75/enqueued-item-file.png b/gfx/75/enqueued-item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..40643b241a540606d4f6eda40bf930814a0f40df GIT binary patch literal 3255 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 HW@i5%-N@F_ literal 0 HcmV?d00001 diff --git a/gfx/75/error-channel-button.png b/gfx/75/error-channel-button.png new file mode 100644 index 0000000000000000000000000000000000000000..8efd3a1aab12ea0438846ef776c1cecf146df2d2 GIT binary patch literal 3483 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 rxm=(q49q%m5CzZ&ZDB%-1z?iR{R!d literal 0 HcmV?d00001 diff --git a/gfx/75/error-channel-file.png b/gfx/75/error-channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..f5c1d6b1cd784c5d2a40de9f545d124f468ca1d8 GIT binary patch literal 3115 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 A!2kdN literal 0 HcmV?d00001 diff --git a/gfx/75/error-item-button.png b/gfx/75/error-item-button.png new file mode 100644 index 0000000000000000000000000000000000000000..3873ad1b8b367e81f251a4fe23f9477f26ec0b08 GIT binary patch literal 3159 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 Y=^a2ccX4m1eg?qJ#nbtYlOW~)06;y7Y5)KL literal 0 HcmV?d00001 diff --git a/gfx/75/error-item-file.png b/gfx/75/error-item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..4e809f5cfbdd6f31b79b508d85970b32ead3d4a7 GIT binary patch literal 2793 zcmXX|dpy(YAAfeSji!x?N!W6a!)zzf!M+o@6i0qtrkk1E$}yEn@@t#B$VB}R+US(a zaSl;&blDhE5~n&kI`xyNbTu&y+xPeFyncT?&*$~Lp4W4GUp~(#Hze3kUvIS@06;&$ z-zOA_^ly!TL;784bv6>PG3+2V0M`mq7q=B7V``*-Xb=D?)&L080Z_w8oB-e$vhV{J zfQ=;p81qZ&%ANwCmlWW`-kw~+TY_PhA_NCeU1?i*ABTP=3Sey%m&fBtuiBO+CsXd4 zxpykB{uV4cC#o`xZ8j!PqpoOa_K_Ke1ES@7A9TqFCCC=L;@_gMt5#x1lpyT*KZg4A9TMTm>IjZ%3=csW4i3PLI(3*!3*hCYM6zKrnVZCp9H9kCz$;F z{AlRlluQ6WtsPDLzQv@J0yA^AFz6FeHjKnyVnrTV4MLFtWtzYIGq3G-JV}u~K>VZ4 z1CSv%Pq5Xi-_g;r8fvN#iziL#Mx}M5$wppx!}$`Aoym);>~g7%14eeu9dlVoRKP4* z$WxcYiA;jvWQV-vBuQ~^fLPu35JRA*2J~JmE}l-Su3lR%l}h#LHd;mq&E#5hvo^Bi zKjU|?2be9|n0d`>BL#fInWBX?>D2}2DvL)avu%kFKS2ZZQCAXGsI;aTadFW&bOLt* z^AeuiaHRl`;u4lH7w1Y$K8OU9UzkggxM*zRJau@Wvq!E}xrgYVCIKwjizE!BZZ3?1 zl=uk|tL7iLcA<@i8Y(DZLezO3F9C>7Z+(@*!#hm_G$G~#`VER>$OE?f zKD-jhPHV>s&n?ovd{Ln|e=t)Q!4zObk0G;_&U~Ty*s2Kb==gv0`YI8DIO}#WTk6v>lSrc3|X7eab~VMv=V;4NR;cV3H}D?Z z5Q{&WyYjCz?!5lNfF{w!KR+dVezU9tqZBW+CR;YS;MWD#oq@ILetBf{-0X;;2j&aw z#%-JKD;I6C>1PI7pNR^{1~J_2e@1eb(r?j-WN5xHiYEIwVu#@ACuZP{ouXr87#|YqtYTFLwNBlR8azcWLXK2r@E(-)ECc|#< zGOK4V#*PzHRFi+(?o2LT&6&TZx8?LgkMpBB_4^gNHXdeZAz1sgB0BAY&vhVg2b?|4 zOEFJe;oh8a|HKuqU>Pf)zh75WUYA^fyexy^VrhQ~+POKYN(Eb3D#VRjDfR4GCS-`Z zO96-|exlWmg|T05seXYz_WgBd)GXP~;oOtu88@-YnQkhe3UlHD>6Yt%Ib5&fu6^5I zzNRr;7X9YkJGk%Oy*WP!dgYwck9HhnrysCN0Y*aNydh$KgRj6&uPoOj6jf(zXvmva zeKc0gO^$>K%_H!cx36EH;YUTik$8A`!2VNMCX?Cb=iiG#)IEp^S?^;_3kw?-gocK) zL_*yOgC1k&{Y@`q0*OYEO=_sGuV-0XSwTC#vvg5o>a)rU@rceOc zqQ|U+goF@7jo87RW*vUp9AOX1dXFf;WMOK|&&Ji&HSq|@a_s9XaV{Gk9)>Z@X$u{l zOqnzU|5kVC)``g@IeB?7Ncq5OO5&k&Q7Vm2_ey%5M&XJ_>85t7zVQ~nj2#IQ$k!Vm zDnAV~ukLA0xR&NUdrxd3EsVl#TrO%w$u;>ruG4~ipZE%J4GBYd~D z|18bSe#XjaTy9}p-zK@EuZ(feE3;3yY_QF>?9i`CbJ$vRihOHKCwgM%EtHD`aR;-q zl6Ewh{TC*yZAn}S@0%oHO2FEi=G?SgPl2{Vmovt|9C{9?q@+kkjY4u2gspS=^3^3K zr6kDG#y6a}qPc%f@!OEqx+oS~Z z5sX9E!ud1f+nu0@EA!;f*xaH+hnqe&c|s2+H?_2SUTN@oEAuTA7koN$I3e$u%BzcW zs>cxO8p0^uuvhosxEo{IQq_#n4EHQX) zt~lh1)B}B8e9;Z7+Vg5G(IpPoMKD_vN|6W+;n1ym# z$8OAAC6zDe&Ga6mzC`oJLJ4HZ=a>_YiMXZRdf9Ho@~gih)}e!m`(pU$p><10tqKBs LgMEJU=BE7*eG1+( literal 0 HcmV?d00001 diff --git a/gfx/75/index.html b/gfx/75/index.html new file mode 100644 index 0000000..8dee7b2 --- /dev/null +++ b/gfx/75/index.html @@ -0,0 +1,89 @@ + + +Index of /mushaspot/50/ + + +


+
+

Index of /mushaspot/50/

+
+
+

Thumbnails

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+
+ + diff --git a/gfx/75/item-button.png b/gfx/75/item-button.png new file mode 100644 index 0000000000000000000000000000000000000000..278eaf20b2e50c4ec4f662b7d3ec173598471cbd GIT binary patch literal 2146 zcmXX|dpK0<8voYZn`X?E<1#a1Ns5{nJV>Lg8Kbg`W}|(S&SOw?9J#c+P%&%pFcneR zOpaJx$nAvMrM+usxl49D5|vIO+G>+>%WY=P>YVe(_r1^i&-?z~+wXnP$bGl7nS3Sy zfbG3Q=10gK#1k=S#DBZM{ZB$rA|yT%0BX*kUi|(Np~GQ2{Cog7X$=6H0>HeUkfQ(` z69Mp10l?-w08C=?$}aZ+Kp*#(Ndn>vLYMSVW?RzTGhZr8=RAC96q@{RRZoOHB?uEebJ3 zFu97#eJZ4Jk$8Wuq0Nt^2dl9$XVx84tF{=}V`!&@0ON|HzzpdU&Sufhn~A`Tq56y~ z5s$jmkrCL;X?0YqG>!}y{hTYw?xFWCan7b2DpHNDGUnQ06s%rLRY?~H^nJ8X(tllB7`jiqs`Z4K-Od2q2-AEHS{bkNLW4f21yOp*W`B*Q$a7%*X2r6ivG z`sr`8Cnnz1On&*Ig@)>umX?%mZf^AsRNhA3e!!oPClmM?M%|c#mggx8r1?4&c__nm zb6>2cCI;&2Ul|!0Dc9TBEDgVXJ4cW5tE<74Z2<gulZg*jFrW;~%Hq z`xwaQDZ)G*Ck;u?^~jjxp9PSt+M4}cGQxQmZG%9i7&*LVprN5buX=gz!-r=#qi*_M z8S3lp)fuc$KYH|NQla?7`NcQCoqCPbSYY>Bk-k{ORd3aEk;Z_f?<6ozY6>JXepqO9 zZzqh{SX<9zWoC|7RaTDGZTRc0Sa8S0l`A6Mc|B1ZGoXV?M0N=Y39)SYZCb!Xb^u~I zzv3pDXf6danZ`}qtYFS@gfaM@HEk(b=37Fk#e8^9LZvcKChYRkykf;t;c&HUN- zQsrzIzkj4Yg&u{I<~pl_>ollsx?uE!1ztHL&>Yc0{oAAPsISX47fsRUTdb;c!?e>M z4Bw4B$#Yv{ZLK8Vd2b)+wrw}?af^Qc29hf*D^L|$>a`KfejTR13LFTdMKW5H|X03y?SGzWn3FbnIU zHWeTnB+oZG{hIi5OX|LEqFAxJ`0BkOwu}SZYBQ*qdmL7DJ$tse?1r8k)XBovYdu5{ zMB1hKOT1V2z}>>VsBMPC%WK45Br;XmW_fvgfAA2!MN}=Uj$|bQ8SF|dK-|Ky*D)u< zT?2RWgL%Y&rj{g{UigQD+y&%1jp4UbcsYLPK_fx&`ZKT69;&5AyQn$L zO_+I__{67b=z+Bm7cS5P`c=0#K9XL_2m5w74Lu3{mY^Z78;Y2djhirZfhG-PICv@WV?ME}S(Pl^Dxa?2lop&DTU=gJ*0r%Vq}kv#kC#;(LGp z#pS~5x<(Q`ILc3eXj|1)_5{JEmL~*?8O_h(ED+SeYH4YC>njw+$~!D`NC?CzZ$|IF z@lY63%ObXQrcDE65&6_Aup*)pWjZ~g`>bRkskF_d9R(C~|kY301ng|3;P{sNQGHO<&K z7Q#cY98a5b-#F|GOgm&OxCc=VPYec-3Alb-^3TSN{jbcfp(|cpX%Ha9DyYg%;*2?| z_@|4|@!XJKSf-=35s1emq+NjWzI8tj!6V}xs(0^MT$-O!;s&;cxALP(Npb<>Ma}#9 zg_#N3-07F$oNBhcA0)3m)zQt}BL&8OTr6=zFfU=s0^TOdFHyCTYS iIkCg9Lo(t_Fa`fqhRUA4WmynM0`T_omEDpmlK%ti(u~#s literal 0 HcmV?d00001 diff --git a/gfx/75/item-file.png b/gfx/75/item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..9e5cc4cc9440d65fdfdf0fb2ea700935c0ded8f4 GIT binary patch literal 1964 zcmX9+_2fyq|!pZ{o48Cea~~A=bY#FJLf&W_o!tF z(Jpg5<^TX(Vx*Btm<{-H$VBW;!Oc`)hL9B=9}d9vszaaGAIE$+Q<@YHK;a?)kWv6< zP|Ust-~g65CI=w27J&JCYMbhY03Zd&M22t7Kc%pvsJK%`1W=c7V6L742m{)WKmx8m zuQs*pTJW!NOZz&VPM3tveqQXtIHyd@B$PDt_4VyT_J3Df`y?^v2*8mWNJs&GWI8!0 zsO5pDr)M-0VXL}QEH1LsXWqX_aUS>zE?OEC1)#D)yiw*)Sow8&`fQoOVBim|Dc^Ty&09M`?*;+;YwK0Su%W%y6*eI6WEACDRJPI2H%5L8?&a zdmELDij3su1tY{mf3TPA&_dO@;iLAmN)D22fJ-Q2%*y~qCJF)TK-_?jO$m#@|KmA; z4BzD-QQY2145B&=i+~YwA@Fd6Y4-DK=SiS7mx(aIu6%GxZT&B#H=`MKtTQBltCVxV z_3$cgB?~|i1z*y-fpoEt?`z9j2Q8QA?Y)`?2=tCZaNqtwg7!Qs76!|mu%6xIt&NSq zyW#_s0WU78AzY=7B`0iGXosz1Pf-urCmCz%mqAY6hJo8!x((1X#4M&DcV#ppie6^~BjYz)u5p^t2oPJy6u7A2x zbQ2f3FjlU@W1m4Iq9bbA1{_9uyF&J4?ogmtPf+$0{*kt#$K&sT(sOqff^ETPC*$aYTK~=5RfSy-J3FUpYimFHi^b^HgoKBvv1nOiVt6wN`QY##`BH$c z3}G?ml*KMhrB$&_P!?1$VjXPIz|lw5>e=M=>t`r7s$sRA^b;dy5_J6PD*-R|nTnGX zU?hM-QKJ(3EQZy$wY}(@Pt%j$0^hX>XIA$UZC(CscAZ7L5{JW+m>otspV0DpQw#jz*{Z zJ=H!#Hn>QD>tzzsmc_fsz#U!^(8a!W`!;&$^M_-uI$G-T^wzHTZ_RfsX=!Qgs)gwI zU_+wj<{r!F%i-bAb2olGBa1^~g%R&DWxmiX$d0EbMwkMqh=_uN16^HRiSj~pk3#V- z8WWb~_~JwpCfi>izhf*FXU4gY>*xRVU3rC7W$jdjm!{<(|I&p1E~@qjVJDCHn{&dH zUbZbW^E3MUQvp-%mO)(PvSWu;oR^nZ{CH@{fqNVv&YwWiw`{SuH#WW&Ll9K{%Ng+v z@OT!_TVWUu2?;SUZ)l{M8*X`0=!lko8v+ECTqOIXM{Ba9vi|Df&J}Hzv!{1U63iLf zKknl#F zGg!i8%6{sb!_MsIudO4T7QD40Qw7dnZ42U1mabrjZ^MiSku zvf-b`8AbQz*ci?M7g^u;=ANC4y+r5(UlJgfpUrejc{=MaJ)@bH@VU}uyZYOH z_!Dqf76am?mJ-iy45nw?h=h^dn|q$`DC zt6m+9gUJ3$Pb8dG9&{m{-z*q$q}+eVW_f&jo-a5roiQbjG8&Z3v{KxO`6Ee&_`~ae zE?{T+no!9b4b|UraJ<_**jJ-W+c|}@%o?U}rB7sQe6@2=O{Huo_R5Of)8;il`q(Iv zeD*K^B@(|0H2Bi8jFm-#*!;5j>;yyT9~C$Sye@3c#s=kJ@ZD2mbu2SNBgW?F$VJ)$gY* zi86lEQeExl%QME)wVk<9VyXS{r4$V;KYw@+>QA%p#*ks8vZ*(9AWUe~ zOj~+;D*H}e9cSA~I{4N7`5`C2CPNRidcoe45cZApCwI!5!Oz7|`Bh=i z3VmY(0l`5;NnoXu$f;FDdd)mF_~$?NjJA&I_f?vTP2D(nPr(1GLoBzHkWyc&!75ql zI#)~pHV_b5D6x)rR?yUvhQGH^DW literal 0 HcmV?d00001 diff --git a/gfx/75/kill-channel-button.png b/gfx/75/kill-channel-button.png new file mode 100644 index 0000000000000000000000000000000000000000..878683e30faad54d4985f3f3da6d24a116ea1563 GIT binary patch literal 3721 zcmWlcc{r5a8^@n#7RJ~f!VF@bvSgVUgit&q%gE9g5~>#?OOhz0l9{oE?2+XavP4Bu zDN8ZQ5=oIliCz>%*(!xGzxkc(y6^9GpFh6$x&Jxme3I!-w&HjNJOBXVb~G!7Kxu-Y z;DiMEUeTU8fnWltj#L1sPmf-Az9Oh$UmC*^0M4rc06Pu<{_+Jn3jh%m0Qlw&0H%2W zKsc3mvtS4SBxLNYsIE~(%nd%@;+Y0l96%)3Eg+6nc2D@+$uaR`Dp0( z!py6Z?a0{kj*bre^f1!}10lQ7vlDGBJ1)Da?8c2qPb(`c@HxMmlFEQ6^v$+&D_?%r z9)3h*@z!#=Y!xl9noAHqfq!z$?^58?}fm z^VV0R$z(Fi&(F_`W@q=rAM;n{0L-c29NfK9ZkwT6Y{Ak&OLY z;S>O3AZI_QE`^k-k0TQKtuegbFy2~(HT+Vv=Bj)vi{Br*{`;i0HvsVh;oi0Km%+a)J1o_48}yTesT;5)95%U8)G6K=7E}k>>DZDVpehdwUCXmy!V#cb}wDhZGC>(D$SL zwcicj^%9Lk*?M`Efcb{%Td+#++>!8ai(0b8Y3K@x!$lz=4lV*Qcu99fPytb`f-5{PxdJ*l z7Oc&_?q|=Q0pv48wsHXQFpBCYjn=r$VGt;4Us32xMOEQ;xPgl>g?pFKF6kHw&$UU3+x-q= z4wWW_zfV_E)NuX-C!%a7f2B=s32{LAu#Bv=MxPg(N9>8W?#}16GI@P4E-xpvI;mkb z1Ov6@NT2SfVpMsuF12r?+dW08v7XWi%QSRB% zIRuBIx|1DJ?;;E9ZIU9x1@xlo8urF~& z=}cLdY$)2_bg(b6X86i5jHEpZdu365?@?P;@%rUr5hE-#0 zn;BXADl#(vjhd}=V?3C!!b<7oZE$r)3wl)lt`aV^NfqWLzg49yLl>S=f+?+bE5xZg z3+vj7Ehn~G<~O;SRgB{)M4h_f0p0QS!~2iV6&= zD}%whU4HNXI2>$tUHOPnIKVkS_qj-0BmdVZ(Lmazrh&jE*F1U^x7<>TT0Cf@3B)3h z^~@+%D9*h;oB&;ByDu%6fdlO_5<6bWpa25@n7is5h6d?Q~ot+aJpqy7z1ImfS( zUu0tf6jlbzrwq*x9Q`Rbskw83W>er)ZMm?vMdD!IGBwiDME+lo#&yk#02O6CJ=se# z{fC!%*EuP@ZApVKJ)P;fNpOvWzD`e;J9fTou>R25&mV4$Mq}WPF*g9ifjzBgoBWc$ zlO^F``5DWLIIRiHz_qZ*fYG+FOUsILbv3$NLds;av}z#mCyS9Xa+;fNJlLHx7%T4I zapMrqv({Jx2I}&eCNtI$6mCCrn^dnGTa9SkkJNR}sC!@a`^j1RiWz6;=?$yL7YwB8 z52oH-_y+|su_izqEH9Xuj$W1P?YS-@ zTYlldHN9j#V#GdI;gK@~I1SSmakf{J0)J8!wdA|Za+lxvkB{A(gEEh$G*6zrae!Os zuf$JoIvVW-;`H)l03TwKLg;m6_0=}(bYE*izo_QyjiUt19WSE?NACsYCd63hlxJG+x!OyYG6 z#HM~!#WJ&%rK98fGhENqHe_w-H36={-#aozJ7m8_VqX-FRXD#$*J~mFGmZ|4D>CXc zdbRd=`});sV$7deg4bWz7Xazs$FCLrH$%R=^ld5OOB$9aVPyZC)Du#Eed@s2 zlN3kFJRXUZTDj>BnG5T7@MxwCU6A(eq+J64os5v1T^NgNYksabY&5PJh##)U1A-~( zYkX2jN_5$4`mS9v+2@ZI#{|?jF9ubqsFxojAr;EVK^2?fgpmxK^yQysTk5jBod$yj zh4T-hHOw6B-vuhDO>k}Y_H|aBnIK-EIBL`NoZm;&*IH#|$HljYJ{%UdD+h{fU>Pd83tQ*?eJxf43| z4?O+L!NJ=H@IPc$(tXhZEej9cxmELp*m{z+R@{UmShbm**9`qqp$m0e=_>oLKKOo7 z?o@=s365(b4Kw#?Ph6+@iPtKCkAF6rf_sKU@J0D7aob|&2p@IE`Pu8AC8VyNELvRs zzJ;olHq>6*(Dbf(aQ0ed4!V4+cc)F@5sJ^}mB7zRW5J3$bIXFM&iSV0JsfWqD%`~wuNs$qJl!T*_4z+pIk{!h;a|P(y;$)mk)9J=9YQ98 z#}>Feir(NGKly}ZniV7`C${)-AL_TP5iaOGf7T9FO?_&ZJ>nFm9&af8<1YE_3sS6xol?wpSw#euA8uI=raobO%LY>SzM(6sVFB{QyRf$j=p;((>2tfLUeUL< zSL_r-VZPw>&F&hnRK5v>%8l~1Dh}}D8vvg!r@inc)Y}JOMEhyevsPPTK6E;PR@H^J z$K5%A28<+JYi-?Rc^k(` z@Uh~18di3B0x1`voi8YDnj}3a>O3xl08+h7hglD?(HM8LOPti3-gWAMSJ;^<@}+P3 z1Ha2!o~QqeyJy(^PoSvMDLFI_j@@~@TA@bgdboO0x`ACI&_%ErsB`g%UQ%Je2B0)tMqFA=LL<#)Zi?V|YobTfF zZEGU#M9CL^T%>I;dM!(G_E1flBP6gEd{D{12x!Hy2CmzT1$`B;bu>B#20j2ryrw`S zcPty+C7Wj|APM7NVie>K$Aou^yct!kyO7X0ZRgQ)=pM;EWKm@2b`LChyVZp literal 0 HcmV?d00001 diff --git a/gfx/75/kill-channel-file.png b/gfx/75/kill-channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..8c971cbba2f5a6cc4c8b83fd00baadd3b2baf41c GIT binary patch literal 3387 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 RQVvwWZPRv_yUzT?{{vjJ*RlWr literal 0 HcmV?d00001 diff --git a/gfx/75/kill-item-file.png b/gfx/75/kill-item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..c8c49800f333f653ee5d8b2b0c58ea17e101ac94 GIT binary patch literal 3177 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 KuKFPell>2&Xe=RD8rIp_U+o(%3!TeZl>WB>rP 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 a0l0g{)_RpRO`>kQfo)rUa=*KYm-IhVOak5j literal 0 HcmV?d00001 diff --git a/gfx/75/play-channel-file.png b/gfx/75/play-channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..b3108175a9352cc7ef849897d74371b8239491f0 GIT binary patch literal 3614 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 literal 0 HcmV?d00001 diff --git a/gfx/75/refresh-channel-file.png b/gfx/75/refresh-channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..7fa4313c1a5752b16dc447143f5d81776fc6980b GIT binary patch literal 3689 zcmW+(dpy(o8~^TN7kwEKTZ$>6a@k0?gH3dmEQ(cPhIRT?he}e(Hp{K#evhm=rPEPH zH#yjtdyAbS4rSqpba7{6+xNH5AD_?j`uy>E-p}Xtyr1{;e3EGgcI#-b)CK@RXYU>l zAB`pbTo{yQ_lGMIH3oUY&C3k{DpF&X4rXc2#E?BcUI1`;9RP560HA<0b_@V6XfBR3 z0APC_02qho{ZY`R@j1KK!|hOX5mO046fq42z#2D6b@_$>QkuR1P=Sh1nY}O0n6ymD zgs=1S^D`mUk`>nQ?vA5NouZC*)k4GYN8yWr+fzZiXvOA@g6x8ovRrvRWhkbS9fs_F^0jU2^P)>tr&^j{zr)L;@p!d)K~&iU1wjP{X8}@pHe$6* z)Z84E%;OE4(vmWKMxQ!7g|5!4pGbe0oWB4$#Iow9#zArN?yrG~1v$mlY^bbDVb$Uk zW`W1MDy!Qkhei%3_~I_ogV<-8wzQx%8y&?PPP5=hy#qMFy*9nLSQS@Yy+|-OH(%H8 z_{&dqPI6ofZ3H|i%4G>98-$sa7yCiM`}474rpwghmyLp*PnIWxa=!b z8vdiww64-EU{4bFZ<;u1@b8&Xu++|ZR2F%;x}fs+0h}cxH8hwNMmneyEcKlYjb2nQ z7iXM$O|X;IbWTqp-0ewPu3@3U^w*LOz*`Eyt~nYYvT&HEaCbFSLSfgbRZDqmluMnm z@csj~j7#!Ga@M2e_Pkf;;Jms=S_r8lc+9(FxJotajIcsC4y4IS9Agwyxo#ZK-1?pN zIrV*eO1O!}V_SA5e4z}GejONS7e$2Q8jCeZ_9$us8TJvv87@)_zu_67p`p=J^R8d} z#0K%9oF?vr8iH5`vGE>?Y!w^%t2W_XEnGk#cBxVDxlgJM{I zdB#k=!K~ou8HEwT(b0r=H`_s+H9CP8#;PSYqSuOvzBlFj?SsO@X#SZeXgQlg7^ur} z1<5&XZaxKriq|-hofB))zrrB`_OxqD`cJ4H1RoDLxE-8C8yft(^>%Vb!Jv3FZ+~L> z6TRgI!OZlm%oFnYud5%X1O4@F9i4n@`__p0ArnhSr*a&;#z#0G6kr)MH}B3m5EX?o zcioo09!%LU0pai>&};yDAN)B?pnB6NFbH+kuzL>BTiXI0F$EI3pmK`qQ#C9Xc3QF@ zEMeE6tjyApt*J7hkgQZJ85dbOh1%B13q~ozNH!XJohHkt#9nzVYVK$U)&r2^_2An)#`9cj8Z(QY(giPu?I*o zORB=bujT%rkl^a*e0847Mdx!zJe-6z3VDj6yVUC2Tb}^%gY#)n2GxYfr;M*rNR!j> ztfDm(k}E#)h?-32eZcBbJ(_?`23f`kzF=t~%e?u?aQ$4%?&!L!?1rXRYe2$JiMV26 zA;+7#%3B4h4~E!n`X9?}sQwidFkazJo%}!a-^X>Gix4=F;33xz!!ywU91{+TrU4sl z#tjIjFThT{4saQpYq4i@SdL_YfP`=)J682(=PqZ`4jP44DaO-9Pdt6^M{kW**Tl}m z5B5y3sTXV*7l`27h3SzKj7#ki+`Z|8V5^3`9@bcHT=EoU1>k7VPdRg>KaF4c?cK#(1bX3=+j zrhwg?6JYQ>QxBt5s#f$K@`H@dxO}PBEB&^xvB%88 z`RXD#CXk7!i?{=RqRiaE(Gq(}Uu9Hy_k9~#jC?X={`~nkL#j-{|mHg5tg@(a((NmMR8Ke|m8)Z4f8EQNBg=*f$i=L=*xX#W8Ne zXr3nY?c|1D$lObJtBHmBYmfad8Wp(F2JxvJ%iZbt-rYpiCs8mmCz74vv-v|TD}9UG z8_WuGZ`6fgHfr|CHY%VmL4ejrP%F<-6JsECF_xanI}U{LR$-0MQ9Gg9%X8Pie|~eT z$l2MMeIYWkZpRyVjtbJSqYY&8x?nC?T_S^gUEho7^2rFMr&cVi#-n9qO_6gZ9sFSU zYg}u(=ezeq5IZv|i>GU6S3UN7Tu9a(>HXPH8RqVp$5NG+kZfE=I7=P3D^ zvyY#bJ%`WTBv)ovmS)cnEES$lAUCrf*D_PkcC}kaJurhvAmMQIgqEpj;CzzR9wG4~ zJc*CyCy2-rM!MC2kll%5BHRrnsQ-naq9_Gs&e5WEwzjIYyu3WOz(BSA9@DY)QR&OL zi*(l*IWXQ`$!V0;UTM(7+m$fYhu1yh-mVF(kc-Pct+$43*2L)|vIs2oOK84Tuo9ErgfiR zeSHAj-`bO$lup@2^%@P(2{0$ z9&j(zF>F72^r$Q+J3E&1?XN2fcGd*)zCC-CXiNLewEggI2-##RIoR4E8gaz~80rba z2LNm!(P%mC?xE1*O3dBwM<(y>oZe{0T+$O_B@V1>C7H$jq~h4{(460zzuhm=x$h%+Zw;78XLBb=bAm7Ti=uZbn8hkh`@^BWcg= zxGa+U8wUJx90K3BpX%)ZtnNTvw`H7L+GuHsN{u)@&mjf&AYd9oKT0N4jKJ`~h?cv% zm?DbQJpkv^kVYk^sc87e&P80;06JNvR^8GcThC(bZ6aD&%o=B-K@e1PGR+b5&(el; z1Dv*DesbW2p3Sq0y>Zi6sXi#WYp|-1nD$>r7Ktuww|hG2eT09pDE_KnXew_;8M(Es zO@(d(_t>ZY>u#t?MKoa;0OClboGTR>QLpvw;NuzbP6!5II4#;F0n6Nu zSgczI!QRc;GvXVOHh%w5jo|L4ne%iy2o$KqHt-NmwV5?Q=hY9-G|G0VSUA?N3 ziM9_@wvk~P{n+S$+GCPLAn=&Tf0O?7FRz51I%>%nL00B#Wk+(twmS-DgHc8~HX;ke zKA(uicctDo{QQ{3+4UwQOFDO_P1d7F8y;qcyo&s?{FjFwa3^2s_qB&IU`XOK@HYVC zM$G5?BUD>rkCg$V z&37I-ay%BP90ggp408M0Jaoxz2LN)N@MyR75c$R6l09r#anqk+7{WpLYkROIOG6xH|rvW9`f^3 zFH2bwy?^ar2r~dfjB_GaqpM!Maw|xM^*XcQEas#kTzZfnGg$%~KsPKCwPCaGaG#S6 z1QtxGR4T{W_yrFO@IOSF;@5OLlIZBQh<>gSr~RypiwlZz?6yAsvLFy|o_H@`$Mdqt z5@QYExiG-{0VXVkjlBdAIg?>SFGVzX&M6ruo@ZF?+-e}&MJU3przWBKpI=l|knL1N ze+ZQuh~t<_;gzya4rt9dcNxg9vqIdcLNVTb(s@|XM2$b`x4b@_aTe6Bx=5{AmA6Jy zdS76Sq{z6pPJ*sv^f@0R89R5!k!)fX9;^jJW>;=#Q>x literal 0 HcmV?d00001 diff --git a/gfx/75/refresh-item-button.png b/gfx/75/refresh-item-button.png new file mode 100644 index 0000000000000000000000000000000000000000..7c340c90deab0f849409c77c781b86703948ccbb GIT binary patch literal 3760 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 literal 0 HcmV?d00001 diff --git a/gfx/75/refresh-item-file.png b/gfx/75/refresh-item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..6f9fb87adaccf53ea20d76e33329e367718746e3 GIT binary patch literal 3348 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 F{1@AfE*t;= literal 0 HcmV?d00001 diff --git a/gfx/75/remove-channel-button.png b/gfx/75/remove-channel-button.png new file mode 100644 index 0000000000000000000000000000000000000000..49479ec815de839e0eb4579bd1c22286df6cbf11 GIT binary patch literal 2961 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 PJvG?q>F06HU6%NNcE}%C literal 0 HcmV?d00001 diff --git a/gfx/75/remove-channel-file.png b/gfx/75/remove-channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..6cc09106260b17a539775bec9d45bda72545543c GIT binary patch literal 2897 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 C@pCr- literal 0 HcmV?d00001 diff --git a/gfx/75/stop-channel-button.png b/gfx/75/stop-channel-button.png new file mode 100644 index 0000000000000000000000000000000000000000..8befb50ab81dba211b07bb6183f6048cba7100b8 GIT binary patch literal 3767 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 L?@sp|*~$M0u1mwV literal 0 HcmV?d00001 diff --git a/gfx/75/stop-channel-file.png b/gfx/75/stop-channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..288df3a4f4f93b738199683efd27d779658a6361 GIT binary patch literal 3500 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 Y;QqsHB|*dbaSQlv+qLzfH$V0N0oWcw&Hw-a literal 0 HcmV?d00001 diff --git a/gfx/75/stop-item-button.png b/gfx/75/stop-item-button.png new file mode 100644 index 0000000000000000000000000000000000000000..31ddf8bd7d5095d9ec45fb789f04bbe7db2e7934 GIT binary patch literal 3450 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 IH&)7j0iI477ytkO literal 0 HcmV?d00001 diff --git a/gfx/75/stop-item-file.png b/gfx/75/stop-item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..3857741867f6f7dc4682e38a4477f4081d64ccab GIT binary patch literal 3191 zcmW+(dpy(o|9@|v*<7YgZsUYWA(Sy)T(^}jq%4JW;nOgulPKvVN4ta}e$k% zvmab{rr&X4N{*k)3leq3wP3Lv3bXBKj2fUa{)FgR3sfpKH#;Y1{qXRxTF-=a^Z8(D z1fotoBV3reb!#L~PTQqM7VYkuz)`)55^ulW{Zt<^AtqMUr~IxX~9URP<%2d zFQ`9AmK|gGzo#AOYmrJ%GXny0%7sEXwguT4+Dv_@Lez7HUuRA@tkq~Pbhg^b8WeNR zR0yIHxj!{X6wBV}RT*ob!dhRb`)M&=_}MR7IlEYf>zaN@pIqiE^;%Z(K>ZgKY>&S7 zTBh6hQqrR|n3Y8Rkjl#`otAgs?LNmi4cg;X#8WTwuN_?C>hF{tTSxL49nfih#P<8?k46(_+Uo;P5@-5;G&@nQ z!cJcXl~-+70HIcs5@j`S$16NiI%6 zAmRN}Urz>Bk@2H65byQSV-+-VY_hWKdp+{Y^I!<&XkL`&I1BznXu^s!8cy0?)l_%) zsvw`6atnp=ET8%P6ds#a+;aB3&+CMJKpqG*? zA;d8kCECWh5TibOGWQ$uz_qUDS&9WmoGM*dAW(8@l6Y1INlIaqn4|$GHozHFm1eH6 z-==2W%tB{kjb7hNX=}ZtzC}M!pdbNV^42|i2dzaedZ_&a^5X7Bl2|-4P`p37j~E`U zoLTg27`=PWg2P$Fu83vU!g0eaSdIHlq+$G)UWtK!#68L2q%V@28(4tM(>1*%66o7` zU|SO3y18i}Hhq&>*pFB zU*rdyjs2cK#d|Z1YsfbbCmmdryMg<$6Myra{@|w3pZaDx*z&;Yk{o`Ck>!#}3MkQA zjFD3VNIr||rCJ$bWEsEeCXE-6mCny8FXZnG(vMe(g>v3&6%}S<*cG@!K3*n%RT2Gm_c)XTVTd=@U@oJ6UC5ETNoSE4HJVRIwU6A>k5<4^&F0{G zhFC2BN4Z9p&WP=sQ8(iULka8-?jA|x#}frx=)fpm=0*>(nTKy+RLi*dNs0#PxT_g5 zFMfZxiA(F@o31dfWT568YV>A?dUqS6?gV=el~$NRy9dR{v+dUC4>dIStd91cJXGa8 z(GYY!lrWKoddOw}d2xE6)8jhL!WSf5K;WiSK#w{$MhKcoYxVwhYrybj9Ke&E?QDBd zXBm%3cYZ;tgCt9+@BdbdYw1&(=mO}eb41@I6gnF|tUKlywu5P0pbOd+BKIYlhu+0S z$uGLk0*LRPV_9La&b&g1udyDCD~L^loC2h;?X)hOGU+^v482}VlH${gbG_Cyj;y1( zdBHpzQOwLB#zdmBt*Hq+p{H5fY>ZrqzG^yl$stipeaVJnmB>Fj=?`;UAUfzbj9}`c zSc{uhe6bjY;eft)jSFipyqm5-^bHc|y zv{N+pl6q-ol+bHU$7xv{bfRd?N73Ja3xlm;9f6mzxp_A&Hg-7b-Me>OnM}qJdY%z1 zO4D)I=>#|6tITg1^6!GQBJwmZYZ%3%v=mCZ)VQSTd-uM$Mn*<9Ifws#3bjpWP?Yuf z$rA+ZcDQr+X~Jn#G%wSl(YE6V_6P~{Zy_MTuT3G*z{*OKurv;$DZf%)Ue4IHYs`jH zsWn>LRJJ*>7TR_lRiZ(v?%zjz&;7G%d9+iA=o=Uy(Aj5<+s3cF(wTUGAxf{2!q;KO znV=9~C-1DUuRn!oE{vGFM%M6@l9(CulH*9#y?bi)w_yXvfYabL2UxWO*>`z1G)|08 z>Nf(VlY+|qfK*pk$1EH~p^5C_Euev1ed+t9C4+dTud zpoC|~D(N-6UADLG1v3_F(%O)HuAuSynf@@kKj2)UvjanqraZ_x7XH@&{8qjGKX>`D z2LH;&wTy#s1vo}bnHx9#I^0&=%a9UWHd#c9Iqmwg8sy32$C|HWV=7}~<7kkYZ8b(V zOGrrA0SnmZzX{d!U^i$6o84Y7l}a(Qs}8zS9-IQcm`&gHZeZyXcp#(XgCUQiyZ!i= zU>s~XA65CGDkb54qw7)8jZwc{N*V8HtanBJ=g{8nLw=*xvX2&(4<%mPY~qhJ%MGKv z{m-@&&o%^_8l|@Fd-L8Oy=^R3T+f0wT7j~n6l0`KvJTvcjfW_@5QCE2V_buT;NhG# z3ufEByaJb#r$(1by)CMAhJ0stvMnc{Pxp{gvTy2!L=p_+9p8;!KkUCT?}c;q96O?X z-ZRFR(-c9)d=n9?@jl7w?=)T=eI)} z;Cys6A-C)KR|m?;?S^A!1N!bhe_QGydPPl_Y9AMY@X(DflG~&wegUhu)aW$2w1m=X z-owDFpnu?Xu1u09!3XZJx3?EDmkB3-M6y-{3>bPAtg6`yqnk*M5o+k_!I}*&Nwu~` z8Cq(>LeeLQ3y5@)z zm$WpzK~fUdXEKNAZ}EX`0)e1UV38dhBgCzsn_4^C^D|K|yR+EXDvWAd%Mq>e7w1Hw z+mZ{UQM~i}uw|B_;WeI?Rv`Dlkq~lt`k^NaeCsZ3ZB&1V?*H0Mm(O>AvvA~Yu&@?T z?G2#yUh_(+jYwTfUs_LeZMdyV=AB9fq;X$Kr4$o%cN$+1l3kJOMCa=S`i1k8orzKP yw~1t)VpF96t!)r2SCn?)0H&*80nm9U5cz5R%+P@C2JPek0=Dn<|9vZb@&5tEF3%Y2$ucv@mLf~(jf`cY6%it423bnhM6!%tM0t@) zDm619`%)<(*;_>z+c5L{rtiDHKhAm1IoEZr=XuWaoa?^tG}puSk`hW1002ljI@r1i zt%Gn7#1O){p~&Kw(7=MohsXf%FyqSRkzC;(7vSJ_2moTV0Dztd02`pteg}X{1OWI+ z0f7Da0H6?(UwwNJ0HptMv?Y5)7x{02AhAW8EeVLEo@VYKe1edG8weBxK#}lGnvEC6 zy7+4gn~L&eeP&&ZIzfA@^^=!Nc*7Q$5}K-HvQS%%F4)pY;A2J9bh{l-3>)> z6|gQZf93vn;wgs4=jE~K8gxKJ%vVB&8W0eR$Kh~oot@Q^Jr`KPQ-cr@c1;_CJGz^R zWdZKlN(PqzNRly~q=sz8GjA>n{nnArc)?Ni-h9a=<&I1oYsyU&MOt@5RiU7H<{;S* z)=I0M?_$7d^mXE3=00K8lSmxXE)?LW&{;U=OS`0S08ezzGz&|PZ-f601mIXJ1ooBs zVMt6@1{~FgN1#a2?kHL9aFG}4%(=bDM;MKc5FBypAXylUDV+|ekOuIpnTU*X9SW7o z>+kF1W?sE2J{QS6M)&0TR+bV$Lxx0fFi|c9fWS~ksHpmDST`!FV_Ze02Q0PR?26g? zbe3`FsZ}_CU6Ai+o5X+0D4Pg!cb}|NQNgpwWZNpFh#0P!iqc$R>;)62)F5=m@&fnA zQ;S)7g`0gPas8WX{n(wU%eOJn(Zd2;yAIa5s-f7|ZN0E%jXonW96i;M%)}#{GHfd4 zdpVr-sP?{Z*7pv-n)&v@gBluojFKfAM2+6!nzvNSA3KgVXwu8hs@fVMm9AmSsu zVsfhWCL(+24u{FO>!Rx3H2&76uYC$An~7Rjs0*=bIQe2Vne2EdoBW+9TjhERl{>T1 z*~x)*`KQ<0(zgLHR39K>(#FxUfR;Z7Gm8?KdsV6+;*wN!5niHw@Kz{sGSH!)NtJ8};wsk1;)DgSvb` za6CylS?yxKRmb8mzD;2i6WRK_CrIaQf6a8*IHOn^&ccLD4@XNdx z6gQOXmSQ@M#kADG)jtG6_`gRR%W91;?^?Xx<{%56)avtWThA>IGdUY23HB@)J z&imQx>bg2mvXvOSihtVJxEgig!aNPvcyP5j#HvB!KaLaQjS0YuVV0Hm<*rEZM=UPo4uj() zD>s7tWn!7{aPUZUZC&psLtG>j4uz6{SKU5vKa51nt{YQ3st0s`x~ddKEbF&%I0~WM z^F=DK3aJt66J=#(`FmnAQYVjs&mQ+Y^ZCLL?}c zFi=8{v$g`GV`dc@0sO5iq_DdQ@fI9rRj{t zWo2kfZ$1)P8gE3n!soC8_BEZ!0J+P_>9=OF8Qk{brHS#{@*BHd;z51N41$#Sh`A2Q`5|O`!_A32)Pu2&vlJ3{%q@2o`Z` zcgQ|BQW#|CEV6A*?&PmJ5ZQ0F1xYrLO>BZ~O0W1XSS=Sft=i9gZSggEelDcaR*Py)ZBWP?A_!h(YqVQUN5qmzaztncuFUKg-CxF*$#Sh?E`&4t^g8F-3Dp zU-sndeTLpDVW(0lu#cg%=*tBHfq-B7qrVh%#^asqWBwvM4EH$Q6O~-1&70G6Ok={& z=1ZwJ1@?hpO77#c5uv9!cdOUX`*k9^P!1iF&39gmlvm?am)zy{{qtpWyICNm&m?Ie z+`~T|J%L}n{NSAlw+z|1kBx~ou;2d7V?eW@!@C=VYn^rTx$Uu|cQexE9mHYYqpI$erXr*d>rAE4?z|nC71tB6T(48slXWDW~)6?|P6&R^73vmc>CFOd_<^E$of{ z*W{ap>qzY8juXK2^$kfXO*x=QGQwJ?!rJ7+fvu2~J;&Aps!|M_xy`3__l4_5%EtJV zeY{+_GGY2VA!0{>kO%xQsXIL) z9==!y!Ef&p5)#(V*gZISZ$LBu#Z0`S9PskZWa^XHEYUQXd#d!;w_}>9Q{Igf)b&5+ z=4_{1=VRu|PfG5|3*YaTb^PJ|r?>1E{`=P^^}Bb-qocmpLLBtFK7DUAc(0{c9a;M! zDD$Pv9GWhDb{K+6^0RSpopu}qL7NLFNIMYJW=&+bD!;J} z8h~=Xm-#s|9{)hT@As{7d*?Pf_B@r;k3pTM4A9;4-IO{kEo=^#?Z(*!?Yv(jZfSjE zxyZP%qmAqs8!G4h$Y09`lDrN|&~b7%-x;Zo*gcr1VHH&W_4J!PTPdSng-+NOX4tdva=ds?h9mO1 zwoZEZLL7M~bB%C!Z~Bl35Vu+zkaszNQ9f0T*w_+OMWpSRJAFyyo_j@&nPRJX`HtFNz5!7ma-+~MZ+Z#yLLN#tSCl4BHx2$U&hK%f_p8RGcs@sLe_ zkY2qYt(`@$P7}vCu$YV_F&xF+*)d~!_ip8BR%U6uv2o}lYfUSWO;#O?kvyh|ISF}m zI|rp18;3acLYjz~(Yh><5U)2%a6{GaNZm_kj_E{aCrb)>SlKI#lOoJ$n^!XZpY|U1 ztv|k$33iv_DOW#9u5j&{`NRV91OB9Nn4H)O3K(2Q1CF4VY6y%vIUOn%d1Ryw**wZNLABggKw6B`_|wM#6H>^_fDJt{x!kV-l%{nV z@6bD#KLVKLf(Y2bPZOH&b)~9aD{f`jt;2ER~>>o-5{CCNi!0z<=*%~^JyI1Y+opC`1~on zw3v~W&B!eM5pv{yYYIg{u>0y*zwKJ-mDd|56H zW;DA3Aq35pHd0x)$P(bJ;&A|aq8BvqdER=F&%5M`GlZPzr1^R7w-V*3z@5z4w@fq$ zp`YlC)~W{&HkAu3$vVih=Rm~KgN@4Iioa-;38X3J{(P|1SwuKMTed{GbdRHXDEEq$Hm4?t|I3R9jWPC#H1VwAjI zrjQR}KlM^z@;%7Z6%$x`B9OJ;^)d_}Qb7N@1&<`t`L!(kIv0fPbk3}nO38M> zi8rK&H2iqHAP6NNxPhJ4;1)yN$b^K-OLXeqF9xu|9a-5|EC6BJd*wJ|@CX|c12#u7 z0s;is2>O4D_QWsEqJB)o>>l zp9~WuDy0pGA{_0rF_qNOx1&B$g$Vmo5E$NV-W*P>uH2&t0fE`M`T zr6hU+7?OKfHB=0D#l63nz1q1TjkRhuCXHC*2sLgfR5KJYsEHf9eo#&5t5{YEjzj{G jJv9xI`oRC|W(q*90qduwcODlia=`JxVcS}3O2YpDpN&Y6 literal 0 HcmV?d00001 diff --git a/gfx/75/www-channel-file.png b/gfx/75/www-channel-file.png new file mode 100644 index 0000000000000000000000000000000000000000..e81cb7f8368f508db348aeedff21aa358bf26dd6 GIT binary patch literal 3643 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 literal 0 HcmV?d00001 diff --git a/gfx/75/www-item-button.png b/gfx/75/www-item-button.png new file mode 100644 index 0000000000000000000000000000000000000000..681fe0927c0fb669e1f086d42c99e6aa57f13313 GIT binary patch literal 3737 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 literal 0 HcmV?d00001 diff --git a/gfx/75/www-item-file.png b/gfx/75/www-item-file.png new file mode 100644 index 0000000000000000000000000000000000000000..9879d5c35b92c9175931fa1a6d823f0ca796e317 GIT binary patch literal 3362 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 J`^$%3_ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/gfx/Icone_source_misterytrain/bepodder-logo1.svg b/gfx/Icone_source_misterytrain/bepodder-logo1.svg new file mode 100644 index 0000000..0216928 --- /dev/null +++ b/gfx/Icone_source_misterytrain/bepodder-logo1.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/gfx/Icone_source_misterytrain/bepodder-logo2.svg b/gfx/Icone_source_misterytrain/bepodder-logo2.svg new file mode 100644 index 0000000..18e2ece --- /dev/null +++ b/gfx/Icone_source_misterytrain/bepodder-logo2.svg @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/gfx/Icone_source_misterytrain/emblem-add.svg b/gfx/Icone_source_misterytrain/emblem-add.svg new file mode 100644 index 0000000..537737f --- /dev/null +++ b/gfx/Icone_source_misterytrain/emblem-add.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/gfx/Icone_source_misterytrain/emblem-delete.svg b/gfx/Icone_source_misterytrain/emblem-delete.svg new file mode 100644 index 0000000..9b34854 --- /dev/null +++ b/gfx/Icone_source_misterytrain/emblem-delete.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gfx/Icone_source_misterytrain/emblem-done.svg b/gfx/Icone_source_misterytrain/emblem-done.svg new file mode 100644 index 0000000..36139fc --- /dev/null +++ b/gfx/Icone_source_misterytrain/emblem-done.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/gfx/Icone_source_misterytrain/emblem-download.svg b/gfx/Icone_source_misterytrain/emblem-download.svg new file mode 100644 index 0000000..f8dc83f --- /dev/null +++ b/gfx/Icone_source_misterytrain/emblem-download.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gfx/Icone_source_misterytrain/emblem-enqueued.svg b/gfx/Icone_source_misterytrain/emblem-enqueued.svg new file mode 100644 index 0000000..774288f --- /dev/null +++ b/gfx/Icone_source_misterytrain/emblem-enqueued.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gfx/Icone_source_misterytrain/emblem-error.svg b/gfx/Icone_source_misterytrain/emblem-error.svg new file mode 100644 index 0000000..fac690b --- /dev/null +++ b/gfx/Icone_source_misterytrain/emblem-error.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/gfx/Icone_source_misterytrain/emblem-kill.svg b/gfx/Icone_source_misterytrain/emblem-kill.svg new file mode 100644 index 0000000..8ad5d76 --- /dev/null +++ b/gfx/Icone_source_misterytrain/emblem-kill.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gfx/Icone_source_misterytrain/emblem-play.svg b/gfx/Icone_source_misterytrain/emblem-play.svg new file mode 100644 index 0000000..f7c6443 --- /dev/null +++ b/gfx/Icone_source_misterytrain/emblem-play.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gfx/Icone_source_misterytrain/emblem-refresh.svg b/gfx/Icone_source_misterytrain/emblem-refresh.svg new file mode 100644 index 0000000..73ec10c --- /dev/null +++ b/gfx/Icone_source_misterytrain/emblem-refresh.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gfx/Icone_source_misterytrain/emblem-remove.svg b/gfx/Icone_source_misterytrain/emblem-remove.svg new file mode 100644 index 0000000..9ab384b --- /dev/null +++ b/gfx/Icone_source_misterytrain/emblem-remove.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/gfx/Icone_source_misterytrain/emblem-stop.svg b/gfx/Icone_source_misterytrain/emblem-stop.svg new file mode 100644 index 0000000..1404869 --- /dev/null +++ b/gfx/Icone_source_misterytrain/emblem-stop.svg @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gfx/Icone_source_misterytrain/emblem-www.svg b/gfx/Icone_source_misterytrain/emblem-www.svg new file mode 100644 index 0000000..57a2662 --- /dev/null +++ b/gfx/Icone_source_misterytrain/emblem-www.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gfx/Icone_source_misterytrain/kind-button.svg b/gfx/Icone_source_misterytrain/kind-button.svg new file mode 100644 index 0000000..598f548 --- /dev/null +++ b/gfx/Icone_source_misterytrain/kind-button.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/gfx/Icone_source_misterytrain/kind-file.svg b/gfx/Icone_source_misterytrain/kind-file.svg new file mode 100644 index 0000000..558e902 --- /dev/null +++ b/gfx/Icone_source_misterytrain/kind-file.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/gfx/Icone_source_misterytrain/logo-channel.svg b/gfx/Icone_source_misterytrain/logo-channel.svg new file mode 100644 index 0000000..7840c1e --- /dev/null +++ b/gfx/Icone_source_misterytrain/logo-channel.svg @@ -0,0 +1,106 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/gfx/Icone_source_misterytrain/logo-item.svg b/gfx/Icone_source_misterytrain/logo-item.svg new file mode 100644 index 0000000..efd1378 --- /dev/null +++ b/gfx/Icone_source_misterytrain/logo-item.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/gfx/Icone_source_misterytrain/make.sh b/gfx/Icone_source_misterytrain/make.sh new file mode 100644 index 0000000..ce4eafa --- /dev/null +++ b/gfx/Icone_source_misterytrain/make.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +cd $(dirname $0) + +mkdir distro + +for a in kind*; do +widget=$(echo "$a" | sed 's/.svg//g' | sed 's/kind-//g') +for b in logo*; do +type=$(echo "$b" | sed 's/.svg//g' | sed 's/logo-//g') +for c in emblem*; do +name=$(echo "$c" | sed 's/.svg//g' | sed 's/emblem-//g') +file="distro/$name-$type-$widget.svg" + +if [ "$widget" == "button" ] +then +echo "" > "$file" +else +echo "" > "$file" +fi + +cat "$a" | sed '/svg/d' >> "$file" +if [ "$widget" == "button" ] +then +echo "" >> "$file" +else +echo "" >> "$file" +fi +cat "$b" | sed '/svg/d' >> "$file" +echo "" >> "$file" +if [ "$widget" == "button" ] +then +echo "" >> "$file" +else +echo "" >> "$file" +fi +cat "$c" | sed '/svg/d' >> "$file" +echo "" >> "$file" +echo "" >> "$file" +echo "$file - FATTO" +done +done +done \ No newline at end of file diff --git a/gfx/bebits_logo.gif b/gfx/bebits_logo.gif new file mode 100644 index 0000000000000000000000000000000000000000..092b6f4c70072dcee1c9bec114dcf5a0a0f97284 GIT binary patch literal 1473 zcmchW=~L5Z6op^5CZt7!fPx6bh={36qSXOyr$KfX1hg7lXj%b99Smp{9A^wfkQ9&z z3I8$5fh1%lK=@@LZ=rugpE+}8&X;>=j@MoElmT$19)6v>aNQjaugP?jtxTLvB&LLSP)3l$NC3a287FM+hundmZQ zOu6z(g)**c=4Q3ZzYZq7oIP9*Q(w>CZJayN2s4`I9&+a+x$tSHy1ZA-h@bPKfA0?7ZOYnXt2le&*W9ajj4M7m+IZgg5Fl`f3QbbWF-q0mn$_44_} z*#*NKvN($@E@%yEtwF1Yh9w|Gp>pl)3T@Xvv%^=Q+<90}zNHs`tsnpRNe<-{=TP+U z@wm~D>!ZQ+u_N(g==d3If)brDgJmeGx5jL5DQpv!uD9i`$#No7Mr6v}ewVtX$jE6@ z-#Ze&I}&h5b2xn(q-#LB_83bX$eO0yoes?qQ!~XN+dwEY&}&pTYg7q;su;DZ+}8O= z%TizNfU#Y$q+4CwtuE_P-{^tmy$f_6tnEWy_9HC=YVN>7(;(6~h_sF%t)Db)qnh?n zO^-m^KdBp-(h7z1B9VGXtREKZN2c{ciB=@l3Z(imnf{Ah*Dr@sg-)W-O)B(4rG8Ke zhm>%52F|D#Rm&$bs5J(S&VVdQ4;LX^ddB~s^%~RvmTp=07-owi~5Pufy!cb*7yKGU|{W7l~LTmPD;U70SCAJDBGEP6KaOn0vTEZ@;O z4=wuCb@}Y}6+bYhO%w5ECFX0$2g&8uk;&#RrClV_`qsoETxCG#p5`MM8@4lj4Ck>W z#QZhi@A*%>;jQM8SMN_^BcetF2o%b7tTB&)s!3Yp;d$K*YKtR`a`sKe~cYOCxPI&WtR?dnt>&uUVlEJlJ(| zJf9i0HR4KU4%gXu$zMt8 z6`)OU#$!oVxP(D2xJseMJ9Nwi;!Ofx8F?|&ddXZoW}=j{^0cUwZi!z7&+e;2dAS@hdx8&avw4$frH_(x&y-CfvDv4O?b_JM)%wwrQsK4#Vzao%jl8`R>0 zFh`b$*|jKo+iGW4khe`3>$%zLw2TmsuTb|M`){%Y>*yX8VdXJAhZ~jk#d)#0%KhxR z@jVx+!-H7|?VEN>F4({QW?1~kaF;V0C}o_km<0DJ!hSd-;F literal 0 HcmV?d00001 diff --git a/gfx/bepodder_ban1.png b/gfx/bepodder_ban1.png new file mode 100644 index 0000000000000000000000000000000000000000..b7a2ed9e62a0cebdeff9d3bd04db263b73e1ff4c GIT binary patch literal 26035 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 literal 0 HcmV?d00001 diff --git a/gfx/bepodder_splashscreen_prova2.jpg b/gfx/bepodder_splashscreen_prova2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7bd3f2a6ade2cef82baa7976f2e10a1507bf1243 GIT binary patch literal 42365 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 C|Ciwa literal 0 HcmV?d00001 diff --git a/gfx/bepodder_splashscreen_prova3.jpg b/gfx/bepodder_splashscreen_prova3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ec9843cd4e7fd97ee16509414fb87c5b93804e67 GIT binary patch literal 45923 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 literal 0 HcmV?d00001 diff --git a/gfx/bp_icon.bmp b/gfx/bp_icon.bmp new file mode 100644 index 0000000000000000000000000000000000000000..814408a52e60460a069528627c80f5d5058063cd GIT binary patch literal 3126 zcmcJRU2Icj7{}jUm=QmcE=04D7%L`bnrKEy2wpKi67Yfmn#fRNc7q9b8*;&n31dTa zGB%hAa{PS5NA^gTU2ZHJDeHcy-X z^SuA(_rB*jr%m75yW?q+dhNhx8Qv!KZ6GC3cwv3>Q|!$OgxpNM9JQ6d?=GF#P6`r} zZxjK@$oRCsQ|vuT5-o(b7bfI30-*hEBjAqD54nyM2Agv{U>&sw?R&N)n*SHR&_dYE zv-UNY(@s-XW#dCbBieO-b~iJX-U`b5Y4@v{iq8DsMKq!vkaSlTzqdk;t?E}b+hd4q zNQR$Xe+*#ysF@ZWO6BKWmtwxUmHzNTrYoPLRbYczOCi#827i1zk-Ku|rkMNRrQS)} zZpdoXLsV^0Y%uGWa`@jVJLV1FKm*e>Fh!li{}wQW=Ch8WL#gKnAG_=7>S2ESj7q#L z%T!KM_h{BGNKvFRO(y907n#FnLsY(YY3b`q`%~9$Jwok`lv||_Ep+fhB_NQZh$a0D z^X_9V9~Mj0B4 z;f1Wp=e4hM{yYyIJ+6=uE~|PAAe7-J>118z@cE7H%CG%sISJQqa#b5288yYi$`n64 zDEgQEZ3hq#NKtgv6hE@7+892$3Gk8ENT|WMT5Hn6duA6uJEWx$!H&bA1v@@X@@q*x z3Xw_=>pf^eqrMWVHv)e96%zWg#M4mD!q>D*3O)??)M}NK*e3bzQ%O(VJ6b_4`xyR3TB2Bh40 z7uvO6U;($hL;_!x`7i88gu1Geu|VMBA(qCh7x_gi)BXzwM2}t zc0knh>oULxOvK+<9=uY8Nc?Hz#;!6QxpqR1uZ4fCW+^_SgXhJ-1If1pp%r0(4Q5v1 z#ya^$8`FWta=`naC%$iXV$)FfQJIfMuGcBLt6Ff*a1-53hs?(!y{Okn!4)awf>2WP zF}4bu=$d6Za{UCJ0iclj&+G)ecMHM9;E&lZNg*c$V(phES%^pa8dxgg`JA~4E&O#y zSQ>{wiXvN${9F$+T38B5%yt>tceVoXp67_Sc{gq!Kh-a;&O@YhpX6C&n!EG89FIhY zT9HcbdC9$?)Q4J=To_BtBf1yRu4>mTKYat*+q?&G^Jd~{*%uqRlDI!6I;SCWwc}Up ziy}WaB#Q}I`d&1v$ z3m(fS-~Z{wlHrdl2VZ|OK4Zl%KmmiBxee^_M+fm2wBy-gOW6|(HG7?H#|sk6r>X!1 YR{INWsjTcMEo~>HAaSXv2tWq^2acGZv;Y7A literal 0 HcmV?d00001 diff --git a/gfx/item.png b/gfx/item.png new file mode 100644 index 0000000000000000000000000000000000000000..6b05dc985bce65508813210eba3b5e6a1546a64f GIT binary patch literal 1915 zcmV->2ZZ>EP)SQ)!t8W_Z#rUGZF}1 zn)CuKkQ7xHq9iSD({LLn9sikqXw6o-3$@)i2@5~TitNlB|9s}0^P7w_D1?Bo8D!D~ zCXH_nm^6V&g9UAP|Ni~&DW$&wz+E9kE=Ep~frxDYct{BO_1?XE{|(e9ND+MS;6dJT zoc{p8cNgS179e7e5OOn!69Pqm>$?9!#P2AjPt)o2zg1Q3T%6|U(eL*cK79D_i|e{S zdY<=B0QmX5K7ky7h<5=1GMUWpw{G3~ha^cW7vvfXY}?-6*x2~J+wJ}c0C$7*30ebk z00640?lZ=I5JI?7NyZ7r*bl0z?svOgfK$%r_6gDm5di>z5W)b!j!JMGAcQcVZxDoX z03uS)^QLn2eIOzoxdVIryK(#Yy>a>nDz*WF9n1UR0uKE5g>$!F9p7o z8W5&^6czBo(;6SXsX!bmaMl4rh^dZ%SY_}_QGqb+zePYmqy8roQ@)58%RJzWaSBte z0 ; + # + # Sets up the compiler flags and defines based on the WARNINGS, DEBUG, and + # OPTIMIZE variables. Also sets the locations for the targets (objects, + # libraries and executables). + # + # : Parameters as passed to the SubDir rule, i.e. the name of the + # TOP variable and the subdir tokens. + # + local dir = $(1) ; + + # warnings settings + if $(WARNINGS) != 0 { + if $(OSPLAT) = X86 { + CCFLAGS += -Wall -Wno-multichar -Wmissing-prototypes ; + CCFLAGS += -Wpointer-arith -Wcast-align -Wsign-compare ; + C++FLAGS += -Wall -Wno-multichar -Wmissing-prototypes ; + C++FLAGS += -Wno-ctor-dtor-privacy -Woverloaded-virtual ; + C++FLAGS += -Wpointer-arith -Wcast-align -Wsign-compare ; + C++FLAGS += -Wno-unknown-pragmas ; + } else { + CCFLAGS += -w on -requireprotos ; + } + } + + # set the objects-folder according to debugging settings: + if $(DEBUG) && $(DEBUG) != 0 + { + OBJECTS_DIR = [ FDirName $(TOP) generated objects-debug ] ; + } + else + { + OBJECTS_DIR = [ FDirName $(TOP) generated objects-nodebug ] ; + } + + # debugging settings + if $(DEBUG) > 0 { + OPTIMIZE = 0 ; + STRIP_APPS = 0 ; + DEFINES += DEBUG=$(DEBUG) ; + CCFLAGS += -g ; + C++FLAGS += -g ; + LINKFLAGS += -g ; + } + + # optimization settings + if $(OPTIMIZE) = 0 { + if $(OSPLAT) = X86 { + OPTIM = -O0 ; + } else { + OPTIM = -O0 ; + } + } else { + if $(OSPLAT) = X86 { + OPTIM ?= -O2 ; + } else { + OPTIM ?= -O7 ; + } + } + + # setup objects location + local objdir = [ FDirName $(OBJECTS_DIR) $(dir[2-]) ] ; + SEARCH_SOURCE += $(objdir) ; + LOCATE_SOURCE = $(objdir) ; + LOCATE_TARGET = $(objdir) ; + + # setup main targets location + LOCATE_MAIN_TARGET ?= [ FDirName $(DISTRO_DIR) ] ; +} + +# The LOCATE_MAIN_TARGET variable shall be reset for each subdirectory. +AUTO_SET_UP_CONFIG_VARIABLES += LOCATE_MAIN_TARGET ; + +# Add the rules setting up the build settings for a subdirectory to the +# rules invoked by SubDir. +SUBDIRRULES += SetUpSubDirBuildSettings ; diff --git a/library/build/ConfigRules b/library/build/ConfigRules new file mode 100644 index 0000000..082ec46 --- /dev/null +++ b/library/build/ConfigRules @@ -0,0 +1,146 @@ +# ConfigRules +# +# Contains rules providing the config variable feature. It allows to set the +# values for certain variables for subdirectories in a central place. That is +# one can, for instance, specify in a file like UserBuildConfig for which +# directories to enable debugging, warnings, set special defines, compiler +# flags and the like without needing to edit the Jamfiles for the respective +# dirs. + +rule ConfigObject +{ + # ConfigObject ; + # + # Private rule. Returns the dummy object on which the config variables are + # set for a given subdir. + # + # : Parameters as passed to the SubDir rule, i.e. the name of the + # TOP variable and the subdir tokens. + # + local config = __config__ ; + local grist = [ FGrist root $(1) ] ; + return $(config:G=$(grist)) ; +} + +rule SetConfigVar +{ + # SetConfigVar : : [ : ] ; + # + # Sets a config variable for a specified directory to the given value. + # + # : The name of the variable to be set. + # : Parameters as passed to the SubDir rule, i.e. the name of the + # TOP variable and the subdir tokens. + # : The value to which the variable shall be set. + # : Either "global" or "local". The former implies that the variable + # value shall also be used for subdirectories (recursively), if + # for them the variable has not been set. The latter has the same + # effect regarding subdirs as if the variable for the directory + # is not set. Defaults to "global". + # + local var = $(1[1]) ; + local config = [ ConfigObject $(2) ] ; + local scope = $(4) ; + if ! $(scope) { + scope = global ; + } + $(var) on $(config) = $(3) ; + __set_$(var) on $(config) = $(scope) ; +} + +rule AppendToConfigVar +{ + # AppendToConfigVar : : [ : ] ; + # + # Appends a value to a config variable for a specified directory. Shortcut + # for + # SetConfigVar : : [ ConfigVar : ] ; + # + # : The name of the variable to be set. + # : Parameters as passed to the SubDir rule, i.e. the name of the + # TOP variable and the subdir tokens. + # : The value which to append to the variables current value. + # : Either "global" or "local". The former implies that the variable + # value shall also be used for subdirectories (recursively), if + # for them the variable has not been set. The latter has the same + # effect regarding subdirs as if the variable for the directory + # is not set. Defaults to "global". + # + SetConfigVar $(1) : $(2) : [ ConfigVar $(1) : $(2) ] $(3) : $(4) ; +} + +rule ConfigVar +{ + # ConfigVar : [ : ] ; + # + # Returns the value of a configuration variable for a given subdir. + # If the variable is not set for the subdir, the rule is invoked + # recursively for the parent directory with the scope "global". When + # the root is reached without yielding a value, the value of the global + # variable is returned. + # + # : The name of the variable whose value shall be returned. + # : Parameters as passed to the SubDir rule, i.e. the name of the + # TOP variable and the subdir tokens. + # : If not given any scope passed to SetConfigVar for the given + # directory will be accepted, otherwise it must match the scope + # passed to SetConfigVar. + # + local var = $(1[1]) ; + local dir = $(2) ; + local config = [ ConfigObject $(dir) ] ; + local scope = $(3) ; + local varScope = [ on $(config) return $(__set_$(var)) ] ; + if ( ! $(scope) && $(varScope) ) + || ( $(scope) && $(scope) = $(varScope) ) + || ! $(dir) { + on $(config) return $($(var)) ; + } else { + dir = [ FReverse $(dir) ] ; + return [ ConfigVar $(var) : [ FReverse $(dir[2-]) ] : global ] ; + } +} + +rule SetUpConfigVars { + # SetUpConfigVars ; + # + # Sets the global variables defined in AUTO_SET_UP_CONFIG_VARIABLES to the + # values specified for the subdirectory . + # + # : Parameters as passed to the SubDir rule, i.e. the name of the + # TOP variable and the subdir tokens. + # + local dir = $(1) ; + + # Backup the global variable value on first invocation, otherwise restore + # them, so that ConfigVar returns the right values for not explicity set + # local variables. + local var ; + if ! $(__config_var_backup__) { + __config_var_backup__ = true ; + for var in $(AUTO_SET_UP_CONFIG_VARIABLES) { + __config_var_backup_$(var)__ = $($(var)) ; + } + } else { + for var in $(AUTO_SET_UP_CONFIG_VARIABLES) { + $(var) = $(__config_var_backup_$(var)__) ; + } + } + + # Set the variables to their configured values. + for var in $(AUTO_SET_UP_CONFIG_VARIABLES) { + $(var) = [ ConfigVar $(var) : $(dir) ] ; + } +} + +# Add the SetUpConfigVars rule to the rules that are invoked at the end of the +# SubDir rule. Prepend it, so that the variables are set up before any other +# rule is invoked. +SUBDIRRULES = SetUpConfigVars $(SUBDIRRULES) ; + +# Some config variables that should be set up automatically for subdirs. +AUTO_SET_UP_CONFIG_VARIABLES += + CCFLAGS C++FLAGS DEBUG DEFINES HDRS LINKFLAGS OPTIM OPTIMIZE + SYSHDRS WARNINGS +; diff --git a/library/build/HelperRules b/library/build/HelperRules new file mode 100644 index 0000000..dda3e89 --- /dev/null +++ b/library/build/HelperRules @@ -0,0 +1,51 @@ +# HelperRules +# +# Helper rules without side effects. + +rule FFilter +{ + # FFilter : ; + # + # Removes all occurrences of in . + + local list = $(1) ; + local excludes = $(2) ; + local newList ; + local item ; + for item in $(list) { + local skip ; + local exclude ; + for exclude in $(excludes) { + if $(item) = $(exclude) { + skip = true ; + } + } + if ! $(skip) { + newList += $(item) ; + } + } + return $(newList) ; +} + +rule FSplitPath +{ + # FSplitPath ; + # + # Decomposes a path into its components. + # + # : The path to be decomposed. + # + local path = $(1:G=) ; + + local components ; + # $(path:D) for "/" is "/". Therefore the second condition. + while $(path:D) && $(path:D) != $(path) + { + # Note: $(path:B) returns "." for "..", but $(path:D=) is fine. + components = $(path:D=) $(components) ; + path = $(path:D) ; + } + components = $(path) $(components) ; + return $(components) ; +} + diff --git a/library/build/MainBuildRules b/library/build/MainBuildRules new file mode 100644 index 0000000..f5768f3 --- /dev/null +++ b/library/build/MainBuildRules @@ -0,0 +1,428 @@ +# MainBuildRules +# +# Rules that specify what to build and how to do it. + +rule Application +{ + # Application : : ; + # + # Creates an application from sources. + # + # : Name of the application. Grist is allowed. + # : List of source files. Grist will be set. + # : List of libraries to link against. + # + local app = $(1) ; + local sources = $(2) ; + local libs = $(3) ; + + Main $(app) : $(sources) ; + MakeLocate $(app) : $(LOCATE_MAIN_TARGET) ; + LinkAgainst $(app) : $(libs) ; + +} + +actions Strip +{ + strip "$(1)" ; +} + +rule AddOn +{ + # AddOn : : ; + # + # Creates an add-on from sources. + # + # : Name of the add-on. Grist is allowed. + # : List of source files. Grist will be set. + # : List of libraries to link against. + # + SharedLibrary $(1) : $(2) : $(3) ; +} + +rule SharedLibrary +{ + # SharedLibrary : : ; + # + # Creates a shared library from sources. + # + # : Name of the shared library. Grist is allowed. + # : List of source files. Grist will be set. + # : List of libraries to link against. + # + local lib = $(1) ; + local sources = $(2) ; + local libs = $(3) ; + + Main $(lib) : $(sources) ; + MakeLocate $(lib) : $(LOCATE_MAIN_TARGET) ; + local linkFlags ; + if $(OSPLAT) = X86 { + linkFlags = -nostart -Xlinker -soname=\"$(lib)\" ; + } else { + linkFlags = -xms ; + } + LINKFLAGS on $(lib) = [ on $(lib) return $(LINKFLAGS) ] $(linkFlags) ; + LinkAgainst $(lib) : $(libs) ; +} + +rule StaticLibrary +{ + # StaticLibrary : ; + # + # Creates a static library from sources. + # + # : Name of the static library. Grist is allowed. + # : List of source files. Grist will be set. + # + local lib = $(1) ; + Library $(lib) : $(2) ; + MakeLocate $(lib) : $(LOCATE_MAIN_TARGET) ; + + # If KEEPOBJS is set, Library doesn't make the library depend on `lib'. + if $(KEEPOBJS) { + Depends lib : $(lib) ; + } +} + +rule LinkAgainst +{ + # LinkAgainst : ; + # + # Adds libraries to the list of libraries a (Main) target shall be linked + # against. + # + # : The name of the target for which to add libraries. + # : The libraries (actually arbitrary shared objects and static + # libraries) to be added. Valid elements are e.g. "be" or + # "libopenbeos.so" or "/boot/.../libfoo.so". If the basename starts + # with "lib" or the thingy has a dirname or grist, it is added to + # the NEEDLIBS variable (i.e. the file will be bound!), otherwise + # it is prefixed "-l" and added to LINKLIBS. If you want to specify + # a target that isn't a library and also has neither grist nor a + # dirname, you can prepend "" as grist; it will be + # stripped by this rule. + # + for i in $(>) + { + local isfile = ; + if $(i:D) || $(i:G) { + isfile = true ; + if $(i:G) = { + i = $(i:G=) ; + } + } else { + switch $(i:B) + { + # XXX: _APP_ and _KERNEL_ should not be needed for ELF. + case _APP_ : isfile = true ; + case _KERNEL_ : isfile = true ; + case lib* : isfile = true ; + case * : isfile = ; + } + if ! $(isfile) && ( $(i:S) = .so || $(i:S) = .a ) { + isfile = true ; + } + } + if $(isfile) { + NEEDLIBS on $(1) = [ on $(1) return $(NEEDLIBS) ] $(i) ; + Depends $(1) : $(i) ; + } else { + LINKLIBS on $(1) = [ on $(1) return $(LINKLIBS) ] -l$(i) ; + } + } +} + +rule XRes +{ + # XRes : ; + # + # Adds resources to a file. + # + # : The files to which resources shall be added. + # : The resource files. + # + if $(2) + { + Depends $(1) : $(2) ; + XRes1 $(1) : $(2) ; + } +} + +actions XRes1 +{ + xres -o "$(1)" "$(2)" ; +} + +actions MimeSet +{ + mimeset -f "$(1)" ; +} + +rule LexC++ +{ + Depends $(1) : $(2) ; + MakeLocate $(1) : $(LOCATE_SOURCE) ; + Clean clean : $(1) ; +} + +actions LexC++ +{ + $(LEX) -i -o$(1) $(2) +} + +rule Bison +{ + local _h ; + + _h = $(1).h ; + + MakeLocate $(<) $(_h) : $(LOCATE_SOURCE) ; + + Depends $(<) $(_h) : $(>) ; + BisonC++ $(<) $(_h) : $(>) ; + Clean clean : $(<) $(_h) ; + + # make sure someone includes $(_h) else it will be + # a deadly independent target + + Includes $(<) : $(_h) ; +} + +actions BisonC++ +{ + $(BISON) $(YACCFLAGS) -o $(1[1]) $(2) +} + +rule Rez +{ + # Rez : [ : ] ; + # + local output = $(1) ; + local rezFile = $(2) ; + local flags = $(3) ; + + REZHDRS on $(output) = [ on $(output) FIncludes $(HDRS) ] ; + REZFLAGS on $(output) = [ on $(output) return $(REZFLAGS) ] $(flags) ; + Depends $(output) : rez $(rezFile) ; + Rez1 $(output) : rez $(rezFile) ; +} + +actions Rez1 +{ + $(2[1]) $(REZFLAGS) $(REZHDRS) -o "$(1)" "$(2[2-])" ; +} + +rule RezObjects +{ + local rezFiles = $(1) ; + local rezFile ; + for rezFile in $(rezFiles) { + local rsrcFile = $(rezFile:BS=.rsrc) ; + RezObject $(rsrcFile) : [ FGristFiles $(rezFile) ] ; + } +} + +rule RezObject +{ + # RezObject : ; + # + local _rsrc = $(1) ; + local _r = $(2) ; + + local tmp = [ FGristFiles $(_rsrc)_tmp ] ; + + SEARCH on $(_r) = $(SEARCH_SOURCE) ; + + # include directories to by used + HDRS on $(_rsrc) $(tmp) = $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ; + + # preprocess the rez file + PreProcess $(tmp) : $(_r) ; + + # generate the resource file from the preprocessed rez file + MakeLocate $(_rsrc) : $(LOCATE_TARGET) ; + Rez $(_rsrc) : $(tmp) : -t ; + + RmTemps $(_rsrc) : $(tmp) ; + Clean clean : $(_rsrc) ; +} + +rule PreProcess +{ + # PreProcess : ; + # + local target = $(1) ; + local source = $(2) ; + + Depends $(target) : $(source) ; + + CPPHDRS on $(target) = [ on $(target) FIncludes $(HDRS) ] ; + + MakeLocate $(target) : $(LOCATE_SOURCE) ; +} + +if $(OSPLAT) = PPC { + actions PreProcess + { + mwcc -preprocess $(CPPHDRS) -o "$(1)" $(2) + } +} else { + actions PreProcess + { + gcc -E -x c $(CPPHDRS) -o "$(1)" $(2) + } +} + +rule RezHeader +{ + # RezHeader : : + # + # generates a header from a given resource file. + # + local _hdr = $(1) ; + local _rsrc = $(2) ; + + SEARCH on $(_rsrc) = $(SEARCH_SOURCE) ; + HDRS on $(_hdr) = $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ; + MakeLocate $(_hdr) : $(LOCATE_SOURCE) ; + Clean clean : $(_hdr) ; + + Rez $(_hdr) : $(_rsrc) : -h ; +} + +rule PreCompile +{ + # PreCompile : + # + # precompiles the given src (a headerfile) into the specified header. + # + local _hdr = $(1) ; + local _src = $(2) ; + MakeLocate $(_hdr) : $(LOCATE_TARGET) ; + PreComp $(_hdr) : $(_src) ; + Clean clean : $(_hdr) ; +} + +rule PreComp +{ + Depends $(<) : $(>) ; +} + +actions PreComp +{ + mwcc -precompile $(<) -lang cplus "$(>)" ; +} + +rule PeLanguage +{ + # PeLanguage : : : + # + # generates a SharedLib which extends Pe with syntax-highlighting for + # that specific language. + # + local lang = $(1) ; + local srcs = $(2) ; + local libs = $(3) ; + local rsrc = $(4) ; # contains keywords + + SharedLibrary $(lang) : $(srcs) : $(libs) ; + XRes $(lang) : $(rsrc) ; +} + +rule PeExtension +{ + # PeExtension : : : + # + # generates a SharedLib which extends Pe with a specific feature. + # + local ext = $(1) ; + local srcs = [ FGristFiles $(2) ] ; + local libs = $(3) ; + local rsrc = [ FGristFiles $(4) ] ; # optional resource file + + if $(rsrc) { + local header = $(rsrc:BS=.r.h) ; + + Includes $(srcs) : $(header) ; + RezHeader $(header) : $(rsrc) ; + } + SharedLibrary $(ext) : $(srcs) : $(libs) ; + + SymlinkDistroExtensionsLibDir $(ext) ; +} + +rule SymlinkDistroExtensionsLibDir +{ + # SymlinkDistroExtensionsLibDir ; + # + local extension = $(1) ; + + Depends $(extension) : lib ; + NoUpdate lib ; + MakeLocate lib : $(DISTRO_DIR)/Extensions ; + + SymlinkDistroExtensionsLibDir1 lib ; +} + +actions together SymlinkDistroExtensionsLibDir1 +{ # create a link to the folder where libhekkel.so lives + ln -sfn ../lib $(1) ; +} + +rule SubDirSysHdrs +{ + # SubDirSysHdrs ; + # + # Adds directories to the system include search paths for the current + # subdirectory. Counterpart of SubDirHdrs which adds non-system include + # search paths. + # + # : The directories to be added to the current subdir's system + # include search paths. + # + SUBDIRSYSHDRS += [ FDirName $(1) ] ; +} + +rule ObjectSysHdrs +{ + # SubDirSysHdrs : ; + # + # Adds directories to the system include search paths for the given + # sources or objects. Counterpart of ObjectHdrs which adds non-system + # include search paths. + # + # NOTE: This rule must be invoked *after* the rule that generates the + # objects. + # + # : The targets for which to add system include + # search paths. + # : The directories to be added to the given objects' system + # include search paths. + # + + local s ; + for s in [ FGristFiles $(<:S=$(SUFOBJ)) ] { + SYSHDRS on $(s) += $(>) ; + CCHDRS on $(s) = [ on $(s) FIncludes $(HDRS) ] + $(HDRS_INCLUDES_SEPARATOR) [ on $(s) FSysIncludes $(SYSHDRS) ] ; + } +} + + +# FSysIncludes ; +# +# Counterpart of FIncludes for system include search paths. +# +if $(OSPLAT) = X86 { + rule FSysIncludes { return -I$(<) ; } +} else { + rule FSysIncludes { return "-i "$(<) ; } +} + +# Variable referring to the STL. +if $(OSPLAT) = X86 { + STDC++LIB = stdc++.r4 ; +} else { + STDC++LIB = mslcpp_4_0 ; +} diff --git a/library/build/OverriddenJamRules b/library/build/OverriddenJamRules new file mode 100644 index 0000000..c0fef0c --- /dev/null +++ b/library/build/OverriddenJamRules @@ -0,0 +1,214 @@ +# OverriddenJamRules +# +# Jam rules that need to be overridden for good reasons. + +# Overridden to allow for spaces in file names and to support resources. +# Also set the on target LINKFLAGS variable to prevent later changes to +# the global variable from having an effect on the setting for the target. +rule Link +{ + local dbg = [ on $(1) return $(DEBUG) ] ; + if $(STRIP_APPS) && $(STRIP_APPS) != 0 && (!$(dbg) || $(dbg) = 0) { + # strip app if requested so and if not in debug mode! + Strip $(1) ; + } + # Note: RESFILES must be set before invocation. + MODE on $(1) = $(EXEMODE) ; + on $(1) XRes $(1) : $(RESFILES) ; + Chmod $(1) ; + MimeSet $(1) ; + LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ] ; +} + +actions Link bind NEEDLIBS +{ + $(LINK) $(LINKFLAGS) -o "$(1)" $(UNDEFS) "$(2)" "$(NEEDLIBS)" $(LINKLIBS) +} + + +# Overridden to allow for spaces in file names. +actions Chmod1 +{ + $(CHMOD) "$(MODE)" "$(1)" +} + +# Overridden to allow for spaces in file names. +actions piecemeal together existing Clean +{ + $(RM) "$(>)" +} + +# Changes to rules for sake of discrimination between system and non-system +# headers. + +if $(OSPLAT) = X86 { + HDRS_INCLUDES_SEPARATOR = -I- ; +} else { + HDRS_INCLUDES_SEPARATOR = -i- ; +} + +rule Cc +{ + Depends $(<) : $(>) ; + + # If the compiler's -o flag doesn't work, relocate the .o + + if $(RELOCATE) + { + CcMv $(<) : $(>) ; + } + + # Just to clarify here: this sets the per-target CCFLAGS to + # be the current value of (global) CCFLAGS and SUBDIRCCFLAGS. + # CCHDRS and CCDEFS must be reformatted each time for some + # compiles (VMS, NT) that malign multiple -D or -I flags. + + CCFLAGS on $(<) += $(CCFLAGS) $(SUBDIRCCFLAGS) $(OPTIM) ; + + CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] + $(HDRS_INCLUDES_SEPARATOR) [ on $(<) FSysIncludes $(SYSHDRS) ] ; + CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ; +} + +rule C++ +{ + Depends $(<) : $(>) ; + + if $(RELOCATE) + { + CcMv $(<) : $(>) ; + } + + C++FLAGS on $(<) += $(C++FLAGS) $(SUBDIRC++FLAGS) $(OPTIM) ; + + CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] + $(HDRS_INCLUDES_SEPARATOR) [ on $(<) FSysIncludes $(SYSHDRS) ] ; + CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ; +} + +rule Object +{ + # locate object and search for source, if wanted + + Clean clean : $(<) ; + + MakeLocate $(<) : $(LOCATE_TARGET) ; + SEARCH on $(>) = $(SEARCH_SOURCE) ; + + # Save HDRS for -I$(HDRS) on compile. + # We shouldn't need -I$(SEARCH_SOURCE) as cc can find headers + # in the .c file's directory, but generated .c files (from + # yacc, lex, etc) are located in $(LOCATE_TARGET), possibly + # different from $(SEARCH_SOURCE). + + HDRS on $(<) = $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ; + SYSHDRS on $(<) = $(SUBDIRSYSHDRS) $(SYSHDRS) ; + + # handle #includes for source: Jam scans for headers with + # the regexp pattern $(HDRSCAN) and then invokes $(HDRRULE) + # with the scanned file as the target and the found headers + # as the sources. HDRSEARCH is the value of SEARCH used for + # the found header files. Finally, if jam must deal with + # header files of the same name in different directories, + # they can be distinguished with HDRGRIST. + + # $(SEARCH_SOURCE:E) is where cc first looks for #include + # "foo.h" files. If the source file is in a distant directory, + # look there. Else, look in "" (the current directory). + + HDRRULE on $(>) = HdrRule ; + HDRSCAN on $(>) = $(HDRPATTERN) ; + HDRSEARCH on $(>) = + $(SEARCH_SOURCE:E) $(SUBDIRHDRS) $(HDRS) $(SYSHDRS) $(STDHDRS) ; + + HDRGRIST on $(>) = $(HDRGRIST) ; + + # propagate target specific-defines + + DEFINES on $(<) += $(DEFINES) ; + + # if source is not .c, generate .c with specific rule + + switch $(>:S) + { + case .asm : As $(<) : $(>) ; + case .c : Cc $(<) : $(>) ; + case .C : C++ $(<) : $(>) ; + case .cc : C++ $(<) : $(>) ; + case .cpp : C++ $(<) : $(>) ; + case .f : Fortran $(<) : $(>) ; + case .l : C++ $(<) : $(<:S=.cpp) ; + LexC++ $(<:S=.cpp) : $(>) ; + case .s : As $(<) : $(>) ; + case .y : C++ $(<) : $(<:S=.cpp) ; + Bison $(<:S=.cpp) : $(>) ; + case * : UserObject $(<) : $(>) ; + } +} + +rule ObjectHdrs +{ + local s ; + for s in [ FGristFiles $(<:S=$(SUFOBJ)) ] { + HDRS on $(s) += $(>) ; + CCHDRS on $(s) = [ on $(s) FIncludes $(HDRS) ] + $(HDRS_INCLUDES_SEPARATOR) [ on $(s) FSysIncludes $(SYSHDRS) ] ; + } +} + +# Override Jam 2.5rc3 MakeLocate and MkDir to deal more intelligently +# with grist set on the supplied directory name. +rule MakeLocate +{ + if $(2[1]) + { + local dir = $(2[1]) ; + if ! $(dir:G) { + dir = $(dir:G=dir) ; + } + LOCATE on $(1) = $(dir:G=) ; + Depends $(1) : $(dir) ; + MkDir $(dir) ; + } +} + +rule MkDir +{ + # If dir exists, don't update it + # Do this even for $(DOT). + + local dir = $(<) ; + if ! $(dir:G) { + dir = $(dir:G=dir) ; + } + + NoUpdate $(dir) ; + + if $(dir:G=) != $(DOT) && ! $($(dir:G=)-mkdir) { + local s ; + + # Cheesy gate to prevent multiple invocations on same dir + # MkDir1 has the actions + # Arrange for jam dirs + + $(dir:G=)-mkdir = true ; + MkDir1 $(dir) ; + Depends dirs : $(dir) ; + + # Recursively make parent directories. + # $(dir:P) = $(dir)'s parent, & we recurse until root + + s = $(dir:P) ; # parent keeps grist + + if $(s:G=) && $(s) != $(dir) { + Depends $(dir) : $(s) ; + MkDir $(s) ; + } else if $(s) { + NotFile $(s) ; + } + } +} + +# Add SUBDIRSYSHDRS to the variables that shall be reset automatically by the +# SubDir rule. +SUBDIRRESET += SYSHDRS ; diff --git a/library/build/UserBuildConfig b/library/build/UserBuildConfig new file mode 100644 index 0000000..f2165f0 --- /dev/null +++ b/library/build/UserBuildConfig @@ -0,0 +1,63 @@ +# UserBuildConfig +# +# Sample of a UserBuildConfig file. It is a central place where the user can +# set variables affecting certain aspects of the build, such as debug, +# warnings and optimization settings. The file is ignored by CVS. +# +# The following variables can be set: +# +# CCFLAGS, C++FLAGS - Flags passed to the C/C++ compiler. +# DEBUG - If not empty, will turn on debugging, i.e. will +# add respective C/C++ compiler and linker flags and +# the CPP DEBUG macro. +# DEFINES - CPP macros to be defined, e.g. something like +# `SPECIAL_FEATURE' or `CACHE_SIZE=1024'. +# HDRS - List of directories to be added to the local include +# search paths. +# LINKFLAGS - Flags passed to the linker. +# LOCATE_MAIN_TARGET - Directory where the main targets (i.e. applications, +# libraries shall be placed). Should usually not be +# tampered with by the user. +# OPTIM - Optimization specific flags passed to the C/C++ +# compiler. Usually you want to use OPTIMIZE instead. +# OPTIMIZE - If not set to `0', will turn on optimization, i.e. +# will set the respective C/C++ compiler flags +# (i.e. the OPTIM variable). +# STRIP_APPS - if not set to '0', will cause all generated apps to +# be stripped. Default is '0', i.e. no stripping +# SYSHDRS - List of directories to be added to the system include +# search paths. +# WARNINGS - If not set to `0', will turn on warnings, i.e. will +# set the respective C/C++ compiler flags. + +# Examples: + +OPTIMIZE = 0 ; + +# Globally turn off debugging: +# +# DEBUG = 0 ; + +# Globally activate debugging: +# +# DEBUG = 1 ; + +# ... e.g. like this, for the `add-ons/catalogs' directory and all its +# subdirectories. +# +# SetConfigVar WARNINGS : TOP add-ons catalogs : 1 ; + +# Turn on debugging for the the directory `Languages' and all its subdirectories. +# +# SetConfigVar DEBUG : TOP Languages : 1 ; + +# Turn off optimization for the `rez' directory and all its subdirectories. +# +# SetConfigVar OPTIMIZE : TOP rez : 0 ; + +# Define the CPP macro INSANE_DEBUGGING_LEVEL to the value `100' in the +# `lpe' directory, but NOT in its subdirectories (note the use of the +# optional fourth parameter `local', which works for both SetConfigVar and +# AppendToConfigVar). +# +# AppendToConfigVar DEFINES : TOP lpe : INSANE_DEBUGGING_LEVEL=100 : local ; diff --git a/library/build/UserBuildConfig.sample b/library/build/UserBuildConfig.sample new file mode 100644 index 0000000..67cf7c7 --- /dev/null +++ b/library/build/UserBuildConfig.sample @@ -0,0 +1,61 @@ +# UserBuildConfig +# +# Sample of a UserBuildConfig file. It is a central place where the user can +# set variables affecting certain aspects of the build, such as debug, +# warnings and optimization settings. The file is ignored by CVS. +# +# The following variables can be set: +# +# CCFLAGS, C++FLAGS - Flags passed to the C/C++ compiler. +# DEBUG - If not empty, will turn on debugging, i.e. will +# add respective C/C++ compiler and linker flags and +# the CPP DEBUG macro. +# DEFINES - CPP macros to be defined, e.g. something like +# `SPECIAL_FEATURE' or `CACHE_SIZE=1024'. +# HDRS - List of directories to be added to the local include +# search paths. +# LINKFLAGS - Flags passed to the linker. +# LOCATE_MAIN_TARGET - Directory where the main targets (i.e. applications, +# libraries shall be placed). Should usually not be +# tampered with by the user. +# OPTIM - Optimization specific flags passed to the C/C++ +# compiler. Usually you want to use OPTIMIZE instead. +# OPTIMIZE - If not set to `0', will turn on optimization, i.e. +# will set the respective C/C++ compiler flags +# (i.e. the OPTIM variable). +# STRIP_APPS - if not set to '0', will cause all generated apps to +# be stripped. Default is '0', i.e. no stripping +# SYSHDRS - List of directories to be added to the system include +# search paths. +# WARNINGS - If not set to `0', will turn on warnings, i.e. will +# set the respective C/C++ compiler flags. + +# Examples: + +# Globally turn off debugging: +# +# DEBUG = 0 ; + +# Globally activate debugging: +# +# DEBUG = 1 ; + +# ... e.g. like this, for the `add-ons/catalogs' directory and all its +# subdirectories. +# +# SetConfigVar WARNINGS : TOP add-ons catalogs : 1 ; + +# Turn on debugging for the the directory `Languages' and all its subdirectories. +# +# SetConfigVar DEBUG : TOP Languages : 1 ; + +# Turn off optimization for the `rez' directory and all its subdirectories. +# +# SetConfigVar OPTIMIZE : TOP rez : 0 ; + +# Define the CPP macro INSANE_DEBUGGING_LEVEL to the value `100' in the +# `lpe' directory, but NOT in its subdirectories (note the use of the +# optional fourth parameter `local', which works for both SetConfigVar and +# AppendToConfigVar). +# +# AppendToConfigVar DEFINES : TOP lpe : INSANE_DEBUGGING_LEVEL=100 : local ; diff --git a/library/libclv/ColorTools.cpp b/library/libclv/ColorTools.cpp new file mode 100644 index 0000000..4865d3b --- /dev/null +++ b/library/libclv/ColorTools.cpp @@ -0,0 +1,76 @@ +/******************************************************************************* +/ +/ File: ColorTools.cpp +/ +/ Description: Additional experimental color manipulation functions. +/ +/ Copyright 2000, Be Incorporated, All Rights Reserved +/ +*******************************************************************************/ + +#include "ColorTools.h" + +#if B_BEOS_VERSION <= B_BEOS_VERSION_MAUI + +namespace BExperimental { + +#if DEBUG +#define DB_INLINE +#else +#define DB_INLINE inline +#endif + +static DB_INLINE void mix_color_func(rgb_color* target, const rgb_color other, uint8 amount) +{ + target->red = (uint8)( ((int16(other.red)-int16(target->red))*amount)/255 + + target->red ); + target->green = (uint8)( ((int16(other.green)-int16(target->green))*amount)/255 + + target->green ); + target->blue = (uint8)( ((int16(other.blue)-int16(target->blue))*amount)/255 + + target->blue ); + target->alpha = (uint8)( ((int16(other.alpha)-int16(target->alpha))*amount)/255 + + target->alpha ); +} + +static DB_INLINE void blend_color_func(rgb_color* target, const rgb_color other, uint8 amount) +{ + const uint8 alphaMix = (uint8)( ((int16(other.alpha)-int16(255-target->alpha))*amount)/255 + + (255-target->alpha) ); + target->red = (uint8)( ((int16(other.red)-int16(target->red))*alphaMix)/255 + + target->red ); + target->green = (uint8)( ((int16(other.green)-int16(target->green))*alphaMix)/255 + + target->green ); + target->blue = (uint8)( ((int16(other.blue)-int16(target->blue))*alphaMix)/255 + + target->blue ); + target->alpha = (uint8)( ((int16(other.alpha)-int16(target->alpha))*amount)/255 + + target->alpha ); +} + +static DB_INLINE void disable_color_func(rgb_color* target, const rgb_color background) +{ + blend_color_func(target, background, 255-70); +} + +// -------------------------------------------------------------------------- + +rgb_color mix_color(rgb_color color1, rgb_color color2, uint8 amount) +{ + mix_color_func(&color1, color2, amount); + return color1; +} + +rgb_color blend_color(rgb_color color1, rgb_color color2, uint8 amount) +{ + blend_color_func(&color1, color2, amount); + return color1; +} + +rgb_color disable_color(rgb_color color, rgb_color background) +{ + disable_color_func(&color, background); + return color; +} + +} + +#endif diff --git a/library/libclv/ColumnListView.cpp b/library/libclv/ColumnListView.cpp new file mode 100644 index 0000000..05bc07b --- /dev/null +++ b/library/libclv/ColumnListView.cpp @@ -0,0 +1,4128 @@ +/******************************************************************************* +/ +/ File: ColumnListView.cpp +/ +/ Description: Experimental multi-column list view. +/ +/ Copyright 2000+, Be Incorporated, All Rights Reserved +/ By Jeff Bush +/ +*******************************************************************************/ + +#include + +#include +#include + +#include +#include +#if _INCLUDES_CLASS_CURSOR +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ObjectList.h" +#include "ColumnListView.h" +#include "ColorTools.h" +/* +#ifndef _ARCHIVE_DEFS_H +#include +#endif +*/ +#define DOUBLE_BUFFERED_COLUMN_RESIZE 1 +#define SMART_REDRAW 0 +#define DRAG_TITLE_OUTLINE 1 +#define CONSTRAIN_CLIPPING_REGION 1 +#define LOWER_SCROLLBAR 1 + +namespace BPrivate { + +static const unsigned char kResizeCursorData[] = { + 16, 1, 8, 8, + 0, 0, 1, 0x80, 1, 0x80, 1, 0x80, 9, 0x90, 0x19, 0x98, 0x39, 0x09c, 0x79, 0x9e, + 0x79, 0x9e, 0x39, 0x9c, 0x19, 0x98, 0x9, 0x90, 1, 0x80, 1, 0x80, 1, 0x80, 0, 0, + 3, 0xc0, 3, 0xc0, 3, 0xc0, 0xf, 0xf0, 0x1f, 0xf8, 0x3f, 0xfa, 0x7f, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0xfe, 0x3f, 0xfa, 0x1f, 0xf8, 0xf, 0xf0, 3, 0xc0, 3, 0xc0, 3, 0xc0 +}; + +static const unsigned char kMaxResizeCursorData[] = { + 16, 1, 8, 8, + 0, 0, 1, 0x80, 1, 0x80, 1, 0x80, 9, 0x80, 0x19, 0x80, 0x39, 0x80, 0x79, 0x80, + 0x79, 0x80, 0x39, 0x80, 0x19, 0x80, 0x9, 0x80, 1, 0x80, 1, 0x80, 1, 0x80, 0, 0, + 3, 0xc0, 3, 0xc0, 3, 0xc0, 0xf, 0xc0, 0x1f, 0xc0, 0x3f, 0xc0, 0x7f, 0xc0, 0xff, 0xc0, + 0xff, 0xc0, 0x7f, 0xc0, 0x3f, 0xc0, 0x1f, 0xc0, 0xf, 0xc0, 3, 0xc0, 3, 0xc0, 3, 0xc0 +}; + +static const unsigned char kMinResizeCursorData[] = { + 16, 1, 8, 8, + 0, 0, 1, 0x80, 1, 0x80, 1, 0x80, 1, 0x90, 1, 0x98, 1, 0x09c, 1, 0x9e, + 1, 0x9e, 1, 0x9c, 1, 0x98, 1, 0x90, 1, 0x80, 1, 0x80, 1, 0x80, 0, 0, + 3, 0xc0, 3, 0xc0, 3, 0xc0, 3, 0xf0, 3, 0xf8, 3, 0xfa, 3, 0xfe, 3, 0xff, + 3, 0xff, 3, 0xfe, 3, 0xfa, 3, 0xf8, 3, 0xf0, 3, 0xc0, 3, 0xc0, 3, 0xc0 +}; + +static const unsigned char kColumnMoveCursorData[] = { + 16, 1, 8, 8, + 1, 0x80, 3, 0xc0, 7, 0xe0, 0, 0, 0, 0, 0x20, 4, 0x61, 0x86, 0xe3, 0xc7, + 0xe3, 0xc7, 0x61, 0x86, 0x20, 4, 0, 0, 0, 0, 7, 0xe0, 3, 0xc0, 1, 0x80, + 1, 0x80, 3, 0xc0, 7, 0xe0, 0, 0, 0, 0, 0x20, 4, 0x61, 0x86, 0xe3, 0xc7, + 0xe3, 0xc7, 0x61, 0x86, 0x20, 4, 0, 0, 0, 0, 7, 0xe0, 3, 0xc0, 1, 0x80 +}; + +static const unsigned char kUpSortArrow8x8[] = { + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff +}; + +static const unsigned char kDownSortArrow8x8[] = { + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff +}; + +static const unsigned char kUpSortArrow8x8Invert[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x1f, 0x1f, 0x1f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff +}; + +static const unsigned char kDownSortArrow8x8Invert[] = { + 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x1f, 0x1f, 0x1f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +/* +static const rgb_color kTitleColor = {215, 215, 215, 255}; +static const rgb_color kTitleTextColor = { 0, 0, 0, 255 }; +static const rgb_color kDefaultBackgroundColor = {236, 236, 236, 255}; +static const rgb_color kRowDividerColor = {148, 148, 148, 255}; +static const rgb_color kDefaultSelectionColor = {255, 255, 255, 255}; +static const rgb_color kDefaultEditColor = {180, 180, 180, 180}; +static const rgb_color kNonFocusSelectionColor = {220, 220, 220, 255}; +*/ + +static const float kTitleHeight = 17.0; +static const float kLatchWidth = 15.0; + + +static const rgb_color kColor[B_COLOR_TOTAL] = +{ + {236, 236, 236, 255}, // B_COLOR_BACKGROUND + { 0, 0, 0, 255}, // B_COLOR_TEXT + {148, 148, 148, 255}, // B_COLOR_ROW_DIVIDER + {255, 255, 255, 255}, // B_COLOR_SELECTION + { 0, 0, 0, 255}, // B_COLOR_SELECTION_TEXT + {220, 220, 220, 255}, // B_COLOR_NON_FOCUS_SELECTION + {180, 180, 180, 180}, // B_COLOR_EDIT_BACKGROUND + { 0, 0, 0, 255}, // B_COLOR_EDIT_TEXT + {215, 215, 215, 255}, // B_COLOR_HEADER_BACKGROUND + { 0, 0, 0, 255}, // B_COLOR_HEADER_TEXT + { 0, 0, 0, 255}, // B_COLOR_SEPARATOR_LINE + { 0, 0, 0, 255}, // B_COLOR_SEPARATOR_BORDER +}; + +static const int32 kMaxDepth = 1024; +static const float kLeftMargin = kLatchWidth; +static const float kRightMargin = kLatchWidth; +static const float kBottomMargin = kLatchWidth; +static const float kOutlineLevelIndent = kLatchWidth; +static const float kColumnResizeAreaWidth = 10.0; +static const float kRowDragSensitivity = 5.0; +static const float kDoubleClickMoveSensitivity = 4.0; +static const float kSortIndicatorWidth = 9.0; +static const float kDropHighlightLineHeight = 2.0; + +static const uint32 kToggleColumn = 'BTCL'; + +class BRowContainer : public BObjectList +{ +}; + +class TitleView : public BView { +public: + TitleView(BRect, OutlineView*, BList *visibleColumns, BList *sortColumns, + BColumnListView *masterView); + ~TitleView(); + void ColumnAdded(BColumn*); + void SetColumnVisible(BColumn*, bool); + + virtual void Draw(BRect rect); + virtual void ScrollTo(BPoint); + virtual void MessageReceived(BMessage*); + virtual void MouseDown(BPoint); + virtual void MouseMoved(BPoint, uint32, const BMessage*); + virtual void MouseUp(BPoint position); + virtual void FrameResized(float width, float height); + + void MoveColumn(BColumn *column, int32 index); + void SetColumnFlags(column_flags flags); + + void SetEditMode(bool state) { fEditMode = state; } + + +private: + void GetTitleRect(BColumn*, BRect *out_rect); + int32 FindColumn(BPoint, float *out_leftEdge); + void FixScrollBar(bool scrollToFit); + void DragSelectedColumn(BPoint); + void ResizeSelectedColumn(BPoint); + void ComputeDragBoundries(BColumn*, BPoint); + void DrawTitle(BView*, BRect, BColumn*, bool depressed); + + OutlineView *fOutlineView; + BList *fColumns; + BList *fSortColumns; + float fColumnsWidth; + BRect fVisibleRect; + +#if DOUBLE_BUFFERED_COLUMN_RESIZE + BBitmap *fDrawBuffer; + BView *fDrawBufferView; +#endif + + enum { + INACTIVE, + RESIZING_COLUMN, + PRESSING_COLUMN, + DRAG_COLUMN_INSIDE_TITLE, + DRAG_COLUMN_OUTSIDE_TITLE + } fCurrentState; + + BPopUpMenu *fColumnPop; + BColumnListView *fMasterView; + bool fEditMode; + int32 fColumnFlags; + + // State information for resizing/dragging + BColumn *fSelectedColumn; + BRect fSelectedColumnRect; + bool fResizingFirstColumn; + BPoint fClickPoint; // offset within cell + float fLeftDragBoundry; + float fRightDragBoundry; + BPoint fCurrentDragPosition; + + + BBitmap *fUpSortArrow; + BBitmap *fDownSortArrow; +#if _INCLUDES_CLASS_CURSOR + BCursor *fResizeCursor; + BCursor *fMinResizeCursor; + BCursor *fMaxResizeCursor; + BCursor *fColumnMoveCursor; +#endif + + + typedef BView _inherited; +}; + +class OutlineView : public BView { +public: + OutlineView(BRect, BList *visibleColumns, BList *sortColumns, BColumnListView *listView); + ~OutlineView(); + + virtual void Draw(BRect); + const BRect& VisibleRect() const; + + void RedrawColumn(BColumn *column, float leftEdge, bool isFirstColumn); + void StartSorting(); + + void AddRow(BRow*, int32 index, BRow *TheRow); + BRow* CurrentSelection(BRow *lastSelected) const; + void ToggleFocusRowSelection(bool selectRange); + void ToggleFocusRowOpen(); + void ChangeFocusRow(bool up, bool updateSelection, bool addToCurrentSelection); + void MoveFocusToVisibleRect(); + void ExpandOrCollapse(BRow *parent, bool expand); + void RemoveRow(BRow*); + BRowContainer* RowList(); + void UpdateRow(BRow*); + bool FindParent(BRow *row, BRow **out_parent, bool *out_isVisible); + int32 IndexOf(BRow *row); + void Deselect(BRow*); + void AddToSelection(BRow*); + void DeselectAll(); + BRow* FocusRow() const; + void SetFocusRow(BRow *row, bool select); + BRow* FindRow(float ypos, int32 *out_indent, float *out_top); + bool FindRect(const BRow *row, BRect *out_rect); + void ScrollTo(const BRow* Row); + + void Clear(); + void SetSelectionMode(list_view_type); + list_view_type SelectionMode() const; + void SetMouseTrackingEnabled(bool); + void FixScrollBar(bool scrollToFit); + void SetEditMode(bool state) { fEditMode = state; } + + virtual void FrameResized(float width, float height); + virtual void ScrollTo(BPoint pt); + virtual void MouseDown(BPoint); + virtual void MouseMoved(BPoint, uint32, const BMessage*); + virtual void MouseUp(BPoint); + virtual void MessageReceived(BMessage*); + +private: + bool SortList(BRowContainer *list, bool isVisible); + static int32 DeepSortThreadEntry(void *outlineView); + void DeepSort(); + void SelectRange(BRow *start, BRow *end); + int32 CompareRows(BRow *row1, BRow *row2); + void AddSorted(BRowContainer *list, BRow *row); + void RecursiveDeleteRows(BRowContainer *list, bool owner); + void InvalidateCachedPositions(); + bool FindVisibleRect(BRow *row, BRect *out_rect); + + BList* fColumns; + BList* fSortColumns; + float fItemsHeight; + BRowContainer fRows; + BRect fVisibleRect; + +#if DOUBLE_BUFFERED_COLUMN_RESIZE + BBitmap* fDrawBuffer; + BView* fDrawBufferView; +#endif + + BRow* fFocusRow; + BRect fFocusRowRect; + BRow* fRollOverRow; + + BRow fSelectionListDummyHead; + BRow* fLastSelectedItem; + BRow* fFirstSelectedItem; + + thread_id fSortThread; + int32 fNumSorted; + bool fSortCancelled; + + enum CurrentState + { + INACTIVE, + LATCH_CLICKED, + ROW_CLICKED, + DRAGGING_ROWS + }; + + CurrentState fCurrentState; + + + BColumnListView* fMasterView; + list_view_type fSelectionMode; + bool fTrackMouse; + BField* fCurrentField; + BRow* fCurrentRow; + BColumn* fCurrentColumn; + bool fMouseDown; + BRect fFieldRect; + int32 fCurrentCode; + bool fEditMode; + + // State information for mouse/keyboard interaction + BPoint fClickPoint; + bool fDragging; + int32 fClickCount; + BRow *fTargetRow; + float fTargetRowTop; + BRect fLatchRect; + float fDropHighlightY; + + friend class RecursiveOutlineIterator; + typedef BView _inherited; +}; + +class RecursiveOutlineIterator { +public: + RecursiveOutlineIterator(BRowContainer*, bool openBranchesOnly = true); + BRow *CurrentRow() const; + int32 CurrentLevel() const; + void GoToNext(); + +private: + struct { + BRowContainer *fRowSet; + int32 fIndex; + int32 fDepth; + } fStack[kMaxDepth]; + + int32 fStackIndex; + BRowContainer *fCurrentList; + int32 fCurrentListIndex; + int32 fCurrentListDepth; + bool fOpenBranchesOnly; +}; + +} // namespace BPrivate + +using namespace BPrivate; + +BField::BField() +{ +} + +BField::~BField() +{ +} + +// #pragma mark - + +void BColumn::MouseMoved(BColumnListView */*parent*/, BRow */*row*/, BField */*field*/, + BRect /*field_rect*/, BPoint/*point*/, uint32 /*buttons*/, int32 /*code*/) +{ +} + +void BColumn::MouseDown( BColumnListView */*parent*/, BRow */*row*/, BField */*field*/, + BRect /*field_rect*/, BPoint /*point*/, uint32 /*buttons*/) +{ +} + +void BColumn::MouseUp(BColumnListView */*parent*/, BRow */*row*/, BField */*field*/) +{ +} + +// #pragma mark - + +BRow::BRow(float height) + : fChildList(NULL), + fIsExpanded(false), + fHeight(height), + fNextSelected(NULL), + fPrevSelected(NULL), + fParent(NULL), + fList(NULL) +{ +} + +BRow::~BRow() +{ + while (true) { + BField *field = (BField*) fFields.RemoveItem(0L); + if (field == 0) + break; + + delete field; + } +} + +bool BRow::HasLatch() const +{ + return fChildList != 0; +} + +int32 BRow::CountFields() const +{ + return fFields.CountItems(); +} + +BField* BRow::GetField(int32 index) +{ + return (BField*) fFields.ItemAt(index); +} + +const BField* BRow::GetField(int32 index) const +{ + return (const BField*) fFields.ItemAt(index); +} + +void BRow::SetField(BField *field, int32 logicalFieldIndex) +{ + if (fFields.ItemAt(logicalFieldIndex) != 0) + delete (BField*) fFields.RemoveItem(logicalFieldIndex); + + if( NULL != fList ) { + ValidateField(field, logicalFieldIndex); + BRect inv; + fList->GetRowRect(this, &inv); + fList->Invalidate(inv); + } + + fFields.AddItem(field, logicalFieldIndex); +} + +float BRow::Height() const +{ + return fHeight; +} + +bool BRow::IsExpanded() const +{ + return fIsExpanded; +} + +void +BRow::ValidateFields() const +{ + for( int32 i = 0; i < CountFields(); i++ ) + { + ValidateField(GetField(i), i); + } +} + +void +BRow::ValidateField(const BField *field, int32 logicalFieldIndex) const +{ + // The Fields may be moved by the user, but the logicalFieldIndexes + // do not change, so we need to map them over when checking the + // Field types. + BColumn* col = NULL; + int32 items = fList->CountColumns(); + for( int32 i = 0 ; i < items; ++i ) + { + col = fList->ColumnAt(i); + if( col->LogicalFieldNum() == logicalFieldIndex ) + break; + } + + if( NULL == col ) + { + BString dbmessage("\n\n\tThe parent BColumnListView does not have " + "\n\ta BColumn at the logical field index "); + dbmessage << logicalFieldIndex << ".\n\n"; + printf(dbmessage.String()); + } + else + { + if( false == col->AcceptsField(field) ) + { + BString dbmessage("\n\n\tThe BColumn of type "); + dbmessage << typeid(*col).name() << "\n\tat logical field index " + << logicalFieldIndex << "\n\tdoes not support the field type " + << typeid(*field).name() << ".\n\n"; + debugger(dbmessage.String()); + } + } +} + + +// #pragma mark - + +BColumn::BColumn(float width, float minWidth, float maxWidth, alignment align) + : fWidth(width), + fMinWidth(minWidth), + fMaxWidth(maxWidth), + fVisible(true), + fList(0), + fShowHeading(true), + fAlignment(align) +{ +} + +BColumn::~BColumn() +{ +} + +float BColumn::Width() const +{ + return fWidth; +} + +void BColumn::SetWidth(float width) +{ + fWidth = width; +} + +float BColumn::MinWidth() const +{ + return fMinWidth; +} + +float BColumn::MaxWidth() const +{ + return fMaxWidth; +} + +void BColumn::DrawTitle(BRect, BView*) +{ +} + +void BColumn::DrawField(BField*, BRect, BView*) +{ +} + +int BColumn::CompareFields(BField *, BField *) +{ + return 0; +} + +void BColumn::GetColumnName(BString* into) const +{ + *into = "(Unnamed)"; +} + +bool BColumn::IsVisible() const +{ + return fVisible; +} + +void BColumn::SetVisible(bool visible) +{ + if (fList && (fVisible != visible)) + fList->SetColumnVisible(this, visible); +} + +bool BColumn::ShowHeading() const +{ + return fShowHeading; +} + +void BColumn::SetShowHeading(bool state) +{ + fShowHeading = state; +} + +alignment BColumn::Alignment() const +{ + return fAlignment; +} + +void BColumn::SetAlignment(alignment align) +{ + fAlignment = align; +} + +bool BColumn::WantsEvents() const +{ + return fWantsEvents; +} + +void BColumn::SetWantsEvents(bool state) +{ + fWantsEvents = state; +} + +int32 BColumn::LogicalFieldNum() const +{ + return fFieldID; +} + +bool +BColumn::AcceptsField(const BField*) const +{ + return true; +} + + +// #pragma mark - + +BColumnListView::BColumnListView(BRect rect, const char *name, uint32 resizingMode, + uint32 drawFlags, border_style border, bool showHorizontalScrollbar) + : BView(rect, name, resizingMode, drawFlags | B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE), + fStatusView(0), + fSelectionMessage(0), + fSortingEnabled(true), + fLatchWidth(kLatchWidth), + fBorderStyle(border) +{ + SetViewColor(B_TRANSPARENT_32_BIT); + + BRect bounds(rect); + bounds.OffsetTo(0, 0); + + for (int i = 0; i < (int)B_COLOR_TOTAL; i++) + fColorList[i] = kColor[i]; + + BRect titleRect(bounds); + titleRect.bottom = titleRect.top + kTitleHeight; +#if !LOWER_SCROLLBAR + titleRect.right -= B_V_SCROLL_BAR_WIDTH + 1; +#endif + + BRect outlineRect(bounds); + outlineRect.top = titleRect.bottom + 1.0; + outlineRect.right -= B_V_SCROLL_BAR_WIDTH + 1; + if(showHorizontalScrollbar) + outlineRect.bottom -= B_H_SCROLL_BAR_HEIGHT + 1; + + BRect vScrollBarRect(bounds); +#if LOWER_SCROLLBAR + vScrollBarRect.top += kTitleHeight; +#endif + + vScrollBarRect.left = vScrollBarRect.right - B_V_SCROLL_BAR_WIDTH; + if(showHorizontalScrollbar) + vScrollBarRect.bottom -= B_H_SCROLL_BAR_HEIGHT; + + BRect hScrollBarRect(bounds); + hScrollBarRect.top = hScrollBarRect.bottom - B_H_SCROLL_BAR_HEIGHT; + hScrollBarRect.right -= B_V_SCROLL_BAR_WIDTH; + + // Adjust stuff so the border will fit. + if (fBorderStyle == B_PLAIN_BORDER) { + titleRect.InsetBy(1, 0); + titleRect.top++; + outlineRect.InsetBy(1, 0); + outlineRect.bottom--; + + vScrollBarRect.OffsetBy(-1, 0); + vScrollBarRect.InsetBy(0, 1); + hScrollBarRect.OffsetBy(0, -1); + hScrollBarRect.InsetBy(1, 0); + } else if (fBorderStyle == B_FANCY_BORDER) { + titleRect.InsetBy(2, 0); + titleRect.top += 2; + outlineRect.InsetBy(2, 0); + outlineRect.bottom -= 2; + + vScrollBarRect.OffsetBy(-2, 0); + vScrollBarRect.InsetBy(0, 2); + hScrollBarRect.OffsetBy(0, -2); + hScrollBarRect.InsetBy(2, 0); + } + + fOutlineView = new OutlineView(outlineRect, &fColumns, &fSortColumns, this); + AddChild(fOutlineView); + fTitleView = new TitleView(titleRect, fOutlineView, &fColumns, &fSortColumns, this); + + AddChild(fTitleView); + fVerticalScrollBar = new BScrollBar(vScrollBarRect, "vertical_scroll_bar", + fOutlineView, 0.0, bounds.Height(), B_VERTICAL); + AddChild(fVerticalScrollBar); + fHorizontalScrollBar = new BScrollBar(hScrollBarRect, "horizontal_scroll_bar", + fTitleView, 0.0, bounds.Width(), B_HORIZONTAL); + AddChild(fHorizontalScrollBar); + if(!showHorizontalScrollbar) + fHorizontalScrollBar->Hide(); + fOutlineView->FixScrollBar(true); +} + +BColumnListView::~BColumnListView() +{ + while (true) { + BColumn *column = (BColumn*) fColumns.RemoveItem(0L); + if (column == 0) + break; + + delete column; + } +} + +bool BColumnListView::InitiateDrag(BPoint, bool) +{ + return false; +} + +void BColumnListView::MessageDropped(BMessage*, BPoint) +{ +} + +void BColumnListView::ExpandOrCollapse(BRow* Row, bool Open) +{ + fOutlineView->ExpandOrCollapse(Row, Open); +} + +status_t BColumnListView::Invoke(BMessage *message) +{ + if (message == 0) + message = Message(); + + return BInvoker::Invoke(message); +} + +void BColumnListView::ItemInvoked() +{ + Invoke(); +} + +void BColumnListView::SetInvocationMessage(BMessage *message) +{ + SetMessage(message); +} + +BMessage* BColumnListView::InvocationMessage() const +{ + return Message(); +} + +uint32 BColumnListView::InvocationCommand() const +{ + return Command(); +} + +BRow* BColumnListView::FocusRow() const +{ + return fOutlineView->FocusRow(); +} + +void BColumnListView::SetFocusRow(int32 Index, bool Select) +{ + SetFocusRow(RowAt(Index), Select); +} + +void BColumnListView::SetFocusRow(BRow* Row, bool Select) +{ + fOutlineView->SetFocusRow(Row, Select); +} + +void BColumnListView::SetMouseTrackingEnabled(bool Enabled) +{ + fOutlineView->SetMouseTrackingEnabled(Enabled); +} + +list_view_type BColumnListView::SelectionMode() const +{ + return fOutlineView->SelectionMode(); +} + +void BColumnListView::Deselect(BRow *row) +{ + fOutlineView->Deselect(row); +} + +void BColumnListView::AddToSelection(BRow *row) +{ + fOutlineView->AddToSelection(row); +} + +void BColumnListView::DeselectAll() +{ + fOutlineView->DeselectAll(); +} + +BRow* BColumnListView::CurrentSelection(BRow *lastSelected) const +{ + return fOutlineView->CurrentSelection(lastSelected); +} + +void BColumnListView::SelectionChanged() +{ + if (fSelectionMessage) + Invoke(fSelectionMessage); +} + +void BColumnListView::SetSelectionMessage(BMessage *message) +{ + if (fSelectionMessage == message) + return; + + delete fSelectionMessage; + fSelectionMessage = message; +} + +BMessage* BColumnListView::SelectionMessage() +{ + return fSelectionMessage; +} + +uint32 BColumnListView::SelectionCommand() const +{ + if (fSelectionMessage) + return fSelectionMessage->what; + + return 0; +} + +void BColumnListView::SetSelectionMode(list_view_type mode) +{ + fOutlineView->SetSelectionMode(mode); +} + +void BColumnListView::SetSortingEnabled(bool enabled) +{ + fSortingEnabled = enabled; + fSortColumns.MakeEmpty(); + fTitleView->Invalidate(); // Erase sort indicators +} + +bool BColumnListView::SortingEnabled() const +{ + return fSortingEnabled; +} + +void BColumnListView::SetSortColumn(BColumn *column, bool add, bool ascending) +{ + if (!SortingEnabled()) + return; + + if (!add) + fSortColumns.MakeEmpty(); + + if (!fSortColumns.HasItem(column)) + fSortColumns.AddItem(column); + + column->fSortAscending = ascending; + fTitleView->Invalidate(); + fOutlineView->StartSorting(); +} + +void BColumnListView::ClearSortColumns() +{ + fSortColumns.MakeEmpty(); + fTitleView->Invalidate(); // Erase sort indicators +} + +void BColumnListView::AddStatusView(BView *view) +{ + BRect bounds = Bounds(); + float width = view->Bounds().Width(); + if (width > bounds.Width() / 2) + width = bounds.Width() / 2; + + fStatusView = view; + + Window()->BeginViewTransaction(); + fHorizontalScrollBar->ResizeBy(-(width + 1), 0); + fHorizontalScrollBar->MoveBy((width + 1), 0); + AddChild(view); + + BRect viewRect(bounds); + viewRect.right = width; + viewRect.top = viewRect.bottom - B_H_SCROLL_BAR_HEIGHT; + if (fBorderStyle == B_PLAIN_BORDER) + viewRect.OffsetBy(1, -1); + else if (fBorderStyle == B_FANCY_BORDER) + viewRect.OffsetBy(2, -2); + + view->SetResizingMode(B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); + view->ResizeTo(viewRect.Width(), viewRect.Height()); + view->MoveTo(viewRect.left, viewRect.top); + Window()->EndViewTransaction(); +} + +BView* BColumnListView::RemoveStatusView() +{ + if (fStatusView) { + float width = fStatusView->Bounds().Width(); + Window()->BeginViewTransaction(); + fStatusView->RemoveSelf(); + fHorizontalScrollBar->MoveBy(-width, 0); + fHorizontalScrollBar->ResizeBy(width, 0); + Window()->EndViewTransaction(); + } + + BView *view = fStatusView; + fStatusView = 0; + return view; +} +void BColumnListView::AddColumn(BColumn *column, int32 logicalFieldIndex) +{ + ASSERT(column != 0); + + column->fList = this; + column->fFieldID = logicalFieldIndex; + + // sanity check. If there is already a field with this ID, remove it. + for (int32 index = 0; index < fColumns.CountItems(); index++) { + BColumn *existingColumn = (BColumn*) fColumns.ItemAt(index); + if (existingColumn && existingColumn->fFieldID == logicalFieldIndex) { + RemoveColumn(existingColumn); + break; + } + } + + if (column->Width() < column->MinWidth()) + column->SetWidth(column->MinWidth()); + else if (column->Width() > column->MaxWidth()) + column->SetWidth(column->MaxWidth()); + + fColumns.AddItem((void*) column); + fTitleView->ColumnAdded(column); +} + +void BColumnListView::MoveColumn(BColumn *column, int32 index) +{ + ASSERT(column != 0); + fTitleView->MoveColumn(column, index); +} + +void BColumnListView::RemoveColumn(BColumn *column) +{ + if (fColumns.HasItem(column)) { + SetColumnVisible(column, false); + Window()->UpdateIfNeeded(); + fColumns.RemoveItem(column); + } +} + +int32 BColumnListView::CountColumns() const +{ + return fColumns.CountItems(); +} + +BColumn* BColumnListView::ColumnAt(int32 field) const +{ + return (BColumn*) fColumns.ItemAt(field); +} + +void BColumnListView::SetColumnVisible(BColumn *column, bool visible) +{ + fTitleView->SetColumnVisible(column, visible); +} + +void BColumnListView::SetColumnVisible(int32 index, bool isVisible) +{ + BColumn *column = ColumnAt(index); + if (column) + column->SetVisible(isVisible); +} + +bool BColumnListView::IsColumnVisible(int32 index) const +{ + BColumn *column = ColumnAt(index); + if (column) + return column->IsVisible(); + + return false; +} + +void BColumnListView::SetColumnFlags(column_flags flags) +{ + fTitleView->SetColumnFlags(flags); +} + +const BRow* BColumnListView::RowAt(int32 Index, BRow* ParentRow) const +{ + if (ParentRow == 0) + return fOutlineView->RowList()->ItemAt(Index); + + return ParentRow->fChildList ? ParentRow->fChildList->ItemAt(Index) : NULL; +} + +BRow* BColumnListView::RowAt(int32 Index, BRow* ParentRow) +{ + if (ParentRow == 0) + return fOutlineView->RowList()->ItemAt(Index); + + return ParentRow->fChildList ? ParentRow->fChildList->ItemAt(Index) : 0; +} + +const BRow* BColumnListView::RowAt(BPoint point) const +{ + float top; + int32 indent; + return fOutlineView->FindRow(point.y, &indent, &top); +} + +BRow* BColumnListView::RowAt(BPoint point) +{ + float top; + int32 indent; + return fOutlineView->FindRow(point.y, &indent, &top); +} + +bool BColumnListView::GetRowRect(const BRow *row, BRect *outRect) const +{ + return fOutlineView->FindRect(row, outRect); +} + +bool BColumnListView::FindParent(BRow *row, BRow **out_parent, bool *out_isVisible) const +{ + return fOutlineView->FindParent(row, out_parent, out_isVisible); +} + +int32 BColumnListView::IndexOf(BRow *row) +{ + return fOutlineView->IndexOf(row); +} + +int32 BColumnListView::CountRows(BRow* ParentRow) const +{ + if (ParentRow == 0) + return fOutlineView->RowList()->CountItems(); + if (ParentRow->fChildList) + return ParentRow->fChildList->CountItems(); + else + return 0; +} + +void BColumnListView::AddRow(BRow *row, BRow* ParentRow) +{ + AddRow(row, -1, ParentRow); +} + +void BColumnListView::AddRow(BRow *row, int32 index, BRow* ParentRow) +{ + row->fChildList = 0; + row->fList = this; + row->ValidateFields(); + fOutlineView->AddRow(row, index, ParentRow); +} + +void BColumnListView::RemoveRow(BRow *row) +{ + fOutlineView->RemoveRow(row); + row->fList = NULL; +} + +void BColumnListView::UpdateRow(BRow *row) +{ + fOutlineView->UpdateRow(row); +} + +void BColumnListView::ScrollTo(const BRow* Row) +{ + fOutlineView->ScrollTo(Row); +} + +void BColumnListView::Clear() +{ + fOutlineView->Clear(); +} + +void BColumnListView::SetFont(const BFont *font, uint32 mask) +{ + // This method is deprecated. + fOutlineView->SetFont(font, mask); + fTitleView->SetFont(font, mask); +} + +void BColumnListView::SetFont(ColumnListViewFont font_num, const BFont* font, uint32 mask) +{ + switch (font_num) { + case B_FONT_ROW: + fOutlineView->SetFont(font, mask); + break; + + case B_FONT_HEADER: + fTitleView->SetFont(font, mask); + break; + + default: + ASSERT(false); + break; + }; +} + +void BColumnListView::GetFont(ColumnListViewFont font_num, BFont* font) const +{ + switch (font_num) { + case B_FONT_ROW: + fOutlineView->GetFont(font); + break; + + case B_FONT_HEADER: + fTitleView->GetFont(font); + break; + + default: + ASSERT(false); + break; + }; +} + +void BColumnListView::SetColor(ColumnListViewColor color_num, const rgb_color color) +{ + if ((int)color_num < 0) + { + ASSERT(false); + color_num = (ColumnListViewColor) 0; + } + + if ((int)color_num >= (int)B_COLOR_TOTAL) + { + ASSERT(false); + color_num = (ColumnListViewColor) (B_COLOR_TOTAL - 1); + } + + fColorList[color_num] = color; +} + +rgb_color BColumnListView::Color(ColumnListViewColor color_num) const +{ + if ((int)color_num < 0) + { + ASSERT(false); + color_num = (ColumnListViewColor) 0; + } + + if ((int)color_num >= (int)B_COLOR_TOTAL) + { + ASSERT(false); + color_num = (ColumnListViewColor) (B_COLOR_TOTAL - 1); + } + + return fColorList[color_num]; +} + +void BColumnListView::SetHighColor(rgb_color color) +{ + BView::SetHighColor(color); +// fOutlineView->Invalidate(); // Redraw things with the new color + // Note that this will currently cause + // an infinite loop, refreshing over and over. + // A better solution is needed. +} + +void BColumnListView::SetSelectionColor(rgb_color color) +{ + fColorList[B_COLOR_SELECTION] = color; +} + +void BColumnListView::SetBackgroundColor(rgb_color color) +{ + fColorList[B_COLOR_BACKGROUND] = color; + fOutlineView->Invalidate(); // Repaint with new color +} + +void BColumnListView::SetEditColor(rgb_color color) +{ + fColorList[B_COLOR_EDIT_BACKGROUND] = color; +} + +const rgb_color BColumnListView::SelectionColor() const +{ + return fColorList[B_COLOR_SELECTION]; +} + +const rgb_color BColumnListView::BackgroundColor() const +{ + return fColorList[B_COLOR_BACKGROUND]; +} + +const rgb_color BColumnListView::EditColor() const +{ + return fColorList[B_COLOR_EDIT_BACKGROUND]; +} + +BPoint BColumnListView::SuggestTextPosition(const BRow* row, const BColumn* inColumn) const +{ + BRect rect; + GetRowRect(row, &rect); + if (inColumn) { + float leftEdge = MAX(kLeftMargin, LatchWidth()); + for (int index = 0; index < fColumns.CountItems(); index++) { + BColumn *column = (BColumn*) fColumns.ItemAt(index); + if (!column->IsVisible()) + continue; + + if (column == inColumn) { + rect.left = leftEdge; + rect.right = rect.left + column->Width(); + break; + } + + leftEdge += column->Width() + 1; + } + } + + font_height fh; + fOutlineView->GetFontHeight(&fh); + float baseline = floor(rect.top + fh.ascent + + (rect.Height()+1-(fh.ascent+fh.descent))/2); + return BPoint(rect.left + 8, baseline); +} + +void BColumnListView::SetLatchWidth(float width) +{ + fLatchWidth = width; + Invalidate(); +} + +float BColumnListView::LatchWidth() const +{ + return fLatchWidth; +} + +void BColumnListView::DrawLatch(BView *view, BRect rect, LatchType position, BRow *) +{ + const int32 rectInset = 4; + + view->SetHighColor(0, 0, 0); + + // Make Square + int32 sideLen = rect.IntegerWidth(); + if( sideLen > rect.IntegerHeight() ) + { + sideLen = rect.IntegerHeight(); + } + + // Make Center + int32 halfWidth = rect.IntegerWidth() / 2; + int32 halfHeight = rect.IntegerHeight() / 2; + int32 halfSide = sideLen / 2; + + float left = rect.left + halfWidth - halfSide; + float top = rect.top + halfHeight - halfSide; + + BRect itemRect(left, top, left + sideLen, top + sideLen); + + // Why it is a pixel high? I don't know. + itemRect.OffsetBy(0, -1); + + itemRect.InsetBy(rectInset, rectInset); + + // Make it an odd number of pixels wide, the latch looks better this way + if (1 == (itemRect.IntegerWidth() % 2)) + { + itemRect.right += 1; + itemRect.bottom += 1; + } + + switch (position) { + case B_OPEN_LATCH: + view->StrokeRect(itemRect); + view->StrokeLine(BPoint(itemRect.left + 2, (itemRect.top + itemRect.bottom) / 2), + BPoint(itemRect.right - 2, (itemRect.top + itemRect.bottom) / 2)); + break; + + case B_PRESSED_LATCH: + view->StrokeRect(itemRect); + view->StrokeLine(BPoint(itemRect.left + 2, (itemRect.top + itemRect.bottom) / 2), + BPoint(itemRect.right - 2, (itemRect.top + itemRect.bottom) / 2)); + view->StrokeLine(BPoint((itemRect.left + itemRect.right) / 2, itemRect.top + 2), + BPoint((itemRect.left + itemRect.right) / 2, itemRect.bottom - 2)); + view->InvertRect(itemRect); + break; + + case B_CLOSED_LATCH: + view->StrokeRect(itemRect); + view->StrokeLine(BPoint(itemRect.left + 2, (itemRect.top + itemRect.bottom) / 2), + BPoint(itemRect.right - 2, (itemRect.top + itemRect.bottom) / 2)); + view->StrokeLine(BPoint((itemRect.left + itemRect.right) / 2, itemRect.top + 2), + BPoint((itemRect.left + itemRect.right) / 2, itemRect.bottom - 2)); + break; + + case B_NO_LATCH: + // No drawing + break; + } +} + +void BColumnListView::MakeFocus(bool isFocus) +{ + Invalidate(); // Redraw focus marks around view + BView::MakeFocus(isFocus); +} + +void BColumnListView::MessageReceived(BMessage *message) +{ + // Propagate mouse wheel messages down to child, so that it can + // scroll. Note we have done so, so we don't go into infinite + // recursion if this comes back up here. + if (message->what == B_MOUSE_WHEEL_CHANGED) { + bool handled; + if (message->FindBool("be:clvhandled", &handled) != B_OK) { + message->AddBool("be:clvhandled", true); + fOutlineView->MessageReceived(message); + return; + } + } + BView::MessageReceived(message); +} + +void BColumnListView::KeyDown(const char *bytes, int32 numBytes) +{ + char c = bytes[0]; + switch (c) { + case B_RIGHT_ARROW: + case B_LEFT_ARROW: { + float minVal, maxVal; + fHorizontalScrollBar->GetRange(&minVal, &maxVal); + float smallStep, largeStep; + fHorizontalScrollBar->GetSteps(&smallStep, &largeStep); + float oldVal = fHorizontalScrollBar->Value(); + float newVal = oldVal; + + if (c == B_LEFT_ARROW) + newVal -= smallStep; + else if (c == B_RIGHT_ARROW) + newVal += smallStep; + + if (newVal < minVal) + newVal = minVal; + else if (newVal > maxVal) + newVal = maxVal; + + fHorizontalScrollBar->SetValue(newVal); + break; + } + + case B_DOWN_ARROW: + fOutlineView->ChangeFocusRow(false, (modifiers() & B_CONTROL_KEY) == 0, + (modifiers() & B_SHIFT_KEY) != 0); + break; + + case B_UP_ARROW: + fOutlineView->ChangeFocusRow(true, (modifiers() & B_CONTROL_KEY) == 0, + (modifiers() & B_SHIFT_KEY) != 0); + break; + + case B_PAGE_UP: + case B_PAGE_DOWN: { + float minValue, maxValue; + fVerticalScrollBar->GetRange(&minValue, &maxValue); + float smallStep, largeStep; + fVerticalScrollBar->GetSteps(&smallStep, &largeStep); + float currentValue = fVerticalScrollBar->Value(); + float newValue = currentValue; + + if (c == B_PAGE_UP) + newValue -= largeStep; + else + newValue += largeStep; + + if (newValue > maxValue) + newValue = maxValue; + else if (newValue < minValue) + newValue = minValue; + + fVerticalScrollBar->SetValue(newValue); + + // Option + pgup or pgdn scrolls and changes the selection. + if (modifiers() & B_OPTION_KEY) + fOutlineView->MoveFocusToVisibleRect(); + + break; + } + + case B_ENTER: + Invoke(); + break; + + case B_SPACE: + fOutlineView->ToggleFocusRowSelection((modifiers() & B_SHIFT_KEY) != 0); + break; + + case '+': + case '-': + fOutlineView->ToggleFocusRowOpen(); + break; + + default: + BView::KeyDown(bytes, numBytes); + } +} + +void BColumnListView::AttachedToWindow() +{ + if (!Messenger().IsValid()) + SetTarget(Window()); + + if (SortingEnabled()) fOutlineView->StartSorting(); +} + +void BColumnListView::WindowActivated(bool active) +{ + fOutlineView->Invalidate(); + // Focus and selection appearance changes with focus + + Invalidate(); // Redraw focus marks around view + BView::WindowActivated(active); +} + +void BColumnListView::Draw(BRect) +{ + BRect rect = Bounds(); + PushState(); + + BRect cornerRect(rect.right - B_V_SCROLL_BAR_WIDTH, rect.bottom - B_H_SCROLL_BAR_HEIGHT, + rect.right, rect.bottom); + if (fBorderStyle == B_PLAIN_BORDER) { + BView::SetHighColor(0, 0, 0); + StrokeRect(rect); + cornerRect.OffsetBy(-1, -1); + } else if (fBorderStyle == B_FANCY_BORDER) { + bool isFocus = IsFocus() && Window()->IsActive(); + + if (isFocus) + BView::SetHighColor(0, 0, 190); // Need to find focus color programatically + else + BView::SetHighColor(255, 255, 255); + + StrokeRect(rect); + if (!isFocus) + BView::SetHighColor(184, 184, 184); + else + BView::SetHighColor(152, 152, 152); + + rect.InsetBy(1,1); + StrokeRect(rect); + cornerRect.OffsetBy(-2, -2); + } + + BView::SetHighColor(215, 215, 215); // fills lower right rect between scroll bars + FillRect(cornerRect); + PopState(); +} + +void BColumnListView::SaveState(BMessage *msg) +{ + msg->MakeEmpty(); + + // Damn compiler issuing l43m incorrect warnings. + int i; + for (i = 0; ;i++) + { + BColumn *col = (BColumn*) fColumns.ItemAt(i); + if(!col) + break; + msg->AddInt32("ID",col->fFieldID); + msg->AddFloat("width",col->fWidth); + msg->AddBool("visible",col->fVisible); + } + + msg->AddBool("sortingenabled",fSortingEnabled); + + if(fSortingEnabled) + { + for (i = 0; ;i++) + { + BColumn *col = (BColumn*) fSortColumns.ItemAt(i); + if(!col) + break; + msg->AddInt32("sortID",col->fFieldID); + msg->AddBool("sortascending",col->fSortAscending); + } + } +} + +void BColumnListView::LoadState(BMessage *msg) +{ + for(int i=0;;i++) + { + int32 ID; + if(B_OK!=msg->FindInt32("ID",i,&ID)) + break; + for(int j=0;;j++) + { + BColumn *col = (BColumn*) fColumns.ItemAt(j); + if(!col) + break; + if(col->fFieldID==ID) + { + // move this column to position 'i' and set its attributes + MoveColumn(col,i); + float f; + if(B_OK==msg->FindFloat("width",i,&f)) + col->SetWidth(f); + bool b; + if(B_OK==msg->FindBool("visible",i,&b)) + col->SetVisible(b); + } + } + } + bool b; + if(B_OK==msg->FindBool("sortingenabled",&b)) + { + SetSortingEnabled(b); + // Damn compiler issuing l43m incorrect warnings. + for(int k=0;;k++) + { + int32 ID; + if(B_OK!=msg->FindInt32("sortID", k, &ID)) + break; + for(int j=0;;j++) + { + BColumn *col = (BColumn*) fColumns.ItemAt(j); + if(!col) + break; + if(col->fFieldID==ID) + { + // add this column to the sort list + bool val; + if(B_OK==msg->FindBool("sortascending", k, &val)) + SetSortColumn(col, true, val); + } + } + } + } +} + +void BColumnListView::SetEditMode(bool state) +{ + fOutlineView->SetEditMode(state); + fTitleView->SetEditMode(state); +} + +void BColumnListView::Refresh() +{ + if(LockLooper()) + { + Invalidate(); + fOutlineView->FixScrollBar (true); + fOutlineView->Invalidate(); + Window()->UpdateIfNeeded(); + UnlockLooper(); + } +} + +// #pragma mark - + + +TitleView::TitleView(BRect rect, OutlineView *horizontalSlave, BList *visibleColumns, + BList *sortColumns, BColumnListView *listView) + : BView(rect, "title_view", B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW | B_FRAME_EVENTS), + fOutlineView(horizontalSlave), + fColumns(visibleColumns), + fSortColumns(sortColumns), + fColumnsWidth(0), + fVisibleRect(rect.OffsetToCopy(0, 0)), + fCurrentState(INACTIVE), + fColumnPop(NULL), + fMasterView(listView), + fEditMode(false), + fColumnFlags(B_ALLOW_COLUMN_MOVE|B_ALLOW_COLUMN_RESIZE|B_ALLOW_COLUMN_POPUP|B_ALLOW_COLUMN_REMOVE) +{ + SetViewColor(B_TRANSPARENT_32_BIT); + +#if DOUBLE_BUFFERED_COLUMN_RESIZE + // xxx this needs to be smart about the size of the backbuffer. + BRect doubleBufferRect(0, 0, 600, 35); + fDrawBuffer = new BBitmap(doubleBufferRect, B_RGB32, true); + fDrawBufferView = new BView(doubleBufferRect, "double_buffer_view", + B_FOLLOW_ALL_SIDES, 0); + fDrawBuffer->Lock(); + fDrawBuffer->AddChild(fDrawBufferView); + fDrawBuffer->Unlock(); +#endif + + fUpSortArrow = new BBitmap(BRect(0, 0, 7, 7), B_COLOR_8_BIT); + fDownSortArrow = new BBitmap(BRect(0, 0, 7, 7), B_COLOR_8_BIT); + + fUpSortArrow->SetBits((const void*) kUpSortArrow8x8, 64, 0, B_COLOR_8_BIT); + fDownSortArrow->SetBits((const void*) kDownSortArrow8x8, 64, 0, B_COLOR_8_BIT); + +#if _INCLUDES_CLASS_CURSOR + fResizeCursor = new BCursor(kResizeCursorData); + fMinResizeCursor = new BCursor(kMinResizeCursorData); + fMaxResizeCursor = new BCursor(kMaxResizeCursorData); + fColumnMoveCursor = new BCursor(kColumnMoveCursorData); +#endif + FixScrollBar(true); +} + +TitleView::~TitleView() +{ + delete fColumnPop; + fColumnPop = NULL; + + fDrawBuffer->Lock(); + fDrawBufferView->RemoveSelf(); + fDrawBuffer->Unlock(); + delete fDrawBufferView; + delete fDrawBuffer; + delete fUpSortArrow; + delete fDownSortArrow; + +#if _INCLUDES_CLASS_CURSOR + delete fResizeCursor; + delete fMaxResizeCursor; + delete fMinResizeCursor; + delete fColumnMoveCursor; +#endif +} + +void TitleView::ColumnAdded(BColumn *column) +{ + fColumnsWidth += column->Width() + 1; + FixScrollBar(false); + Invalidate(); +} +// Could use a CopyBits here. +void TitleView::SetColumnVisible(BColumn *column, bool visible) +{ + if (column->fVisible == visible) + return; + + // If setting it visible, do this first so we can find its position + // to invalidate. If hiding it, do it last. + if (visible) + column->fVisible = visible; + + BRect titleInvalid; + GetTitleRect(column, &titleInvalid); + + // Now really set the visibility + column->fVisible = visible; + + if (visible) + fColumnsWidth += column->Width(); + else + fColumnsWidth -= column->Width(); + + BRect outlineInvalid(fOutlineView->VisibleRect()); + outlineInvalid.left = titleInvalid.left; + titleInvalid.right = outlineInvalid.right; + + Invalidate(titleInvalid); + fOutlineView->Invalidate(outlineInvalid); +} + +void TitleView::GetTitleRect(BColumn *findColumn, BRect *out_rect) +{ + float leftEdge = MAX(kLeftMargin, fMasterView->LatchWidth()); + int32 numColumns = fColumns->CountItems(); + for (int index = 0; index < numColumns; index++) { + BColumn *column = (BColumn*) fColumns->ItemAt(index); + if (!column->IsVisible()) + continue; + + if (column == findColumn) { + out_rect->Set(leftEdge, 0, leftEdge + column->Width(), fVisibleRect.bottom); + return; + } + + leftEdge += column->Width() + 1; + } + + TRESPASS(); +} + +int32 TitleView::FindColumn(BPoint position, float *out_leftEdge) +{ + float leftEdge = MAX(kLeftMargin, fMasterView->LatchWidth()); + int32 numColumns = fColumns->CountItems(); + for (int index = 0; index < numColumns; index++) { + BColumn *column = (BColumn*) fColumns->ItemAt(index); + if (!column->IsVisible()) + continue; + + if (leftEdge > position.x) + break; + + if (position.x >= leftEdge && position.x <= leftEdge + column->Width()) { + *out_leftEdge = leftEdge; + return index; + } + + leftEdge += column->Width() + 1; + } + + return 0; +} + +void TitleView::FixScrollBar(bool scrollToFit) +{ + BScrollBar *hScrollBar = ScrollBar(B_HORIZONTAL); + if (hScrollBar) { + float virtualWidth = fColumnsWidth + MAX(kLeftMargin, fMasterView->LatchWidth()) + + kRightMargin * 2; + + if (virtualWidth > fVisibleRect.Width()) { + hScrollBar->SetProportion(fVisibleRect.Width() / virtualWidth); + + // Perform the little trick if the user is scrolled over too far. + // See OutlineView::FixScrollBar for a more in depth explanation + float maxScrollBarValue = virtualWidth - fVisibleRect.Width(); + if (scrollToFit || hScrollBar->Value() <= maxScrollBarValue) { + hScrollBar->SetRange(0.0, maxScrollBarValue); + hScrollBar->SetSteps(50, fVisibleRect.Width()); + } + } else if (hScrollBar->Value() == 0.0) + hScrollBar->SetRange(0.0, 0.0); // disable scroll bar. + } +} + +void TitleView::DragSelectedColumn(BPoint position) +{ + float invalidLeft = fSelectedColumnRect.left; + float invalidRight = fSelectedColumnRect.right; + + float leftEdge; + int32 columnIndex = FindColumn(position, &leftEdge); + fSelectedColumnRect.OffsetTo(leftEdge, 0); + + MoveColumn(fSelectedColumn, columnIndex); + + fSelectedColumn->fVisible = true; + ComputeDragBoundries(fSelectedColumn, position); + + // Redraw the new column position + GetTitleRect(fSelectedColumn, &fSelectedColumnRect); + invalidLeft = MIN(fSelectedColumnRect.left, invalidLeft); + invalidRight = MAX(fSelectedColumnRect.right, invalidRight); + + Invalidate(BRect(invalidLeft, 0, invalidRight, fVisibleRect.bottom)); + fOutlineView->Invalidate(BRect(invalidLeft, 0, invalidRight, + fOutlineView->VisibleRect().bottom)); + + DrawTitle(this, fSelectedColumnRect, fSelectedColumn, true); +} + +void TitleView::MoveColumn(BColumn *column, int32 index) +{ + fColumns->RemoveItem((void*) column); + + if (-1 == index) + { + // Re-add the column at the end of the list. + fColumns->AddItem((void*) column); + } + else + { + fColumns->AddItem((void*) column, index); + } +} + +void TitleView::SetColumnFlags(column_flags flags) +{ + fColumnFlags = flags; +} + + +void TitleView::ResizeSelectedColumn(BPoint position) +{ + float minWidth = fSelectedColumn->MinWidth(); + float maxWidth = fSelectedColumn->MaxWidth(); + + float originalEdge = fSelectedColumnRect.left + fSelectedColumn->Width(); + if (position.x > fSelectedColumnRect.left + maxWidth) + fSelectedColumn->SetWidth(maxWidth); + else if (position.x < fSelectedColumnRect.left + minWidth) + fSelectedColumn->SetWidth(minWidth); + else + fSelectedColumn->SetWidth(position.x - fSelectedColumnRect.left - 1); + + float dX = fSelectedColumnRect.left + fSelectedColumn->Width() - originalEdge; + if (dX != 0) { + BRect originalRect(originalEdge, 0, 1000000.0, fVisibleRect.Height()); + BRect movedRect(originalRect); + movedRect.OffsetBy(dX, 0); + + // Update the size of the title column + BRect sourceRect(0, 0, fSelectedColumn->Width(), fVisibleRect.Height()); + BRect destRect(sourceRect); + destRect.OffsetBy(fSelectedColumnRect.left, 0); + +#if DOUBLE_BUFFERED_COLUMN_RESIZE + fDrawBuffer->Lock(); + fDrawBufferView->SetHighColor(fMasterView->Color(B_COLOR_HEADER_BACKGROUND)); + fDrawBufferView->FillRect(sourceRect); + DrawTitle(fDrawBufferView, sourceRect, fSelectedColumn, false); + fDrawBufferView->Sync(); + fDrawBuffer->Unlock(); + + CopyBits(originalRect, movedRect); + DrawBitmap(fDrawBuffer, sourceRect, destRect); +#else + CopyBits(originalRect, movedRect); + SetHighColor(fMasterView->Color(B_COLOR_HEADER_BACKGROUND)); + FillRect(destRect); + DrawTitle(this, destRect, fSelectedColumn, false); +#endif + + // Update the body view + BRect slaveSize = fOutlineView->VisibleRect(); + BRect slaveSource(originalRect); + slaveSource.bottom = slaveSize.bottom; + BRect slaveDest(movedRect); + slaveDest.bottom = slaveSize.bottom; + fOutlineView->CopyBits(slaveSource, slaveDest); + fOutlineView->RedrawColumn(fSelectedColumn, fSelectedColumnRect.left, + fResizingFirstColumn); + + fColumnsWidth += dX; + + // Update the cursor +#if _INCLUDES_CLASS_CURSOR + if (fSelectedColumn->Width() == minWidth) + SetViewCursor(fMinResizeCursor, false); + else if (fSelectedColumn->Width() == maxWidth) + SetViewCursor(fMaxResizeCursor, false); + else + SetViewCursor(fResizeCursor, false); +#endif + } +} + +void TitleView::ComputeDragBoundries(BColumn *findColumn, BPoint ) +{ + float previousColumnLeftEdge = -1000000.0; + float nextColumnRightEdge = 1000000.0; + + bool foundColumn = false; + float leftEdge = MAX(kLeftMargin, fMasterView->LatchWidth()); + int32 numColumns = fColumns->CountItems(); + for (int index = 0; index < numColumns; index++) { + BColumn *column = (BColumn*) fColumns->ItemAt(index); + if (!column->IsVisible()) + continue; + + if (column == findColumn) { + foundColumn = true; + continue; + } + + if (foundColumn) { + nextColumnRightEdge = leftEdge + column->Width(); + break; + } else + previousColumnLeftEdge = leftEdge; + + leftEdge += column->Width() + 1; + } + + float rightEdge = leftEdge + findColumn->Width(); + + fLeftDragBoundry = MIN(previousColumnLeftEdge + findColumn->Width(), leftEdge); + fRightDragBoundry = MAX(nextColumnRightEdge, rightEdge); +} + +void TitleView::DrawTitle(BView *view, BRect rect, BColumn *column, bool depressed) +{ + BRect drawRect; + rgb_color borderColor = mix_color(fMasterView->Color(B_COLOR_HEADER_BACKGROUND), make_color(0, 0, 0, 255), 128); + rgb_color backgroundColor; + + rgb_color bevelHigh; + rgb_color bevelLow; + // Want exterior borders to overlap. + rect.right += 1; + drawRect = rect; + drawRect.InsetBy(2, 2); + if (depressed) { + backgroundColor = mix_color(fMasterView->Color(B_COLOR_HEADER_BACKGROUND), make_color(0, 0, 0), 64); + bevelHigh = mix_color(backgroundColor, make_color(0, 0, 0), 64); + bevelLow = mix_color(backgroundColor, make_color(255, 255, 255), 128); + drawRect.left++; + drawRect.top++; + } else { + backgroundColor = fMasterView->Color(B_COLOR_HEADER_BACKGROUND); + bevelHigh = mix_color(backgroundColor, make_color(255, 255, 255), 192); + bevelLow = mix_color(backgroundColor, make_color(0, 0, 0), 64); + drawRect.bottom--; + drawRect.right--; + } + + view->SetHighColor(borderColor); + view->StrokeRect(rect); + view->BeginLineArray(4); + view->AddLine(BPoint(rect.left+1, rect.top+1), BPoint(rect.right-1, rect.top+1), bevelHigh); + view->AddLine(BPoint(rect.left+1, rect.top+1), BPoint(rect.left+1, rect.bottom-1), bevelHigh); + view->AddLine(BPoint(rect.right-1, rect.top+1), BPoint(rect.right-1, rect.bottom-1), bevelLow); + view->AddLine(BPoint(rect.left+2, rect.bottom-1), BPoint(rect.right-1, rect.bottom-1), bevelLow); + view->EndLineArray(); + + font_height fh; + GetFontHeight(&fh); + + float baseline = floor(drawRect.top + fh.ascent + + (drawRect.Height()+1-(fh.ascent+fh.descent))/2); + + view->SetHighColor(backgroundColor); + view->SetLowColor(backgroundColor); + + view->FillRect(rect.InsetByCopy(2, 2)); + + + // If no column given, nothing else to draw. + if (!column) + return; + + view->SetHighColor(fMasterView->Color(B_COLOR_HEADER_TEXT)); + + BFont font; + GetFont(&font); + view->SetFont(&font); + + int sortIndex = fSortColumns->IndexOf(column); + if (sortIndex >= 0) { + // Draw sort notation. + BPoint upperLeft(drawRect.right-kSortIndicatorWidth, baseline); + +// if (fSortColumns->CountItems() > 1) { +// char str[256]; +// sprintf(str, "%d", sortIndex + 1); +// const float w = view->StringWidth(str); +// upperLeft.x -= w; +// +// view->SetDrawingMode(B_OP_COPY); +// view->MovePenTo(BPoint(upperLeft.x + kSortIndicatorWidth, baseline)); +// view->DrawString(str); +// } + + float bmh = fDownSortArrow->Bounds().Height()+1; + + view->SetDrawingMode(B_OP_OVER); + + if (column->fSortAscending) { + BPoint leftTop(upperLeft.x, drawRect.top + (drawRect.IntegerHeight()-fDownSortArrow->Bounds().IntegerHeight())/2); + view->DrawBitmapAsync(fDownSortArrow, leftTop); + } else { + BPoint leftTop(upperLeft.x, drawRect.top + (drawRect.IntegerHeight()-fUpSortArrow->Bounds().IntegerHeight())/2); + view->DrawBitmapAsync(fUpSortArrow, leftTop); + } + + upperLeft.y = baseline-bmh+floor((fh.ascent+fh.descent-bmh)/2); + if (upperLeft.y < drawRect.top) upperLeft.y = drawRect.top; + + // Adjust title stuff for sort indicator + drawRect.right = upperLeft.x - 2; + } + + if (drawRect.right > drawRect.left) { +#if CONSTRAIN_CLIPPING_REGION + BRegion clipRegion; + clipRegion.Set(drawRect); + view->ConstrainClippingRegion(&clipRegion); + view->PushState(); +#endif + view->MovePenTo(BPoint(drawRect.left+8, baseline)); + view->SetDrawingMode(B_OP_COPY); + view->SetHighColor(fMasterView->Color(B_COLOR_HEADER_TEXT)); + column->DrawTitle(drawRect, view); + +#if CONSTRAIN_CLIPPING_REGION + view->PopState(); + view->ConstrainClippingRegion(NULL); +#endif + } +} + +void TitleView::Draw(BRect invalidRect) +{ + float columnLeftEdge = MAX(kLeftMargin, fMasterView->LatchWidth()); + for (int32 columnIndex = 0; columnIndex < fColumns->CountItems(); columnIndex++) { + BColumn *column = (BColumn*) fColumns->ItemAt(columnIndex); + if (!column->IsVisible()) + continue; + + if (columnLeftEdge > invalidRect.right) + break; + + if (columnLeftEdge + column->Width() >= invalidRect.left) { + BRect titleRect(columnLeftEdge, 0, + columnLeftEdge + column->Width(), fVisibleRect.Height()); + DrawTitle(this, titleRect, column, + (fCurrentState == DRAG_COLUMN_INSIDE_TITLE && fSelectedColumn == column)); + } + + columnLeftEdge += column->Width() + 1; + } + + + // Bevels for right title margin + if (columnLeftEdge <= invalidRect.right) { + BRect titleRect(columnLeftEdge, 0, Bounds().right+2, fVisibleRect.Height()); + DrawTitle(this, titleRect, NULL, false); + } + + // Bevels for left title margin + if (invalidRect.left < MAX(kLeftMargin, fMasterView->LatchWidth())) { + BRect titleRect(0, 0, MAX(kLeftMargin, fMasterView->LatchWidth()) - 1, fVisibleRect.Height()); + DrawTitle(this, titleRect, NULL, false); + } + +#if DRAG_TITLE_OUTLINE + // (Internal) Column Drag Indicator + if (fCurrentState == DRAG_COLUMN_INSIDE_TITLE) { + BRect dragRect(fSelectedColumnRect); + dragRect.OffsetTo(fCurrentDragPosition.x - fClickPoint.x, 0); + if (dragRect.Intersects(invalidRect)) { + SetHighColor(0, 0, 255); + StrokeRect(dragRect); + } + } +#endif +} + +void TitleView::ScrollTo(BPoint position) +{ + fOutlineView->ScrollBy(position.x - fVisibleRect.left, 0); + fVisibleRect.OffsetTo(position.x, position.y); + + // Perform the little trick if the user is scrolled over too far. + // See OutlineView::ScrollTo for a more in depth explanation + float maxScrollBarValue = fColumnsWidth + MAX(kLeftMargin, fMasterView->LatchWidth()) + + kRightMargin * 2 - fVisibleRect.Width(); + BScrollBar *hScrollBar = ScrollBar(B_HORIZONTAL); + float min, max; + hScrollBar->GetRange(&min, &max); + if (max != maxScrollBarValue && position.x > maxScrollBarValue) + FixScrollBar(true); + + _inherited::ScrollTo(position); +} + +void TitleView::MessageReceived(BMessage *message) +{ + if (message->what == kToggleColumn) { + int32 num; + if (message->FindInt32("be:field_num", &num) == B_OK) { + for (int index = 0; index < fColumns->CountItems(); index++) { + BColumn *column = (BColumn*) fColumns->ItemAt(index); + if (!column) continue; + if (column->LogicalFieldNum() == num) { + column->SetVisible(!column->IsVisible()); + FixScrollBar(false); + } + } + } + return; + } else { + BView::MessageReceived(message); + } +} + +void TitleView::MouseDown(BPoint position) +{ + if(fEditMode) + return; + + int32 buttons=1; + Window()->CurrentMessage()->FindInt32("buttons", &buttons); + if (buttons == B_SECONDARY_MOUSE_BUTTON && (fColumnFlags & B_ALLOW_COLUMN_POPUP)) { + // Right mouse button -- bring up menu to show/hide columns. + if (!fColumnPop) fColumnPop = new BPopUpMenu("Columns", false, false); + fColumnPop->RemoveItems(0, fColumnPop->CountItems(), true); + BMessenger me(this); + for (int index = 0; index < fColumns->CountItems(); index++) { + BColumn *column = (BColumn*) fColumns->ItemAt(index); + if (!column) continue; + if (column->ShowHeading() == false) continue; + BString name; + column->GetColumnName(&name); + BMessage* msg = new BMessage(kToggleColumn); + msg->AddInt32("be:field_num", column->LogicalFieldNum()); + BMenuItem* it = new BMenuItem(name.String(), msg); + it->SetMarked(column->IsVisible()); + it->SetTarget(me); + fColumnPop->AddItem(it); + } + BPoint screenPosition = ConvertToScreen(position); + BRect sticky(screenPosition, screenPosition); + sticky.InsetBy(-5, -5); + fColumnPop->Go(ConvertToScreen(position), true, false, sticky, true); + return; + } + + fResizingFirstColumn = true; + float leftEdge = MAX(kLeftMargin, fMasterView->LatchWidth()); + for (int index = 0; index < fColumns->CountItems(); index++) { + BColumn *column = (BColumn*) fColumns->ItemAt(index); + if (!column->IsVisible()) + continue; + + if (leftEdge > position.x + kColumnResizeAreaWidth / 2) + break; + + // Check for resizing a column + float rightEdge = leftEdge + column->Width(); + + if(column->ShowHeading()) { + if (position.x > rightEdge - kColumnResizeAreaWidth / 2 + && position.x < rightEdge + kColumnResizeAreaWidth / 2 + && column->MaxWidth() > column->MinWidth() + && (fColumnFlags & B_ALLOW_COLUMN_RESIZE)) { + fCurrentState = RESIZING_COLUMN; + fSelectedColumn = column; + fSelectedColumnRect.Set(leftEdge, 0, rightEdge, fVisibleRect.Height()); + SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS | + B_NO_POINTER_HISTORY); + break; + } + + fResizingFirstColumn = false; + + // Check for clicking on a column. + if (position.x > leftEdge && position.x < rightEdge) { + fCurrentState = PRESSING_COLUMN; + fSelectedColumn = column; + fSelectedColumnRect.Set(leftEdge, 0, rightEdge, fVisibleRect.Height()); + DrawTitle(this, fSelectedColumnRect, fSelectedColumn, true); + fClickPoint = BPoint(position.x - fSelectedColumnRect.left, position.y + - fSelectedColumnRect.top); + SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS | + B_NO_POINTER_HISTORY); + break; + } + } + leftEdge = rightEdge + 1; + } +} + +void TitleView::MouseMoved(BPoint position, uint32 transit, const BMessage *) +{ + if(fEditMode) + return; + + // Handle column manipulation + switch (fCurrentState) { + case RESIZING_COLUMN: + ResizeSelectedColumn(position); + break; + + case PRESSING_COLUMN: { + if (abs((int32)(position.x - (fClickPoint.x + fSelectedColumnRect.left))) > kColumnResizeAreaWidth + || abs((int32)(position.y - (fClickPoint.y + fSelectedColumnRect.top))) > kColumnResizeAreaWidth) { + // User has moved the mouse more than the tolerable amount, + // initiate a drag. + if (transit == B_INSIDE_VIEW || transit == B_ENTERED_VIEW) { + if(fColumnFlags & B_ALLOW_COLUMN_MOVE) { + fCurrentState = DRAG_COLUMN_INSIDE_TITLE; + ComputeDragBoundries(fSelectedColumn, position); +#if _INCLUDES_CLASS_CURSOR + SetViewCursor(fColumnMoveCursor, false); +#endif +#if DRAG_TITLE_OUTLINE + BRect invalidRect(fSelectedColumnRect); + invalidRect.OffsetTo(position.x - fClickPoint.x, 0); + fCurrentDragPosition = position; + Invalidate(invalidRect); +#endif + } + } else { + if(fColumnFlags & B_ALLOW_COLUMN_REMOVE) { + // Dragged outside view + fCurrentState = DRAG_COLUMN_OUTSIDE_TITLE; + fSelectedColumn->SetVisible(false); + BRect dragRect(fSelectedColumnRect); + + // There is a race condition where the mouse may have moved by the + // time we get to handle this message. If the user drags a column very + // quickly, this results in the annoying bug where the cursor is outside + // of the rectangle that is being dragged around. + // Call GetMouse with the checkQueue flag set to false so we + // can get the most recent position of the mouse. This minimizes + // this problem (although it is currently not possible to completely + // eliminate it). + uint32 buttons; + GetMouse(&position, &buttons, false); + dragRect.OffsetTo(position.x - fClickPoint.x, position.y - dragRect.Height() / 2); + BeginRectTracking(dragRect, B_TRACK_WHOLE_RECT); + } + } + } + + break; + } + + case DRAG_COLUMN_INSIDE_TITLE: { + if (transit == B_EXITED_VIEW && (fColumnFlags & B_ALLOW_COLUMN_REMOVE)) { + // Dragged outside view + fCurrentState = DRAG_COLUMN_OUTSIDE_TITLE; + fSelectedColumn->SetVisible(false); + BRect dragRect(fSelectedColumnRect); + + // See explanation above. + uint32 buttons; + GetMouse(&position, &buttons, false); + + dragRect.OffsetTo(position.x - fClickPoint.x, position.y - fClickPoint.y); + BeginRectTracking(dragRect, B_TRACK_WHOLE_RECT); + } else if (position.x < fLeftDragBoundry || position.x > fRightDragBoundry) + DragSelectedColumn(position); + +#if DRAG_TITLE_OUTLINE + // Set up the invalid rect to include the rect for the previous position + // of the drag rect, as well as the new one. + BRect invalidRect(fSelectedColumnRect); + invalidRect.OffsetTo(fCurrentDragPosition.x - fClickPoint.x, 0); + if (position.x < fCurrentDragPosition.x) + invalidRect.left -= fCurrentDragPosition.x - position.x; + else + invalidRect.right += position.x - fCurrentDragPosition.x; + + fCurrentDragPosition = position; + Invalidate(invalidRect); +#endif + break; + } + + case DRAG_COLUMN_OUTSIDE_TITLE: + if (transit == B_ENTERED_VIEW) { + // Drag back into view + EndRectTracking(); + fCurrentState = DRAG_COLUMN_INSIDE_TITLE; + fSelectedColumn->SetVisible(true); + DragSelectedColumn(position); + } + + break; + + case INACTIVE: + // Check for cursor changes if we are over the resize area for + // a column. + BColumn *resizeColumn = 0; + float leftEdge = MAX(kLeftMargin, fMasterView->LatchWidth()); + for (int index = 0; index < fColumns->CountItems(); index++) { + BColumn *column = (BColumn*) fColumns->ItemAt(index); + if (!column->IsVisible()) + continue; + + if (leftEdge > position.x + kColumnResizeAreaWidth / 2) + break; + + float rightEdge = leftEdge + column->Width(); + if (position.x > rightEdge - kColumnResizeAreaWidth / 2 + && position.x < rightEdge + kColumnResizeAreaWidth / 2 + && column->MaxWidth() > column->MinWidth()) { + resizeColumn = column; + break; + } + + leftEdge = rightEdge + 1; + } + + // Update the cursor +#if _INCLUDES_CLASS_CURSOR + if (resizeColumn) { + if (resizeColumn->Width() == resizeColumn->MinWidth()) + SetViewCursor(fMinResizeCursor, false); + else if (resizeColumn->Width() == resizeColumn->MaxWidth()) + SetViewCursor(fMaxResizeCursor, false); + else + SetViewCursor(fResizeCursor, false); + } else + SetViewCursor(B_CURSOR_SYSTEM_DEFAULT, false); +#endif + break; + } +} + +void TitleView::MouseUp(BPoint position) +{ + if(fEditMode) + return; + + switch (fCurrentState) { + case RESIZING_COLUMN: + ResizeSelectedColumn(position); + fCurrentState = INACTIVE; + FixScrollBar(false); +#if _INCLUDES_CLASS_CURSOR + SetViewCursor(B_CURSOR_SYSTEM_DEFAULT, false); +#endif + break; + + case PRESSING_COLUMN: { + if (fMasterView->SortingEnabled()) { + if (fSortColumns->HasItem(fSelectedColumn)) { + if ((modifiers() & B_CONTROL_KEY) == 0 && fSortColumns->CountItems() > 1) { + fSortColumns->MakeEmpty(); + fSortColumns->AddItem(fSelectedColumn); + } + + fSelectedColumn->fSortAscending = !fSelectedColumn->fSortAscending; + } else { + if ((modifiers() & B_CONTROL_KEY) == 0) + fSortColumns->MakeEmpty(); + + fSortColumns->AddItem(fSelectedColumn); + fSelectedColumn->fSortAscending = true; + } + + fOutlineView->StartSorting(); + } + + fCurrentState = INACTIVE; + Invalidate(); + break; + } + + case DRAG_COLUMN_INSIDE_TITLE: + fCurrentState = INACTIVE; + +#if DRAG_TITLE_OUTLINE + Invalidate(); // xxx Can make this smaller +#else + Invalidate(fSelectedColumnRect); +#endif +#if _INCLUDES_CLASS_CURSOR + SetViewCursor(B_CURSOR_SYSTEM_DEFAULT, false); +#endif + break; + + case DRAG_COLUMN_OUTSIDE_TITLE: + fCurrentState = INACTIVE; + EndRectTracking(); +#if _INCLUDES_CLASS_CURSOR + SetViewCursor(B_CURSOR_SYSTEM_DEFAULT, false); +#endif + break; + + default: + ; + } +} + +void TitleView::FrameResized(float width, float height) +{ + fVisibleRect.right = fVisibleRect.left + width; + fVisibleRect.bottom = fVisibleRect.top + height; + FixScrollBar(true); +} + +// #pragma mark - + +OutlineView::OutlineView(BRect rect, BList *visibleColumns, BList *sortColumns, + BColumnListView *listView) + : BView(rect, "outline_view", B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_FRAME_EVENTS), + fColumns(visibleColumns), + fSortColumns(sortColumns), + fItemsHeight(24.), + fVisibleRect(rect.OffsetToCopy(0, 0)), + fFocusRow(0), + fRollOverRow(0), + fLastSelectedItem(0), + fFirstSelectedItem(0), + fSortThread(B_BAD_THREAD_ID), + fCurrentState(INACTIVE), + fMasterView(listView), + fSelectionMode(B_MULTIPLE_SELECTION_LIST), + fTrackMouse(false), + fCurrentField(0), + fCurrentRow(0), + fCurrentColumn(0), + fMouseDown(false), + fCurrentCode(B_OUTSIDE_VIEW), + fEditMode(false), + fDragging(false), + fClickCount(0), + fDropHighlightY(-1) +{ + SetViewColor(B_TRANSPARENT_32_BIT); + +#if DOUBLE_BUFFERED_COLUMN_RESIZE + // xxx this needs to be smart about the size of the buffer. Also, the buffer can + // be shared with the title's buffer. + BRect doubleBufferRect(0, 0, 600, 35); + fDrawBuffer = new BBitmap(doubleBufferRect, B_RGB32, true); + fDrawBufferView = new BView(doubleBufferRect, "double_buffer_view", + B_FOLLOW_ALL_SIDES, 0); + fDrawBuffer->Lock(); + fDrawBuffer->AddChild(fDrawBufferView); + fDrawBuffer->Unlock(); +#endif + + FixScrollBar(true); + fSelectionListDummyHead.fNextSelected = &fSelectionListDummyHead; + fSelectionListDummyHead.fPrevSelected = &fSelectionListDummyHead; +} + +OutlineView::~OutlineView() +{ + fDrawBuffer->Lock(); + fDrawBufferView->RemoveSelf(); + fDrawBuffer->Unlock(); + delete fDrawBufferView; + delete fDrawBuffer; + + Clear(); +} + +void OutlineView::Clear() +{ + DeselectAll(); // Make sure selection list doesn't point to deleted rows! + RecursiveDeleteRows(&fRows, false); + Invalidate(); + fItemsHeight = 24.; + FixScrollBar(true); +} + +void OutlineView::SetSelectionMode(list_view_type mode) +{ + DeselectAll(); + fSelectionMode = mode; +} + +list_view_type OutlineView::SelectionMode() const +{ + return fSelectionMode; +} + +void OutlineView::Deselect(BRow *row) +{ + if (row) { + if (row->fNextSelected != 0) { + row->fNextSelected->fPrevSelected = row->fPrevSelected; + row->fPrevSelected->fNextSelected = row->fNextSelected; + row->fNextSelected = 0; + row->fPrevSelected = 0; + Invalidate(); + } + } +} + +void OutlineView::AddToSelection(BRow *row) +{ + if (row) { + if (row->fNextSelected == 0) { + if (fSelectionMode == B_SINGLE_SELECTION_LIST) + DeselectAll(); + + row->fNextSelected = fSelectionListDummyHead.fNextSelected; + row->fPrevSelected = &fSelectionListDummyHead; + row->fNextSelected->fPrevSelected = row; + row->fPrevSelected->fNextSelected = row; + + BRect invalidRect; + if (FindVisibleRect(row, &invalidRect)) + Invalidate(invalidRect); + } + } +} + +void OutlineView::RecursiveDeleteRows(BRowContainer* List, bool IsOwner) +{ + if (List) { + while (true) { + BRow *row = List->RemoveItemAt(0L); + if (row == 0) + break; + + if (row->fChildList) + RecursiveDeleteRows(row->fChildList, true); + + delete row; + } + + if (IsOwner) + delete List; + } +} + + +void OutlineView::RedrawColumn(BColumn *column, float leftEdge, bool isFirstColumn) +{ + if (column) { + font_height fh; + GetFontHeight(&fh); + float line = 0.0; + for (RecursiveOutlineIterator iterator(&fRows); iterator.CurrentRow(); + line += iterator.CurrentRow()->Height() + 1, iterator.GoToNext()) { + BRow *row = iterator.CurrentRow(); + float rowHeight = row->Height(); + if (line > fVisibleRect.bottom) + break; + + if (line + rowHeight >= fVisibleRect.top) { + BRect sourceRect(0, 0, column->Width(), rowHeight); + BRect destRect(leftEdge, line, leftEdge + column->Width(), line + rowHeight); + + #if DOUBLE_BUFFERED_COLUMN_RESIZE + fDrawBuffer->Lock(); + if (row->fNextSelected != 0) { + if(fEditMode) { + fDrawBufferView->SetHighColor(fMasterView->Color(B_COLOR_EDIT_BACKGROUND)); + fDrawBufferView->SetLowColor(fMasterView->Color(B_COLOR_EDIT_BACKGROUND)); + } else { + fDrawBufferView->SetHighColor(fMasterView->Color(B_COLOR_SELECTION)); + fDrawBufferView->SetLowColor(fMasterView->Color(B_COLOR_SELECTION)); + } + } else { + fDrawBufferView->SetHighColor(fMasterView->Color(B_COLOR_BACKGROUND)); + fDrawBufferView->SetLowColor(fMasterView->Color(B_COLOR_BACKGROUND)); + } + BFont font; + GetFont(&font); + fDrawBufferView->SetFont(&font); + fDrawBufferView->FillRect(sourceRect); + + if (isFirstColumn) { + // + //debugger("First"); + //row->DrawBackground(sourceRect,fDrawBufferView,false,false); + // If this is the first column, double buffer drawing the latch too. + destRect.left += iterator.CurrentLevel() * kOutlineLevelIndent + - fMasterView->LatchWidth(); + sourceRect.left += iterator.CurrentLevel() * kOutlineLevelIndent + - fMasterView->LatchWidth(); + + LatchType pos = B_NO_LATCH; + if (row->HasLatch()) + pos = row->fIsExpanded ? B_OPEN_LATCH : B_CLOSED_LATCH; + + BRect latchRect(sourceRect); + latchRect.right = latchRect.left + fMasterView->LatchWidth(); + fMasterView->DrawLatch(fDrawBufferView, latchRect, pos, row); + + } + + BField *field = row->GetField(column->fFieldID); + if (field) { + BRect fieldRect(sourceRect); + if (isFirstColumn) + fieldRect.left += fMasterView->LatchWidth(); + + #if CONSTRAIN_CLIPPING_REGION + BRegion clipRegion; + clipRegion.Set(fieldRect); + fDrawBufferView->ConstrainClippingRegion(&clipRegion); + fDrawBufferView->PushState(); + #endif + fDrawBufferView->SetHighColor(fMasterView->Color(row->fNextSelected ? B_COLOR_SELECTION_TEXT : B_COLOR_TEXT)); + float baseline = floor(fieldRect.top + fh.ascent + + (fieldRect.Height()+1-(fh.ascent+fh.descent))/2); + fDrawBufferView->MovePenTo(fieldRect.left + 8, baseline); + column->DrawField(field, fieldRect, fDrawBufferView); + #if CONSTRAIN_CLIPPING_REGION + fDrawBufferView->PopState(); + fDrawBufferView->ConstrainClippingRegion(NULL); + #endif + } + + if (fFocusRow == row) { + if(!fEditMode) { + fDrawBufferView->SetHighColor(fMasterView->Color(row->fNextSelected ? B_COLOR_SELECTION_TEXT : B_COLOR_TEXT)); + fDrawBufferView->StrokeRect(BRect(-1, sourceRect.top, 10000.0, sourceRect.bottom - 1)); + } + } + + fDrawBufferView->SetHighColor(fMasterView->Color(B_COLOR_ROW_DIVIDER)); + //1 StrokeLine(BPoint(0, line + rowHeight - 2), BPoint(Bounds().Width(), line + rowHeight - 2)); + //RedrawColumn StrokeLine(BPoint(0, line + rowHeight - 1), BPoint(Bounds().Width(), line + rowHeight - 1)); + fDrawBufferView->StrokeLine(BPoint(0, rowHeight), BPoint(Bounds().right, rowHeight)); + + fDrawBufferView->Sync(); + fDrawBuffer->Unlock(); + SetDrawingMode(B_OP_OVER); + DrawBitmap(fDrawBuffer, sourceRect, destRect); + + #else + + if (row->fNextSelected != 0) { + if(fEditMode) { + SetHighColor(fMasterView->Color(B_COLOR_EDIT_BACKGROUND)); + SetLowColor(fMasterView->Color(B_COLOR_EDIT_BACKGROUND)); + } + else { + SetHighColor(fMasterView->Color(B_COLOR_SELECTION)); + SetLowColor(fMasterView->Color(B_COLOR_SELECTION)); + } + } else { + SetHighColor(fMasterView->Color(B_COLOR_BACKGROUND)); + SetLowColor(fMasterView->Color(B_COLOR_BACKGROUND)); + } + + FillRect(destRect); + + BField *field = row->GetField(column->fFieldID); + if (field) { + #if CONSTRAIN_CLIPPING_REGION + BRegion clipRegion; + clipRegion.Set(destRect); + ConstrainClippingRegion(&clipRegion); + PushState(); + #endif + SetHighColor(fColorList[row->fNextSelected ? B_COLOR_SELECTION_TEXT : B_COLOR_TEXT]); + float baseline = floor(destRect.top + fh.ascent + + (destRect.Height()+1-(fh.ascent+fh.descent))/2); + MovePenTo(destRect.left + 8, baseline); + column->DrawField(field, destRect, this); + #if CONSTRAIN_CLIPPING_REGION + PopState(); + ConstrainClippingRegion(NULL); + #endif + } + + if (fFocusRow == row) { + if(!fEditMode) { + SetHighColor(fColorList[row->fNextSelected ? B_COLOR_SELECTION_TEXT : B_COLOR_TEXT]); + StrokeRect(BRect(0, destRect.top, 10000.0, destRect.bottom - 1)); + } + } + + rgb_color color = HighColor(); + SetHighColor(fMasterView->Color(B_COLOR_ROW_DIVIDER)); + //2 StrokeLine(BPoint(0, line + rowHeight - 2), BPoint(Bounds().Width(), line + rowHeight - 2)); + //RedrawColumn StrokeLine(BPoint(0, line + rowHeight - 1), BPoint(Bounds().Width(), line + rowHeight - 1)); + StrokeLine(BPoint(0, line + rowHeight), BPoint(Bounds().right, line + rowHeight)); + SetHighColor(color); + #endif + } + } + } +} + +void OutlineView::Draw(BRect invalidBounds) +{ +#if SMART_REDRAW + BRegion invalidRegion; + GetClippingRegion(&invalidRegion); +#endif + + font_height fh; + GetFontHeight(&fh); + + float line = 0.0; + int32 numColumns = fColumns->CountItems(); + for (RecursiveOutlineIterator iterator(&fRows); iterator.CurrentRow(); + iterator.GoToNext()) { + BRow *row = iterator.CurrentRow(); + if (line > invalidBounds.bottom) + break; + + float rowHeight = row->Height(); + + if (line > invalidBounds.top - rowHeight) { + bool isFirstColumn = true; + float fieldLeftEdge = MAX(kLeftMargin, fMasterView->LatchWidth()); + for (int columnIndex = 0; columnIndex < numColumns; columnIndex++) { + BColumn *column = (BColumn*) fColumns->ItemAt(columnIndex); + if (!column->IsVisible()) + continue; + + if (!isFirstColumn && fieldLeftEdge > invalidBounds.right) + break; + + if (fieldLeftEdge + column->Width() >= invalidBounds.left) { + BRect fullRect(fieldLeftEdge, line, + fieldLeftEdge + column->Width(), line + rowHeight); + + bool clippedFirstColumn = false; + // This happens when a column is indented past the + // beginning of the next column. + + if (row->fNextSelected != 0) { + if (Window()->IsActive()) { + if(fEditMode) + SetHighColor(fMasterView->Color(B_COLOR_EDIT_BACKGROUND)); + else + SetHighColor(fMasterView->Color(B_COLOR_SELECTION)); + } + else + SetHighColor(fMasterView->Color(B_COLOR_NON_FOCUS_SELECTION)); + } else + SetHighColor(fMasterView->Color(B_COLOR_BACKGROUND)); + + BRect destRect(fullRect); + if (isFirstColumn) { + fullRect.left -= fMasterView->LatchWidth(); + destRect.left += iterator.CurrentLevel() * kOutlineLevelIndent; + if (destRect.left >= destRect.right) { + // clipped + FillRect(BRect(0, line, fieldLeftEdge + column->Width(), + line + rowHeight)); + clippedFirstColumn = true; + } + + //SetHighColor(255,0,0); + FillRect(BRect(0, line, MAX(kLeftMargin, fMasterView->LatchWidth()), line + row->Height())); + + + + } + + +#if SMART_REDRAW + if (!clippedFirstColumn && invalidRegion.Intersects(fullRect)) +#else + if (!clippedFirstColumn) +#endif + { + FillRect(fullRect); // Using color set above + if (isFirstColumn) row->DrawBackground(fullRect,this,false,false); + + + // Draw the latch widget if it has one. + if (isFirstColumn) { + if (row == fTargetRow && fCurrentState == LATCH_CLICKED) { + // Note that this only occurs if the user is holding + // down a latch while items are added in the background. + BPoint pos; + uint32 buttons; + GetMouse(&pos, &buttons); + if (fLatchRect.Contains(pos)) + fMasterView->DrawLatch(this, fLatchRect, B_PRESSED_LATCH, + fTargetRow); + else + fMasterView->DrawLatch(this, fLatchRect, + row->fIsExpanded ? B_OPEN_LATCH : B_CLOSED_LATCH, + fTargetRow); + } else { + LatchType pos = B_NO_LATCH; + if (row->HasLatch()) + pos = row->fIsExpanded ? B_OPEN_LATCH : B_CLOSED_LATCH; + + fMasterView->DrawLatch(this, BRect(destRect.left - + fMasterView->LatchWidth(), + destRect.top, destRect.left, destRect.bottom), pos, + row); + } + } + + if (row->fNextSelected != 0) { + if (Window()->IsActive()) { + if(fEditMode) + SetLowColor(fMasterView->Color(B_COLOR_EDIT_BACKGROUND)); + else + SetLowColor(fMasterView->Color(B_COLOR_SELECTION)); + } + else + SetLowColor(fMasterView->Color(B_COLOR_NON_FOCUS_SELECTION)); + } else + SetLowColor(fMasterView->Color(B_COLOR_BACKGROUND)); + + SetHighColor(fMasterView->HighColor()); + // The master view just holds the high color for us. + + BField *field = row->GetField(column->fFieldID); + if (field) { +#if CONSTRAIN_CLIPPING_REGION + BRegion clipRegion; + clipRegion.Set(destRect); + ConstrainClippingRegion(&clipRegion); + PushState(); +#endif + SetHighColor(fMasterView->Color(row->fNextSelected ? B_COLOR_SELECTION_TEXT : B_COLOR_TEXT)); + float baseline = floor(destRect.top + fh.ascent + + (destRect.Height()+1-(fh.ascent+fh.descent))/2); + MovePenTo(destRect.left + 8, baseline); + column->DrawField(field, destRect, this); +#if CONSTRAIN_CLIPPING_REGION + PopState(); + ConstrainClippingRegion(NULL); +#endif + } + } + } + + isFirstColumn = false; + fieldLeftEdge += column->Width() + 1; + } + + if (fieldLeftEdge <= invalidBounds.right) { + if (row->fNextSelected != 0) { + if (Window()->IsActive()) { + if(fEditMode) + SetHighColor(fMasterView->Color(B_COLOR_EDIT_BACKGROUND)); + else + SetHighColor(fMasterView->Color(B_COLOR_SELECTION)); + } + else + SetHighColor(fMasterView->Color(B_COLOR_NON_FOCUS_SELECTION)); + } else + SetHighColor(fMasterView->Color(B_COLOR_BACKGROUND)); + + FillRect(BRect(fieldLeftEdge, line, invalidBounds.right, + line + rowHeight)); + } + } + + if (fFocusRow == row && fMasterView->IsFocus() && Window()->IsActive()) { + if(!fEditMode) { + SetHighColor(fMasterView->Color(row->fNextSelected ? B_COLOR_SELECTION_TEXT : B_COLOR_TEXT)); + StrokeRect(BRect(0, line, 10000.0, line + rowHeight - 1)); + } + } + rgb_color color = HighColor(); + SetHighColor(fMasterView->Color(B_COLOR_ROW_DIVIDER)); + StrokeLine(BPoint(invalidBounds.left, line + rowHeight), BPoint(invalidBounds.right, line + rowHeight)); + SetHighColor(color); + line += rowHeight + 1; + } + + if (line <= invalidBounds.bottom) { + SetHighColor(fMasterView->Color(B_COLOR_BACKGROUND)); + FillRect(BRect(invalidBounds.left, line, invalidBounds.right, invalidBounds.bottom)); + } + + // Draw the drop target line + if (fDropHighlightY != -1) + InvertRect(BRect(0, fDropHighlightY - kDropHighlightLineHeight / 2, 1000000, + fDropHighlightY + kDropHighlightLineHeight / 2)); +} + +BRow* OutlineView::FindRow(float ypos, int32 *out_rowIndent, float *out_top) +{ + if (out_rowIndent && out_top) { + float line = 0.0; + for (RecursiveOutlineIterator iterator(&fRows); iterator.CurrentRow(); + iterator.GoToNext()) { + BRow *row = iterator.CurrentRow(); + if (line > ypos) + break; + + float rowHeight = row->Height(); + if (ypos <= line + rowHeight) { + *out_top = line; + *out_rowIndent = iterator.CurrentLevel(); + return row; + } + + line += rowHeight + 1; + } + } + return 0; +} + +void OutlineView::SetMouseTrackingEnabled(bool enabled) +{ + fTrackMouse = enabled; + if (!enabled && fDropHighlightY != -1) { + InvertRect(BRect(0, fDropHighlightY - kDropHighlightLineHeight / 2, 1000000, + fDropHighlightY + kDropHighlightLineHeight / 2)); // Erase the old target line + fDropHighlightY = -1; + } +} + + +// +// Note that this interaction is not totally safe. If items are added to +// the list in the background, the widget rect will be incorrect, possibly +// resulting in drawing glitches. The code that adds items needs to be a little smarter +// about invalidating state. +// +void OutlineView::MouseDown(BPoint position) +{ + if(!fEditMode) + fMasterView->MakeFocus(true); + + // Check to see if the user is clicking on a widget to open a section + // of the list. + bool reset_click_count = false; + int32 indent; + float rowTop; + BRow *row = FindRow(position.y, &indent, &rowTop); + if (row) { + + // Update fCurrentField + bool handle_field = false; + BField *new_field = 0; + BRow *new_row = 0; + BColumn *new_column = 0; + BRect new_rect; + + if(position.y >=0 ) { + if(position.x >=0 ) { + float x=0; + for(int32 c=0;cCountColumns();c++) { + new_column = fMasterView->ColumnAt(c); + if (!new_column->IsVisible()) + continue; + if((MAX(kLeftMargin, fMasterView->LatchWidth())+x)+new_column->Width() >= position.x) { + if(new_column->WantsEvents()) { + new_field = row->GetField(c); + new_row = row; + FindRect(new_row,&new_rect); + new_rect.left = MAX(kLeftMargin, fMasterView->LatchWidth()) + x; + new_rect.right = new_rect.left + new_column->Width() - 1; + handle_field = true; + } + break; + } + x += new_column->Width(); + } + } + } + + // Handle mouse down + if(handle_field) { + fMouseDown = true; + fFieldRect = new_rect; + fCurrentColumn = new_column; + fCurrentRow = new_row; + fCurrentField = new_field; + fCurrentCode = B_INSIDE_VIEW; + fCurrentColumn->MouseDown(fMasterView,fCurrentRow,fCurrentField,fFieldRect,position,1); + } + + if(!fEditMode) { + + fTargetRow = row; + fTargetRowTop = rowTop; + FindVisibleRect(fFocusRow, &fFocusRowRect); + + float leftWidgetBoundry = indent * kOutlineLevelIndent + MAX(kLeftMargin, fMasterView->LatchWidth()) - + fMasterView->LatchWidth(); + fLatchRect.Set(leftWidgetBoundry, rowTop, leftWidgetBoundry + + fMasterView->LatchWidth(), rowTop + row->Height()); + if (fLatchRect.Contains(position) && row->HasLatch()) { + fCurrentState = LATCH_CLICKED; + if (fTargetRow->fNextSelected != 0) { + if(fEditMode) + SetHighColor(fMasterView->Color(B_COLOR_EDIT_BACKGROUND)); + else + SetHighColor(fMasterView->Color(B_COLOR_SELECTION)); + } + else + SetHighColor(fMasterView->Color(B_COLOR_BACKGROUND)); + + FillRect(fLatchRect); + if (fLatchRect.Contains(position)) + fMasterView->DrawLatch(this, fLatchRect, B_PRESSED_LATCH, row); + else + fMasterView->DrawLatch(this, fLatchRect, fTargetRow->fIsExpanded + ? B_OPEN_LATCH : B_CLOSED_LATCH, row); + + } else { + Invalidate(fFocusRowRect); + fFocusRow = fTargetRow; + FindVisibleRect(fFocusRow, &fFocusRowRect); + + ASSERT(fTargetRow != 0); + + if ((modifiers() & B_CONTROL_KEY) == 0) + DeselectAll(); + + if ((modifiers() & B_SHIFT_KEY) != 0 && fFirstSelectedItem != 0 + && fSelectionMode == B_MULTIPLE_SELECTION_LIST) { + SelectRange(fFirstSelectedItem, fTargetRow); + } + else { + if (fTargetRow->fNextSelected != 0) { + // Unselect row + fTargetRow->fNextSelected->fPrevSelected = fTargetRow->fPrevSelected; + fTargetRow->fPrevSelected->fNextSelected = fTargetRow->fNextSelected; + fTargetRow->fPrevSelected = 0; + fTargetRow->fNextSelected = 0; + fFirstSelectedItem = NULL; + } else { + // Select row + if (fSelectionMode == B_SINGLE_SELECTION_LIST) + DeselectAll(); + + fTargetRow->fNextSelected = fSelectionListDummyHead.fNextSelected; + fTargetRow->fPrevSelected = &fSelectionListDummyHead; + fTargetRow->fNextSelected->fPrevSelected = fTargetRow; + fTargetRow->fPrevSelected->fNextSelected = fTargetRow; + fFirstSelectedItem = fTargetRow; + } + + Invalidate(BRect(fVisibleRect.left, fTargetRowTop, fVisibleRect.right, + fTargetRowTop + fTargetRow->Height())); + } + + fCurrentState = ROW_CLICKED; + if (fLastSelectedItem != fTargetRow) + reset_click_count = true; + fLastSelectedItem = fTargetRow; + fMasterView->SelectionChanged(); + + } + } + + SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS | + B_NO_POINTER_HISTORY); + + } else if (fFocusRow != 0) { + // User clicked in open space, unhighlight focus row. + FindVisibleRect(fFocusRow, &fFocusRowRect); + fFocusRow = 0; + Invalidate(fFocusRowRect); + } + + // We stash the click counts here because the 'clicks' field + // is not in the CurrentMessage() when MouseUp is called... ;( + if (reset_click_count) + fClickCount = 1; + else + Window()->CurrentMessage()->FindInt32("clicks", &fClickCount); + fClickPoint = position; + +} // end of MouseDown() + +void OutlineView::MouseMoved(BPoint position, uint32 /*transit*/, const BMessage */*message*/) +{ + if(!fMouseDown) { + // Update fCurrentField + bool handle_field = false; + BField *new_field = 0; + BRow *new_row = 0; + BColumn *new_column = 0; + BRect new_rect(0,0,0,0); + if(position.y >=0 ) { + float top; + int32 indent; + BRow *row = FindRow(position.y, &indent, &top); + if(row && position.x >=0 ) { + float x=0; + for(int32 c=0;cCountColumns();c++) { + new_column = fMasterView->ColumnAt(c); + if (!new_column->IsVisible()) + continue; + if((MAX(kLeftMargin, fMasterView->LatchWidth())+x)+new_column->Width() > position.x) { + if(new_column->WantsEvents()) { + new_field = row->GetField(c); + new_row = row; + FindRect(new_row,&new_rect); + new_rect.left = MAX(kLeftMargin, fMasterView->LatchWidth()) + x; + new_rect.right = new_rect.left + new_column->Width() - 1; + handle_field = true; + } + break; + } + x += new_column->Width(); + } + } + } + + // Handle mouse moved + if(handle_field) { + if(new_field != fCurrentField) { + if(fCurrentField) { + fCurrentColumn->MouseMoved(fMasterView, fCurrentRow, + fCurrentField, fFieldRect, position, 0, fCurrentCode = B_EXITED_VIEW); + } + fCurrentColumn = new_column; + fCurrentRow = new_row; + fCurrentField = new_field; + fFieldRect = new_rect; + if(fCurrentField) { + fCurrentColumn->MouseMoved(fMasterView, fCurrentRow, + fCurrentField, fFieldRect, position, 0, fCurrentCode = B_ENTERED_VIEW); + } + } else { + if(fCurrentField) { + fCurrentColumn->MouseMoved(fMasterView, fCurrentRow, + fCurrentField, fFieldRect, position, 0, fCurrentCode = B_INSIDE_VIEW); + } + } + } else { + if(fCurrentField) { + fCurrentColumn->MouseMoved(fMasterView, fCurrentRow, + fCurrentField, fFieldRect, position, 0, fCurrentCode = B_EXITED_VIEW); + fCurrentField = 0; + fCurrentColumn = 0; + fCurrentRow = 0; + } + } + } else { + if(fCurrentField) { + if(fFieldRect.Contains(position)) { + if ( fCurrentCode == B_OUTSIDE_VIEW + || fCurrentCode == B_EXITED_VIEW + ) { + fCurrentColumn->MouseMoved(fMasterView, fCurrentRow, + fCurrentField, fFieldRect, position, 1, fCurrentCode = B_ENTERED_VIEW); + } else { + fCurrentColumn->MouseMoved(fMasterView, fCurrentRow, + fCurrentField, fFieldRect, position, 1, fCurrentCode = B_INSIDE_VIEW); + } + } else { + if ( fCurrentCode == B_INSIDE_VIEW + || fCurrentCode == B_ENTERED_VIEW + ) { + fCurrentColumn->MouseMoved(fMasterView, fCurrentRow, + fCurrentField, fFieldRect, position, 1, fCurrentCode = B_EXITED_VIEW); + } else { + fCurrentColumn->MouseMoved(fMasterView, fCurrentRow, + fCurrentField, fFieldRect, position, 1, fCurrentCode = B_OUTSIDE_VIEW); + } + } + } + } + + if(!fEditMode) { + + switch (fCurrentState) { + case LATCH_CLICKED: + if (fTargetRow->fNextSelected != 0) { + if(fEditMode) + SetHighColor(fMasterView->Color(B_COLOR_EDIT_BACKGROUND)); + else + SetHighColor(fMasterView->Color(B_COLOR_SELECTION)); + } + else + SetHighColor(fMasterView->Color(B_COLOR_BACKGROUND)); + + FillRect(fLatchRect); + if (fLatchRect.Contains(position)) + fMasterView->DrawLatch(this, fLatchRect, B_PRESSED_LATCH, fTargetRow); + else + fMasterView->DrawLatch(this, fLatchRect, fTargetRow->fIsExpanded + ? B_OPEN_LATCH : B_CLOSED_LATCH, fTargetRow); + + break; + + + case ROW_CLICKED: + if (abs((int)(position.x - fClickPoint.x)) > kRowDragSensitivity + || abs((int)(position.y - fClickPoint.y)) > kRowDragSensitivity) { + fCurrentState = DRAGGING_ROWS; + fMasterView->InitiateDrag(fClickPoint, fTargetRow->fNextSelected != 0); + } + break; + + case DRAGGING_ROWS: +#if 0 + // falls through... +#else + if (fTrackMouse /*&& message*/) { + if (fVisibleRect.Contains(position)) { + float top; + int32 indent; + BRow *target = FindRow(position.y, &indent, &top); + if(target) + SetFocusRow(target,true); + } + } + break; +#endif + + default: { + + if (fTrackMouse /*&& message*/) { + // Draw a highlight line... + if (fVisibleRect.Contains(position)) { + float top; + int32 indent; + BRow *target = FindRow(position.y, &indent, &top); + if(target==fRollOverRow) + break; + if(fRollOverRow) + { + BRect rect; + FindRect(fRollOverRow, &rect); + Invalidate(rect); + } + fRollOverRow=target; +#if 0 + SetFocusRow(fRollOverRow,false); +#else + PushState(); + SetDrawingMode(B_OP_BLEND); + SetHighColor(255,255,255,255); + BRect rect; + FindRect(fRollOverRow, &rect); + rect.bottom -= 1.0; + FillRect(rect); + PopState(); +#endif + } else { + if(fRollOverRow) + { + BRect rect; + FindRect(fRollOverRow, &rect); + Invalidate(rect); + fRollOverRow = NULL; + } + } + } + } + } + } +} // end of MouseMoved() + +void OutlineView::MouseUp(BPoint position) +{ + if(fCurrentField) { + fCurrentColumn->MouseUp(fMasterView,fCurrentRow,fCurrentField); + fMouseDown = false; + } + + if(!fEditMode) { + switch (fCurrentState) { + case LATCH_CLICKED: + if (fLatchRect.Contains(position)) + fMasterView->ExpandOrCollapse(fTargetRow, !fTargetRow->fIsExpanded); + + Invalidate(fLatchRect); + fCurrentState = INACTIVE; + break; + + case ROW_CLICKED: + if (fClickCount > 1 + && abs((int)fClickPoint.x - (int)position.x) < kDoubleClickMoveSensitivity + && abs((int)fClickPoint.y - (int)position.y) < kDoubleClickMoveSensitivity) { + fMasterView->ItemInvoked(); + } + fCurrentState = INACTIVE; + break; + + case DRAGGING_ROWS: + fCurrentState = INACTIVE; + // Falls through + + default: + if (fDropHighlightY != -1) { + InvertRect(BRect(0, fDropHighlightY - kDropHighlightLineHeight / 2, 1000000, + fDropHighlightY + kDropHighlightLineHeight / 2)); // Erase the old target line + fDropHighlightY = -1; + } + } + } +} // end of MouseUp() + +void OutlineView::MessageReceived(BMessage *message) +{ + if (message->WasDropped()) { + fMasterView->MessageDropped(message, ConvertFromScreen(message->DropPoint())); + } else { + BView::MessageReceived(message); + } +} + +void OutlineView::ChangeFocusRow(bool up, bool updateSelection, bool addToCurrentSelection) +{ + int32 indent; + float top; + float newRowPos = 0; + float verticalScroll = 0; + + if (fFocusRow) { + // A row currently has the focus, get information about it + newRowPos = fFocusRowRect.top + (up ? -4 : fFocusRow->Height() + 4); + if (newRowPos < fVisibleRect.top + 20) + verticalScroll = newRowPos - 20; + else if (newRowPos > fVisibleRect.bottom - 20) + verticalScroll = newRowPos - fVisibleRect.Height() + 20; + } else + newRowPos = fVisibleRect.top + 2; + // no row is currently focused, set this to the top of the window + // so we will select the first visible item in the list. + + BRow *newRow = FindRow(newRowPos, &indent, &top); + if (newRow) { + if (fFocusRow) { + fFocusRowRect.right = 10000; + Invalidate(fFocusRowRect); + } + fFocusRow = newRow; + fFocusRowRect.top = top; + fFocusRowRect.left = 0; + fFocusRowRect.right = 10000; + fFocusRowRect.bottom = fFocusRowRect.top + fFocusRow->Height(); + Invalidate(fFocusRowRect); + + if (updateSelection) { + if (!addToCurrentSelection || fSelectionMode == B_SINGLE_SELECTION_LIST) + DeselectAll(); + + if (fFocusRow->fNextSelected == 0) { + fFocusRow->fNextSelected = fSelectionListDummyHead.fNextSelected; + fFocusRow->fPrevSelected = &fSelectionListDummyHead; + fFocusRow->fNextSelected->fPrevSelected = fFocusRow; + fFocusRow->fPrevSelected->fNextSelected = fFocusRow; + } + + fLastSelectedItem = fFocusRow; + } + } else + Invalidate(fFocusRowRect); + + if (verticalScroll != 0) { + BScrollBar *vScrollBar = ScrollBar(B_VERTICAL); + float min, max; + vScrollBar->GetRange(&min, &max); + if (verticalScroll < min) + verticalScroll = min; + else if (verticalScroll > max) + verticalScroll = max; + + vScrollBar->SetValue(verticalScroll); + } + + if (newRow && updateSelection) + fMasterView->SelectionChanged(); +} + +void OutlineView::MoveFocusToVisibleRect() +{ + fFocusRow = 0; + ChangeFocusRow(true, true, false); +} + +BRow* OutlineView::CurrentSelection(BRow *lastSelected) const +{ + BRow *row; + if (lastSelected == 0) + row = fSelectionListDummyHead.fNextSelected; + else + row = lastSelected->fNextSelected; + + + if (row == &fSelectionListDummyHead) + row = 0; + + return row; +} + +void OutlineView::ToggleFocusRowSelection(bool selectRange) +{ + if (fFocusRow == 0) + return; + + if (selectRange && fSelectionMode == B_MULTIPLE_SELECTION_LIST) + SelectRange(fLastSelectedItem, fFocusRow); + else { + if (fFocusRow->fNextSelected != 0) { + // Unselect row + fFocusRow->fNextSelected->fPrevSelected = fFocusRow->fPrevSelected; + fFocusRow->fPrevSelected->fNextSelected = fFocusRow->fNextSelected; + fFocusRow->fPrevSelected = 0; + fFocusRow->fNextSelected = 0; + } else { + // Select row + if (fSelectionMode == B_SINGLE_SELECTION_LIST) + DeselectAll(); + + fFocusRow->fNextSelected = fSelectionListDummyHead.fNextSelected; + fFocusRow->fPrevSelected = &fSelectionListDummyHead; + fFocusRow->fNextSelected->fPrevSelected = fFocusRow; + fFocusRow->fPrevSelected->fNextSelected = fFocusRow; + } + } + + fLastSelectedItem = fFocusRow; + fMasterView->SelectionChanged(); + Invalidate(fFocusRowRect); +} + +void OutlineView::ToggleFocusRowOpen() +{ + if (fFocusRow) + fMasterView->ExpandOrCollapse(fFocusRow, !fFocusRow->fIsExpanded); +} + + +// xxx Could use CopyBits here to speed things up. +void OutlineView::ExpandOrCollapse(BRow* ParentRow, bool Expand) +{ + if (ParentRow) { + if (ParentRow->fIsExpanded == Expand) + return; + + ParentRow->fIsExpanded = Expand; + + BRect parentRect; + if (FindRect(ParentRow, &parentRect)) { + // Determine my new height + float subTreeHeight = 0.0; + if (ParentRow->fIsExpanded) + for (RecursiveOutlineIterator iterator(ParentRow->fChildList); + iterator.CurrentRow(); + iterator.GoToNext() + ) + { + subTreeHeight += iterator.CurrentRow()->Height()+1; + } + else + for (RecursiveOutlineIterator iterator(ParentRow->fChildList); + iterator.CurrentRow(); + iterator.GoToNext() + ) + { + subTreeHeight -= iterator.CurrentRow()->Height()+1; + } + fItemsHeight += subTreeHeight; + + // Adjust focus row if necessary. + if (FindRect(fFocusRow, &fFocusRowRect) == false) { + // focus row is in a subtree that has collapsed, move it up to the parent. + fFocusRow = ParentRow; + FindRect(fFocusRow, &fFocusRowRect); + } + + Invalidate(BRect(0, parentRect.top, fVisibleRect.right, fVisibleRect.bottom)); + FixScrollBar(false); + } + } +} + +void OutlineView::RemoveRow(BRow *row) +{ + if (row) { + BRow *parentRow; + bool parentIsVisible; + float subTreeHeight = row->Height(); + if (FindParent(row, &parentRow, &parentIsVisible)) { + // adjust height + if (parentIsVisible && (parentRow == 0 || parentRow->fIsExpanded)) { + if (row->fIsExpanded) { + for (RecursiveOutlineIterator iterator(row->fChildList); + iterator.CurrentRow(); iterator.GoToNext()) + subTreeHeight += iterator.CurrentRow()->Height(); + } + } + } + fItemsHeight -= subTreeHeight + 1; + FixScrollBar(false); + + if (parentRow) + parentRow->fChildList->RemoveItem(row); + else + fRows.RemoveItem(row); + + if (parentRow != 0 && parentRow->fChildList->CountItems() == 0) { + delete parentRow->fChildList; + parentRow->fChildList = 0; + if (parentIsVisible) + Invalidate(); // xxx crude way of redrawing latch + } + + if (parentIsVisible && (parentRow == 0 || parentRow->fIsExpanded)) + Invalidate(); // xxx make me smarter. + + + // Adjust focus row if necessary. + if (fFocusRow && FindRect(fFocusRow, &fFocusRowRect) == false) { + // focus row is in a subtree that is gone, move it up to the parent. + fFocusRow = parentRow; + if (fFocusRow) + FindRect(fFocusRow, &fFocusRowRect); + } + + // Remove this from the selection if necessary + if (row->fNextSelected != 0) { + row->fNextSelected->fPrevSelected = row->fPrevSelected; + row->fPrevSelected->fNextSelected = row->fNextSelected; + row->fPrevSelected = 0; + row->fNextSelected = 0; + fMasterView->SelectionChanged(); + } + + fCurrentColumn = 0; + fCurrentRow = 0; + fCurrentField = 0; + } +} + +BRowContainer* OutlineView::RowList() +{ + return &fRows; +} + +void OutlineView::UpdateRow(BRow *row) +{ + if (row) { + // Determine if this row has changed its sort order + BRow *parentRow = NULL; + bool parentIsVisible = false; + FindParent(row, &parentRow, &parentIsVisible); + + BRowContainer* list = (parentRow == NULL) ? &fRows : parentRow->fChildList; + + if(list) { + int32 rowIndex = list->IndexOf(row); + ASSERT(rowIndex >= 0); + ASSERT(list->ItemAt(rowIndex) == row); + + bool rowMoved = false; + if (rowIndex > 0 && CompareRows(list->ItemAt(rowIndex - 1), row) > 0) + rowMoved = true; + + if (rowIndex < list->CountItems() - 1 && CompareRows(list->ItemAt(rowIndex + 1), + row) < 0) + rowMoved = true; + + if (rowMoved) { + // Sort location of this row has changed. + // Remove and re-add in the right spot + SortList(list, parentIsVisible && (parentRow == NULL || parentRow->fIsExpanded)); + } else if (parentIsVisible && (parentRow == NULL || parentRow->fIsExpanded)) { + BRect invalidRect; + if (FindVisibleRect(row, &invalidRect)) + Invalidate(invalidRect); + } + } + } +} + +void OutlineView::AddRow(BRow* Row, int32 Index, BRow* ParentRow) +{ + if(Row) { + Row->fParent = ParentRow; + + if (fMasterView->SortingEnabled()) { + // Ignore index here. + if (ParentRow) { + if (ParentRow->fChildList == 0) + ParentRow->fChildList = new BRowContainer; + + AddSorted(ParentRow->fChildList, Row); + } else + AddSorted(&fRows, Row); + } else { + // Note, a -1 index implies add to end if sorting is not enabled + if (ParentRow) { + if (ParentRow->fChildList == 0) + ParentRow->fChildList = new BRowContainer; + + if (Index < 0 || Index > ParentRow->fChildList->CountItems()) + ParentRow->fChildList->AddItem(Row); + else + ParentRow->fChildList->AddItem(Row, Index); + } else { + if (Index < 0 || Index >= fRows.CountItems()) + fRows.AddItem(Row); + else + fRows.AddItem(Row, Index); + } + } + + if (ParentRow == 0 || ParentRow->fIsExpanded) + fItemsHeight += Row->Height() + 1; + + FixScrollBar(false); + + BRect newRowRect; + bool newRowIsInOpenBranch = FindRect(Row, &newRowRect); + + if (fFocusRow && fFocusRowRect.top > newRowRect.bottom) { + // The focus row has moved. + Invalidate(fFocusRowRect); + FindRect(fFocusRow, &fFocusRowRect); + Invalidate(fFocusRowRect); + } + + if (newRowIsInOpenBranch) { + if (fCurrentState == INACTIVE) { + if (newRowRect.bottom < fVisibleRect.top) { + // The new row is totally above the current viewport, move + // everything down and redraw the first line. + BRect source(fVisibleRect); + BRect dest(fVisibleRect); + source.bottom -= Row->Height() + 1; + dest.top += Row->Height() + 1; + CopyBits(source, dest); + Invalidate(BRect(fVisibleRect.left, fVisibleRect.top, fVisibleRect.right, + fVisibleRect.top + newRowRect.Height())); + } else if (newRowRect.top < fVisibleRect.bottom) { + // New item is somewhere in the current region. Scroll everything + // beneath it down and invalidate just the new row rect. + BRect source(fVisibleRect.left, newRowRect.top, fVisibleRect.right, + fVisibleRect.bottom - newRowRect.Height()); + BRect dest(source); + dest.OffsetBy(0, newRowRect.Height() + 1); + CopyBits(source, dest); + Invalidate(newRowRect); + } // otherwise, this is below the currently visible region + } else { + // Adding the item may have caused the item that the user is currently + // selected to move. This would cause annoying drawing and interaction + // bugs, as the position of that item is cached. If this happens, resize + // the scroll bar, then scroll back so the selected item is in view. + BRect targetRect; + if (FindRect(fTargetRow, &targetRect)) { + float delta = targetRect.top - fTargetRowTop; + if (delta != 0) { + // This causes a jump because ScrollBy will copy a chunk of the view. + // Since the actual contents of the view have been offset, we don't + // want this, we just want to change the virtual origin of the window. + // Constrain the clipping region so everything is clipped out so no + // copy occurs. + // + // xxx this currently doesn't work if the scroll bars aren't enabled. + // everything will still move anyway. A minor annoyance. + BRegion emptyRegion; + ConstrainClippingRegion(&emptyRegion); + PushState(); + ScrollBy(0, delta); + PopState(); + ConstrainClippingRegion(NULL); + + fTargetRowTop += delta; + fClickPoint.y += delta; + fLatchRect.OffsetBy(0, delta); + } + } + } + } + + // If the parent was previously childless, it will need to have a latch drawn. + BRect parentRect; + if (ParentRow && ParentRow->fChildList->CountItems() == 1 + && FindVisibleRect(ParentRow, &parentRect)) + Invalidate(parentRect); + } +} + + +void OutlineView::FixScrollBar(bool scrollToFit) +{ + BScrollBar *vScrollBar = ScrollBar(B_VERTICAL); + if (vScrollBar) { + if (fItemsHeight > fVisibleRect.Height()) { + float maxScrollBarValue = (fItemsHeight + kBottomMargin) - fVisibleRect.Height(); + vScrollBar->SetProportion(fVisibleRect.Height() / (fItemsHeight + kBottomMargin)); + + // If the user is scrolled down too far when makes the range smaller, the list + // will jump suddenly, which is undesirable. In this case, don't fix the scroll + // bar here. In ScrollTo, it checks to see if this has occured, and will + // fix the scroll bars sneakily if the user has scrolled up far enough. + if (scrollToFit || vScrollBar->Value() <= maxScrollBarValue) { + vScrollBar->SetRange(0.0, maxScrollBarValue); + vScrollBar->SetSteps(20.0, fVisibleRect.Height()); + } + } else if (vScrollBar->Value() == 0.0) + vScrollBar->SetRange(0.0, 0.0); // disable scroll bar. + } +} + +void OutlineView::AddSorted(BRowContainer *list, BRow *row) +{ + if (list && row) { + // Find general vicinity with binary search. + int32 lower = 0; + int32 upper = list->CountItems()-1; + while( lower < upper ) { + int32 middle = lower + (upper-lower+1)/2; + int32 cmp = CompareRows(row, list->ItemAt(middle)); + if( cmp < 0 ) upper = middle-1; + else if( cmp > 0 ) lower = middle+1; + else lower = upper = middle; + } + + // At this point, 'upper' and 'lower' at the last found item. + // Arbitrarily use 'upper' and determine the final insertion + // point -- either before or after this item. + if( upper < 0 ) upper = 0; + else if( upper < list->CountItems() ) { + if( CompareRows(row, list->ItemAt(upper)) > 0 ) upper++; + } + + if (upper >= list->CountItems()) + list->AddItem(row); // Adding to end. + else + list->AddItem(row, upper); // Insert + } +} + +int32 OutlineView::CompareRows(BRow *row1, BRow *row2) +{ + if (row1 && row2) { + for (int32 index = 0; index < fSortColumns->CountItems(); index++) { + BColumn *column = (BColumn*) fSortColumns->ItemAt(index); + int comp = 0; + BField *field1 = (BField*) row1->GetField(column->fFieldID); + BField *field2 = (BField*) row2->GetField(column->fFieldID); + if (field1 && field2) + comp = column->CompareFields(field1, field2); + + if (!column->fSortAscending) + comp = -comp; + + if (comp != 0) + return comp; + } + } + return 0; +} + +void OutlineView::FrameResized(float width, float height) +{ + fVisibleRect.right = fVisibleRect.left + width; + fVisibleRect.bottom = fVisibleRect.top + height; + FixScrollBar(true); + _inherited::FrameResized(width, height); +} + +void OutlineView::ScrollTo(BPoint position) +{ + fVisibleRect.OffsetTo(position.x, position.y); + + // In FixScrollBar, we might not have been able to change the size of + // the scroll bar because the user was scrolled down too far. Take + // this opportunity to sneak it in if we can. + BScrollBar *vScrollBar = ScrollBar(B_VERTICAL); + float maxScrollBarValue = (fItemsHeight + kBottomMargin) - fVisibleRect.Height(); + float min, max; + vScrollBar->GetRange(&min, &max); + if (max != maxScrollBarValue && position.y > maxScrollBarValue) + FixScrollBar(true); + + _inherited::ScrollTo(position); +} + +const BRect& OutlineView::VisibleRect() const +{ + return fVisibleRect; +} + + +bool OutlineView::FindVisibleRect(BRow *row, BRect *out_rect) +{ + if (row && out_rect) { + float line = 0.0; + for (RecursiveOutlineIterator iterator(&fRows); iterator.CurrentRow(); + iterator.GoToNext()) { + if (line > fVisibleRect.bottom) + break; + + if (iterator.CurrentRow() == row) { + out_rect->Set(fVisibleRect.left, line, fVisibleRect.right, line + row->Height()); + return true; + } + + line += iterator.CurrentRow()->Height() + 1; + } + } + return false; +} + +bool OutlineView::FindRect(const BRow *row, BRect *out_rect) +{ + float line = 0.0; + for (RecursiveOutlineIterator iterator(&fRows); iterator.CurrentRow(); + iterator.GoToNext()) { + if (iterator.CurrentRow() == row) { + out_rect->Set(fVisibleRect.left, line, fVisibleRect.right, line + row->Height()); + return true; + } + + line += iterator.CurrentRow()->Height() + 1; + } + + return false; +} + + +void OutlineView::ScrollTo(const BRow* Row) +{ + BRect rect; + if( true == FindRect(Row, &rect) ) + { + ScrollTo(BPoint(rect.left, rect.top)); + } +} + + +void OutlineView::DeselectAll() +{ + // Invalidate all selected rows + float line = 0.0; + for (RecursiveOutlineIterator iterator(&fRows); iterator.CurrentRow(); + iterator.GoToNext()) { + if (line > fVisibleRect.bottom) + break; + + BRow *row = iterator.CurrentRow(); + if (line + row->Height() > fVisibleRect.top) { + if (row->fNextSelected != 0) + Invalidate(BRect(fVisibleRect.left, line, fVisibleRect.right, + line + row->Height())); + } + + line += row->Height() + 1; + } + + // Set items not selected + while (fSelectionListDummyHead.fNextSelected != &fSelectionListDummyHead) { + BRow *row = fSelectionListDummyHead.fNextSelected; + row->fNextSelected->fPrevSelected = row->fPrevSelected; + row->fPrevSelected->fNextSelected = row->fNextSelected; + row->fNextSelected = 0; + row->fPrevSelected = 0; + } +} + +BRow* OutlineView::FocusRow() const +{ + return fFocusRow; +} + +void OutlineView::SetFocusRow(BRow* Row, bool Select) +{ + if (Row) + { + if(Select) + AddToSelection(Row); + + if(fFocusRow == Row) + return; + + Invalidate(fFocusRowRect); // invalidate previous + + fTargetRow = fFocusRow = Row; + + FindVisibleRect(fFocusRow, &fFocusRowRect); + Invalidate(fFocusRowRect); // invalidate current + + fFocusRowRect.right = 10000; + fMasterView->SelectionChanged(); + } +} + +bool OutlineView::SortList(BRowContainer *list, bool isVisible) +{ + if (list) { + // Shellsort + BRow **items = (BRow**) list->AsBList()->Items(); + int32 numItems = list->CountItems(); + int h; + for (h = 1; h < numItems / 9; h = 3 * h + 1) + ; + + for (;h > 0; h /= 3) { + for (int step = h; step < numItems; step++) { + BRow *temp = items[step]; + int i; + for (i = step - h; i >= 0; i -= h) { + if (CompareRows(temp, items[i]) < 0) + items[i + h] = items[i]; + else + break; + } + + items[i + h] = temp; + } + } + + if (isVisible) { + Invalidate(); + + InvalidateCachedPositions(); + int lockCount = Window()->CountLocks(); + for (int i = 0; i < lockCount; i++) + Window()->Unlock(); + + while (lockCount--) + if (!Window()->Lock()) + return false; // Window is gone... + } + } + return true; +} + +int32 OutlineView::DeepSortThreadEntry(void *_outlineView) +{ + ((OutlineView*) _outlineView)->DeepSort(); + return 0; +} + +void OutlineView::DeepSort() +{ + struct stack_entry { + bool isVisible; + BRowContainer *list; + int32 listIndex; + } stack[kMaxDepth]; + int32 stackTop = 0; + + stack[stackTop].list = &fRows; + stack[stackTop].isVisible = true; + stack[stackTop].listIndex = 0; + fNumSorted = 0; + + if (Window()->Lock() == false) + return; + + bool doneSorting = false; + while (!doneSorting && !fSortCancelled) { + + stack_entry *currentEntry = &stack[stackTop]; + + // xxx Can make the invalidate area smaller by finding the rect for the + // parent item and using that as the top of the invalid rect. + + bool haveLock = SortList(currentEntry->list, currentEntry->isVisible); + if (!haveLock) + return ; // window is gone. + + // Fix focus rect. + InvalidateCachedPositions(); + if (fCurrentState != INACTIVE) + fCurrentState = INACTIVE; // sorry... + + // next list. + bool foundNextList = false; + while (!foundNextList && !fSortCancelled) { + for (int32 index = currentEntry->listIndex; index < currentEntry->list->CountItems(); + index++) { + BRow *parentRow = currentEntry->list->ItemAt(index); + BRowContainer *childList = parentRow->fChildList; + if (childList != 0) { + currentEntry->listIndex = index + 1; + stackTop++; + ASSERT(stackTop < kMaxDepth); + stack[stackTop].listIndex = 0; + stack[stackTop].list = childList; + stack[stackTop].isVisible = (currentEntry->isVisible && parentRow->fIsExpanded); + foundNextList = true; + break; + } + } + + if (!foundNextList) { + // back up + if (--stackTop < 0) { + doneSorting = true; + break; + } + + currentEntry = &stack[stackTop]; + } + } + } + + Window()->Unlock(); +} + +void OutlineView::StartSorting() +{ + // If this view is not yet attached to a window, don't start a sort thread! + if (Window() == NULL) + return; + + if (fSortThread != B_BAD_THREAD_ID) { + thread_info tinfo; + if (get_thread_info(fSortThread, &tinfo) == B_OK) { + // Unlock window so this won't deadlock (sort thread is probably + // waiting to lock window). + + int lockCount = Window()->CountLocks(); + for (int i = 0; i < lockCount; i++) + Window()->Unlock(); + + fSortCancelled = true; + int32 status; + wait_for_thread(fSortThread, &status); + + while (lockCount--) + if (!Window()->Lock()) + return ; // Window is gone... + } + } + + fSortCancelled = false; + fSortThread = spawn_thread(DeepSortThreadEntry, "sort_thread", B_NORMAL_PRIORITY, this); + resume_thread(fSortThread); +} + +void OutlineView::SelectRange(BRow *start, BRow *end) +{ + if (!start || !end) + return; + + if (start == end) // start is always selected when this is called + return; + + RecursiveOutlineIterator iterator(&fRows, false); + while (iterator.CurrentRow() != 0) { + if (iterator.CurrentRow() == end) { + // reverse selection, swap to fix special case + BRow *temp = start; + start = end; + end = temp; + break; + } else if (iterator.CurrentRow() == start) + break; + + iterator.GoToNext(); + } + + while (true) { + BRow *row = iterator.CurrentRow(); + if(row) { + if (row->fNextSelected == 0) { + row->fNextSelected = fSelectionListDummyHead.fNextSelected; + row->fPrevSelected = &fSelectionListDummyHead; + row->fNextSelected->fPrevSelected = row; + row->fPrevSelected->fNextSelected = row; + } + } else + break; + + if (row == end) + break; + + iterator.GoToNext(); + } + + Invalidate(); // xxx make invalidation smaller +} + +bool OutlineView::FindParent(BRow *row, BRow **outParent, bool *out_parentIsVisible) +{ + bool result = false; + if (row && outParent) { + *outParent = row->fParent; + + // Walk up the parent chain to determine if this row is visible + bool isVisible = true; + for (BRow *currentRow = row->fParent; currentRow; currentRow = currentRow->fParent) { + if (!currentRow->fIsExpanded) { + isVisible = false; + break; + } + } + + if (out_parentIsVisible) *out_parentIsVisible = isVisible; + result = (NULL != *outParent); + } + + return result; +} + +int32 OutlineView::IndexOf(BRow *row) +{ + if (row) { + if (row->fParent == 0) + return fRows.IndexOf(row); + + ASSERT(row->fParent->fChildList); + return row->fParent->fChildList->IndexOf(row); + } + + return B_ERROR; +} + +void OutlineView::InvalidateCachedPositions() +{ + if (fFocusRow) + FindRect(fFocusRow, &fFocusRowRect); +} + +// #pragma mark - + + +RecursiveOutlineIterator::RecursiveOutlineIterator(BRowContainer *list, bool openBranchesOnly) + : fStackIndex(0), + fCurrentListIndex(0), + fCurrentListDepth(0), + fOpenBranchesOnly(openBranchesOnly) +{ + if (list == 0 || list->CountItems() == 0) + fCurrentList = 0; + else + fCurrentList = list; +} + +BRow* RecursiveOutlineIterator::CurrentRow() const +{ + if (fCurrentList == 0) + return 0; + + return fCurrentList->ItemAt(fCurrentListIndex); +} + +void RecursiveOutlineIterator::GoToNext() +{ + if (fCurrentList == 0) + return; + if (fCurrentListIndex < 0 || fCurrentListIndex >= fCurrentList->CountItems()) { + fCurrentList = 0; + return; + } + + BRow *currentRow = fCurrentList->ItemAt(fCurrentListIndex); + if(currentRow) { + if (currentRow->fChildList && (currentRow->fIsExpanded || !fOpenBranchesOnly) + && currentRow->fChildList->CountItems() > 0) { + // Visit child. + // Put current list on the stack if it needs to be revisited. + if (fCurrentListIndex < fCurrentList->CountItems() - 1) { + fStack[fStackIndex].fRowSet = fCurrentList; + fStack[fStackIndex].fIndex = fCurrentListIndex + 1; + fStack[fStackIndex].fDepth = fCurrentListDepth; + fStackIndex++; + } + + fCurrentList = currentRow->fChildList; + fCurrentListIndex = 0; + fCurrentListDepth++; + } else if (fCurrentListIndex < fCurrentList->CountItems() - 1) + fCurrentListIndex++; // next item in current list + else if (--fStackIndex >= 0) { + fCurrentList = fStack[fStackIndex].fRowSet; + fCurrentListIndex = fStack[fStackIndex].fIndex; + fCurrentListDepth = fStack[fStackIndex].fDepth; + } else + fCurrentList = 0; + } +} + +int32 RecursiveOutlineIterator::CurrentLevel() const +{ + return fCurrentListDepth; +} diff --git a/library/libclv/ColumnTypes.cpp b/library/libclv/ColumnTypes.cpp new file mode 100644 index 0000000..efa6c12 --- /dev/null +++ b/library/libclv/ColumnTypes.cpp @@ -0,0 +1,667 @@ +/******************************************************************************* +/ +/ File: ColumnTypes.h +/ +/ Description: Experimental classes that implement particular column/field +/ data types for use in BColumnListView. +/ +/ Copyright 2000+, Be Incorporated, All Rights Reserved +/ +*******************************************************************************/ + +#include "ColumnTypes.h" +#include +#include +#include + +#define kTEXT_MARGIN 8 + + +//===================================================================== + +BTitledColumn::BTitledColumn(const char* title, float width, float minWidth, + float maxWidth, alignment align) + :BColumn(width, minWidth, maxWidth, align), + fTitle(title) +{ + font_height fh; + + be_plain_font->GetHeight(&fh); + fFontHeight = fh.descent + fh.leading; +} + + +//-------------------------------------------------------------------- + +void BTitledColumn::DrawTitle(BRect rect, BView* parent) +{ + float width = rect.Width() - (2 * kTEXT_MARGIN); + BString out_string(fTitle); + + parent->TruncateString(&out_string, B_TRUNCATE_END, width + 2); + DrawString(out_string.String(), parent, rect); +} + + +//-------------------------------------------------------------------- + +void BTitledColumn::GetColumnName(BString* into) const +{ + *into = fTitle; +} + + +//-------------------------------------------------------------------- + +void BTitledColumn::DrawString(const char* string, BView* parent, BRect rect) +{ + float width = rect.Width() - (2 * kTEXT_MARGIN); + float y; + BFont font; + font_height finfo; + + parent->GetFont(&font); + font.GetHeight(&finfo); + y = rect.top + ((rect.Height() - (finfo.ascent + finfo.descent + finfo.leading)) / 2) + + (finfo.ascent + finfo.descent) - 2; + + switch (Alignment()) + { + case B_ALIGN_LEFT: + parent->MovePenTo(rect.left + kTEXT_MARGIN, y); + break; + + case B_ALIGN_CENTER: + parent->MovePenTo(rect.left + kTEXT_MARGIN + ((width - font.StringWidth(string)) / 2), y); + break; + + case B_ALIGN_RIGHT: + parent->MovePenTo(rect.right - kTEXT_MARGIN - font.StringWidth(string), y); + break; + } + parent->DrawString(string); +} + + +//-------------------------------------------------------------------- + +void BTitledColumn::SetTitle(const char* title) +{ + fTitle.SetTo(title); +} + + +//-------------------------------------------------------------------- + +void BTitledColumn::Title(BString* forTitle) const +{ + if (forTitle) + forTitle->SetTo(fTitle.String()); +} + + +//-------------------------------------------------------------------- + +float BTitledColumn::FontHeight() const +{ + return fFontHeight; +} + +// #pragma mark - + +//===================================================================== + +BStringField::BStringField(const char* string) + :fWidth(0), + fString(string), + fClippedString(string) +{ +} + + +//-------------------------------------------------------------------- + +void BStringField::SetString(const char* val) +{ + fString = val; + fClippedString = ""; + fWidth = 0; +} + + +//-------------------------------------------------------------------- + +const char* BStringField::String() const +{ + return fString.String(); +} + + +//-------------------------------------------------------------------- + +void BStringField::SetWidth(float width) +{ + fWidth = width; +} + +//-------------------------------------------------------------------- + +float BStringField::Width() +{ + return fWidth; +} + + +//-------------------------------------------------------------------- + +void BStringField::SetClippedString(const char* val) +{ + fClippedString = val; +} + + +//-------------------------------------------------------------------- + +const char* BStringField::ClippedString() +{ + return fClippedString.String(); +} + +// #pragma mark - + +//===================================================================== + +BStringColumn::BStringColumn(const char* title, float width, float minWidth, + float maxWidth, uint32 truncate, alignment align) + :BTitledColumn(title, width, minWidth, maxWidth, align), + fTruncate(truncate) +{ +} + + +//-------------------------------------------------------------------- + +void BStringColumn::DrawField(BField* _field, BRect rect, BView* parent) +{ + float width = rect.Width() - (2 * kTEXT_MARGIN); + BStringField* field = static_cast(_field); + + if (width != field->Width()) + { + BString out_string(field->String()); + + parent->TruncateString(&out_string, fTruncate, width + 2); + field->SetClippedString(out_string.String()); + field->SetWidth(width); + } + DrawString(field->ClippedString(), parent, rect); +} + + +//-------------------------------------------------------------------- + +int BStringColumn::CompareFields(BField* field1, BField* field2) +{ + return(ICompare(((BStringField*)field1)->String(), + (((BStringField*)field2)->String()))); +} + + +//-------------------------------------------------------------------- + +bool BStringColumn::AcceptsField(const BField *field) const +{ + return static_cast(dynamic_cast(field)); +} + +// #pragma mark - + +//===================================================================== + +BDateField::BDateField(time_t *t) + :fTime(*localtime(t)), + fUnixTime(*t), + fSeconds(0), + fClippedString(""), + fWidth(0) +{ + fSeconds = mktime(&fTime); +} + + +//-------------------------------------------------------------------- + +void BDateField::SetWidth(float width) +{ + fWidth = width; +} + + +//-------------------------------------------------------------------- + +float BDateField::Width() +{ + return fWidth; +} + + +//-------------------------------------------------------------------- + +void BDateField::SetClippedString(const char* val) +{ + fClippedString = val; +} + + +//-------------------------------------------------------------------- + +const char* BDateField::ClippedString() +{ + return fClippedString.String(); +} + + +//-------------------------------------------------------------------- + +time_t BDateField::Seconds() +{ + return fSeconds; +} + + +//-------------------------------------------------------------------- + +time_t BDateField::UnixTime() +{ + return fUnixTime; +} + +// #pragma mark - + +//===================================================================== + +BDateColumn::BDateColumn(const char* title, float width, float minWidth, + float maxWidth, alignment align) + :BTitledColumn(title, width, minWidth, maxWidth, align), + fTitle(title) +{ +} + + +//-------------------------------------------------------------------- + +const char *kTIME_FORMATS[] = { + "%A, %B %d %Y, %I:%M:%S %p", // Monday, July 09 1997, 05:08:15 PM + "%a, %b %d %Y, %I:%M:%S %p", // Mon, Jul 09 1997, 05:08:15 PM + "%a, %b %d %Y, %I:%M %p", // Mon, Jul 09 1997, 05:08 PM + "%b %d %Y, %I:%M %p", // Jul 09 1997, 05:08 PM + "%m/%d/%y, %I:%M %p", // 07/09/97, 05:08 PM + "%m/%d/%y", // 07/09/97 + NULL +}; + +void BDateColumn::DrawField(BField* _field, BRect rect, BView* parent) +{ + float width = rect.Width() - (2 * kTEXT_MARGIN); + BDateField* field = (BDateField*)_field; + + if (field->Width() != rect.Width()) + { + char dateString[256]; + time_t curtime = field->UnixTime(); + tm time_data; + BFont font; + + parent->GetFont(&font); + localtime_r(&curtime, &time_data); + for (int32 index = 0; ; index++) + { + if (!kTIME_FORMATS[index]) + break; + strftime(dateString, 256, kTIME_FORMATS[index], &time_data); + if (font.StringWidth(dateString) <= width) + break; + } + + if (font.StringWidth(dateString) > width) + { + BString out_string(dateString); + + parent->TruncateString(&out_string, B_TRUNCATE_MIDDLE, width + 2); + strcpy(dateString, out_string.String()); + } + field->SetClippedString(dateString); + field->SetWidth(width); + } + + DrawString(field->ClippedString(), parent, rect); +} + + +//-------------------------------------------------------------------- + +int BDateColumn::CompareFields(BField* field1, BField* field2) +{ + return((BDateField*)field1)->Seconds() - ((BDateField*)field2)->Seconds(); +} + +// #pragma mark - + +//===================================================================== + +BSizeField::BSizeField(off_t size) + :fSize(size) +{ +} + + +//-------------------------------------------------------------------- + +void BSizeField::SetSize(off_t size) +{ + fSize = size; +} + + +//-------------------------------------------------------------------- + +off_t BSizeField::Size() +{ + return fSize; +} + +// #pragma mark - + +//===================================================================== + +BSizeColumn::BSizeColumn(const char* title, float width, float minWidth, + float maxWidth, alignment align) + :BTitledColumn(title, width, minWidth, maxWidth, align) +{ +} + + +//-------------------------------------------------------------------- + +const int64 kKB_SIZE = 1024; +const int64 kMB_SIZE = 1048576; +const int64 kGB_SIZE = 1073741824; +const int64 kTB_SIZE = kGB_SIZE * kKB_SIZE; + +const char *kSIZE_FORMATS[] = { + "%.2f %s", + "%.1f %s", + "%.f %s", + "%.f%s", + 0 +}; + +void BSizeColumn::DrawField(BField* _field, BRect rect, BView* parent) +{ + char str[256]; + float width = rect.Width() - (2 * kTEXT_MARGIN); + BFont font; + BString string; + off_t size = ((BSizeField*)_field)->Size(); + + parent->GetFont(&font); + if (size < kKB_SIZE) + { + sprintf(str, "%Ld bytes", size); + if (font.StringWidth(str) > width) + sprintf(str, "%Ld B", size); + } + else + { + const char* suffix; + float float_value; + if (size >= kTB_SIZE) + { + suffix = "TB"; + float_value = (float)size / kTB_SIZE; + } + else if (size >= kGB_SIZE) + { + suffix = "GB"; + float_value = (float)size / kGB_SIZE; + } + else if (size >= kMB_SIZE) + { + suffix = "MB"; + float_value = (float)size / kMB_SIZE; + } + else + { + suffix = "KB"; + float_value = (float)size / kKB_SIZE; + } + + for (int32 index = 0; ; index++) + { + if (!kSIZE_FORMATS[index]) + break; + + sprintf(str, kSIZE_FORMATS[index], float_value, suffix); + // strip off an insignificant zero so we don't get readings + // such as 1.00 + char *period = 0; + char *tmp (NULL); + for (tmp = str; *tmp; tmp++) + { + if (*tmp == '.') + period = tmp; + } + if (period && period[1] && period[2] == '0') + // move the rest of the string over the insignificant zero + for (tmp = &period[2]; *tmp; tmp++) + *tmp = tmp[1]; + if (font.StringWidth(str) <= width) + break; + } + } + + + string = str; + parent->TruncateString(&string, B_TRUNCATE_MIDDLE, width + 2); + DrawString(string.String(), parent, rect); +} + + +//-------------------------------------------------------------------- + +int BSizeColumn::CompareFields(BField* field1, BField* field2) +{ + return ((BSizeField*)field1)->Size() - ((BSizeField*)field2)->Size(); +} + +// #pragma mark - + +//===================================================================== + +BIntegerField::BIntegerField(int32 number) + :fInteger(number) +{ +} + + +//-------------------------------------------------------------------- + +void BIntegerField::SetValue(int32 value) +{ + fInteger = value; +} + + +//-------------------------------------------------------------------- + +int32 BIntegerField::Value() +{ + return fInteger; +} + +// #pragma mark - + +//===================================================================== + +BIntegerColumn::BIntegerColumn(const char* title, float width, float minWidth, + float maxWidth, alignment align) + :BTitledColumn(title, width, minWidth, maxWidth, align) +{ +} + + +//-------------------------------------------------------------------- + +void BIntegerColumn::DrawField(BField *field, BRect rect, BView* parent) +{ + char formatted[256]; + float width = rect.Width() - (2 * kTEXT_MARGIN); + BString string; + + sprintf(formatted, "%d", (int)((BIntegerField*)field)->Value()); + + string = formatted; + parent->TruncateString(&string, B_TRUNCATE_MIDDLE, width + 2); + DrawString(string.String(), parent, rect); +} + + +//-------------------------------------------------------------------- + +int BIntegerColumn::CompareFields(BField *field1, BField *field2) +{ + return (((BIntegerField*)field1)->Value() - ((BIntegerField*)field2)->Value()); +} + +// #pragma mark - + +//===================================================================== + +GraphColumn::GraphColumn(const char* name, float width, float minWidth, + float maxWidth, alignment align) + :BIntegerColumn(name, width, minWidth, maxWidth, align) +{ +} + + +//-------------------------------------------------------------------- + +void GraphColumn::DrawField(BField* field, BRect rect, BView* parent) +{ + int number = ((BIntegerField*)field)->Value(); + + if (number > 100) + number = 100; + else if (number < 0) + number = 0; + + BRect graphRect(rect); + graphRect.InsetBy(5, 3); + parent->StrokeRect(graphRect); + if (number > 0) { + graphRect.InsetBy(1, 1); + float val = graphRect.Width() * (float) number / 100; + graphRect.right = graphRect.left + val; + parent->SetHighColor(0, 0, 190); + parent->FillRect(graphRect); + } + + parent->SetDrawingMode(B_OP_INVERT); + parent->SetHighColor(128, 128, 128); + char numstr[256]; + sprintf(numstr, "%d%%", number); + + float width = be_plain_font->StringWidth(numstr); + parent->MovePenTo(rect.left + rect.Width() / 2 - width / 2, rect.bottom - FontHeight()); + parent->DrawString(numstr); +} + +// #pragma mark - + +//===================================================================== + +BBitmapField::BBitmapField(BBitmap *bitmap) + :fBitmap(bitmap) +{ +} + + +//-------------------------------------------------------------------- + +const BBitmap* BBitmapField::Bitmap() +{ + return fBitmap; +} + +//-------------------------------------------------------------------- + +void BBitmapField::SetBitmap(BBitmap* bitmap) +{ + fBitmap = bitmap; +} + +// #pragma mark - + +//===================================================================== + +BBitmapColumn::BBitmapColumn(const char* title, float width, float minWidth, + float maxWidth, alignment align) + :BTitledColumn(title, width, minWidth, maxWidth, align) +{ +} + + +//-------------------------------------------------------------------- + +void BBitmapColumn::DrawField(BField* field, BRect rect, BView* parent) +{ + BBitmapField *bitmapField = static_cast(field); + const BBitmap *bitmap = bitmapField->Bitmap(); + + if (bitmap != NULL) + { + float x = 0.0; + float y; + BRect r = bitmap->Bounds(); + + y = rect.top + ((rect.Height() - r.Height()) / 2); + + switch (Alignment()) + { + case B_ALIGN_LEFT: + x = rect.left + kTEXT_MARGIN; + break; + + case B_ALIGN_CENTER: + x = rect.left + ((rect.Width() - r.Width()) / 2); + break; + + case B_ALIGN_RIGHT: + x = rect.right - kTEXT_MARGIN - r.Width(); + break; + } + parent->SetDrawingMode(B_OP_ALPHA); + parent->DrawBitmap(bitmap, BPoint(x, y)); + parent->SetDrawingMode(B_OP_OVER); + } +} + + +//-------------------------------------------------------------------- + +int BBitmapColumn::CompareFields(BField* /*field1*/, BField* /*field2*/) +{ + // Comparing bitmaps doesn't really make sense... + return 0; +} + + +//-------------------------------------------------------------------- + +bool +BBitmapColumn::AcceptsField(const BField *field) const +{ + return static_cast(dynamic_cast(field)); +} + + diff --git a/library/libclv/Jamfile b/library/libclv/Jamfile new file mode 100644 index 0000000..3392855 --- /dev/null +++ b/library/libclv/Jamfile @@ -0,0 +1,27 @@ + +SubDir TOP libclv ; + +if $(OSPLAT) = X86 { + C++FLAGS += -Wno-sign-compare -Wno-overloaded-virtual ; +} + + +SAVED_DEFINES = $(DEFINES) ; + +DEFINES = $(SAVED_DEFINES) ; + +SubDirSysHdrs $(TOP)/libclv/include ; +SubDirSysHdrs /boot/home/config/include ; +SubDirSysHdrs /boot/beos/etc/develop/zeta-r1-gcc2-x86/headers/be/locale ; + +LINKFLAGS += -L/boot/home/config/lib ; +LINKFLAGS += -L$(TOP)/libs ; +LINKFLAGS += -L/boot/develop/headers/be ; + +# +StaticLibrary libclv.a : + ColorTools.cpp + ColumnListView.cpp + ColumnTypes.cpp + ; +# diff --git a/library/libclv/ObjectList.h b/library/libclv/ObjectList.h new file mode 100644 index 0000000..bfa1832 --- /dev/null +++ b/library/libclv/ObjectList.h @@ -0,0 +1,866 @@ +/* +Open Tracker License + +Terms and Conditions + +Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice applies to all licensees +and shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Be Incorporated shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from Be Incorporated. + +Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks +of Be Incorporated in the United States and other countries. Other brand product +names are registered trademarks or trademarks of their respective holders. +All rights reserved. +*/ + +/**************************************************************************** +** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ** +** ** +** DANGER, WILL ROBINSON! ** +** ** +** The interfaces contained here are part of BeOS's ** +** ** +** >> PRIVATE NOT FOR PUBLIC USE << ** +** ** +** implementation. ** +** ** +** These interfaces WILL CHANGE in future releases. ** +** If you use them, your app WILL BREAK at some future time. ** +** ** +** (And yes, this does mean that binaries built from OpenTracker will not ** +** be compatible with some future releases of the OS. When that happens, ** +** we will provide an updated version of this file to keep compatibility.) ** +** ** +** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ** +****************************************************************************/ + +// +// ObjectList is a wrapper around BList that adds type safety, +// optional object ownership, search, insert operations, etc. +// + +#ifndef __OBJECT_LIST__ +#define __OBJECT_LIST__ + +#ifndef _BE_H +#include +#endif + +#include + + +template class BObjectList; + +template +struct UnaryPredicate { + + virtual int operator()(const T *) const + // virtual could be avoided here if FindBinaryInsertionIndex, + // etc. were member template functions + { return 0; } + +private: + static int _unary_predicate_glue(const void *item, void *context); + +friend class BObjectList; +}; + +template +int +UnaryPredicate::_unary_predicate_glue(const void *item, void *context) +{ + return ((UnaryPredicate *)context)->operator()((const T *)item); +} + + +class _PointerList_ : public BList { +public: + _PointerList_(const _PointerList_ &list); + _PointerList_(int32 itemsPerBlock = 20, bool owning = false); + ~_PointerList_(); + + typedef void *(* GenericEachFunction)(void *, void *); + typedef int (* GenericCompareFunction)(const void *, const void *); + typedef int (* GenericCompareFunctionWithState)(const void *, const void *, + void *); + typedef int (* UnaryPredicateGlue)(const void *, void *); + + void *EachElement(GenericEachFunction, void *); + void SortItems(GenericCompareFunction); + void SortItems(GenericCompareFunctionWithState, void *state); + void HSortItems(GenericCompareFunction); + void HSortItems(GenericCompareFunctionWithState, void *state); + + void *BinarySearch(const void *, GenericCompareFunction) const; + void *BinarySearch(const void *, GenericCompareFunctionWithState, void *state) const; + + int32 BinarySearchIndex(const void *, GenericCompareFunction) const; + int32 BinarySearchIndex(const void *, GenericCompareFunctionWithState, void *state) const; + int32 BinarySearchIndexByPredicate(const void *, UnaryPredicateGlue) const; + + bool Owning() const; + bool ReplaceItem(int32, void *); + +protected: + bool owning; + +}; + +template +class BObjectList : private _PointerList_ { +public: + + // iteration and sorting + typedef T *(* EachFunction)(T *, void *); + typedef const T *(* ConstEachFunction)(const T *, void *); + typedef int (* CompareFunction)(const T *, const T *); + typedef int (* CompareFunctionWithState)(const T *, const T *, void *state); + + BObjectList(int32 itemsPerBlock = 20, bool owning = false); + BObjectList(const BObjectList &list); + // clones list; if list is owning, makes copies of all + // the items + + virtual ~BObjectList(); + + BObjectList &operator=(const BObjectList &list); + // clones list; if list is owning, makes copies of all + // the items + + // adding and removing + // ToDo: + // change Add calls to return const item + bool AddItem(T *); + bool AddItem(T *, int32); + bool AddList(BObjectList *); + bool AddList(BObjectList *, int32); + + bool RemoveItem(T *, bool deleteIfOwning = true); + // if owning, deletes the removed item + T *RemoveItemAt(int32); + // returns the removed item + + void MakeEmpty(bool deleteIfOwning = true); + + // item access + T *ItemAt(int32) const; + + bool ReplaceItem(int32 index, T *); + // if list is owning, deletes the item at first + T *SwapWithItem(int32 index, T *newItem); + // same as ReplaceItem, except does not delete old item at , + // returns it instead + + T *FirstItem() const; + T *LastItem() const; + + // misc. getters + int32 IndexOf(const T *) const; + bool HasItem(const T *) const; + bool IsEmpty() const; + int32 CountItems() const; + + T *EachElement(EachFunction, void *); + const T *EachElement(ConstEachFunction, void *) const; + + void SortItems(CompareFunction); + void SortItems(CompareFunctionWithState, void *state); + void HSortItems(CompareFunction); + void HSortItems(CompareFunctionWithState, void *state); + + // linear search, returns first item that matches predicate + const T *FindIf(const UnaryPredicate &) const; + T *FindIf(const UnaryPredicate &); + + // list must be sorted with CompareFunction for these to work + T *BinarySearch(const T &, CompareFunction) const; + T *BinarySearch(const T &, CompareFunctionWithState, void *state) const; + + template + T *BinarySearchByKey(const Key &key, int (*compare)(const Key *, const T *)) + const; + + template + T *BinarySearchByKey(const Key &key, + int (*compare)(const Key *, const T *, void *), void *state) const; + + int32 BinarySearchIndex(const T &item, CompareFunction compare) const; + int32 BinarySearchIndex(const T &item, CompareFunctionWithState compare, + void *state) const; + + template + int32 BinarySearchIndexByKey(const Key &key, + int (*compare)(const Key *, const T *)) const; + + // Binary insertion - list must be sorted with CompareFunction for + // these to work + + // simple insert + bool BinaryInsert(T *, CompareFunction); + bool BinaryInsert(T *, CompareFunctionWithState, void *state); + bool BinaryInsert(T *, const UnaryPredicate &); + + // unique insert, returns false if item already in list + bool BinaryInsertUnique(T *, CompareFunction); + bool BinaryInsertUnique(T *, CompareFunctionWithState, void *state); + bool BinaryInsertUnique(T *, const UnaryPredicate &); + + // insert a copy of the item, returns new inserted item + T *BinaryInsertCopy(const T ©This, CompareFunction); + T *BinaryInsertCopy(const T ©This, CompareFunctionWithState, void *state); + + // insert a copy of the item if not in list already + // returns new inserted item or existing item in case of a conflict + T *BinaryInsertCopyUnique(const T ©This, CompareFunction); + T *BinaryInsertCopyUnique(const T ©This, CompareFunctionWithState, void *state); + + int32 FindBinaryInsertionIndex(const UnaryPredicate &, bool *alreadyInList = 0) const; + // returns either the index into which a new item should be inserted + // or index of an existing item that matches the predicate + + // deprecated API, will go away + BList *AsBList() + { return this; } + const BList *AsBList() const + { return this; } +private: + void SetItem(int32, T *); +}; + +template +Result +WhileEachListItem(BObjectList *list, Result (Item::*func)(Param1), Param1 p1) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (list->ItemAt(index)->*func)(p1)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (*func)(Item *, Param1), Param1 p1) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (*func)(list->ItemAt(index), p1)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (Item::*func)(Param1, Param2), + Param1 p1, Param2 p2) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (list->ItemAt(index)->*func)(p1, p2)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (*func)(Item *, Param1, Param2), + Param1 p1, Param2 p2) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (*func)(list->ItemAt(index), p1, p2)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (*func)(Item *, Param1, Param2, + Param3, Param4), Param1 p1, Param2 p2, Param3 p3, Param4 p4) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (*func)(list->ItemAt(index), p1, p2, p3, p4)) != 0) + break; + + return result; +} + +template +void +EachListItemIgnoreResult(BObjectList *list, Result (Item::*func)()) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (list->ItemAt(index)->*func)(); +} + +template +void +EachListItem(BObjectList *list, void (*func)(Item *, Param1), Param1 p1) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1); +} + +template +void +EachListItem(BObjectList *list, void (Item::*func)(Param1, Param2), + Param1 p1, Param2 p2) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (list->ItemAt(index)->*func)(p1, p2); +} + +template +void +EachListItem(BObjectList *list, void (*func)(Item *,Param1, Param2), + Param1 p1, Param2 p2) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1, p2); +} + +template +void +EachListItem(BObjectList *list, void (*func)(Item *,Param1, Param2, + Param3), Param1 p1, Param2 p2, Param3 p3) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1, p2, p3); +} + + +template +void +EachListItem(BObjectList *list, void (*func)(Item *,Param1, Param2, + Param3, Param4), Param1 p1, Param2 p2, Param3 p3, Param4 p4) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1, p2, p3, p4); +} + +// inline code + +inline bool +_PointerList_::Owning() const +{ + return owning; +} + +template +BObjectList::BObjectList(int32 itemsPerBlock, bool owning) + : _PointerList_(itemsPerBlock, owning) +{ +} + +template +BObjectList::BObjectList(const BObjectList &list) + : _PointerList_(list) +{ + owning = list.owning; + if (owning) { + // make our own copies in an owning list + int32 count = list.CountItems(); + for (int32 index = 0; index < count; index++) { + T *item = list.ItemAt(index); + if (item) + item = new T(*item); + SetItem(index, item); + } + } +} + +template +BObjectList::~BObjectList() +{ + if (Owning()) + // have to nuke elements first + MakeEmpty(); +} + +template +BObjectList & +BObjectList::operator=(const BObjectList &list) +{ + owning = list.owning; + BObjectList &result = (BObjectList &)_PointerList_::operator=(list); + if (owning) { + // make our own copies in an owning list + int32 count = list.CountItems(); + for (int32 index = 0; index < count; index++) { + T *item = list.ItemAt(index); + if (item) + item = new T(*item); + SetItem(index, item); + } + } + return result; +} + +template +bool +BObjectList::AddItem(T *item) +{ + // need to cast to void * to make T work for const pointers + return _PointerList_::AddItem((void *)item); +} + +template +bool +BObjectList::AddItem(T *item, int32 atIndex) +{ + return _PointerList_::AddItem((void *)item, atIndex); +} + +template +bool +BObjectList::AddList(BObjectList *newItems) +{ + return _PointerList_::AddList(newItems); +} + +template +bool +BObjectList::AddList(BObjectList *newItems, int32 atIndex) +{ + return _PointerList_::AddList(newItems, atIndex); +} + + +template +bool +BObjectList::RemoveItem(T *item, bool deleteIfOwning) +{ + bool result = _PointerList_::RemoveItem((void *)item); + + if (result && Owning() && deleteIfOwning) + delete item; + + return result; +} + +template +T * +BObjectList::RemoveItemAt(int32 index) +{ + return (T *)_PointerList_::RemoveItem(index); +} + +template +inline T * +BObjectList::ItemAt(int32 index) const +{ + return (T *)_PointerList_::ItemAt(index); +} + +template +bool +BObjectList::ReplaceItem(int32 index, T *item) +{ + if (owning) + delete ItemAt(index); + return _PointerList_::ReplaceItem(index, (void *)item); +} + +template +T * +BObjectList::SwapWithItem(int32 index, T *newItem) +{ + T *result = ItemAt(index); + _PointerList_::ReplaceItem(index, (void *)newItem); + return result; +} + +template +void +BObjectList::SetItem(int32 index, T *newItem) +{ + _PointerList_::ReplaceItem(index, (void *)newItem); +} + +template +int32 +BObjectList::IndexOf(const T *item) const +{ + return _PointerList_::IndexOf((void *)item); +} + +template +T * +BObjectList::FirstItem() const +{ + return (T *)_PointerList_::FirstItem(); +} + +template +T * +BObjectList::LastItem() const +{ + return (T *)_PointerList_::LastItem(); +} + +template +bool +BObjectList::HasItem(const T *item) const +{ + return _PointerList_::HasItem((void *)item); +} + +template +bool +BObjectList::IsEmpty() const +{ + return _PointerList_::IsEmpty(); +} + +template +int32 +BObjectList::CountItems() const +{ + return _PointerList_::CountItems(); +} + +template +void +BObjectList::MakeEmpty(bool deleteIfOwning) +{ + if (owning && deleteIfOwning) { + int32 count = CountItems(); + for (int32 index = 0; index < count; index++) + delete ItemAt(index); + } + _PointerList_::MakeEmpty(); +} + +template +T * +BObjectList::EachElement(EachFunction func, void *params) +{ + return (T *)_PointerList_::EachElement((GenericEachFunction)func, params); +} + + +template +const T * +BObjectList::EachElement(ConstEachFunction func, void *params) const +{ + return (const T *) + const_cast *>(this)->_PointerList_::EachElement( + (GenericEachFunction)func, params); +} + +template +const T * +BObjectList::FindIf(const UnaryPredicate &predicate) const +{ + int32 count = CountItems(); + for (int32 index = 0; index < count; index++) + if (predicate.operator()(ItemAt(index)) == 0) + return ItemAt(index); + return 0; +} + +template +T * +BObjectList::FindIf(const UnaryPredicate &predicate) +{ + int32 count = CountItems(); + for (int32 index = 0; index < count; index++) + if (predicate.operator()(ItemAt(index)) == 0) + return ItemAt(index); + return 0; +} + + +template +void +BObjectList::SortItems(CompareFunction function) +{ + _PointerList_::SortItems((GenericCompareFunction)function); +} + +template +void +BObjectList::SortItems(CompareFunctionWithState function, void *state) +{ + _PointerList_::SortItems((GenericCompareFunctionWithState)function, state); +} + +template +void +BObjectList::HSortItems(CompareFunction function) +{ + _PointerList_::HSortItems((GenericCompareFunction)function); +} + +template +void +BObjectList::HSortItems(CompareFunctionWithState function, void *state) +{ + _PointerList_::HSortItems((GenericCompareFunctionWithState)function, state); +} + +template +T * +BObjectList::BinarySearch(const T &key, CompareFunction func) const +{ + return (T*)_PointerList_::BinarySearch(&key, + (GenericCompareFunction)func); +} + +template +T * +BObjectList::BinarySearch(const T &key, CompareFunctionWithState func, void *state) const +{ + return (T*)_PointerList_::BinarySearch(&key, + (GenericCompareFunctionWithState)func, state); +} + + +template +template +T * +BObjectList::BinarySearchByKey(const Key &key, + int (*compare)(const Key *, const T *)) const +{ + return (T*)_PointerList_::BinarySearch(&key, + (GenericCompareFunction)compare); +} + + +template +template +T * +BObjectList::BinarySearchByKey(const Key &key, + int (*compare)(const Key *, const T *, void *), void *state) const +{ + return (T*)_PointerList_::BinarySearch(&key, + (GenericCompareFunctionWithState)compare, state); +} + + +template +int32 +BObjectList::BinarySearchIndex(const T &item, CompareFunction compare) const +{ + return _PointerList_::BinarySearchIndex(&item, + (GenericCompareFunction)compare); +} + + +template +int32 +BObjectList::BinarySearchIndex(const T &item, + CompareFunctionWithState compare, void *state) const +{ + return _PointerList_::BinarySearchIndex(&item, + (GenericCompareFunctionWithState)compare, state); +} + + +template +template +int32 +BObjectList::BinarySearchIndexByKey(const Key &key, + int (*compare)(const Key *, const T *)) const +{ + return _PointerList_::BinarySearchIndex(&key, + (GenericCompareFunction)compare); +} + + +template +bool +BObjectList::BinaryInsert(T *item, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunction)func); + if (index >= 0) { + // already in list, add after existing + return AddItem(item, index + 1); + } + + return AddItem(item, -index - 1); +} + +template +bool +BObjectList::BinaryInsert(T *item, CompareFunctionWithState func, void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunctionWithState)func, state); + if (index >= 0) { + // already in list, add after existing + return AddItem(item, index + 1); + } + + return AddItem(item, -index - 1); +} + +template +bool +BObjectList::BinaryInsertUnique(T *item, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunction)func); + if (index >= 0) + return false; + + return AddItem(item, -index - 1); +} + +template +bool +BObjectList::BinaryInsertUnique(T *item, CompareFunctionWithState func, void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunctionWithState)func, state); + if (index >= 0) + return false; + + return AddItem(item, -index - 1); +} + + +template +T * +BObjectList::BinaryInsertCopy(const T ©This, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunction)func); + + if (index >= 0) + index++; + else + index = -index - 1; + + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +T * +BObjectList::BinaryInsertCopy(const T ©This, CompareFunctionWithState func, void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunctionWithState)func, state); + + if (index >= 0) + index++; + else + index = -index - 1; + + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +T * +BObjectList::BinaryInsertCopyUnique(const T ©This, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunction)func); + if (index >= 0) + return ItemAt(index); + + index = -index - 1; + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +T * +BObjectList::BinaryInsertCopyUnique(const T ©This, CompareFunctionWithState func, + void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunctionWithState)func, state); + if (index >= 0) + return ItemAt(index); + + index = -index - 1; + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +int32 +BObjectList::FindBinaryInsertionIndex(const UnaryPredicate &pred, bool *alreadyInList) + const +{ + int32 index = _PointerList_::BinarySearchIndexByPredicate(&pred, + (UnaryPredicateGlue)&UnaryPredicate::_unary_predicate_glue); + + if (alreadyInList) + *alreadyInList = index >= 0; + + if (index < 0) + index = -index - 1; + + return index; +} + +template +bool +BObjectList::BinaryInsert(T *item, const UnaryPredicate &pred) +{ + return AddItem(item, FindBinaryInsertionIndex(pred)); +} + +template +bool +BObjectList::BinaryInsertUnique(T *item, const UnaryPredicate &pred) +{ + bool alreadyInList; + int32 index = FindBinaryInsertionIndex(pred, &alreadyInList); + if (alreadyInList) + return false; + + AddItem(item, index); + return true; +} + +#endif /* __OBJECT_LIST__ */ diff --git a/library/libclv/include/ColorTools.h b/library/libclv/include/ColorTools.h new file mode 100644 index 0000000..ad23154 --- /dev/null +++ b/library/libclv/include/ColorTools.h @@ -0,0 +1,69 @@ +/******************************************************************************* +/ +/ File: ColorTools.h +/ +/ Description: Additional experimental color manipulation functions. +/ +/ Copyright 2000, Be Incorporated, All Rights Reserved +/ +*******************************************************************************/ + + +#ifndef _COLOR_TOOLS_H +#define _COLOR_TOOLS_H + +#include + +#if B_BEOS_VERSION <= B_BEOS_VERSION_MAUI + +namespace BExperimental { + +// Comparison operators. + +inline bool operator==(const rgb_color c1, const rgb_color c2) +{ + return (*((uint32*)&c1)) == (*((uint32*)&c2)); +} + +inline bool operator!=(const rgb_color c1, const rgb_color c2) +{ + return (*((uint32*)&c1)) != (*((uint32*)&c2)); +} + +// Color creation. +/* +inline rgb_color make_color(uint8 red, uint8 green, uint8 blue, uint8 alpha=255) +{ + rgb_color c; + c.red = red; + c.green = green; + c.blue = blue; + c.alpha = alpha; + return c; +}*/ + +// Mix two colors together, ignoring their relative alpha channels. +// If amount is 0, the result is color1; if 255, the result is color2; +// if another value, it is somewhere in-between. The resulting alpha +// channel is mixed exactly like the other color channels. +rgb_color mix_color(rgb_color color1, rgb_color color2, uint8 amount); + +// Blend two colors together, weighting by their relative alpha channels. +// The resulting color is the same as mix_color(), except that the amount +// used from color1 and color2's color channels is dependent on that color's +// alpha channel. For example, if color1.alpha is 0 and color2.alpha is +// 255, the resulting red, green, and blue values will be the same as those +// in color2, regardless of 'amount'. +rgb_color blend_color(rgb_color color1, rgb_color color2, uint8 amount); + +// Return a color that is the disabled representation of 'color' when drawn +// on a solid color 'background'. +rgb_color disable_color(rgb_color color, rgb_color background); + +} // namespace BExperimental + +using namespace BExperimental; + +#endif + +#endif diff --git a/library/libclv/include/ColumnListView.h b/library/libclv/include/ColumnListView.h new file mode 100644 index 0000000..6df9d99 --- /dev/null +++ b/library/libclv/include/ColumnListView.h @@ -0,0 +1,343 @@ +/******************************************************************************* +/ +/ File: ColumnListView.h +/ +/ Description: Experimental multi-column list view. +/ +/ Copyright 2000+, Be Incorporated, All Rights Reserved +/ +*******************************************************************************/ + + +#ifndef _COLUMN_LIST_VIEW_H +#define _COLUMN_LIST_VIEW_H + +#include +#include +#include +#include +#include + +class BScrollBar; + +namespace BPrivate { + +class OutlineView; +class TitleView; +class BRowContainer; +class RecursiveOutlineIterator; + +} // ns BPrivate + +class BField; +class BRow; +class BColumn; +class BColumnListView; + +enum LatchType { + B_NO_LATCH, + B_OPEN_LATCH, + B_PRESSED_LATCH, + B_CLOSED_LATCH +}; + +typedef enum { + B_ALLOW_COLUMN_NONE = 0, + B_ALLOW_COLUMN_MOVE = 1, + B_ALLOW_COLUMN_RESIZE = 2, + B_ALLOW_COLUMN_POPUP = 4, + B_ALLOW_COLUMN_REMOVE = 8, +} column_flags; + +enum ColumnListViewColor { + B_COLOR_BACKGROUND = 0, + B_COLOR_TEXT = 1, + B_COLOR_ROW_DIVIDER = 2, + B_COLOR_SELECTION = 3, + B_COLOR_SELECTION_TEXT = 4, + B_COLOR_NON_FOCUS_SELECTION = 5, + B_COLOR_EDIT_BACKGROUND = 6, + B_COLOR_EDIT_TEXT = 7, + B_COLOR_HEADER_BACKGROUND = 8, + B_COLOR_HEADER_TEXT = 9, + B_COLOR_SEPARATOR_LINE = 10, + B_COLOR_SEPARATOR_BORDER = 11, + + B_COLOR_TOTAL = 12 +}; + +enum ColumnListViewFont { + B_FONT_ROW = 0, + B_FONT_HEADER = 1, + + B_FONT_TOTAL = 2 +}; + + +// A single row/column intersection in the list. +class BField { +public: + BField(); + virtual ~BField(); +}; + +// A single line in the list. Each line contains a BField object +// for each column in the list, associated by their "logical field" +// index. Hierarchies are formed by adding other BRow objects as +// a parent of a row, using the AddRow() function in BColumnListView(). +class BRow { +public: + BRow(float height = 16.0); + virtual ~BRow(); + virtual bool HasLatch() const; + + int32 CountFields() const; + BField* GetField(int32 logicalFieldIndex); + const BField* GetField(int32 logicalFieldIndex) const; + void SetField(BField* field, int32 logicalFieldIndex); + + float Height() const; + void SetHeight(float h){fHeight=h;}; + bool IsExpanded() const; + + virtual void DrawBackground( + BRect /*_rect*/, + BView* /*_target_view*/, + bool /*_is_selected*/, + bool /*_is_focus */){} +private: + // Blows up into the debugger if the validation fails. + void ValidateFields() const; + void ValidateField(const BField *field, int32 logicalFieldIndex) const; +private: + BList fFields; + BPrivate:: + BRowContainer* fChildList; + bool fIsExpanded; + float fHeight; + BRow* fNextSelected; + BRow* fPrevSelected; + BRow* fParent; +protected: + BColumnListView* fList; +private: + + friend class BColumnListView; + friend class BPrivate::RecursiveOutlineIterator; + friend class BPrivate::OutlineView; +}; + +// Information about a single column in the list. A column knows +// how to display the BField objects that occur at its location in +// each of the list's rows. See ColumnTypes.h for particular +// subclasses of BField and BColumn that handle common data types. +class BColumn +{ +public: + BColumn(float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + virtual ~BColumn(); + + float Width() const; + void SetWidth(float width); + float MinWidth() const; + float MaxWidth() const; + + virtual void DrawTitle(BRect rect, BView *targetView); + virtual void DrawField(BField *field, BRect rect, BView *targetView); + virtual int CompareFields(BField *field1, BField *field2); + + virtual void MouseMoved(BColumnListView *parent, BRow *row, BField *field, + BRect field_rect, BPoint point, uint32 buttons, int32 code); + virtual void MouseDown(BColumnListView *parent, BRow *row, BField *field, + BRect field_rect, BPoint point, uint32 buttons); + virtual void MouseUp(BColumnListView *parent, BRow *row, BField *field); + + virtual void GetColumnName(BString* into) const; + + bool IsVisible() const; + void SetVisible(bool); + + bool WantsEvents() const; + void SetWantsEvents(bool); + + bool ShowHeading() const; + void SetShowHeading(bool); + + alignment Alignment() const; + void SetAlignment(alignment); + + int32 LogicalFieldNum() const; + + /*! + \param field The BField derivative to validate. + + Implement this function on your BColumn derivatives to validate BField derivatives + that your BColumn will be drawing/manipulating. + + This function will be called when BFields are added to the Column, use dynamic_cast<> to + determine if it is of a kind that your BColumn know how ot handle. return false if it is not. + + \note The debugger will be called if you return false from here with information about + what type of BField and BColumn and the logical field index where it occured. + + \note Do not call the inherited version of this, it just returns true; + */ + virtual bool AcceptsField(const BField* field) const; + +private: + float fWidth; + float fMinWidth; + float fMaxWidth; + bool fVisible; + int32 fFieldID; + BColumnListView *fList; + bool fSortAscending; + bool fWantsEvents; + bool fShowHeading; + alignment fAlignment; + + friend class BPrivate::OutlineView; + friend class BColumnListView; + friend class BPrivate::TitleView; +}; + +// The column list view class. +class BColumnListView : public BView, public BInvoker +{ +public: + BColumnListView(BRect rect, + const char *name, + uint32 resizingMode, + uint32 drawFlags, + border_style = B_NO_BORDER, + bool showHorizontalScrollbar = true); + virtual ~BColumnListView(); + + // Interaction + virtual bool InitiateDrag(BPoint, bool wasSelected); + virtual void MessageDropped(BMessage*, BPoint point); + virtual void ExpandOrCollapse(BRow *row, bool expand); + virtual status_t Invoke(BMessage *message = NULL); + virtual void ItemInvoked(); + virtual void SetInvocationMessage(BMessage*); + BMessage* InvocationMessage() const; + uint32 InvocationCommand() const; + BRow* FocusRow() const; + void SetFocusRow(int32 index, bool select=false); + void SetFocusRow(BRow *row, bool select=false); + void SetMouseTrackingEnabled(bool); + + // Selection + list_view_type SelectionMode() const; + void Deselect(BRow *row); + void AddToSelection(BRow *row); + void DeselectAll(); + BRow* CurrentSelection(BRow *lastSelected = 0) const; + virtual void SelectionChanged(); + virtual void SetSelectionMessage(BMessage *); + BMessage* SelectionMessage(); + uint32 SelectionCommand() const; + void SetSelectionMode(list_view_type); // list_view_type is defined in ListView.h. + + // Sorting + void SetSortingEnabled(bool); + bool SortingEnabled() const; + void SetSortColumn(BColumn *column, bool add, bool ascending); + void ClearSortColumns(); + + // The status view is a little area in the lower left hand corner. + void AddStatusView(BView *view); + BView* RemoveStatusView(); + + // Column Manipulation + void AddColumn(BColumn*, int32 logicalFieldIndex); + void MoveColumn(BColumn*, int32 index); + void RemoveColumn(BColumn*); + int32 CountColumns() const; + BColumn* ColumnAt(int32 index) const; + void SetColumnVisible(BColumn*, bool isVisible); + void SetColumnVisible(int32, bool); + bool IsColumnVisible(int32) const; + void SetColumnFlags(column_flags flags); + + // Row manipulation + const BRow* RowAt(int32 index, BRow *parent = 0) const; + BRow* RowAt(int32 index, BRow *parent = 0); + const BRow* RowAt(BPoint) const; + BRow* RowAt(BPoint); + bool GetRowRect(const BRow *row, BRect *outRect) const; + bool FindParent(BRow *row, BRow **outs_parent, bool *out_isVisible) const; + int32 IndexOf(BRow *row); + int32 CountRows(BRow *parent = 0) const; + void AddRow(BRow*, BRow *parent = 0); + void AddRow(BRow*, int32 index, BRow *parent = 0); + + void ScrollTo(const BRow* Row); + + // Does not delete row or children at this time. + // todo: Make delete row and children + void RemoveRow(BRow*); + + void UpdateRow(BRow*); + void Clear(); + + // Appearance (DEPRECATED) + void GetFont(BFont* font) const {BView::GetFont(font);} + virtual void SetFont(const BFont *font, uint32 mask = B_FONT_ALL); + virtual void SetHighColor(rgb_color); + void SetSelectionColor(rgb_color); + void SetBackgroundColor(rgb_color); + void SetEditColor(rgb_color); + const rgb_color SelectionColor() const; + const rgb_color BackgroundColor() const; + const rgb_color EditColor() const; + + // Appearance (NEW STYLE) + void SetColor(ColumnListViewColor color_num, rgb_color color); + void SetFont(ColumnListViewFont font_num, const BFont* font, uint32 mask = B_FONT_ALL); + rgb_color Color(ColumnListViewColor color_num) const; + void GetFont(ColumnListViewFont font_num, BFont* font) const; + + BPoint SuggestTextPosition(const BRow* row, const BColumn* column=NULL) const; + + void SetLatchWidth(float width); + float LatchWidth() const; + virtual void DrawLatch(BView*, BRect, LatchType, BRow*); + virtual void MakeFocus(bool isfocus = true); + void SaveState(BMessage *msg); + void LoadState(BMessage *msg); + + BView* ScrollView() const { return (BView *)fOutlineView; } + void SetEditMode(bool state); + void Refresh(); + BView* GetScrollView(){ return (BView*)fOutlineView;} + BView* GetTitleView(){ return (BView*)fTitleView;} +protected: + virtual void MessageReceived(BMessage *message); + virtual void KeyDown(const char *bytes, int32 numBytes); + virtual void AttachedToWindow(); + virtual void WindowActivated(bool active); + virtual void Draw(BRect); + + + + +private: + rgb_color fColorList[B_COLOR_TOTAL]; + BPrivate::TitleView* fTitleView; + BPrivate::OutlineView* fOutlineView; + BList fColumns; + BScrollBar* fHorizontalScrollBar; + BScrollBar* fVerticalScrollBar; + BList fSortColumns; + BView* fStatusView; + BMessage* fSelectionMessage; + bool fSortingEnabled; + float fLatchWidth; + border_style fBorderStyle; +}; + +#endif diff --git a/library/libclv/include/ColumnTypes.h b/library/libclv/include/ColumnTypes.h new file mode 100644 index 0000000..9a02beb --- /dev/null +++ b/library/libclv/include/ColumnTypes.h @@ -0,0 +1,254 @@ +/******************************************************************************* +/ +/ File: ColumnTypes.h +/ +/ Description: Experimental classes that implement particular column/field +/ data types for use in BColumnListView. +/ +/ Copyright 2000+, Be Incorporated, All Rights Reserved +/ +*******************************************************************************/ + + +#ifndef _COLUMN_TYPES_H +#define _COLUMN_TYPES_H + +#include "ColumnListView.h" +#include +#include +#include + + +//===================================================================== +// Common base-class: a column that draws a standard title at its top. + +class BTitledColumn : public BColumn +{ + public: + BTitledColumn (const char *title, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + virtual void DrawTitle (BRect rect, + BView* parent); + virtual void GetColumnName (BString* into) const; + + void DrawString (const char*, + BView*, + BRect); + void SetTitle (const char* title); + void Title (BString* forTitle) const; // sets the BString arg to be the title + float FontHeight () const; + + private: + float fFontHeight; + BString fTitle; +}; + + +//===================================================================== +// Field and column classes for strings. + +class BStringField : public BField +{ + public: + BStringField (const char* string); + + void SetString (const char* string); + const char* String () const; + void SetClippedString (const char* string); + const char* ClippedString (); + void SetWidth (float); + float Width (); + + private: + float fWidth; + BString fString; + BString fClippedString; +}; + + +//-------------------------------------------------------------------- + +class BStringColumn : public BTitledColumn +{ + public: + BStringColumn (const char *title, + float width, + float maxWidth, + float minWidth, + uint32 truncate, + alignment align = B_ALIGN_LEFT); + virtual void DrawField (BField* field, + BRect rect, + BView* parent); + virtual int CompareFields (BField* field1, + BField* field2); + virtual bool AcceptsField (const BField* field) const; + + private: + uint32 fTruncate; +}; + + +//===================================================================== +// Field and column classes for dates. + +class BDateField : public BField +{ + public: + BDateField (time_t* t); + void SetWidth (float); + float Width (); + void SetClippedString (const char*); + const char* ClippedString (); + time_t Seconds (); + time_t UnixTime (); + + private: + struct tm fTime; + time_t fUnixTime; + time_t fSeconds; + BString fClippedString; + float fWidth; +}; + + +//-------------------------------------------------------------------- + +class BDateColumn : public BTitledColumn +{ + public: + BDateColumn (const char* title, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + virtual void DrawField (BField* field, + BRect rect, + BView* parent); + virtual int CompareFields (BField* field1, + BField* field2); + private: + BString fTitle; +}; + + +//===================================================================== +// Field and column classes for numeric sizes. + +class BSizeField : public BField +{ + public: + BSizeField (off_t size); + void SetSize (off_t); + off_t Size (); + + private: + off_t fSize; +}; + + +//-------------------------------------------------------------------- + +class BSizeColumn : public BTitledColumn +{ + public: + BSizeColumn (const char* title, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + virtual void DrawField (BField* field, + BRect rect, + BView* parent); + virtual int CompareFields (BField* field1, + BField* field2); +}; + + +//===================================================================== +// Field and column classes for integers. + +class BIntegerField : public BField +{ + public: + BIntegerField (int32 number); + void SetValue (int32); + int32 Value (); + + private: + int32 fInteger; +}; + + +//-------------------------------------------------------------------- + +class BIntegerColumn : public BTitledColumn +{ + public: + BIntegerColumn (const char* title, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + virtual void DrawField (BField* field, + BRect rect, + BView* parent); + virtual int CompareFields (BField* field1, + BField* field2); +}; + + +//===================================================================== +// Field and column classes for bitmaps + +class BBitmapField : public BField +{ + public: + BBitmapField (BBitmap* bitmap); + const BBitmap* Bitmap (); + void SetBitmap (BBitmap* bitmap); + + private: + BBitmap* fBitmap; +}; + + +//-------------------------------------------------------------------- + +class BBitmapColumn : public BTitledColumn +{ + public: + BBitmapColumn (const char* title, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + virtual void DrawField (BField*field, + BRect rect, + BView* parent); + virtual int CompareFields (BField* field1, BField* field2); + virtual bool AcceptsField (const BField* field) const; +}; + + +//===================================================================== +// Column to display BIntegerField objects as a graph. + +class GraphColumn : public BIntegerColumn +{ + public: + GraphColumn (const char* name, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + virtual void DrawField (BField*field, + BRect rect, + BView* parent); +}; + +#endif + diff --git a/library/libfish/BoxRenderer.cpp b/library/libfish/BoxRenderer.cpp new file mode 100644 index 0000000..5b52daf --- /dev/null +++ b/library/libfish/BoxRenderer.cpp @@ -0,0 +1,44 @@ +#include "BoxRenderer.h" + +InstanceBox* +BoxRenderer::CreateInstanceBox(BRect preferredSize,BString txt){ + InstanceBox *box=new InstanceBox(preferredSize,txt,this); + return box; +} + +bool +BoxRenderer::HasAction(InstanceBox* ibox,BPoint p,BString* action) { + if(ibox->action != "" && ibox->rect.Contains(p)) { + if(action) action->SetTo(ibox->action); + return true; + } + else + return false; +} + +void +BoxRenderer::HAlignBox(InstanceBox* box,float maxwidth){ + + alignment ali=box->box_alignment; + + switch (ali) + { + case B_ALIGN_LEFT: + break; + + case B_ALIGN_CENTER: + { + float diff = (maxwidth - box->rect.Width()) / 2.0; + if(diff>0) + box->rect.OffsetBy(diff,0); + break; + } + case B_ALIGN_RIGHT: + { + float diff = (maxwidth - box->rect.right); + if(diff>0) + box->rect.OffsetTo(diff, box->rect.top); + } + break; + } +} diff --git a/library/libfish/BoxRenderer.h b/library/libfish/BoxRenderer.h new file mode 100644 index 0000000..b39daf5 --- /dev/null +++ b/library/libfish/BoxRenderer.h @@ -0,0 +1,33 @@ +#ifndef BoxRenderer_H_ +#define BoxRenderer_H_ + +#include +#include "InstanceBox.h" + +class ContainerBox; + +class BoxRenderer { + + public: + + virtual ~BoxRenderer(){} + + virtual void DrawBox(BView* parent,InstanceBox* ibox) = 0; + virtual InstanceBox* CreateInstanceBox(BRect preferredSize,BString txt); + + + + + + virtual bool HasAction(InstanceBox* ibox,BPoint p,BString* action=NULL); + //virtual void InstanceClicked(InstanceBox* ibox,BPoint abs){}; +// protected: +// class HDoc; + virtual void InitInstanceBox(InstanceBox *,ContainerBox *) = 0; + virtual void FreeInstanceBox(InstanceBox*) = 0; + + protected: + void HAlignBox(InstanceBox* box,float maxwidth); +}; +#endif +//-- diff --git a/library/libfish/CompositeRenderer.cpp b/library/libfish/CompositeRenderer.cpp new file mode 100644 index 0000000..60ca2a1 --- /dev/null +++ b/library/libfish/CompositeRenderer.cpp @@ -0,0 +1,78 @@ +#include "CompositeRenderer.h" + +#define DEBUG 0 + +InstanceBox* +CompositeRenderer::CreateInstanceBox(BRect preferredSize,BString txt){ + ContainerBox *box=new ContainerBox(preferredSize,txt,this); + return (InstanceBox*)box; +} + +void +CompositeRenderer::DrawBox(BView* parent,InstanceBox* ibox){ + ContainerBox* doc=(ContainerBox*)ibox; + int32 count = doc->fBoxes.CountItems(); + BRect r(doc->rect); + InstanceBox* box; + for(int i=0;i< count ; i++){ + box = doc->fBoxes.ItemAt(i); + + if(r.Intersects(box->rect)){ + //draw! + if(DEBUG) + parent->StrokeRect(box->rect); + box->renderer->DrawBox(parent,box); + } + + } +} + +bool +CompositeRenderer::HasAction(InstanceBox* ibox,BPoint p,BString* action){ + ContainerBox* doc=(ContainerBox*)ibox; + int32 count = doc->fBoxes.CountItems(); + InstanceBox* box; + for(int i=0;i< count ; i++){ + box = doc->fBoxes.ItemAt(i); + if(box->renderer->HasAction(box,p,action)){ + return true; + } + } + + return false; +} + +void +CompositeRenderer::InitInstanceBox(InstanceBox *ibox,ContainerBox* parent){ + + //devo settare le dimensioni! + + //debugger("h"); + + ContainerBox* doc=(ContainerBox*)ibox; + + doc->InitSize(parent->MaxWidth()); + + InstanceBox* box; + int32 count = doc->fBoxes.CountItems(); + + for(int i=0;i< count ; i++){ + box = doc->fBoxes.ItemAt(i); + + //if(box->text.Compare("testContainer") == 0) debugger("inner"); + + doc->ArrangeBoxPosition(box); + box->renderer->InitInstanceBox(box,doc); + doc->UpdateSize(box); + + box->rect.OffsetBy(doc->rect.left,doc->rect.top); + } + + +} + + +void +CompositeRenderer::FreeInstanceBox(InstanceBox* ibox){ + //no cookie +} diff --git a/library/libfish/CompositeRenderer.h b/library/libfish/CompositeRenderer.h new file mode 100644 index 0000000..2d15c2f --- /dev/null +++ b/library/libfish/CompositeRenderer.h @@ -0,0 +1,22 @@ +#ifndef CompositeRenderer_H_ +#define CompositeRenderer_H_ + +#include +#include "BoxRenderer.h" +#include "ContainerBox.h" + +class CompositeRenderer : public BoxRenderer { + + public: + + InstanceBox* CreateInstanceBox(BRect preferredSize,BString txt); + + void DrawBox(BView* parent,InstanceBox* ibox); + + void InitInstanceBox(InstanceBox *,ContainerBox *); + void FreeInstanceBox(InstanceBox*); + + bool HasAction(InstanceBox* ibox,BPoint p,BString* action=NULL); +}; +#endif +//-- diff --git a/library/libfish/ContainerBox.h b/library/libfish/ContainerBox.h new file mode 100644 index 0000000..c76d034 --- /dev/null +++ b/library/libfish/ContainerBox.h @@ -0,0 +1,50 @@ +#ifndef ContainerBox_H_ +#define ContainerBox_H_ + +#include "InstanceBox.h" +#include + +class ContainerBox : public InstanceBox { + + public: + ContainerBox(BRect preferredSize,BString txt,BoxRenderer* render): + InstanceBox(preferredSize,txt,renderer){ left_margin=top_margin=0.0;} + + virtual ~ContainerBox(){ + + while(fBoxes.CountItems()){ + InstanceBox *box=fBoxes.ItemAt(0); + box->renderer->FreeInstanceBox(box); + delete box; + fBoxes.RemoveItem(box); + } + + } + + + + + virtual void AddInstanceBox(InstanceBox *box){ + if(!box) return; + //box->renderer->InitInstanceBox(box,this); + fBoxes.AddItem(box); + } + + float GetHeight(){ return rect.Height();} + float GetWidth(){ return rect.Width();} + + virtual void ArrangeBoxPosition(InstanceBox*) {}; + virtual void InitSize(float) {}; + virtual void UpdateSize(InstanceBox* box){} + virtual float MaxWidth(){ return rect.Width() ; /*by default*/} + + //this should be wrapped + BObjectList fBoxes; + + float top_margin; + float left_margin; + + + +}; +#endif diff --git a/library/libfish/HDoc.h b/library/libfish/HDoc.h new file mode 100644 index 0000000..d607f5d --- /dev/null +++ b/library/libfish/HDoc.h @@ -0,0 +1,31 @@ +#ifndef HDoc_H_ +#define HDoc_H_ + +#include "BoxRenderer.h" +#include "VerticalContainerBox.h" + +class HDoc : public VerticalContainerBox { //ContainerBox { + + public:// + + //refactoring: using a BRect. if rect.top==rect.bottom then canGrow = false! + + HDoc(BString fid,float w,float h,float margin,float parSpace):VerticalContainerBox(BRect(0,0,w-1,h-1),fid,NULL,parSpace){ + rgb_color white = {255,255,255,255}; + rgb_color black = {0,0,0,255}; + backColor = white; + foreColor = black; + textFontSize = 14; + titleFontSize = 20; + left_margin = top_margin = 5.0; + }; + + BString DocId(){ return text;} + + public: //TEMP fix me! + rgb_color backColor; + rgb_color foreColor; + int textFontSize; + int titleFontSize; +}; +#endif diff --git a/library/libfish/HelpViewer.cpp b/library/libfish/HelpViewer.cpp new file mode 100644 index 0000000..d0adec1 --- /dev/null +++ b/library/libfish/HelpViewer.cpp @@ -0,0 +1,239 @@ +#include "HelpViewer.h" +#include "OneSView.h" +#include +#include +#include "RVActionGoto.h" +#include "RVActionOpenURL.h" + + +OneSView *sview; //temp fix! +BScrollView *scroll; //temp fix + +RVActionGoto* agoto; +RVActionOpenURL* aopenurl; + +HelpViewer::HelpViewer(BRect r):BView(r,"HelpViewer",B_FOLLOW_ALL_SIDES,B_WILL_DRAW){ + //the view: + BRect rect(Bounds()); + rect.right -=B_V_SCROLL_BAR_WIDTH; + //OneSView * + + ///BView *avv=new BView(rect,"",B_FOLLOW_ALL,B_WILL_DRAW); + sview = new OneSView(rect); + //avv->AddChild(sview); + scroll= new BScrollView("",sview,B_FOLLOW_NONE,B_WILL_DRAW,false,true,B_NO_BORDER); + + rgb_color white = {255,255,255,255}; + rgb_color black = {0,0,0,255}; + backColor = white; + foreColor = black; + + Selected = -1; + SetViewColor(backColor); + AddChild(scroll); + + + sview->AddAction("goto",agoto=new RVActionGoto(this)); + sview->AddAction("openUrl",aopenurl=new RVActionOpenURL(this)); + fGotoHand = NULL; + +} + +void +HelpViewer::SetForeColor(rgb_color c){ foreColor=c;} ; + +void +HelpViewer::SetBackColor(rgb_color c){ backColor=c; SetViewColor(backColor); scroll->SetViewColor(backColor); sview->SetViewColor(backColor);} ; + +HelpViewer::~HelpViewer(){ + //first free all the documents ans InstanceBoxes.. + sview->DisplayDocument(NULL); + for(int i=0;i= fPages.CountItems()) return; + + Selected = newindex; + sview->DisplayDocument(fPages.ItemAt(Selected)); + RecalcScrollbar(); + +} + +int +HelpViewer::CountPage(){ + return fPages.CountItems(); +} + + +void +HelpViewer::LoadFile(const char* filename){ + + xmlParserCtxtPtr ctxt = xmlNewParserCtxt(); + xmlDocPtr doc = xmlCtxtReadFile(ctxt, filename, NULL, XML_PARSE_RECOVER); + xmlXPathContextPtr pathCtxt = xmlXPathNewContext(doc); + + { + xmlXPathObjectPtr itemNode = xmlXPathEvalExpression((const xmlChar *)"/help/page", pathCtxt); + if (itemNode == NULL) { + xmlFreeParserCtxt(ctxt); + xmlXPathFreeContext(pathCtxt); + xmlXPathFreeObject(itemNode); + return; + }; + + if(itemNode->nodesetval == NULL){ + xmlFreeParserCtxt(ctxt); + xmlXPathFreeContext(pathCtxt); + xmlXPathFreeObject(itemNode); + return; + }; + + printf("Number of pages %d\n",itemNode->nodesetval->nodeNr); + for(int i=0;inodesetval->nodeNr;i++){ + ParsePage(itemNode->nodesetval->nodeTab[i]); + } + + } + + + xmlFreeParserCtxt(ctxt); + xmlXPathFreeContext(pathCtxt); +} + +void +HelpViewer::AttachedToWindow(){ + SetBackColor(backColor); +} + + +void +HelpViewer::ParsePage(xmlNodePtr node){ + + BMessage attrs; + findAttribute(node,&attrs); + + BString id=attrs.FindString("id"); + if(id==NULL || id == "") return; + + HDoc* doc=sview->createHDoc(node->children,&attrs); + + if(doc) { + doc->foreColor=foreColor; + doc->backColor=backColor; + fPages.AddItem(doc); + } +} + +void +HelpViewer::findAttribute(xmlNodePtr cur_node,BMessage *attrs){ + + xmlAttr *attr = cur_node->properties; + + xmlAttr *cur_attr = NULL; + for (cur_attr = attr; cur_attr; cur_attr = cur_attr->next) { + BString battr((const char*)cur_attr->name); + xmlNodePtr node = cur_attr->children; + attrs->AddString(battr.String(),(const char*)node->content); + } + +} + + +void +HelpViewer::RecalcScrollbar(){ + + //debugger("recalc"); + HDoc* doc= sview->CurrentDisplayed(); + if(!doc) return; + + BScrollBar *bar; + if (scroll == NULL + || (bar = scroll->ScrollBar (B_VERTICAL)) == NULL) + return ; + + BRect bounds (Bounds()); + float div=bounds.Height() / sview->Frame().Height(); + if( div < 1.0){ + bar->Show(); + bar->SetProportion (div); //bounds.Height() / sview->Frame().bottom); + bar->SetRange (0.0, sview->Frame().bottom - bounds.Height()); + } + else { + + bar->Hide(); + bar->SetProportion (1); //bounds.Height() / sview->Frame().bottom); + bar->SetRange (0, 0); + } + sview->ScrollTo(0,0); + scroll->Invalidate(); +} + +void +HelpViewer::SearchSetPage(BString id){ + + for(uint i=0;iDocId().Compare(id) == 0){ + SetPage(i); + if(fGotoHand){ + BMessage* msg=new BMessage(HELPVIEWER_GOTO); + msg->AddInt32("selected",i); + BMessenger(fGotoHand).SendMessage(msg,fGotoHand); + return; + } + } + } +} + +void +HelpViewer::SetOpenUrlHandler(BHandler* hand){ + aopenurl->SetHandler(hand); +} + + +void +HelpViewer::SetGotoHandler(BHandler* hand){ + fGotoHand=hand; +} + +void +HelpViewer::MessageReceived(BMessage* msg){ + + switch(msg->what){ + case HELPVIEWER_GOTO: + { + BString param; + if(msg->FindString("goto",¶m)==B_OK){ + SearchSetPage(param); + + } + } + break; + case HELPVIEWER_OPEN_URL: + { + BString param; + if(msg->FindString("url",¶m)==B_OK){ + + BString app("text/html"); + //Net+ app.SetTo("application/x-vnd.Be-NPOS"); + const char *args[] = { param.String(), 0 }; + be_roster->Launch (app.String(), 1, const_cast(args)); + + } + } + break; + default: + BView::MessageReceived(msg); + break; + }; +} +//.. diff --git a/library/libfish/HorizontalContainerBox.h b/library/libfish/HorizontalContainerBox.h new file mode 100644 index 0000000..53abbb6 --- /dev/null +++ b/library/libfish/HorizontalContainerBox.h @@ -0,0 +1,59 @@ +#ifndef HorizontalContainerBox_H_ +#define HorizontalContainerBox_H_ + +#include "ContainerBox.h" + + +// here only the logic of the horiz stack model + +#define MIN_COLUMN_WIDTH 30 + +class HorizontalContainerBox : public ContainerBox { + + public: + + HorizontalContainerBox(BRect preferredSize,BString txt,BoxRenderer* render,float par_space): + ContainerBox(preferredSize,txt,render){ + fParSpace = par_space; + left_margin = top_margin = 5.0; + } + + void + InitSize(float maxwidth) { + + rect.right = rect.left + maxwidth; + + fStackRect = BRect(0 + left_margin, + 0 + top_margin, + 0 + maxwidth - left_margin - 1, + 0 + top_margin); //0 height box! + maxH = 0; + }; + + void + UpdateSize(InstanceBox* box){ + fStackRect.left = box->rect.right + left_margin; + if(box->rect.bottom > maxH) maxH = box->rect.bottom; + SetSize(rect.Width(),maxH + left_margin + 1); + } + + void + ArrangeBoxPosition(InstanceBox* box){ + box->rect = fStackRect; + if(box->rect.Width() < MIN_COLUMN_WIDTH ) + { + //si dovrebbe andare a capo.. + + } + } + + + + + private: + BRect fStackRect; + float fParSpace; + float maxH; +}; +#endif +//-- diff --git a/library/libfish/ImageRenderer.cpp b/library/libfish/ImageRenderer.cpp new file mode 100644 index 0000000..468b9ce --- /dev/null +++ b/library/libfish/ImageRenderer.cpp @@ -0,0 +1,67 @@ +#include "Utils.h" +#include "ImageRenderer.h" +#include "ImageCache.h" + +struct token { + BBitmap* image; + BPoint shift; +}; +void +ImageRenderer::DrawBox(BView* parent,InstanceBox* ibox) { + token *tok=(token*)ibox->cookie; + if(!tok->image) return; + parent->SetDrawingMode( B_OP_ALPHA ); + parent->DrawBitmap(tok->image,BPoint(ibox->rect.left,ibox->rect.top)+tok->shift); + parent->SetDrawingMode( B_OP_OVER ); +} + +void +ImageRenderer::InitInstanceBox(InstanceBox *ibox,ContainerBox *){ + + BBitmap *icon=LoadIcon(ibox->text.String()); + token *tok=new token; + ibox->cookie=(void*)tok; + tok->image=NULL; + tok->shift=BPoint(0,0); + + if(icon) { + tok->image=icon; + } + + float maxwidth=ibox->rect.Width(); + const float mw=maxwidth; + + float maxheight=ibox->rect.Height(); + if(!icon) return; + + if(icon->Bounds().Width()Bounds().Width(); + + maxheight = icon->Bounds().Height(); + + + //refine size: + if(ibox->hlimit>0 && ibox->hlimithlimit>maxwidth){ + + ibox->SetSize(ibox->hlimit,maxheight); + float diff = (ibox->hlimit -icon->Bounds().Width()) / 2.0; + if(diff<0) diff=0; + tok->shift=BPoint(diff,0); + } + else + { + ibox->SetSize(maxwidth,maxheight); + HAlignBox(ibox,mw); + } + +} + +void +ImageRenderer::FreeInstanceBox(InstanceBox* box){ + token *tok=(token*)box->cookie; + if(tok->image) + ImageCache::DeleteImage(box->text.String()); + + delete tok; +} + diff --git a/library/libfish/ImageRenderer.h b/library/libfish/ImageRenderer.h new file mode 100644 index 0000000..907e3bd --- /dev/null +++ b/library/libfish/ImageRenderer.h @@ -0,0 +1,19 @@ +#ifndef ImageRenderer_H_ +#define ImageRenderer_H_ + +#include +#include "BoxRenderer.h" + +class ContainerBox; + +class ImageRenderer : public BoxRenderer { + + public: + + void DrawBox(BView* parent,InstanceBox* ibox); + void InitInstanceBox(InstanceBox *,ContainerBox *); + void FreeInstanceBox(InstanceBox*); + +}; +#endif +//-- diff --git a/library/libfish/InstanceBox.h b/library/libfish/InstanceBox.h new file mode 100644 index 0000000..ef39ddd --- /dev/null +++ b/library/libfish/InstanceBox.h @@ -0,0 +1,36 @@ +#ifndef InstanceBox_H_ +#define InstanceBox_H_ + +class BoxRenderer; + +#include "String.h" + +class InstanceBox { + +public: + + InstanceBox(BRect preferredSize,BString txt,BoxRenderer* render){ + box_alignment = B_ALIGN_LEFT; + text=txt; + renderer=render; + rect = preferredSize; + hlimit = -1; + } + + void SetSize(float w,float h){ + rect.SetRightBottom(rect.LeftTop() + BPoint(w-1,h-1)); + } + + BString text; + BRect rect; + BoxRenderer* renderer; //don't like this. + + float hlimit; + + alignment box_alignment; + //this is used by the renderer..: + void* cookie; + BString action; +}; +#endif +//-- diff --git a/library/libfish/Jamfile b/library/libfish/Jamfile new file mode 100644 index 0000000..e6dc6c3 --- /dev/null +++ b/library/libfish/Jamfile @@ -0,0 +1,37 @@ + +SubDir TOP libfish ; + +if $(OSPLAT) = X86 { + C++FLAGS += -Wno-sign-compare -Wno-overloaded-virtual ; +} + + +SAVED_DEFINES = $(DEFINES) ; + +DEFINES = $(SAVED_DEFINES) ; + + +SubDirSysHdrs /boot/home/config/include ; +SubDirSysHdrs $(TOP)/libfish/include ; +SubDirSysHdrs $(TOP)/libfunky/include ; +SubDirSysHdrs /boot/beos/etc/develop/zeta-r1-gcc2-x86/headers/be/locale ; +SubDirSysHdrs $(TOP)/../include ; +SubDirSysHdrs $(TOP)/../include/r5-only ; + +LINKFLAGS += -L/boot/home/config/lib ; +LINKFLAGS += -L$(TOP)/libs ; +LINKFLAGS += -L/boot/develop/headers/be ; + +# +StaticLibrary libfish.a : + BoxRenderer.cpp + CompositeRenderer.cpp + ImageRenderer.cpp + OneSView.cpp + ParBoxRenderer.cpp + SView.cpp + TitleBoxRenderer.cpp + HelpViewer.cpp + ; +# + diff --git a/library/libfish/MultiLineBoxRenderer.h b/library/libfish/MultiLineBoxRenderer.h new file mode 100644 index 0000000..35d71a1 --- /dev/null +++ b/library/libfish/MultiLineBoxRenderer.h @@ -0,0 +1,143 @@ +#ifndef MultiLineBoxRenderer_H_ +#define MultiLineBoxRenderer_H_ + +#include "BoxRenderer.h" +#include +#define kTEXT_MARGIN 0 + +struct multi_line { + int count; + BList line; +}; + +class MultiLineBoxRenderer : public BoxRenderer { + + public: + MultiLineBoxRenderer(BFont fnt){ + font = fnt; + align = B_ALIGN_RIGHT; + } + + + void DrawBox(BView* parent,InstanceBox* ibox) { + parent->StrokeRect(ibox->rect); + parent->SetFont(&font); + multi_line *ml=(multi_line*)ibox->cookie; + BRect rect(ibox->rect); + rect.bottom = rect.top + font.Size() - 1; + for(int i=0;icount;i++){ + BString* str=(BString*)ml->line.ItemAt(i); + DrawString(str->String(),parent,rect); + rect.OffsetBy(0, font.Size()); + } + + }; + + float GetHeight(InstanceBox* ibox ) { + multi_line *ml=(multi_line*)ibox->cookie; + return font.Size()*ml->count; + }; + + float GetWidth(InstanceBox* ibox ) { + + multi_line *ml=(multi_line*)ibox->cookie; + + float maxsize=0; + for(int i=0;icount;i++){ + BString* str=(BString*)ml->line.ItemAt(i); + float size = font.StringWidth(str->String()); + if(size > maxsize) maxsize=size; + } + return maxsize; + }; + + + void + InitInstanceBox(InstanceBox* ibox,HDoc*) + { + //debugger("instance"); + //devo dividere il testo in più linee e farne un array di stringhe. + multi_line *ml=new multi_line; + ml->count=0; + + int32 index = 0; + int32 past_index = 0; + + index = ibox->text.FindFirst("\n",past_index); + + while( index > 0){ + ml->count++; + BString *s=new BString(); + ibox->text.CopyInto(*s,past_index,index-past_index); + ml->line.AddItem(s); + + past_index = index + 1; + index = ibox->text.FindFirst("\n",past_index); + } + + index = ibox->text.FindLast("\n",past_index); + if(index > 0){ + ml->count++; + BString *s=new BString(); + ibox->text.CopyInto(*s,past_index,index-past_index); + ml->line.AddItem(s); + } + else + { + ml->count=1; + ml->line.AddItem(&ibox->text); + } + + ibox->cookie=(void*)ml; + + ibox->SetSize(this->GetWidth(ibox),this->GetHeight(ibox)); + + } + + + + void DrawString(const char* string, BView* parent, BRect rect) +{ + float width = rect.Width() - (2 * kTEXT_MARGIN); + float y; + BFont font; + font_height finfo; + + parent->GetFont(&font); + font.GetHeight(&finfo); + y = rect.top + ((rect.Height() - (finfo.ascent + finfo.descent + finfo.leading)) / 2) + + (finfo.ascent + finfo.descent) - 2; + + switch (Alignment()) + { + case B_ALIGN_LEFT: + parent->MovePenTo(rect.left + kTEXT_MARGIN, y); + break; + + case B_ALIGN_CENTER: + parent->MovePenTo(rect.left + kTEXT_MARGIN + ((width - font.StringWidth(string)) / 2), y); + break; + + case B_ALIGN_RIGHT: + parent->MovePenTo(rect.right - kTEXT_MARGIN - font.StringWidth(string), y); + break; + } + parent->DrawString(string); +} + + void SetAlignment(alignment flag){ + align=flag; + }; + + alignment Alignment(void) const { + return align; + }; + + + private: + BFont font; + alignment align; + +}; +#endif +//-- diff --git a/library/libfish/OneSView.cpp b/library/libfish/OneSView.cpp new file mode 100644 index 0000000..f16c571 --- /dev/null +++ b/library/libfish/OneSView.cpp @@ -0,0 +1,402 @@ +#include "OneSView.h" +#include "ParBoxRenderer.h" +#include "TitleBoxRenderer.h" +#include "TextInstanceBox.h" +#include "ImageRenderer.h" +#include "HorizontalContainerBox.h" +#include "ContainerBox.h" +#include "Cursor.h" +#include "RVAction.h" +#ifdef ZETA + #include +#else + #define _T(A) A +#endif +#include +#define PAR_SPACE 14 + +enum{ + TITLE, + TEXT, + IMAGE, + VERTICAL, + HORIZONTAL +}; + +// cursor data for hovering over URLs + +static unsigned char URLCursorData[] = {16,1,2,2, + 0,0,0,0,56,0,36,0,36,0,19,224,18,92,9,42, + 8,1,60,33,76,49,66,121,48,125,12,253,2,0,1,0, + 0,0,0,0,56,0,60,0,60,0,31,224,31,252,15,254, + 15,255,63,255,127,255,127,255,63,255,15,255,3,254,1,248 +}; + +BCursor *fURLCursor; + +//test +ContainerBox *cbox; + +int textSize; //temp +int titleSize; //temp; + +OneSView::OneSView(BRect r):SView(r){ + RegisterBoxRenderer(TITLE,new TitleBoxRenderer()); + RegisterBoxRenderer(TEXT,new ParBoxRenderer()); + RegisterBoxRenderer(IMAGE,new ImageRenderer()); + cbox = (ContainerBox*)GetCompositeRenderer()->CreateInstanceBox(Bounds(),"null"); + fURLCursor = new BCursor (URLCursorData); +} + +OneSView::~OneSView(){ + + //then free all the renderers.. + delete GetRenderer(TITLE); + UnregisterBoxRenderer(TITLE); + + delete GetRenderer(TEXT); + UnregisterBoxRenderer(TEXT); + + delete GetRenderer(IMAGE); + UnregisterBoxRenderer(IMAGE); + + delete fURLCursor; +} + +HDoc* +OneSView::createHDoc(xmlNodePtr node,BMessage* attrs){ + + BString id; + attrs->FindString("id",&id); + HDoc *doc = new HDoc(id,0,0,10,PAR_SPACE); + + checkHDocAttributes(doc,attrs); + textSize = doc->textFontSize; + titleSize = doc->titleFontSize; + + checkContainerAttributes(doc,attrs); + + ParsePars(node,doc); + doc->renderer = GetCompositeRenderer(); + doc->renderer->InitInstanceBox(doc,cbox); + return doc; +} + + +void +OneSView::ParsePars(xmlNodePtr node,ContainerBox* container){ + + xmlNode *cur_node = NULL; + BRect rect(0,0,0,0); + + for (cur_node = node; cur_node; cur_node = cur_node->next) { + + if (cur_node->type == XML_ELEMENT_NODE) { + + + BString bname((const char*)cur_node->name); + + if (cur_node->children && (cur_node->children->type == XML_TEXT_NODE || cur_node->children->type == XML_CDATA_SECTION_NODE) ) { + + //text element.. + if(bname.ICompare("paragraph") == 0){ + // + BString content((const char*)cur_node->children->content); + content.SetTo(_T(content.String())); + + // type. + BMessage attrs; + int type = findAttribute(cur_node,&attrs); + if(type<0) break; + + switch(type){ + case TITLE: + AddTitle(content.String(),rect,container,&attrs); + break; + case TEXT: + AddPar(content.String(),rect,container,&attrs); + break; + case IMAGE: + AddImage(content.String(),rect,container,&attrs); + break; + default: + break; + } + } + else + if(bname.ICompare("block") == 0){ + + //parse degli attributi: + BMessage attrs; + int type = findAttribute(cur_node,&attrs); + ContainerBox* ncontainer = NULL; + //creiamo il tipo di block (v o h) + switch(type){ + case VERTICAL: + ncontainer = new VerticalContainerBox(rect,"testContainerV",GetCompositeRenderer(),5); + ncontainer->renderer = GetCompositeRenderer(); + break; + case HORIZONTAL: + ncontainer = new HorizontalContainerBox(rect,"testContainerH",GetCompositeRenderer(),5); + ncontainer->renderer = GetCompositeRenderer(); + break; + default: + + break; + } + //ricorrere è divino: + if(ncontainer) { + checkContainerAttributes(ncontainer,&attrs); + ParsePars(cur_node->children,ncontainer); + container->AddInstanceBox(ncontainer); + } + } + + + + } + + } + + } +} + +void +OneSView::AddTitle(const char* title,BRect rect,ContainerBox* doc,BMessage* attrs){ + TextInstanceBox* tib=(TextInstanceBox*)GetRenderer(TITLE)->CreateInstanceBox(rect,title); + tib->text_font.SetSize(titleSize); + doc->AddInstanceBox(tib); + checkCommonAttributes(tib,doc,attrs); + checkTextAttributes(tib,doc,attrs); +} + +void +OneSView::AddPar(const char* title,BRect rect,ContainerBox* doc,BMessage* attrs){ + TextInstanceBox* tib=(TextInstanceBox*)GetRenderer(TEXT)->CreateInstanceBox(rect,title); + tib->text_font.SetSize(textSize); + doc->AddInstanceBox(tib); + checkCommonAttributes(tib,doc,attrs); + checkTextAttributes(tib,doc,attrs); +} + +void +OneSView::AddImage(const char* title,BRect rect,ContainerBox* doc,BMessage* attrs){ + InstanceBox* tib=GetRenderer(IMAGE)->CreateInstanceBox(rect,title); + doc->AddInstanceBox(tib); + checkCommonAttributes(tib,doc,attrs); + +} + +void +OneSView::checkCommonAttributes(InstanceBox* box,ContainerBox* doc,BMessage* attrs){ + + BString align; + if(attrs->FindString("align",&align) == B_OK){ + + if(align.ICompare("center") == 0){ + box->box_alignment = B_ALIGN_CENTER; + } + else if(align.ICompare("right") == 0){ + box->box_alignment = B_ALIGN_RIGHT; + } + + } + + BString size; + if(attrs->FindString("hlimit",&size) == B_OK){ + int32 ssize=atoi(size.String()); + if(ssize>0) + box->hlimit = ssize; + } + BString action; + if(attrs->FindString("action",&action) == B_OK){ + box->action=action; + } + +} +void +OneSView::checkTextAttributes(TextInstanceBox* box,ContainerBox* doc,BMessage* attrs){ + + BString size; + if(attrs->FindString("fontsize",&size) == B_OK){ + int32 ssize=atoi(size.String()); + if(ssize>0) + box->text_font.SetSize(ssize); + } + + +} + +void +OneSView::checkHDocAttributes(HDoc* doc, BMessage* attrs){ + BString size; + if(attrs->FindString("textfontsize",&size) == B_OK){ + int32 ssize=atoi(size.String()); + if(ssize>0) + doc->textFontSize = ssize; + } + if(attrs->FindString("titlefontsize",&size) == B_OK){ + int32 ssize=atoi(size.String()); + if(ssize>0) + doc->titleFontSize = ssize; + } + +} + +void +OneSView::checkContainerAttributes(ContainerBox* box, BMessage* attrs){ + BString size; + if(attrs->FindString("leftmargin",&size) == B_OK){ + int32 ssize=atoi(size.String()); + if(ssize>=0) + box->left_margin = ssize; + } + if(attrs->FindString("topmargin",&size) == B_OK){ + int32 ssize=atoi(size.String()); + if(ssize>=0) + box->top_margin = ssize; + } + +} + + + + +int +OneSView::findAttribute(xmlNodePtr cur_node,BMessage *attrs){ + + xmlAttr *attr = cur_node->properties; + int type = -1; + + xmlAttr *cur_attr = NULL; + for (cur_attr = attr; cur_attr; cur_attr = cur_attr->next) { + + BString battr((const char*)cur_attr->name); + + if(battr.ICompare("type") == 0){ + + xmlNodePtr node = cur_attr->children; + BString stype ; + stype << (const char*)node->content; + + if(stype.ICompare("text") == 0){ + type=TEXT; + } + else + if(stype.ICompare("title") == 0){ + type=TITLE; + } + else + if(stype.ICompare("image") == 0){ + type= IMAGE; + } + else + if(stype.ICompare("vertical") == 0){ + type= VERTICAL; + } + else + if(stype.ICompare("horizontal") == 0){ + type= HORIZONTAL; + } + + } + else + { + xmlNodePtr node = cur_attr->children; + if(node){ + battr.ToLower(); + attrs->AddString(battr.String(),(const char*)node->content); + } + } + } + + //attrs->PrintToStream(); + return type; +} + + + +void +OneSView::MouseDown( BPoint /*where*/ ) +{ +/* SetMouseEventMask( B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS ); + + fMouseDown = true; + + Invalidate(); + */ +} + + +void +OneSView::MouseMoved( BPoint p, uint32 transition, const BMessage * ) +{ + switch ( transition ) + { + case B_ENTERED_VIEW: + case B_INSIDE_VIEW: + if(CurrentDisplayed()) + if(GetCompositeRenderer()->HasAction(CurrentDisplayed(),p)){ + SetViewCursor (fURLCursor); //B_CURSOR_I_BEAM + //printf("view c\n"); + } + else + SetViewCursor (B_CURSOR_SYSTEM_DEFAULT); + break; + case B_EXITED_VIEW: + //set mouse normal + SetViewCursor (B_CURSOR_SYSTEM_DEFAULT); + break; + } + +} + + +void +OneSView::MouseUp( BPoint p ) +{ + BString action; + if(CurrentDisplayed()) + if(GetCompositeRenderer()->HasAction(CurrentDisplayed(),p,&action)) + InvokeAction(action.String()); +} + +void +OneSView::ClearActions(){ + actions.MakeEmpty(); +} + +void +OneSView::AddAction(const char* symbolicName,RVAction* action){ + actions.AddPointer(symbolicName,(void*)action); +} + + +RVAction* +OneSView::FindAction(const char* symbolicName){ + RVAction* action=NULL; + actions.FindPointer(symbolicName,(void**)&action); + return action; +} + +void +OneSView::InvokeAction(BString mangledName){ + + int from = mangledName.FindFirst("("); + + BString actionName; + actionName.SetTo(mangledName,from); + + mangledName.Remove(0,from+1); + int to = mangledName.FindFirst(")"); + + BString param; + param.SetTo(mangledName,to); + + RVAction* action=FindAction(actionName.String()); + if(action) + action->Perform(param); + else + debugger(actionName.String()); +} + diff --git a/library/libfish/OneSView.h b/library/libfish/OneSView.h new file mode 100644 index 0000000..2815a00 --- /dev/null +++ b/library/libfish/OneSView.h @@ -0,0 +1,65 @@ +#ifndef OneSView_H_ +#define OneSView_H_ + +#include "SView.h" +#include "HDoc.h" + +#include "libxml/tree.h" +#include "libxml/xpath.h" +#include "libxml/xpathInternals.h" +#include "libxml/parserInternals.h" +#include "libxml/debugXML.h" + +#include "Message.h" + +class TextInstanceBox; +class RVAction; + +class OneSView : public SView { + public: + OneSView(BRect r); + ~OneSView(); + + HDoc* createHDoc(xmlNodePtr node,BMessage* attrs); + void AddAction(const char* symbolicName,RVAction*); //by xeD + + protected: + void AddTitle(const char* title, + BRect rect, + ContainerBox*, + BMessage *attrs); + + void AddPar(const char* title, + BRect rect, + ContainerBox*, + BMessage *attrs); + + void AddImage(const char* title, + BRect rect, + ContainerBox*, + BMessage *attrs); + + void MouseDown( BPoint ); + void MouseUp( BPoint ); + void MouseMoved( BPoint , uint32 transition, const BMessage *); + + + + private: + void ParsePars(xmlNodePtr node,ContainerBox*); + void checkCommonAttributes(InstanceBox* box,ContainerBox* doc,BMessage* attrs); + void checkTextAttributes(TextInstanceBox* box,ContainerBox* doc,BMessage* attrs); + void checkHDocAttributes(HDoc*, BMessage*); + void checkContainerAttributes(ContainerBox*, BMessage*); + + void InvokeAction(BString mangledName); + void ClearActions(); //by xeD + + RVAction* FindAction(const char* symbolicName); //by xeD + + //return type (as int) + int findAttribute(xmlNodePtr node,BMessage *attrs); + + BMessage actions; //by xeD +}; +#endif diff --git a/library/libfish/ParBoxRenderer.cpp b/library/libfish/ParBoxRenderer.cpp new file mode 100644 index 0000000..4a41264 --- /dev/null +++ b/library/libfish/ParBoxRenderer.cpp @@ -0,0 +1,238 @@ +#include "ParBoxRenderer.h" +#include "TextInstanceBox.h" + + +#include +#include + +#define kTEXT_MARGIN 0 + + + +inline int32 +UTF8_CHAR_LEN (uchar c) +{ + return (((0xE5000000 >> (((c) >> 3) & 0x1E)) & 3) + 1); +} + + +void addLine(const char* line,int size,multi_line* ml){ + ml->count++; + BString *s=new BString(line,size); + //ibox->text.CopyInto(*s,line,line + size); + //printf("Added line %d [%s]\n",ml->count-1,s->String()); + ml->line.AddItem(s); + +} + +InstanceBox* +ParBoxRenderer::CreateInstanceBox(BRect preferredSize,BString txt){ + return new TextInstanceBox(preferredSize,txt,this); +} + +void +ParBoxRenderer::DrawBox(BView* parent,InstanceBox* ibox) { + TextInstanceBox* t = (TextInstanceBox*)ibox; + parent->SetFont(&t->text_font); + multi_line *ml=(multi_line*)ibox->cookie; + if(!ml) return; + BRect rect(ibox->rect); + rect.bottom = rect.top + t->font_full_height -1; //t->text_font.Size() - 1; + for(int i=0;icount;i++){ + BString* str=(BString*)ml->line.ItemAt(i); + DrawString(str->String(),parent,rect,B_ALIGN_LEFT); + rect.OffsetBy(0, t->font_full_height); + } +}; + +void +ParBoxRenderer::InitInstanceBox(InstanceBox* ibox,ContainerBox*) { + // devo dividere il testo in più linee e farne un array di stringhe. + // in base agli spazi e non hai \n. + + TextInstanceBox* t = (TextInstanceBox*)ibox; + + multi_line *ml=new multi_line; + ml->count=0; + + + //first: remove all the \n + ibox->text.ReplaceAll("\n"," "); + ibox->text.RemoveAll("\t"); + + float maxwidth=ibox->rect.Width(); + + if(t->hlimit>0 && t->hlimithlimit; + + float width=0; + const int16 fLength=ibox->text.Length(); + int16 *fSpaces; + int16 fSpace_count; + + const char spacers[] = " \t\n-\\/"; + const char *buffer(ibox->text.String()); + size_t offset (0), n; + int16 count (0); + + fSpace_count = 0; + while ((n = strcspn (buffer + offset, spacers)) < fLength - offset){ + ++count; + offset += n + 1; + } + + fSpaces = new int16 [count + 1]; + + offset = 0; + while ((n = strcspn (buffer + offset, spacers)) < fLength - offset){ + fSpaces[fSpace_count++] = n + offset; + offset += n + 1; + } + + fSpaces[fSpace_count++] = ibox->text.Length(); + + //printf("Text: %s\n",ibox->text.String()); + //for(int i=0;i< fSpace_count;i++) + // printf("Space at %d (position %d)\n",i,fSpaces[i]); + + if(fSpace_count<=0) + debugger("no space?"); //impossible! (We just Append(" ")..) + + int curSpace = 0; + int curChar = 0; + + while(curSpacetext_font, + buffer + curChar, + fSpaces[curSpace] - curChar); + { + char copy[fSpaces[curSpace] - curChar + 1]; + memset(copy,0,fSpaces[curSpace] - curChar + 1); + strncpy(copy,buffer + curChar,fSpaces[curSpace] - curChar); + //printf("pixel (%s) until %d: %f (curSpace %d)\n",copy,fSpaces[curSpace],size,curSpace); + + } + + pixel += size; + + if( pixel >= maxwidth && pixel > size) { + addLine(buffer + from,(int)(curChar-from),ml); + if(pixel>width) width=pixel; + curChar++; //skip the space! + break; + } + + else + if(pixel >= maxwidth && pixel == size){ + + // a big word. brute split! + int i; + float size; + + for(i = fSpaces[curSpace] ; i > from; i-- ){ //UTF16 kind? + size = StringSize(&t->text_font,buffer + from, i - from); + if(size <= maxwidth){ + //found the breakpoint! + addLine(buffer + from,i - from,ml); + if(pixel>width) width=pixel; + break; + } + + }//for + if(i <= curSpace){ + i++; + ibox->cookie = NULL; + delete fSpaces; + return; + //debugger("less then one char bug"); + } + curChar = i; + break; + + } + + //qui controllo del flush ultra finale! + if(curSpace == fSpace_count-1) { + addLine(buffer + from,fSpaces[curSpace] - from,ml); + if(pixel>width) width=pixel; + } + + curChar = fSpaces[curSpace]; + curSpace++; + + + } + + //printf("-----\n"); + } + + ibox->cookie=(void*)ml; + font_height fh; + t->text_font.GetHeight(&fh); + t->font_full_height = ceil (fh.ascent + fh.descent + fh.leading); + if(width>ibox->rect.Width()) width = ibox->rect.Width(); + ibox->SetSize(width,t->font_full_height*ml->count); + + HAlignBox(ibox,maxwidth); + + delete fSpaces; + + return; + +} + +void +ParBoxRenderer::FreeInstanceBox(InstanceBox* box){ + if(box->cookie) + delete ((multi_line*)box->cookie); + +} + +float +ParBoxRenderer::StringSize(BFont* f,const char* string){ + return f->StringWidth(string); +} + +float +ParBoxRenderer::StringSize(BFont* f,const char* string,int lenght){ + return f->StringWidth(string,lenght); +} + + +void +ParBoxRenderer::DrawString(const char* string, BView* parent, BRect rect,alignment ali) +{ + float width = rect.Width() - (2 * kTEXT_MARGIN); + float y; + BFont font; + font_height finfo; + + parent->GetFont(&font); + font.GetHeight(&finfo); + y = rect.top + ((rect.Height() - (finfo.ascent + finfo.descent + finfo.leading)) / 2) + + (finfo.ascent + finfo.descent) - 2; + + switch (ali) + { + case B_ALIGN_LEFT: + parent->MovePenTo(rect.left + kTEXT_MARGIN, y); + break; + + case B_ALIGN_CENTER: + parent->MovePenTo(rect.left + kTEXT_MARGIN + ((width - font.StringWidth(string)) / 2), y); + break; + + case B_ALIGN_RIGHT: + parent->MovePenTo(rect.right - kTEXT_MARGIN - font.StringWidth(string), y); + break; + } + parent->DrawString(string); +} + diff --git a/library/libfish/ParBoxRenderer.h b/library/libfish/ParBoxRenderer.h new file mode 100644 index 0000000..6efde1d --- /dev/null +++ b/library/libfish/ParBoxRenderer.h @@ -0,0 +1,28 @@ +#ifndef ParBoxRenderer_H_ +#define ParBoxRenderer_H_ + +#include "BoxRenderer.h" +#include +struct multi_line { + int count; + BList line; +}; + + +class ParBoxRenderer : public BoxRenderer { + + public: + + InstanceBox* CreateInstanceBox(BRect preferredSize,BString txt); + void DrawBox(BView* parent,InstanceBox* ibox); + void InitInstanceBox(InstanceBox* box,ContainerBox*); + void FreeInstanceBox(InstanceBox* box); + + protected: + void DrawString(const char* string, BView* parent, BRect rect,alignment ali); + float StringSize(BFont*,const char* string); + float StringSize(BFont* f,const char* string,int lenght); + +}; +#endif +//-- diff --git a/library/libfish/RVAction.h b/library/libfish/RVAction.h new file mode 100644 index 0000000..4bbeebb --- /dev/null +++ b/library/libfish/RVAction.h @@ -0,0 +1,15 @@ +#ifndef _RVAction_h_ +#define _RVAction_h_ + +class RVAction +{ + public: + + virtual ~RVAction(){}; + + virtual status_t Perform(BString param) = 0; + virtual BString GetDescription() = 0; + +}; + +#endif diff --git a/library/libfish/RVActionGoto.h b/library/libfish/RVActionGoto.h new file mode 100644 index 0000000..994286e --- /dev/null +++ b/library/libfish/RVActionGoto.h @@ -0,0 +1,31 @@ +#ifndef _RVActionGoto_h_ +#define _RVActionGoto_h_ + +#include "RVAction.h" + +#include +#include + + +class RVActionGoto : public RVAction +{ + public: + RVActionGoto(BHandler* h){hand=h;}; + + + virtual status_t Perform(BString param){ + //printf("goto : %s\n",param.String()); + BMessage* msg=new BMessage('goto'); + msg->AddString("goto",param); + BMessenger(hand).SendMessage(msg,hand); + } + virtual BString GetDescription(){ + return "Goto"; + } + + private: + BHandler* hand; + +}; + +#endif diff --git a/library/libfish/RVActionOpenURL.h b/library/libfish/RVActionOpenURL.h new file mode 100644 index 0000000..1afd018 --- /dev/null +++ b/library/libfish/RVActionOpenURL.h @@ -0,0 +1,31 @@ +#ifndef _RVActionOpenURL_h_ +#define _RVActionOpenURL_h_ + +#include "RVAction.h" + +#include +#include + + +class RVActionOpenURL : public RVAction +{ + public: + RVActionOpenURL(BHandler* h){hand=h;}; + void SetHandler(BHandler* h){hand=h;}; + + virtual status_t Perform(BString param){ + BMessage* msg=new BMessage('opur'); + msg->AddString("url",param); + BMessenger(hand).SendMessage(msg,hand); + } + + virtual BString GetDescription(){ + return "OpenURL"; + } + + private: + BHandler* hand; + +}; + +#endif diff --git a/library/libfish/SView.cpp b/library/libfish/SView.cpp new file mode 100644 index 0000000..48db09f --- /dev/null +++ b/library/libfish/SView.cpp @@ -0,0 +1,69 @@ +#include "SView.h" +#include "Application.h" +#include "Bitmap.h" +#include "TranslationUtils.h" + +#include "stdio.h" + +#define DEBUG 0 + +SView::SView(BRect r):BView(r,"",B_FOLLOW_NONE,B_WILL_DRAW){ + fDoc=NULL; + fCompositeRenderer = new CompositeRenderer(); + fMouseDown = false; +} + +void +SView::DisplayDocument(HDoc* doc){ + + fDoc=doc; + if(!fDoc) return; + + ResizeTo(Bounds().Width(),fDoc->GetHeight()); + SetViewColor(fDoc->backColor); + SetHighColor(fDoc->foreColor); + SetLowColor(fDoc->backColor); + Invalidate(); +} + +void +SView::Draw(BRect r) +{ + if(fDoc==NULL) return; + + if(DEBUG) + StrokeRect(BRect(0,0,fDoc->GetWidth(),fDoc->GetHeight())); + + fDoc->renderer->DrawBox(this,fDoc); + //fCompositeRenderer->DrawBox(this,fDoc); +} + +void +SView::RegisterBoxRenderer(int id,BoxRenderer* renderer){ + fRenderers.AddItem(id,renderer); +} + +void +SView::UnregisterBoxRenderer(int id){ + fRenderers.RemoveItemFor(id); +} + +BoxRenderer* +SView::GetRenderer(int id){ + return fRenderers.ValueFor(id); +} + + + +void +SView::GetPreferredSize(float*w,float*h){ + *w=10; + *h=10; +} + +void +SView::AttachedToWindow(){ + SetViewColor(255,0,255,255); +} + +//.. diff --git a/library/libfish/SView.h b/library/libfish/SView.h new file mode 100644 index 0000000..f2b1913 --- /dev/null +++ b/library/libfish/SView.h @@ -0,0 +1,40 @@ +#ifndef SView_H_ +#define SView_H_ + +#include +#include +#include "KeyMap.h" +#include "HDoc.h" + +#include "BoxRenderer.h" +#include "CompositeRenderer.h" + +class SView : public BView +{ + public: + SView(BRect); + void Draw(BRect r); + + void DisplayDocument(HDoc* doc); + HDoc* CurrentDisplayed(){ return fDoc;} + + void RegisterBoxRenderer(int id,BoxRenderer*); + void UnregisterBoxRenderer(int id); + + BoxRenderer* GetRenderer(int); + CompositeRenderer* GetCompositeRenderer(){ return fCompositeRenderer;}; + + virtual void GetPreferredSize(float*,float*); + + void AttachedToWindow(); + + private: + HDoc* fDoc; + CompositeRenderer* fCompositeRenderer; + + KeyMap fRenderers; + bool fMouseDown; +}; + +#endif +//-- diff --git a/library/libfish/TextInstanceBox.h b/library/libfish/TextInstanceBox.h new file mode 100644 index 0000000..767f79a --- /dev/null +++ b/library/libfish/TextInstanceBox.h @@ -0,0 +1,23 @@ +#ifndef TextInstanceBox_H_ +#define TextInstanceBox_H_ + +class BoxRenderer; +#include "Font.h" + +class TextInstanceBox : public InstanceBox { + +public: + + TextInstanceBox(BRect preferredSize,BString txt,BoxRenderer* render): + InstanceBox(preferredSize,txt,render){ + text_font = *be_plain_font; + font_height h; + font_full_height = h.ascent + h.descent + h.leading; + } + + BFont text_font; + float font_full_height; + +}; +#endif +//-- diff --git a/library/libfish/TitleBoxRenderer.cpp b/library/libfish/TitleBoxRenderer.cpp new file mode 100644 index 0000000..81661c9 --- /dev/null +++ b/library/libfish/TitleBoxRenderer.cpp @@ -0,0 +1,23 @@ +#include "TitleBoxRenderer.h" +#include "TextInstanceBox.h" + + +#define kTEXT_MARGIN 0 + +void +TitleBoxRenderer::DrawBox(BView* parent,InstanceBox* ibox) { + TextInstanceBox* t = (TextInstanceBox*)ibox; + parent->SetFont(&t->text_font); + multi_line *ml=(multi_line*)ibox->cookie; + if(!ml) return; + BRect rect(ibox->rect); + rect.bottom = rect.top + t->font_full_height -1; //rect.top + t->text_font.Size() - 1; + for(int i=0;icount;i++){ + BString* str=(BString*)ml->line.ItemAt(i); + BPoint pos(rect.left,rect.bottom + 1); + parent->StrokeLine(pos , pos + BPoint(t->text_font.StringWidth(str->String()),0),B_MIXED_COLORS); + DrawString(str->String(),parent,rect,B_ALIGN_LEFT); + rect.OffsetBy(0, t->font_full_height); + + } +} diff --git a/library/libfish/TitleBoxRenderer.h b/library/libfish/TitleBoxRenderer.h new file mode 100644 index 0000000..8c84945 --- /dev/null +++ b/library/libfish/TitleBoxRenderer.h @@ -0,0 +1,16 @@ +#ifndef TitleBoxRenderer_H_ +#define TitleBoxRenderer_H_ + +#include "ParBoxRenderer.h" + + + +class TitleBoxRenderer : public ParBoxRenderer { + + public: + + void DrawBox(BView* parent,InstanceBox* ibox); + +}; +#endif +//-- diff --git a/library/libfish/VerticalCompositeRenderer.h b/library/libfish/VerticalCompositeRenderer.h new file mode 100644 index 0000000..17027fa --- /dev/null +++ b/library/libfish/VerticalCompositeRenderer.h @@ -0,0 +1,17 @@ +#ifndef VerticalCompositeRenderer_H_ +#define VerticalCompositeRenderer_H_ + + +#include "CompositeRenderer.h" + +class VerticalCompositeRenderer : public CompositeRenderer { + + public: + + void ArrangeBoxPosition(InstanceBox*) = 0; + + + +}; +#endif +//-- diff --git a/library/libfish/VerticalContainerBox.h b/library/libfish/VerticalContainerBox.h new file mode 100644 index 0000000..111e475 --- /dev/null +++ b/library/libfish/VerticalContainerBox.h @@ -0,0 +1,61 @@ +#ifndef VerticalContainerBox_H_ +#define VerticalContainerBox_H_ + +#include "ContainerBox.h" + + +// here only the logic of the vertical stack model + + +class VerticalContainerBox : public ContainerBox { + + public: + + VerticalContainerBox(BRect preferredSize,BString txt,BoxRenderer* render,float par_space): + ContainerBox(preferredSize,txt,render){ + fParSpace = par_space; + //fMargin = margin; + left_margin = top_margin = 5.0; + } + + + void + InitSize(float maxwidth) { + + rect.right = rect.left + maxwidth; + + fStackRect = BRect(0 + left_margin, + 0 + top_margin, + 0 + maxwidth - left_margin - 1, + 0 + top_margin); //0 height box! + //fStackRect.PrintToStream(); + + }; + + void + UpdateSize(InstanceBox* box){ + fStackRect.OffsetTo(fStackRect.left,box->rect.bottom); + SetSize(rect.Width(),fStackRect.bottom + left_margin ); + //rect.PrintToStream(); + fStackRect.top = fStackRect.bottom += fParSpace; + } + + void + ArrangeBoxPosition(InstanceBox* box){ + box->rect.top = fStackRect.bottom; + box->rect.left = fStackRect.left; + box->rect.bottom = box->rect.top; // 0 + box->rect.right = fStackRect.left + fStackRect.right - left_margin; // max size + //box->rect.PrintToStream(); + } + + float MaxWidth(){ return fStackRect.Width();} + + private: + BRect fStackRect; + float fParSpace; + //float fMargin; + +}; +#endif +//-- diff --git a/library/libfish/include/HelpViewer.h b/library/libfish/include/HelpViewer.h new file mode 100644 index 0000000..2776013 --- /dev/null +++ b/library/libfish/include/HelpViewer.h @@ -0,0 +1,60 @@ +#ifndef HelpViewer_H_ +#define HelpViewer_H_ + +#include + +//#include "KeyMap.h" +#include +#include "libxml/tree.h" +#include "libxml/xpath.h" +#include "libxml/xpathInternals.h" +#include "libxml/parserInternals.h" +#include "libxml/debugXML.h" + +class HDoc; + +#define HELPVIEWER_OPEN_URL 'opur' +#define HELPVIEWER_GOTO 'goto' + +class HelpViewer : public BView { + + public: + HelpViewer(BRect r); + virtual ~HelpViewer(); + + void LoadFile(const char* file); + void ParsePage(xmlNodePtr node); + + void SetPage(uint); + int CountPage(); + + void SetForeColor(rgb_color c); + void SetBackColor(rgb_color c); + + void SetOpenUrlHandler(BHandler* hand); + void SetGotoHandler(BHandler* hand); + + void MessageReceived(BMessage* msg); + void SearchSetPage(BString id); + + void AttachedToWindow(); + + private: + + + void RecalcScrollbar(); + void findAttribute(xmlNodePtr node,BMessage*); + + + + //KeyMap fPages; + BObjectList fPages; + int16 Selected; + + rgb_color foreColor; + rgb_color backColor; + BHandler *fGotoHand; + +}; +#endif +// -- diff --git a/library/libfunky/ImageCache.cpp b/library/libfunky/ImageCache.cpp new file mode 100644 index 0000000..2136898 --- /dev/null +++ b/library/libfunky/ImageCache.cpp @@ -0,0 +1,100 @@ +#include "ImageCache.h" + +#include +#include +#include +#include + +// --------------------------------------------------------------------------- +// Class Data Initialization + +ImageCache * +ImageCache::m_instance = NULL; + +// --------------------------------------------------------------------------- +// Constructor/Destructor + +ImageCache::ImageCache() { + +} + +ImageCache::~ImageCache() +{ + while(m_bitmaps.CountItems()) { + BBitmap* bit=m_bitmaps.ValueFor(0); + delete bit; + } +} + +// --------------------------------------------------------------------------- +// Operations + +BBitmap * +ImageCache::GetImage( + BString which, BString name) +{ + if (m_instance == NULL) + m_instance = new ImageCache(); + + /* cerca.. se non c'e' lo carica altrimenti usa quello */ + bool found; + BBitmap *bitmap=m_instance->m_bitmaps.ValueFor(name,&found); + + + if(!found){ + bitmap = LoadImage(which.String(),name.String()); + if(bitmap) m_instance->m_bitmaps.AddItem(name,bitmap); + return bitmap; + } + else { + return bitmap; + } + return NULL; +} + + +void +ImageCache::AddImage(BString name,BBitmap* which){ + + if (m_instance == NULL) + m_instance = new ImageCache(); + + m_instance->m_bitmaps.AddItem(name,which); +} + +void +ImageCache::DeleteImage(BString name){ + + if (m_instance == NULL) + m_instance = new ImageCache(); + + BBitmap* bitmap = m_instance->m_bitmaps.ValueFor(name); + if(bitmap){ + m_instance->m_bitmaps.RemoveItemFor(name); + delete bitmap; + } +} + +void +ImageCache::Release() +{ + if (m_instance != NULL){ + delete m_instance; + m_instance = NULL; + } +} + +BBitmap * +ImageCache::LoadImage( + const char *fullName, const char* shortName) { + BBitmap *bitmap = BTranslationUtils::GetBitmap(fullName); + if(!bitmap){ + bitmap = BTranslationUtils::GetBitmap('PNG ', shortName); + } + + if(!bitmap) + printf("ImageCache: Can't load bitmap! %s\n",fullName); + return bitmap; +} + +// END - ImageCache.cpp diff --git a/library/libfunky/Jamfile b/library/libfunky/Jamfile new file mode 100644 index 0000000..09dc331 --- /dev/null +++ b/library/libfunky/Jamfile @@ -0,0 +1,27 @@ +SubDir TOP libfunky ; + +if $(OSPLAT) = X86 { + C++FLAGS += -Wno-sign-compare -Wno-overloaded-virtual ; +} + +SAVED_DEFINES = $(DEFINES) ; + +DEFINES = $(SAVED_DEFINES) ; + +SubDirSysHdrs /boot/home/config/include ; +SubDirSysHdrs $(TOP)/libfunky/include ; + +LINKFLAGS += -L/boot/home/config/lib ; +LINKFLAGS += -L$(TOP)/libs ; +LINKFLAGS += -L/boot/develop/headers/be ; + +# +StaticLibrary libfunky.a : + PBox.cpp + Setting.cpp + SettingsTextView.cpp + Utils.cpp + ImageCache.cpp + ; +# + diff --git a/library/libfunky/PBox.cpp b/library/libfunky/PBox.cpp new file mode 100644 index 0000000..8d1662a --- /dev/null +++ b/library/libfunky/PBox.cpp @@ -0,0 +1,428 @@ +#include "PBox.h" +#include + +#include +#include +#include +#include +#include +#include + +#include "SettingsTextView.h" + + +#define _T(A) A + +const float kControlOffset = 6.0; +const float kEdgeOffset = 5.0; +const float kDividerWidth = 100; + + + +#define SCROLLBAR 0 + +PBox::PBox(BRect rect, BMessage fT, BMessage fD,const char* settings_name) + : BBox(rect, "Property", B_FOLLOW_ALL,B_WILL_DRAW) +{ + + fSName.SetTo(settings_name); + fTemplate = fT; + fData = fD; + +#if B_BEOS_VERSION > B_BEOS_VERSION_5 + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + SetHighColor(ui_color(B_PANEL_TEXT_COLOR)); +#else + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + SetHighColor(0, 0, 0, 0); +#endif + +}; + +void +PBox::AttachedToWindow(){ + + //calc font height (for nice control size) + font_height fontHeight; + be_bold_font->GetHeight(&fontHeight); + fFontHeight = fontHeight.descent + fontHeight.leading + fontHeight.ascent; + + + BRect frame = Bounds(); + frame.InsetBy(5,5); + + BRect temp = frame; + temp.bottom = temp.top + 40; + + SettingsTextView *testo1=new SettingsTextView(temp,"testo",_T("Settings")); + AddChild(testo1); + frame.top +=40; + //BSeparator *sep=new BSeparator(frame,"sep","cippa"); + //sep->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + //AddChild(sep); + + //frame.InsetBy(kEdgeOffset, kEdgeOffset); + //frame.top += fFontHeight; //some space + +#if SCROLLBAR + frame.right -= B_V_SCROLL_BAR_WIDTH + 2; +#endif + + BView *view = new BView(frame, "", B_FOLLOW_ALL_SIDES,B_WILL_DRAW); + +#if B_BEOS_VERSION > B_BEOS_VERSION_5 + view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + view->SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + view->SetHighColor(ui_color(B_PANEL_TEXT_COLOR)); +#else + view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + view->SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + view->SetHighColor(0, 0, 0, 0); +#endif + + + float settings_height = BuildGUI(fTemplate, fData, view); + + + view->ResizeTo( view->Bounds().Width(), settings_height); +#if SCROLLBAR + + + BScrollView * scroller = new BScrollView( + "scroller", view, B_FOLLOW_ALL, + 0, false, true + ); + float scroll_height = scroller->Bounds().Height(); + float diff = settings_height - scroll_height; + if ( diff < 0 ) diff = 0; + + scroller->ScrollBar(B_VERTICAL)->SetRange(0, diff); + + view = scroller; +#endif + fPrefView = view; + + AddChild(fPrefView); + + testo1->SetText(fTemplate.FindString("name")); +} + +void +PBox::GetData(BMessage* data){ + + + + BView * panel = fPrefView; + BMessage cur; + + for (int i = 0; fTemplate.FindMessage("setting", i, &cur) == B_OK; i++) { + const char *name = cur.FindString("name"); + int32 type = -1; + + cur.FindInt32("type", &type); + + if ( dynamic_cast(panel->FindView(name))) { +// Free text + BTextControl * ctrl = (BTextControl*)panel->FindView(name); + + switch (type) { + case B_STRING_TYPE: { + data->AddString(name, ctrl->Text() ); + } break; + case B_INT32_TYPE: { + data->AddInt32(name, atoi(ctrl->Text()) ); + } break; + default: { + return; + }; + }; + } else if (dynamic_cast(panel->FindView(name))) { +// Provided option + BMenuField * ctrl = (BMenuField*)panel->FindView(name); + BMenuItem * item = ctrl->Menu()->FindMarked(); + + + if (!item) return; + + switch (type) { + case B_STRING_TYPE: { + data->AddString(name, item->Label() ); + BString index(name); + index << "_index"; + data->AddInt32(index.String(), ctrl->Menu()->IndexOf(item)); //index + } break; + case B_INT32_TYPE: { + data->AddInt32(name, atoi(item->Label()) ); + BString index(name); + index << "_index"; + data->AddInt32(index.String(), ctrl->Menu()->IndexOf(item)); //index + } break; + default: { + return; + }; + } + } else + if (dynamic_cast(panel->FindView(name))) { +// Boolean setting + BCheckBox * box = (BCheckBox*)panel->FindView(name); + + if ( box->Value() == B_CONTROL_ON ) { + data->AddBool(name,true); + } else { + data->AddBool(name,false); + } + } else if (dynamic_cast(panel->FindView(name))) { + BTextView *view = (BTextView *)panel->FindView(name); + data->AddString(name, view->Text()); + }; + + + }; + + +} + +void +PBox::MessageReceived(BMessage *msg) { + switch (msg->what) { + + case 'enab': + { + bool value = (bool)msg->FindInt32("be:value"); + for (int j = 0; msg->FindString("enable_control", j); j++) { + const char* name=msg->FindString("enable_control", j); + BView* viewz=fPrefView->FindView(name); + if(viewz) + ((BControl*)viewz)->SetEnabled(value); + } + } + break; + default: + BBox::MessageReceived(msg); + break; + }; +}; + +float PBox::BuildGUI(BMessage viewTemplate, BMessage settings, BView *view) { + + BMessage curr; + float yOffset = kEdgeOffset + kControlOffset; + float xOffset = 0; + + const float kControlWidth = view->Bounds().Width() - (kEdgeOffset * 2); + + BMessage postAdded; + + for (int i=0; viewTemplate.FindMessage("setting",i,&curr) == B_OK; i++ ) { + char temp[512]; + + // get text etc from template + const char * name = curr.FindString("name"); + const char * desc = curr.FindString("description"); + const char * value = NULL; + int32 type = -1; + bool secret = false; + bool freeText = true; + bool multiLine = false; + BView *control = NULL; + BMenu *menu = NULL; + BMessage* enabling = NULL; + + if ( name != NULL && strcmp(name,"app_sig") == 0 ) { + // skip app-sig setting + continue; + } + + if (curr.FindInt32("type", &type) != B_OK) { + printf("Error getting type for %s, skipping\n", name); + continue; + }; + + switch (type) { + case B_STRING_TYPE: { + if (curr.FindString("valid_value")) { + // It's a "select one of these" setting + + freeText = false; + + menu = new BPopUpMenu(name); +// menu->SetDivider(be_plain_font->StringWidth(name) + 10); + + for (int j = 0; curr.FindString("valid_value", j); j++) { + menu->AddItem(new BMenuItem(curr.FindString("valid_value", j),NULL)); + }; + + value = NULL; + value = curr.FindString("default"); + if (value && menu->FindItem(value)) menu->FindItem(value)->SetMarked(true); + + value = settings.FindString(name); + if (value && menu->FindItem(value)) menu->FindItem(value)->SetMarked(true); + + } else { + // It's a free-text setting + + if (curr.FindBool("multi_line", &multiLine) != B_OK) multiLine = false; + value = settings.FindString(name); + if (!value) value = curr.FindString("default"); + if (curr.FindBool("is_secret",&secret) != B_OK) secret = false; + } + } break; + case B_INT32_TYPE: { + if (curr.FindInt32("valid_value")) { + // It's a "select one of these" setting + + freeText = false; + + menu = new BPopUpMenu(name); + + int32 v = 0; + for ( int j = 0; curr.FindInt32("valid_value",j,&v) == B_OK; j++ ) { + sprintf(temp,"%ld", v); + menu->AddItem(new BMenuItem(temp, NULL)); + }; + + if ( curr.FindInt32("default",&v) == B_OK ) { + sprintf(temp,"%ld",v); + value = temp; + menu->FindItem(value)->SetMarked(true); + } + + if ( settings.FindInt32(name,&v) == B_OK ) { + sprintf(temp,"%ld",v); + value = temp; + menu->FindItem(value)->SetMarked(true); + } + + + } else { + // It's a free-text (but number) setting + int32 v = 0; + if (settings.FindInt32(name,&v) == B_OK) { + sprintf(temp,"%ld",v); + value = temp; + } else if ( curr.FindInt32("default",&v) == B_OK ) { + sprintf(temp,"%ld",v); + value = temp; + } + if (curr.FindBool("is_secret",&secret) != B_OK) secret = false; + } + } break; + case B_BOOL_TYPE: { + bool active; + + if (settings.FindBool(name, &active) != B_OK) { + if (curr.FindBool("default", &active) != B_OK) { + active = false; + }; + }; + + for (int j = 0; curr.FindString("enable_control", j); j++) { + if(!enabling) enabling = new BMessage('enab'); + enabling->AddString("enable_control",curr.FindString("enable_control",j) ); + if(!active) postAdded.AddString("disable",curr.FindString("enable_control", j)); + }; + + control = new BCheckBox(BRect(0, 0, kControlWidth, fFontHeight), + name, _T(desc), enabling); + + if (active) ((BCheckBox*)control)->SetValue(B_CONTROL_ON); + + } break; + default: { + continue; + }; + }; + + if (!value) value = ""; + + if (!control) { + if (freeText) { + if (multiLine == false) { + control = new BTextControl( + BRect(0, 0, kControlWidth, fFontHeight), name, + _T(desc), value, NULL); + if (secret) { + ((BTextControl *)control)->TextView()->HideTyping(true); + ((BTextControl *)control)->SetText(_T(value)); + }; + ((BTextControl *)control)->SetDivider(kDividerWidth); + } else + { + BRect rect; + BRect textRect; + if (desc) //andrea: add description only if available. + { + BRect labelRect(0, 0, kDividerWidth, fFontHeight); + BStringView *label = new BStringView(labelRect, "NA", _T(desc), + B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW); + view->AddChild(label); + label->MoveTo(kEdgeOffset, yOffset); + + rect = BRect(0, 0, kControlWidth - kDividerWidth, fFontHeight * 4); + rect.right -= B_V_SCROLL_BAR_WIDTH + kEdgeOffset + kControlOffset; + xOffset = kEdgeOffset + kDividerWidth; + } + else + { + rect = BRect(0, 0, kControlWidth, fFontHeight * 4); + rect.right -= B_V_SCROLL_BAR_WIDTH + kControlOffset; + xOffset = 0; + } + + textRect = rect; + textRect.InsetBy(kEdgeOffset, kEdgeOffset); + textRect.OffsetTo(1.0, 1.0); + + BTextView *textView = new BTextView(rect, name, textRect, + B_FOLLOW_ALL_SIDES, B_WILL_DRAW); + + control = new BScrollView("NA", textView, B_FOLLOW_ALL_SIDES, + B_WILL_DRAW | B_NAVIGABLE, false, true); + textView->SetText(_T(value)); + }; + } else { + control = new BMenuField(BRect(0, 0, kControlWidth, fFontHeight), + name, _T(desc), menu); + + float size=kDividerWidth; + if(control->StringWidth(_T(desc)) > kDividerWidth) + size=control->StringWidth(_T(desc)) + 20; + + ((BMenuField *)control)->SetDivider(size); + }; + }; + + + view->AddChild(control); + + if(enabling) + ((BCheckBox*)control)->SetTarget(this); + + float h, w = 0; + control->GetPreferredSize(&w, &h); + + if (h < control->Bounds().Height()) + h = control->Bounds().Height(); + + control->MoveTo(kEdgeOffset + xOffset, yOffset); + yOffset += kControlOffset + h ; + xOffset = 0; + }; + + for (int j = 0; postAdded.FindString("disable", j); j++) + { + const char* name=postAdded.FindString("disable", j); + BView* viewz=view->FindView(name); + if(viewz) + ((BControl*)viewz)->SetEnabled(false); + + } + + //if ( yOffset < view->Bounds().Height() ) + // yOffset = view->Bounds().Height(); + + return yOffset;//view->ResizeTo( view->Bounds().Width(), yOffset +} diff --git a/library/libfunky/Setting.cpp b/library/libfunky/Setting.cpp new file mode 100644 index 0000000..9ed86f9 --- /dev/null +++ b/library/libfunky/Setting.cpp @@ -0,0 +1,64 @@ +#include "Setting.h" +#include +#include "Utils.h" + +Setting::Setting(const char* settings_name) { + + if(!settings_name) { + filename.SetTo(GetAppFilename()); + filename << ".conf"; + } + else + filename.SetTo(settings_name); + +} + + +void +Setting::Store(){ + //salvataggio rapido ed indolore dei settaggi! + + BPath xpath; + status_t err; + + find_directory (B_USER_SETTINGS_DIRECTORY, &xpath, true); + xpath.Append (filename.String()); + + BFile *file=new BFile(); + err=file->SetTo(xpath.Path(),B_WRITE_ONLY|B_ERASE_FILE|B_CREATE_FILE); + + if(err != B_OK) { + + //printf ("file error %ld\n",err); + delete file; + return; + } + + Flatten(file); + + delete file; + +} + +void +Setting::Retrive(){ + + + status_t err; + + BFile file; + err=file.SetTo(SettingPath().String(),B_READ_ONLY); + + if(err == B_OK) { + MakeEmpty(); + Unflatten(&file); + } +} + +BString +Setting::SettingPath(){ + BPath xpath; + find_directory (B_USER_SETTINGS_DIRECTORY, &xpath, true); + xpath.Append (filename.String()); + return xpath.Path(); +} diff --git a/library/libfunky/SettingsTextView.cpp b/library/libfunky/SettingsTextView.cpp new file mode 100644 index 0000000..bec0c51 --- /dev/null +++ b/library/libfunky/SettingsTextView.cpp @@ -0,0 +1,27 @@ +#include "SettingsTextView.h" +#include "Utils.h" + +#define COLOR 255,255,255 //240,240,96 + +SettingsTextView::SettingsTextView(BRect rect, char *name,BString testo) + : BView(rect, name, B_FOLLOW_ALL, B_WILL_DRAW){ + + fText=testo; + SetViewColor(COLOR); +} + +void SettingsTextView::AttachedToWindow(){ + SetFontSize(12); +} + + +void SettingsTextView::Draw(BRect updateRect) +{ +// MovePenTo(BPoint(10,25)); + SetHighColor(0,0,0); + SetLowColor(COLOR); + + //Utils.cpp function: + BPDrawString(fText.String(),this,Bounds(),B_ALIGN_CENTER); +// DrawString(fText.String()); +} diff --git a/library/libfunky/Utils.cpp b/library/libfunky/Utils.cpp new file mode 100644 index 0000000..55b16c9 --- /dev/null +++ b/library/libfunky/Utils.cpp @@ -0,0 +1,347 @@ +#include "Utils.h" +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "ImageCache.h" + + +BString app_relative(""); + +BString +FindAppRelativePath() +{ + app_info theInfo; + BPath thePath; + status_t status = be_app->GetAppInfo(&theInfo); + + if(status != B_OK) return ""; + + thePath.SetTo(&theInfo.ref); + thePath.GetParent(&thePath); + return thePath.Path(); + +} + + +BString +GetAppRelativePath() +{ + if(app_relative=="") + app_relative=FindAppRelativePath(); + + return app_relative; + +} + +BString +GetAppFilename() +{ + app_info theInfo; + status_t status = be_app->GetAppInfo(&theInfo); + if(status != B_OK) return ""; + else + + return theInfo.ref.name; + +} + + +BBitmap* +LoadIcon(const char* name){ + BPath icon_path(GetAppRelativePath().String()); + icon_path.Append("icons"); + icon_path.Append(name); + return ImageCache::GetImage(icon_path.Path(),BString(name)); +} + +void +AddIcon(const char* name,BBitmap* icon){ + ImageCache::AddImage(name,icon); +} + + +bool +CheckMIME(BString mime,BNode* node){ + + size_t len = mime.Length(); + char buffer[B_MIME_TYPE_LENGTH]; + + memset(buffer,0,B_MIME_TYPE_LENGTH); + + size_t r = node->ReadAttr("BEOS:TYPE",B_MIME_TYPE,0,buffer,len); + + if(r!=mime.Length() || mime.Compare(buffer) != 0) return false; + + return true; +} + +status_t +ReadAttributeData(BNode* node,const char *name, char **buffer, int32 *size) { + attr_info info; + status_t ret = node->GetAttrInfo(name, &info); + if (ret == B_OK) { + *buffer = (char *)calloc(info.size, sizeof(char)); + ret = node->ReadAttr(name, info.type, 0, *buffer, info.size); + if (ret > B_OK) { + *size = ret; + ret = B_OK; + + } else { + free(*buffer); + }; + }; + return ret; +} + +status_t +ReadAttributeInt32(BNode* node,const char *name, int32 *dest) { + attr_info info; + status_t ret = node->GetAttrInfo(name, &info); + if (ret == B_OK) { + //*buffer = (char *)calloc(info.size, sizeof(char)); + ret = node->ReadAttr(name, info.type, 0, dest, info.size); + if (ret > B_OK) { + // *size = ret; + ret = B_OK; + + } + }; + return ret; +} + +int32 +ReadAttributeInt32(BNode* node,const char *name){ + int32 ret=0; + if(ReadAttributeInt32(node,name,&ret)==B_OK){ + return ret; + } + return -1; +} + + +status_t +WriteAttributeInt32(BNode* node,const char *name, int32 dest) { + status_t ret = node->WriteAttr(name, B_INT32_TYPE, 0, &dest, sizeof(int32)); + if (ret > B_OK) ret=B_OK; + return ret; +} + +status_t +WriteAttributeString(BNode* node,const char *name, const char* string) { + status_t ret = node->WriteAttr(name, B_STRING_TYPE, 0, string, strlen(string)); + if (ret > B_OK) ret=B_OK; + return ret; +} + + +status_t +ReadAttributeString(BNode* node,const char *name, char **buffer, int32 *size) { + attr_info info; + status_t ret = node->GetAttrInfo(name, &info); + if (ret == B_OK) { + *buffer = (char *)calloc(info.size + 1, sizeof(char)); + memset(*buffer,'\0',info.size+1); + ret = node->ReadAttr(name, info.type, 0, *buffer, info.size); + if (ret > B_OK) { + *size = ret + 1; + ret = B_OK; + } else { + free(*buffer); + }; + }; + return ret; +} + +BString +ReadAttributeString(BNode* node,const char *name){ + char* buffer=NULL; + int32 size=0; + if(ReadAttributeString(node,name, &buffer,&size)==B_OK){ + BString ret(buffer,size); + free(buffer); + return ret; + } + return ""; +} + + +status_t +WriteAttributeMessage(BNode* node,const char* name,BMessage* data){ + BMallocIO malloc; + status_t ret=data->Flatten(&malloc) ; + if( ret == B_OK) { + ret = node->WriteAttr(name,B_ANY_TYPE,0,malloc.Buffer(),malloc.BufferLength()); + if(ret > B_OK) ret=B_OK; + } + return ret; +} + +status_t +ReadAttributeMessage(BNode* node,const char* name,BMessage* data){ + + char *buffer = NULL; + int32 size = 0; + + status_t ret = ReadAttributeData(node,name,&buffer,&size); + + if(size>0 && buffer!=NULL) { + BMemoryIO mem(buffer,size); + ret = data->Unflatten(&mem); + free(buffer); + } + return ret; +} + + +void BPDrawString(const char* string, BView* parent, BRect rect,alignment ali,float kTEXT_MARGIN) +{ + float width = rect.Width() - (2 * kTEXT_MARGIN); + float y; + BFont font; + font_height finfo; + + parent->GetFont(&font); + font.GetHeight(&finfo); + y = rect.top + ((rect.Height() - (finfo.ascent + finfo.descent + finfo.leading)) / 2) + + (finfo.ascent + finfo.descent) - 2; + + switch (ali) + { + case B_ALIGN_LEFT: + parent->MovePenTo(rect.left + kTEXT_MARGIN, y); + break; + + case B_ALIGN_CENTER: + parent->MovePenTo(rect.left + kTEXT_MARGIN + ((width - font.StringWidth(string)) / 2), y); + break; + + case B_ALIGN_RIGHT: + parent->MovePenTo(rect.right - kTEXT_MARGIN - font.StringWidth(string), y); + break; + } + parent->DrawString(string); +} + + +// file size: + const int64 kKB_SIZE = 1024; + const int64 kMB_SIZE = 1048576; + const int64 kGB_SIZE = 1073741824; + const int64 kTB_SIZE = kGB_SIZE * kKB_SIZE; + +BString +ReadableSize(off_t size) { + + if(size>0 ){ + + char str[256]; + if (size < kKB_SIZE) + { + sprintf(str, "%Ld bytes", size); + } + else + { + const char* suffix; + float float_value; + if (size >= kTB_SIZE) + { + suffix = "TB"; + float_value = (float)size / kTB_SIZE; + } + else if (size >= kGB_SIZE) + { + suffix = "GB"; + float_value = (float)size / kGB_SIZE; + } + else if (size >= kMB_SIZE) + { + suffix = "MB"; + float_value = (float)size / kMB_SIZE; + } + else + { + suffix = "KB"; + float_value = (float)size / kKB_SIZE; + } + + sprintf(str, "%.2f %s", float_value, suffix); + // strip off an insignificant zero so we don't get readings + // such as 1.00 + char *period = 0; + char *tmp (NULL); + for (tmp = str; *tmp; tmp++) + { + if (*tmp == '.') + period = tmp; + } + if (period && period[1] && period[2] == '0') + // move the rest of the string over the insignificant zero + for (tmp = &period[2]; *tmp; tmp++) + *tmp = tmp[1]; + } + return BString(str); + } + return ""; +} + +BString +ReadableSpeed(float size) { + + char str[256]; + if (size < kKB_SIZE) + { + sprintf(str, "%Ld b/s", (off_t)size); + } + else + { + const char* suffix; + float float_value; + if (size >= kTB_SIZE) + { + suffix = "TB/s"; + float_value = (float)size / kTB_SIZE; + } + else if (size >= kGB_SIZE) + { + suffix = "GB/s"; + float_value = (float)size / kGB_SIZE; + } + else if (size >= kMB_SIZE) + { + suffix = "MB/s"; + float_value = (float)size / kMB_SIZE; + } + else + { + suffix = "k/s"; + float_value = (float)size / kKB_SIZE; + } + + sprintf(str, "%.2f %s", float_value, suffix); + // strip off an insignificant zero so we don't get readings + // such as 1.00 + char *period = 0; + char *tmp (NULL); + for (tmp = str; *tmp; tmp++) + { + if (*tmp == '.') + period = tmp; + } + if (period && period[1] && period[2] == '0') + // move the rest of the string over the insignificant zero + for (tmp = &period[2]; *tmp; tmp++) + *tmp = tmp[1]; + } + + return BString(str); +} diff --git a/library/libfunky/extra/Action.h b/library/libfunky/extra/Action.h new file mode 100644 index 0000000..87521fa --- /dev/null +++ b/library/libfunky/extra/Action.h @@ -0,0 +1,26 @@ +#ifndef _Action_h_ +#define _Action_h_ + +#include +#include + +#define ActionID bigtime_t + +class Action +{ + public: + Action(){fActionID=0;}; + virtual ~Action(){}; + + virtual status_t Perform(BMessage* errors) = 0; + virtual BString GetDescription() = 0; + + //general purpose ID.. + void SetActionID(ActionID id){ fActionID=id;} + ActionID GetActionID(){ return fActionID;} + + private: + ActionID fActionID; +}; + +#endif diff --git a/library/libfunky/extra/ActionAsync.cpp b/library/libfunky/extra/ActionAsync.cpp new file mode 100644 index 0000000..0a92a64 --- /dev/null +++ b/library/libfunky/extra/ActionAsync.cpp @@ -0,0 +1,8 @@ +#include "ActionAsync.h" + + +ActionAsync::ActionAsync(BTarget *target = NULL ,uint32 msg = 0){ SetTarget(target,msg);}; + + +void +ActionAsync::SetTarget(BTarget *tar,uint32 msg){ SetTarget(tar); SetMessage(new BMessage(msg);}; diff --git a/library/libfunky/extra/ActionAsync.h b/library/libfunky/extra/ActionAsync.h new file mode 100644 index 0000000..621f3c2 --- /dev/null +++ b/library/libfunky/extra/ActionAsync.h @@ -0,0 +1,15 @@ +#ifndef _ActionAsync_h_ +#define _ActionAsync_h_ + +#include "Action.h" +#include + +class ActionAsync : public Action , BInvoker +{ + public: + ActionAsync(BTarget *target = NULL ,uint32 msg = 0); + + void SetTarget(BTarget *tar,uint32 msg); +}; + +#endif diff --git a/library/libfunky/extra/ActionDownload.cpp b/library/libfunky/extra/ActionDownload.cpp new file mode 100644 index 0000000..977e00a --- /dev/null +++ b/library/libfunky/extra/ActionDownload.cpp @@ -0,0 +1,285 @@ +#include "ActionDownload.h" +#include +#include +#include +#include +//#include "Logger.h" + +#include "DownloadManager.h" +extern DownloadManager* download_manager; + + +ActionDownload::ActionDownload(BString URL, entry_ref dest, + bool allowResume, + BLooper *target, + uint32 msg + ):ActionAsync(target,msg), + fUrl(URL), + fDest(dest), + fAllowResume(allowResume) +{ + file = NULL; + curl=NULL; + resuming = 0.0; + SetShouldStop(false); +// LOG("ActionDownload",liDebug,"downloading URL=%s, to %s",URL.String(),BPath(&dest).Path()); +} + + +status_t +ActionDownload::openFile(BMessage* errors){ + + uint32 openMode = 0; + + if(fAllowResume) + openMode = B_WRITE_ONLY | B_CREATE_FILE | B_OPEN_AT_END; + else + openMode = B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE; + + if(file) return B_ERROR; + + file = new BFile(&fDest,openMode); + + if(!file || file->InitCheck()!=B_OK) + { + BString err("Can't open file!"); + errors->AddInt32("status",ERROR_OPENFILE); + errors->AddString("error",err); + return B_ERROR; + } + + + + + return B_OK; +} + + +status_t +ActionDownload::Perform(BMessage* errors){ + + + //is it these the right place? + fillMessage(this,errors); + // + + CURLcode res; + status_t status = B_OK; + + curl = curl_easy_init(); + + if(!curl) { + BString err("Internal error (CURL can't' init)!"); + errors->AddInt32("status",ERROR_CURL_INIT); + errors->AddString("error",err); + return B_ERROR; + } + + curl_easy_setopt(curl, CURLOPT_URL, fUrl.String()); + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, callback); + curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, this ); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS,FALSE); + + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,save_file); + curl_easy_setopt(curl, CURLOPT_WRITEDATA,this); + + curl_easy_setopt(curl, CURLOPT_PASSWDFUNCTION,passwd); + curl_easy_setopt(curl, CURLOPT_PASSWDDATA,this); + + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION , 1); //follow the white link! + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER , FALSE); //https + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST , FALSE); //https + + curl_easy_setopt(curl, CURLOPT_FAILONERROR , 1); + + download_manager->FinishCurl(curl); + + //RESUME + if(fAllowResume){ + BNode stat(&fDest); + // file->Seek(SEEK_END,0); + // size_t resume = (size_t)file->Position(); + off_t size = 0; + stat.GetSize(&size); + + size_t resume = size; + + + if(resume>0){ + curl_easy_setopt(curl, CURLOPT_RESUME_FROM, resume); + resuming = (double)resume; + } + } + + BMessage connect(*errors); + connect.what = Message(); + connect.AddInt32("status",OK_CONNECTING); + Target()->PostMessage(&connect); + + res = curl_easy_perform(curl); + + if(res !=0) + { + BString err("Can't connect!"); + errors->AddInt32("status",ERROR_PERFORMING); + errors->AddString("error",err); + errors->AddInt32("curl_error",res); + errors->AddBool("should_stop",ShouldStop()); + status = B_ERROR; + } + else + { + errors->AddInt32("status",OK_DOWNLOADED); + } + + curl_easy_cleanup(curl); + + errors->AddString("path",GetLocalPath()); + errors->AddRef("entry",&fDest); + + + + BMimeType mime; + + + if(fFileType != "") + + BNodeInfo(file).SetType(fFileType.String()); + + else + { + + status_t guess=BMimeType::GuessMimeType(&fDest,&mime); // :( return B_ERROR.. why???????????? + if(guess==B_OK) + BNodeInfo(file).SetType(mime.Type()); + } + + delete file; + file = NULL; + + if(res == CURLE_BAD_DOWNLOAD_RESUME || res == CURLE_HTTP_RANGE_ERROR) + { + // sarebbe bello chiedere.. va be per ora ci riprova e basta! + fAllowResume = false; + errors->MakeEmpty(); + Perform(errors); + } + + return status; +} + +BString +ActionDownload::GetDescription(){ + return "HTTP File download"; +} + +BString +ActionDownload::GetLocalPath(){ + return BPath(&fDest).Path(); +} + +void +ActionDownload::fillMessage(ActionDownload* ad,BMessage* msg){ + //fill with common fileds + int32 what=msg->what; //preserve original what. + *msg = ad->extraInfo; + + msg->AddInt64("sid",ad->GetActionID()); + msg->AddString("url",ad->fUrl); + + msg->what=what; +} + + + +void +ActionDownload::sendProgressX(ActionDownload* ad,double max,double current){ + BMessage msg(ad->Message()); + + fillMessage(ad,&msg); + + + + msg.AddInt32("status",OK_PROGRESS); + msg.AddFloat("max_progress",max); + msg.AddFloat("current_progress",current); + //perc + float div = (current / max ) * 100; + + msg.AddInt32("percentage_progress",(int32)floor(div)); + + double speed = 0; + if(curl_easy_getinfo(ad->curl,CURLINFO_SPEED_DOWNLOAD,&speed) == CURLE_OK) + msg.AddFloat("download_speed",speed); + + + //TOTALE: + if(curl_easy_getinfo(ad->curl,CURLINFO_CONTENT_LENGTH_DOWNLOAD,&speed) == CURLE_OK) + msg.AddFloat("total_size",speed); + + // ATTUALE: CURLINFO_SIZE_DOWNLOAD + if(curl_easy_getinfo(ad->curl,CURLINFO_SIZE_DOWNLOAD,&speed) == CURLE_OK) + msg.AddFloat("actual_size",speed); + + char *array = NULL; + + + if(curl_easy_getinfo(ad->curl,CURLINFO_EFFECTIVE_URL,&array) == CURLE_OK) + msg.AddString("effective_url",BString(array)); + + if(ad->fFileType == "" && curl_easy_getinfo(ad->curl,CURLINFO_CONTENT_TYPE,&array) == CURLE_OK) { + ad->fFileType.SetTo(array); + BNodeInfo(ad->file).SetType(ad->fFileType.String()); + msg.AddString("filetype",BString(array)); + } + + ad->Target()->PostMessage(&msg); +} + +/* +void +ActionDownload::sendError(BLooper* looper,uint32 amsg,Status st,BString descr){ + BMessage msg(amsg); + msg.AddInt32("status",st); + msg.AddString("error",descr); + looper->PostMessage(&msg); +} +*/ +// + +int +ActionDownload::callback(void *data, + double dltotal, + double dlnow, + double , + double ) +{ + ActionDownload *ad=((ActionDownload*)data); + + //LOG("ActionDownload",liDebug,"callback total %f, now %f", dltotal,dlnow); + + if(ad->Target()) + sendProgressX(ad,ad->resuming+dltotal,ad->resuming+dlnow); + return 0; +} + +size_t +ActionDownload::save_file( void *ptr, size_t size, size_t nmemb, void *data){ + ActionDownload *ad=((ActionDownload*)data); + + if(!ad->file) { + BMessage errors; //how to report these errors?? + if(ad->openFile(&errors) != B_OK) return 0; + } + BFile* file=ad->file; + if(ad->ShouldStop()) return 0; + return file->Write(ptr,size*nmemb); +} + +int +ActionDownload::passwd (void *clientp, const char *prompt, char *buffer, int buflen){ + debugger(prompt); +} + + +//. diff --git a/library/libfunky/extra/ActionDownload.h b/library/libfunky/extra/ActionDownload.h new file mode 100644 index 0000000..f012b44 --- /dev/null +++ b/library/libfunky/extra/ActionDownload.h @@ -0,0 +1,86 @@ +#ifndef _ActionDownload_h_ +#define _ActionDownload_h_ + +#include "ActionAsync.h" +#include +#include + +#include "curl/curl.h" + +class ActionDownload : public ActionAsync +{ + public: + ActionDownload(BString URL, entry_ref dest,bool allowResume,BLooper *target = NULL ,uint32 msg = 0); + ~ActionDownload(){}; + + status_t Perform(BMessage* errors); + BString GetDescription(); + BString GetLocalPath(); + + //void SetLooper(BLooper *loop,uint32 msg){ fTarget=loop; fMsg=msg;}; + + //for compaatibility: + void SetExtraData(BString extra){ + extraInfo.AddString("extra",extra); + } + + void SetKey(BString key, BString data){ + extraInfo.AddString(key.String(),data); + } + + void SetRef(BString key, entry_ref *ref){ + extraInfo.AddRef(key.String(),ref); + } + + status_t GetRef(BString key, entry_ref* ref){ + return extraInfo.FindRef(key.String(),ref); + } + + BString GetKey(BString key){ + BString data; + extraInfo.FindString(key.String(),&data); + return data; + } + + + void SetShouldStop(bool stop){ fShouldStop=stop;} + bool ShouldStop(){ return fShouldStop; } + + enum Status { + ERROR_OPENFILE, // 0 + ERROR_CURL_INIT, // 1 + ERROR_PERFORMING, // 2 + OK_CONNECTING, // 3 + OK_PROGRESS, // 4 + OK_DOWNLOADED // 5 + }; + +private: + + + status_t openFile(BMessage*); + + static void fillMessage(ActionDownload*,BMessage*); + static void sendProgressX(ActionDownload*,double max,double current); + + //curl callbacks: + static size_t save_file ( void *ptr, size_t size, size_t nmemb, void *stream); + static int callback (void *clientp,double dltotal,double dlnow,double , double); + static int passwd (void *clientp, const char *prompt, char *buffer, int buflen); + + + CURL* curl; + BString fUrl; //from. + entry_ref fDest; + //BLooper* fTarget; //target progess + //uint32 fMsg; + BMessage extraInfo; + bool fShouldStop; + BFile* file; + double resuming; + bool fAllowResume; + + BString fFileType; +}; + +#endif diff --git a/library/libfunky/extra/Colors.h b/library/libfunky/extra/Colors.h new file mode 100644 index 0000000..42a582f --- /dev/null +++ b/library/libfunky/extra/Colors.h @@ -0,0 +1,53 @@ +//Useful until be gets around to making these sorts of things +//globals akin to be_plain_font, etc. + + +#ifndef _SGB_COLORS_H_ +#define _SGB_COLORS_H_ + + +//****************************************************************************************************** +//**** SYSTEM HEADER FILES +//****************************************************************************************************** +#include + + +//****************************************************************************************************** +//**** CONSTANT DEFINITIONS +//****************************************************************************************************** +//Be standard UI colors +const rgb_color BeBackgroundGrey = {216,216,216, 255}; +const rgb_color BeInactiveControlGrey = {240,240,240, 255}; +const rgb_color BeFocusBlue = {0, 0, 229, 255}; +const rgb_color BeHighlight = {255,255,255, 255}; +const rgb_color BeShadow = {152,152,152, 255}; +const rgb_color BeDarkShadow = {108,108,108, 255}; +const rgb_color BeLightShadow = {194,194,194, 255}; +const rgb_color BeButtonGrey = {232,232,232, 255}; +const rgb_color BeInactiveGrey = {127,127,127, 255}; +const rgb_color BeListSelectGrey = {178,178,178, 255}; +const rgb_color BeTitleBarYellow = {255,203,0, 255}; + +//Other colors +const rgb_color Black = {0, 0, 0, 255}; +const rgb_color White = {255,255,255, 255}; +const rgb_color Red = {255,0, 0, 255}; +const rgb_color Green = {0, 167,0, 255}; +const rgb_color LightGreen = {90, 240,90, 255}; +const rgb_color Blue = {49, 61, 225, 255}; +const rgb_color LightBlue = {64, 162,255, 255}; +const rgb_color Purple = {144,64, 221, 255}; +const rgb_color LightPurple = {166,74, 255, 255}; +const rgb_color Lavender = {193,122,255, 255}; +const rgb_color Yellow = {255,203,0, 255}; +const rgb_color Orange = {255,163,0, 255}; +const rgb_color Flesh = {255,231,186, 255}; +const rgb_color Tan = {208,182,121, 255}; +const rgb_color Brown = {154,110,45, 255}; +const rgb_color Grey = {200,200,200, 255}; +const rgb_color LightMetallicBlue = {143,166,240, 255}; +const rgb_color MedMetallicBlue = {75, 96, 154, 255}; +const rgb_color DarkMetallicBlue = {78, 89, 126, 255}; + + +#endif diff --git a/library/libfunky/extra/Hashtable.h b/library/libfunky/extra/Hashtable.h new file mode 100644 index 0000000..11e8c01 --- /dev/null +++ b/library/libfunky/extra/Hashtable.h @@ -0,0 +1,1609 @@ +/* This file is Copyright 2005 Level Control Systems. See the included LICENSE.txt file for details. */ + +#ifndef MuscleHashtable_h +#define MuscleHashtable_h + +#include "support/MuscleSupport.h" + +#ifdef _MSC_VER +# pragma warning(disable: 4786) +#endif + +#ifndef MUSCLE_HASHTABLE_DEFAULT_CAPACITY +# define MUSCLE_HASHTABLE_DEFAULT_CAPACITY 7 +#endif + +BEGIN_NAMESPACE(muscle); + +// implementation detail; please ignore this! +static const uint32 MUSCLE_HASHTABLE_INVALID_HASH_CODE = (uint32)-1; + +/** This hashing functor type handles the "easy" cases, where the KeyType is + * something that can be static_cast into a uint32 by the compiler. + * For more complicated key types, you'll need to define your own + * specialization of this functor template. (See util/String.h for an example of this) + */ +template class HashFunctor +{ +public: + /** Default implementation just casts the key to a uint32 to get the hash value. */ + uint32 operator () (const T x) const {return (uint32) x;} +}; + +template class Hashtable; // forward declaration + +/** + * This class is an iterator object, used for iterating over the set + * of keys or values in a Hashtable. Note that the Hashtable + * maintains the ordering of keys and values, unlike many hash table + * implementations. + * + * Given a Hashtable object, you can obtain one or more of these + * iterator objects by calling the Hashtable's GetIterator() method. + * + * This iterator actually contains separate state for two iterations: + * one for iterating over the values in the Hashtable, and one for + * iterating over the keys. These two iterations can be done independently + * of each other. + * + * It is safe to modify or delete a hashtable during a traversal; the active iterators + * will be automatically notified so that they do the right thing. + */ +template > class HashtableIterator +{ +public: + /** + * Default constructor. It's here only so that you can include HashtableIterators + * as member variables, in arrays, etc. HashtableIterators created with this + * constructor are "empty", so they won't be useful until you set them equal to a + * HashtableIterator that was returned by Hashtable::GetIterator(). + */ + HashtableIterator(); + + /** Copy Constructor. */ + HashtableIterator(const HashtableIterator & rhs); + + /** Convenience Constructor -- makes an iterator equivalent to the value returned by table.GetIterator(). */ + HashtableIterator(const Hashtable & table, bool backwards = false); + + /** Convenience Constructor -- makes an iterator equivalent to the value returned by table.GetIteratorAt(). */ + HashtableIterator(const Hashtable & table, const KeyType & startAt, bool backwards); + + /** Destructor */ + ~HashtableIterator(); + + /** Assignment operator. */ + HashtableIterator & operator=(const HashtableIterator & rhs); + + /** Returns true iff there are more keys left in the key traversal. */ + bool HasMoreKeys() const {return (_nextKeyCookie != NULL);} + + /** + * Gets the next key in the key traversal. + * @param setNextKey On success, the next key is copied into this object. + * @return B_NO_ERROR on success, B_ERROR if there are no more keys left. + */ + status_t GetNextKey(KeyType & setNextKey); + + /** + * Gets a pointer to the next key in the key traversal. + * Note that the returned pointer is only guaranteed valid as long as the Hashtable remains unchanged. + * @return A pointer to the next key in the key traversal, or NULL if there are no more keys left. + */ + const KeyType * GetNextKey(); + + /** + * Peek at the next key without modifying the state of the traversal. + * @param setKey On success, the next key is copied into this object. + * @return B_NO_ERROR on success, or B_ERROR if there are no more keys left. + */ + status_t PeekNextKey(KeyType & setKey) const; + + /** + * Peek at the next key without modifying the state of the traversal. + * Note that the returned pointer is only guaranteed valid as long as the Hashtable remains unchanged. + * @return a pointer to the next key in the key traversal, or NULL if there are no keys left. + */ + const KeyType * PeekNextKey() const; + + /** Returns true iff there are more values left in the value traversal. */ + bool HasMoreValues() const {return (_nextValueCookie != NULL);} + + /** + * Get the next value in the values traversal. + * @param setNextValue On success, the next value in the traversal is copied into this object. + * @return B_NO_ERROR on success, B_ERROR if there are no more values left in the value traversal. + */ + status_t GetNextValue(ValueType & setNextValue); + + /** + * Get the next value in the values traversal. + * Note that the returned pointer is only guaranteed valid as long as the Hashtable remains unchanged. + * @return a pointer to the next value in the value traversal, or NULL if there are no values left. + */ + ValueType * GetNextValue(); + + /** + * Peek at the next value without modifying the state of the traversal. + * @param setValue On success, the next value is copied into this object. + * @return B_NO_ERROR on success, or B_ERROR if there are no more values left. + */ + status_t PeekNextValue(ValueType & setValue) const; + + /** + * Peek at the next value without modifying the state of the traversal. + * Note that the returned pointer is only guaranteed valid as long as the Hashtable remains unchanged. + * @return a pointer to the next value in the value traversal, or NULL if there are no values left. + */ + ValueType * PeekNextValue() const; + + /** Convenience method -- equivalent to calling both GetNextKey() and GetNextValue(). + * @param setKey on success, this parameter will contain the next key in the iteration. + * @param setValue on success, this parameter will contain the next value in the iteration. + * @returns B_NO_ERROR if values were written into (setKey) and (setValue), or B_ERROR if the iteration is complete. + */ + status_t GetNextKeyAndValue(KeyType & setKey, ValueType & setValue); + + /** Convenience method -- equivalent to calling both GetNextKey() and GetNextValue(). + * @param setKey on success, this parameter will contain the next key in the iteration. + * @param setValuePtr on success, this pointer will point to the next value in the iteration. + * @returns B_NO_ERROR if values were written into (setKey) and (setValue), or B_ERROR if the iteration is complete. + */ + status_t GetNextKeyAndValue(KeyType & setKey, ValueType * & setValuePtr); + + /** Convenience method -- equivalent to calling both GetNextKey() and GetNextValue(). + * @param setKey on success, this parameter will contain the next key in the iteration. + * @param setValuePtr on success, this pointer will point to the next value in the iteration. + * @returns B_NO_ERROR if values were written into (setKey) and (setValue), or B_ERROR if the iteration is complete. + */ + status_t GetNextKeyAndValue(KeyType & setKey, const ValueType * & setValuePtr); + + /** Convenience method -- equivalent to calling both GetNextKey() and GetNextValue(). + * @param setKeyPtr on success, this pointer will point to the next key in the iteration. + * @param setValue on success, this parameter will contain the next value in the iteration. + * @returns B_NO_ERROR if values were written into (setKey) and (setValue), or B_ERROR if the iteration is complete. + */ + status_t GetNextKeyAndValue(const KeyType * & setKeyPtr, ValueType & setValue); + + /** Convenience method -- equivalent to calling both GetNextKey() and GetNextValue(). + * @param setKeyPtr on success, this pointer will point to the next key in the iteration. + * @param setValuePtr on success, this pointer will point to the next value in the iteration. + * @returns B_NO_ERROR if values were written into (setKey) and (setValue), or B_ERROR if the iteration is complete. + */ + status_t GetNextKeyAndValue(const KeyType * & setKeyPtr, ValueType * & setValuePtr); + + /** Convenience method -- equivalent to calling both GetNextKey() and GetNextValue(). + * @param setKeyPtr on success, this pointer will point to the next key in the iteration. + * @param setValuePtr on success, this pointer will point to the next value in the iteration. + * @returns B_NO_ERROR if values were written into (setKey) and (setValue), or B_ERROR if the iteration is complete. + */ + status_t GetNextKeyAndValue(const KeyType * & setKeyPtr, const ValueType * & setValuePtr); + +private: + void SetOwner(const Hashtable * optTable); + + /** The Hashtable class needs access to our internals to do the iteration operation */ + friend class Hashtable; + + void * _scratchSpace[2]; // ignore this; it's temp scratch space used by EnsureSize(). + + void * _nextKeyCookie; + void * _nextValueCookie; + bool _backwards; + + HashtableIterator * _prevIter; // for the doubly linked list so that the table can notify us if it is modified + HashtableIterator * _nextIter; // for the doubly linked list so that the table can notify us if it is modified + const Hashtable * _owner; // table that we are associated with +}; + +/** + * This is a handy templated Hashtable class, rather similar to Java's java.util.Hashtable, + * but with a number of enhancements. Enhancements include: Iterator objects that are + * safe to use even if the table is modified or deleted during a traversal (not thread-safe though), + * traversal ordering is maintained at all times and may optionally be sorted or auto-sorted, + * and the traversal order may be manually changed as well. + * + * The Hashtable class uses a HashFunctor template argument to specify how the hash code for + * a given KeyType object can be computed. For built-in numeric types (e.g. int, long, etc) + * the default HashFunctor can be used. For more complex types (e.g. class objects), you will + * need to either create your own custom HashFunctor, or add a () operator to your class that + * returns a uint32 HashCode. The best way to do a custom HashFunctor is to specialize the + * default HashFunctor type for your class; check the example in util/String.h for how to do this. + */ +template > class Hashtable +{ +public: + /** This is the signature of the type of callback function that you can pass into the + * SetKeyCompareFunction() and SortByKey() methods. The function should work like strcmp(), + * return a negative value if (key1) is less than (key2), 0 if the two keys are equal, + * or a positive value if (key1) is greater than (key2). + * @param key1 The first key. + * @param key2 The second key. + * @param cookie A user-defined value that was passed in to the Sort() or SetCompareCookie() method. + * @return An integer indicating which key is "larger", as defined above. + */ + typedef int (*KeyCompareFunc)(const KeyType& key1, const KeyType& key2, void * cookie); + + /** This is the signature of the type of callback function that you can pass into the + * SetValueCompareFunction() and SortByValue() methods. The function should work like strcmp(), + * return a negative value if (value1) is less than (value2), 0 if the two values are equal, + * or a positive value if (value1) is greater than (value2). + * @param value1 The first value. + * @param value2 The second value. + * @param cookie A user-defined value that was passed in to the Sort() or SetCompareCookie() method. + * @return An integer indicating which value is "larger", as defined above. + */ + typedef int (*ValueCompareFunc)(const ValueType& key1, const ValueType& key2, void * cookie); + + /** Tokens for the various auto-sort modes we know how to do. */ + enum { + AUTOSORT_DISABLED = 0, + AUTOSORT_BY_KEY, + AUTOSORT_BY_VALUE + }; + + /** This constructor creates a standard, non-sorting Hashtable. + * @param initialCapacity Specifies the number of table slots to initially pre-allocate. Defaults to 7. + */ + Hashtable(uint32 initialCapacity = MUSCLE_HASHTABLE_DEFAULT_CAPACITY); + + /** Copy Constructor. */ + Hashtable(const Hashtable & rhs); + + /** Assignment operator. */ + Hashtable & operator= (const Hashtable & rhs); + + /** Equality operator. Returns true iff both hash tables contains the same set of keys and values. + * Note that the ordering of the keys is NOT taken into account! + */ + bool operator== (const Hashtable & rhs) const; + + /** Returns the opposite of the equality operator. */ + bool operator!= (const Hashtable & rhs) const {return !(*this == rhs);} + + /** Destructor. */ + ~Hashtable(); + + /** Returns the number of items stored in the table. */ + uint32 GetNumItems() const {return _count;} + + /** Convenience method; Returns true iff the table is empty (i.e. if GetNumItems() is zero). */ + bool IsEmpty() const {return _count == 0;} + + /** Returns true iff the table contains a mapping with the given key. (O(1) search time) */ + bool ContainsKey(const KeyType& key) const {return ((_count>0)&&(GetEntry(ComputeHash(key), key) != NULL));} + + /** Returns true iff the table contains a mapping with the given value. (O(n) search time) */ + bool ContainsValue(const ValueType& value) const; + + /** Returns the given key's position in the hashtable's linked list, or -1 if the key wasn't found. O(n) count time (if the key exists, O(1) if it doesn't) */ + int32 IndexOfKey(const KeyType& key) const; + + /** Attempts to retrieve the associated value from the table for a given key. (O(1) lookup time) + * @param key The key to use to look up a value. + * @param setValue On success, the associated value is copied into this object. + * @return B_NO_ERROR on success, B_ERROR if their was no value found for the given key. + */ + status_t GetValue(const KeyType& key, ValueType& setValue) const; + + /** Retrieve a pointer to the associated value object for the given key. (O(1) lookup time) + * @param key The key to use to look up a value. + * @return A pointer to the internally held value object for the given key, + * or NULL of no object was found. Note that this object is only + * guaranteed to remain valid as long as the Hashtable remains unchanged. + */ + ValueType * GetValue(const KeyType & key) const; + + /** Given a lookup key, returns the a copy of the actual key as held by the table. + * This method is only useful in rare situations where the hashing or comparison + * functions are such that lookupKeys and held keys are not guaranteed equivalent. + * @param lookupKey The key used to look up the held key object. + * @param setKey On success, the actual key held in the table is placed here. + * @return B_NO_ERROR on success, or B_ERROR on failure. + */ + status_t GetKey(const KeyType & lookupKey, KeyType & setKey) const; + + /** Given a key, returns a pointer to the actual key object in this table that matches + * that key, or NULL if there is no matching key. This method is only useful in rare + * situations where the hashing or comparison functions are such that lookup keys and + * held keys are not guaranteed equivalent. + * @param lookupKey The key used to look up the key object + * @return A pointer to an internally held key object on success, or NULL on failure. + */ + const KeyType * GetKey(const KeyType & lookupKey) const; + + /** Get an iterator for use with this table. + * @param backwards Set this to true if you want to iterate through the item list backwards. Defaults to false. + * @return an iterator object that can be used to examine the items in the hash table. + */ + HashtableIterator GetIterator(bool backwards = false) const + { + HashtableIterator ret; + InitializeIterator(ret, backwards); + return ret; + } + + /** Get an iterator for use with this table, starting at the given entry. + * @param startAt The key in this table to start the iteration at. + * @param backwards Set this to true if you want to iterate through the item list backwards. Defaults to false. + * @return an iterator object that can be used to examine the items in the hash table, starting at + * the specified key. If the specified key is not in this table, an empty iterator will be returned. + */ + HashtableIterator GetIteratorAt(const KeyType & startAt, bool backwards = false) const + { + HashtableIterator ret; + InitializeIteratorAt(ret, startAt, backwards); + return ret; + } + + /** Returns a pointer to the (index)'th key in this Hashtable. + * (This Hashtable class keeps its entries in a well-defined order) + * Note that this method is an O(N) operation, so for iteration, always use GetIterator() instead. + * @param index Index of the key to return a pointer to. Should be in the range [0, GetNumItems()-1]. + * @returns Pointer to the key at position (index) on success, or NULL on failure (bad index?) + */ + const KeyType * GetKeyAt(uint32 index) const; + + /** Returns the (index)'th key in this Hashtable. + * (This Hashtable class keeps its entries in a well-defined order) + * Note that this method is an O(N) operation, so for iteration, always use GetIterator() instead. + * @param index Index of the key to return a pointer to. Should be in the range [0, GetNumItems()-1]. + * @param retKey On success, the contents of the (index)'th key will be written into this object. + * @return B_NO_ERROR on success, or B_ERROR on failure. + */ + status_t GetKeyAt(uint32 index, KeyType & retKey) const; + + /** Places the given (key, value) mapping into the table. Any previous entry with a key of (key) will be replaced. + * (average O(1) insertion time, unless auto-sorting is enabled, in which case it becomes O(N) insertion time for + * keys that are not already in the table) + * @param key The key that the new value is to be associated with. + * @param value The value to associate with the new key. + * @param setPreviousValue If there was a previously existing value associated with (key), it will be copied into this object. + * @param optSetReplaced If set non-NULL, this boolean will be set to true if (setPreviousValue) was written into, false otherwise. + * @return B_NO_ERROR If the operation succeeded, B_ERROR if it failed (out of memory?) + */ + status_t Put(const KeyType& key, const ValueType& value, ValueType & setPreviousValue, bool * optSetReplaced = NULL) {return (PutAux(ComputeHash(key), key, value, &setPreviousValue, optSetReplaced) != NULL) ? B_NO_ERROR : B_ERROR;} + + /** Places the given (key, value) mapping into the table. Any previous entry with a key of (key) will be replaced. + * (average O(1) insertion time, unless auto-sorting is enabled, in which case it becomes O(N) insertion time for + * keys that are not already in the table) + * @param key The key that the new value is to be associated with. + * @param value The value to associate with the new key. + * @return B_NO_ERROR If the operation succeeded, B_ERROR if it failed (out of memory?) + */ + status_t Put(const KeyType& key, const ValueType& value) {return (PutAux(ComputeHash(key), key, value, NULL, NULL) != NULL) ? B_NO_ERROR : B_ERROR;} + + /** Removes a mapping from the table. (O(1) removal time) + * @param key The key of the key-value mapping to remove. + * @return B_NO_ERROR if a key was found and the mapping removed, or B_ERROR if the key wasn't found. + */ + status_t Remove(const KeyType& key) {return RemoveAux(key, NULL);} + + /** Removes the mapping with the given (key) and places its value into (setRemovedValue). (O(1) removal time) + * @param key The key of the key-value mapping to remove. + * @param setRemovedValue On success, the removed value is copied into this object. + * @return B_NO_ERROR if a key was found and the mapping removed, or B_ERROR if the key wasn't found. + */ + status_t Remove(const KeyType& key, ValueType & setRemovedValue) {return RemoveAux(key, &setRemovedValue);} + + /** Removes all mappings from the hash table. (O(N) clear time) + * @param releaseCachedData If set true, we will immediately free any buffers we may contain. + * Otherwise, we'll keep them around in case they can be re-used later on. + */ + void Clear(bool releaseCachedData = false); + + /** This method can be used to activate or deactivate auto-sorting on this Hashtable. + * If active, auto-sorting ensures that whenever Put() is called, the new/updated item is + * moved to the correct place in the iterator traversal list. Note that using auto-sort + * means that Put() becomes an O(N) operation instead of O(1). + * Default mode is AUTOSORT_DISABLED. + * @param mode Either AUTOSORT_DISABLED, AUTOSORT_BY_KEY, or AUTOSORT_BY_VALUE. + * @param sortNow If true, Sort() will be called to ensure that the table is in a sorted state. + * You can avoid an immediate sort by specifying this parameter as false, but be aware + * that auto-sorting won't sort properly if the contents of the table aren't already in + * in a correctly sorted state--so you may then need to call Sort() before auto-sorting + * will sort properly. + */ + void SetAutoSortMode(int mode, bool sortNow = true) {_autoSortMode = mode; if (sortNow) (void) Sort();} + + /** Returns this hash table's current auto-sort mode. */ + int GetAutoSortMode() const {return _autoSortMode;} + + /** This method can be used to set the "cookie value" that will be passed in to the + * comparison functions specified by SetKeyCompareFunction() and SetValueCompareFunction(). + * This value will be passed along during whenever a user-defined compare function is called implicitely. + * + */ + void SetCompareCookie(void * cookie) {_compareCookie = cookie;} + + /** Returns the current comparison cookie, as previously set by SetCompareCookie(). Default value is NULL. */ + void * GetCompareCookie() const {return _compareCookie;} + + /** You can call this to set a custom function to use to compare keys. By default, the Key class's '==' operator + * is used to compare keys, and no key sorting is done. But for some key types (e.g. const char *'s) '==' is not + * terribly useful, and in any case it doesn't handle sorting properly, so if you like you you can supply your + * own key-comparison-function here. + * @see KeyCompareFunc for a description of the callback function's required semantics. + * @param func The new comparison function to use for this table, or NULL to revert to no key-sorting-function. + */ + void SetKeyCompareFunction(KeyCompareFunc func) {_userKeyCompareFunc = func;} + + /** Returns the current comparison function used for comparing keys. Default value is NULL. */ + KeyCompareFunc GetKeyCompareFunction() const {return _userKeyCompareFunc;} + + /** You can call this to set a custom function to use to compare values. By default, no value sorting is done. + * If you wish to enable auto-sort-by-value, you will need to a value-comparison-function here. + * @see ValueCompareFunc for a description of the callback function's required semantics. + * @param func The new comparison function to use for this table, or NULL to revert to no value-sorting-function. + */ + void SetValueCompareFunction(ValueCompareFunc func) {_userValueCompareFunc = func;} + + /** Returns the current comparison function used for comparing values. Default value is NULL. */ + ValueCompareFunc GetValueCompareFunction() const {return _userValueCompareFunc;} + + /** This method doesn anhefficient zero-copy swap of this hash table's contents with those of (swapMe). + * That is to say, when this method returns, (swapMe) will be identical to the old state of this + * Hashtable, and this Hashtable will be identical to the old state of (swapMe). + * Any active iterators present for either table will swap owners also, becoming associated with the other table. + * @param swapMe The table whose contents and iterators are to be swapped with this table's. + */ + void SwapContents(Hashtable & swapMe); + + /** Moves the given entry to the head of the HashtableIterator traversal sequence. + * Note that calling this method is generally a bad idea of the table is in auto-sort mode, + * as it is likely to unsort the traversal ordering and thus break auto-sorting. However, + * calling Sort() will restore the sort-order and make auto-sorting work again) + * @param moveMe Key of the item to be moved to the front of the sequence. + * @return B_NO_ERROR on success, or B_ERROR if (moveMe) was not found in the table. + */ + status_t MoveToFront(const KeyType & moveMe); + + /** Moves the given entry to the tail of the HashtableIterator traversal sequence. + * Note that calling this method is generally a bad idea of the table is in auto-sort mode, + * as it is likely to unsort the traversal ordering and thus break auto-sorting. However, + * calling Sort() will restore the sort-order and make auto-sorting work again) + * @param moveMe Key of the item to be moved to the end of the sequence. + * @return B_NO_ERROR on success, or B_ERROR if (moveMe) was not found in the table. + */ + status_t MoveToBack(const KeyType & moveMe); + + /** Moves the given entry to the spot just in front of the other specified entry in the + * HashtableIterator traversal sequence. + * Note that calling this method is generally a bad idea of the table is in auto-sort mode, + * as it is likely to unsort the traversal ordering and thus break auto-sorting. However, + * calling Sort() will restore the sort-order and make auto-sorting work again) + * @param moveMe Key of the item to be moved. + * @param toBeforeMe Key of the item that (moveMe) should be placed in front of. + * @return B_NO_ERROR on success, or B_ERROR if (moveMe) was not found in the table, + * or was the same item as (toBeforeMe). + */ + status_t MoveToBefore(const KeyType & moveMe, const KeyType & toBeforeMe); + + /** Moves the given entry to the spot just behind the other specified entry in the + * HashtableIterator traversal sequence. + * Note that calling this method is generally a bad idea of the table is in auto-sort mode, + * as it is likely to unsort the traversal ordering and thus break auto-sorting. However, + * calling Sort() will restore the sort-order and make auto-sorting work again) + * @param moveMe Key of the item to be moved. + * @param toBehindMe Key of the item that (moveMe) should be placed behind. + * @return B_NO_ERROR on success, or B_ERROR if (moveMe) was not found in the table, + * or was the same item as (toBehindMe). + */ + status_t MoveToBehind(const KeyType & moveMe, const KeyType & toBehindMe); + + /** Forcefully sorts the iteration traversal list of this table using the preferred sorting mode. + * The preferred sorting mode will be determined as follows: + *
    + *
  1. If the auto-sort mode is set, the auto-sort mode will be used.
  2. + *
  3. Else if the sort-by-value callback function is set, sort-by-value will be used.
  4. + *
  5. Else if the sort-by-key callback function is set, sort-by-key will be used.
  6. + *
  7. Else we return B_ERROR.
  8. + *
+ * This method uses a very efficient O(log(N)) MergeSort algorithm. + * @return B_NO_ERROR on success, or B_ERROR if no sort method could be determined (as described above) + */ + status_t Sort() {return SortByAux((_autoSortMode != AUTOSORT_BY_VALUE) ? _userKeyCompareFunc : NULL, (_autoSortMode != AUTOSORT_BY_KEY) ? _userValueCompareFunc : NULL, _compareCookie);} + + /** Forcefully sorts the iteration traversal list of this table using the given key comparison function. + * This method uses a very efficient O(log(N)) MergeSort algorithm. + * @param func The key-comparison function to use. (If NULL, this call becomes a no-op) + * @param optCompareCookie Optional cookie to pass to func(). + */ + void SortByKey(KeyCompareFunc func, void * optCompareCookie = NULL) {(void) SortByAux(func, NULL, optCompareCookie);} + + /** Forcefully sorts the iteration traversal list of this table using the given value comparison function. + * This method uses a very efficient O(log(N)) MergeSort algorithm. + * @param func The value-comparison function to use. (If NULL, this call becomes a no-op) + * @param optCompareCookie Optional cookie to func(). + */ + void SortByValue(ValueCompareFunc func, void * optCompareCookie = NULL) {(void) SortByAux(NULL, func, optCompareCookie);} + + /** Synonym for GetValue(), retained for compatibility with old code. + * @deprecated Use GetValue() instead + */ + status_t Get(const KeyType& key, ValueType& setValue) const {return GetValue(key, setValue);} + + /** Synonym for GetValue(), retained for compatibility with old code. + * @deprecated Use GetValue() instead + */ + ValueType * Get(const KeyType & key) const {return GetValue(key);} + + /** Convenience method -- returns a pointer to the value specified by (key), + * or if no such value exists, it will Put() a (key,value) pair in the Hashtable, + * and then return a pointer to the newly-placed value. Returns NULL on + * error only (out of memory?) + * @param key The key to look for a value with + * @param defValue The value to auto-place in the Hashtable if (key) isn't found. + * @returns a Pointer to the retrieved or placed value. + */ + ValueType * GetOrPut(const KeyType & key, const ValueType & defValue = ValueType()) + { + ValueType * ret = Get(key); + if ((ret == NULL)&&(Put(key, defValue) == B_NO_ERROR)) ret = Get(key); + return ret; + } + + /** This method resizes the Hashtable larger if necessary, so that it has at least (newTableSize) + * entries in it. It is not necessary to call this method, but if you know in advance how many + * items you will be adding to the table, you can make the population of the table more efficient + * by calling this method before adding the items. This method will only grow the table, it will + * never shrink it. + * @param newTableSize Number of slots that you with to have in the table (note that this is different + * from the number of actual items in the table) + * @return B_NO_ERROR on success, or B_ERROR on failure (out of memory?) + */ + status_t EnsureSize(uint32 newTableSize); + + /** Returns the number of table-slots that we currently have allocated. Since we often + * pre-allocate slots to avoid unnecessary reallocations, this number will usually be + * greater than the value returned by GetNumItems(). It will never be less than that value. + */ + uint32 GetNumAllocatedSlots() const {return _tableSize;} + +private: + /** Our hashtable iterator class needs access to our internals to register itself with us. */ + friend class HashtableIterator; + + void InitializeIterator(HashtableIterator & iter, bool backwards) const + { + iter.SetOwner(this); + iter._backwards = backwards; + iter._nextKeyCookie = iter._nextValueCookie = (backwards ? _iterTail : _iterHead); + } + + void InitializeIteratorAt(HashtableIterator & iter, const KeyType & startAt, bool backwards) const + { + iter.SetOwner(this); + iter._backwards = backwards; + iter._nextKeyCookie = iter._nextValueCookie = ((_count>0)?GetEntry(ComputeHash(startAt), startAt):NULL); + } + + class HashtableEntry + { + public: + // Note: _bucketPrev and _bucketNext are intentionally not set here + HashtableEntry() : _hash(MUSCLE_HASHTABLE_INVALID_HASH_CODE), _iterPrev(NULL), _iterNext(NULL) +#ifndef _MSC_VER + , _mapTo(this), _mappedFrom(this) // this is slightly more efficient... +#endif + { +#ifdef _MSC_VER + _mapTo = this; // ... but VC++ complains if (this) is in the init list, so for VC++ we do it here + _mappedFrom = this; +#endif + } + + ~HashtableEntry() {/* empty */} + + // Frees up our memory and returns us to the free-list. + void ReturnToFreeList(const KeyType & defaultKey, const ValueType & defaultValue, HashtableEntry ** freeHead) + { + _hash = MUSCLE_HASHTABLE_INVALID_HASH_CODE; + _key = defaultKey; + _value = defaultValue; + + _iterPrev = _iterNext = _bucketPrev = NULL; + _bucketNext = *freeHead; + if (_bucketNext) _bucketNext->_bucketPrev = this; + *freeHead = this; + } + + /** Removes this entry from the free list, so that we are ready for use. + * @param freeHead current head of the free list + * @returns the new head of the free list + */ + HashtableEntry * RemoveFromFreeList(HashtableEntry * freeHead) + { + if (_bucketNext) _bucketNext->_bucketPrev = _bucketPrev; + if (_bucketPrev) _bucketPrev->_bucketNext = _bucketNext; + HashtableEntry * ret = (freeHead == this) ? _bucketNext : freeHead; + _bucketPrev = _bucketNext = NULL; + return ret; + } + + void SwapMaps(HashtableEntry * e) + { + muscleSwap(e->_mapTo, _mapTo); + _mapTo->_mappedFrom = this; + e->_mapTo->_mappedFrom = e; + } + + inline HashtableEntry * GetMapTo() const {return _mapTo;} + inline HashtableEntry * GetMappedFrom() const {return _mappedFrom;} + + static HashtableEntry * CreateEntriesArray(uint32 size) + { + HashtableEntry * ret = newnothrow_array(HashtableEntry,size); + if (ret) + { + HashtableEntry * prev = NULL; + for (uint32 i=0; i_bucketPrev = prev; + if (prev) prev->_bucketNext = cur; + prev = cur; + } + ret[size-1]._bucketNext = NULL; + } + else WARN_OUT_OF_MEMORY; + return ret; + } + + uint32 _hash; // precalculated for efficiency + KeyType _key; // used for '==' checking + ValueType _value; // payload + HashtableEntry* _bucketPrev; // for making linked lists in our bucket + HashtableEntry* _bucketNext; // for making linked lists in our bucket + HashtableEntry* _iterPrev; // for user's table iteration + HashtableEntry* _iterNext; // for user's table iteration + + private: + HashtableEntry* _mapTo; + HashtableEntry* _mappedFrom; + }; + +private: + // Auxilliary methods + HashtableEntry * PutAux(uint32 hash, const KeyType& key, const ValueType& value, ValueType * optSetPreviousValue, bool * optReplacedFlag); + status_t RemoveAux(const KeyType& key, ValueType * setRemovedValue); + status_t SortByAux(KeyCompareFunc optKeyFunc, ValueCompareFunc optValueFunc, void * cookie); + + inline uint32 ComputeHash(const KeyType & key) const + { + uint32 ret = _functor(key); + if (ret == MUSCLE_HASHTABLE_INVALID_HASH_CODE) ret++; // avoid using the guard value as a hash code (unlikely but possible) + return ret; + } + + // Linked list maintainence + void InsertSortedIterationEntry(HashtableEntry * e, KeyCompareFunc optKeyFunc, ValueCompareFunc optValueCompareFunc, void * cookie); + void InsertIterationEntry(HashtableEntry * e, HashtableEntry * optBehindThisOne); + void RemoveIterationEntry(HashtableEntry * e); + HashtableEntry * GetEntry(uint32 hash, const KeyType& key) const; + HashtableEntry * GetEntryAt(uint32 idx) const; + bool IsBucketHead(const HashtableEntry * e) const {return ((e->_hash != MUSCLE_HASHTABLE_INVALID_HASH_CODE)&&(_table[e->_hash%_tableSize].GetMapTo() == e));} + + int CompareEntries(const HashtableEntry & left, const HashtableEntry & right, KeyCompareFunc optKeyFunc, ValueCompareFunc optValueFunc, void * cookie) const; + + // HashtableIterator's private API + void RegisterIterator(HashtableIterator * iter) const + { + // add him to the head of our linked list of iterators + iter->_prevIter = NULL; + iter->_nextIter = _iterList; + if (_iterList) _iterList->_prevIter = iter; + _iterList = iter; + } + + void UnregisterIterator(HashtableIterator * iter) const + { + if (iter->_prevIter) iter->_prevIter->_nextIter = iter->_nextIter; + if (iter->_nextIter) iter->_nextIter->_prevIter = iter->_prevIter; + if (iter == _iterList) _iterList = iter->_nextIter; + iter->_prevIter = iter->_nextIter = NULL; + } + + KeyType * GetKeyFromCookie(void * c) const {return c ? &(((HashtableEntry *)c)->_key) : NULL;} + ValueType * GetValueFromCookie(void * c) const {return c ? &(((HashtableEntry *)c)->_value) : NULL;} + + void IterateCookie(void ** c, bool backwards) const + { + HashtableEntry * entry = *((HashtableEntry **)c); + *c = entry ? (backwards ? entry->_iterPrev : entry->_iterNext) : NULL; + } + + uint32 NextPrime(uint32 start) const; + + const uint32 _initialCapacity; + uint32 _count; // the number of valid elements in the hashtable + uint32 _tableSize; // the number of entries in _table (or the number to allocate if _table is NULL) + + HashtableEntry * _table; // our array of table entries + HashtableEntry * _iterHead; // start of linked list to iterate through + HashtableEntry * _iterTail; // end of linked list to iterate through + + HashtableEntry * _freeHead; // head of the list of unused HashtableEntries in our _table array + + KeyCompareFunc _userKeyCompareFunc; // (optional) used to compare two Keys + ValueCompareFunc _userValueCompareFunc; // (optional) used to compare two Values + int _autoSortMode; // one of the AUTOSORT_BY_* tokens + void * _compareCookie; // (optional) passed to the CompareFuncs + + HashFunctorType _functor; // used to compute hash codes for key objects + + mutable HashtableIterator * _iterList; // list of existing iterators for this table +}; + +//=============================================================== +// Implementation of Hashtable +// Necessary location for appropriate template instantiation. +//=============================================================== +template +Hashtable::Hashtable(uint32 initialCapacity) + : _initialCapacity(initialCapacity), _count(0), _tableSize(initialCapacity), _table(NULL), _iterHead(NULL), _iterTail(NULL), _freeHead(NULL), _userKeyCompareFunc(NULL), _userValueCompareFunc(NULL), _autoSortMode(AUTOSORT_DISABLED), _compareCookie(NULL), _iterList(NULL) +{ + // empty +} + +template +Hashtable:: +Hashtable(const Hashtable & rhs) + : _initialCapacity(rhs._initialCapacity), _count(0), _tableSize(rhs._tableSize), _table(NULL), _iterHead(NULL), _iterTail(NULL), _freeHead(NULL), _userKeyCompareFunc(rhs._userKeyCompareFunc), _userValueCompareFunc(rhs._userValueCompareFunc), _autoSortMode(rhs._autoSortMode), _compareCookie(rhs._compareCookie), _iterList(NULL) +{ + *this = rhs; +} + +template +Hashtable & +Hashtable :: +operator=(const Hashtable & rhs) +{ + if (this != &rhs) + { + Clear(); + if (EnsureSize(rhs.GetNumItems()) == B_NO_ERROR) + { + HashtableIterator iter(rhs); + const KeyType * nextKey; + while((nextKey = iter.GetNextKey()) != NULL) (void) Put(*nextKey, *iter.GetNextValue()); // no good way to handle out-of-mem here? + } + } + return *this; +} + +template +bool +Hashtable :: +operator==(const Hashtable & rhs) const +{ + if (this == &rhs) return true; + if (GetNumItems() != rhs.GetNumItems()) return false; + + HashtableIterator iter(*this); + const KeyType * myNextKey; + const ValueType * myNextValue; + while(iter.GetNextKeyAndValue(myNextKey, myNextValue) == B_NO_ERROR) + { + const ValueType * hisNextValue = rhs.Get(*myNextKey); + if ((hisNextValue == NULL)||(*hisNextValue != *myNextValue)) return false; + } + return true; +} + +template +Hashtable::~Hashtable() +{ + Clear(); + delete [] _table; +} + +template +bool +Hashtable::ContainsValue(const ValueType& value) const +{ + HashtableIterator iter(*this); + ValueType * v; + while((v = iter.GetNextValue()) != NULL) if (*v == value) return true; + return false; +} + +template +int32 +Hashtable::IndexOfKey(const KeyType& key) const +{ + const HashtableEntry * entry = (_count>0)?GetEntry(ComputeHash(key), key):NULL; + int32 count = -1; + if (entry) + { + if (entry == _iterTail) count = GetNumItems()-1; + else + { + while(entry) + { + entry = entry->_iterPrev; + count++; + } + } + } + return count; +} + +template +const KeyType * +Hashtable::GetKeyAt(uint32 index) const +{ + HashtableEntry * e = GetEntryAt(index); + return e ? &e->_key : NULL; +} + +template +status_t +Hashtable::GetKeyAt(uint32 index, KeyType & retKey) const +{ + HashtableEntry * e = GetEntryAt(index); + if (e) + { + retKey = e->_key; + return B_NO_ERROR; + } + return B_ERROR; +} + +template +status_t +Hashtable::GetValue(const KeyType& key, ValueType & setValue) const +{ + ValueType * ptr = GetValue(key); + if (ptr) + { + setValue = *ptr; + return B_NO_ERROR; + } + else return B_ERROR; +} + +template +ValueType * +Hashtable::GetValue(const KeyType& key) const +{ + HashtableEntry * e = (_count>0)?GetEntry(ComputeHash(key), key):NULL; + return e ? &e->_value : NULL; +} + +template +const KeyType * +Hashtable::GetKey(const KeyType& lookupKey) const +{ + HashtableEntry * e = (_count>0)?GetEntry(ComputeHash(lookupKey), lookupKey):NULL; + return e ? &e->_key : NULL; +} + +template +status_t +Hashtable::GetKey(const KeyType& lookupKey, KeyType & setKey) const +{ + const KeyType * ptr = GetKey(lookupKey); + if (ptr) + { + setKey = *ptr; + return B_NO_ERROR; + } + else return B_ERROR; +} + +template +typename Hashtable::HashtableEntry * +Hashtable::GetEntry(uint32 hash, const KeyType& key) const +{ + HashtableEntry * e = _table[hash%_tableSize].GetMapTo(); + if (IsBucketHead(e)) // if the e isn't the start of a bucket, then we know our entry doesn't exist + { + // While loops separated out for efficiency (one less if statement) --jaf + if (_userKeyCompareFunc) + { + while(e) + { + if ((e->_hash == hash)&&(_userKeyCompareFunc(e->_key, key, _compareCookie) == 0)) return e; + e = e->_bucketNext; + } + } + else + { + while(e) + { + if ((e->_hash == hash)&&(e->_key == key)) return e; + e = e->_bucketNext; + } + } + } + return NULL; +} + +template +typename Hashtable::HashtableEntry * +Hashtable::GetEntryAt(uint32 idx) const +{ + HashtableEntry * e = NULL; + if (idx < _count) + { + if (idx < _count/2) + { + e = _iterHead; + while((e)&&(idx--)) e = e->_iterNext; + } + else + { + idx = _count-(idx+1); + e = _iterTail; + while((e)&&(idx--)) e = e->_iterPrev; + } + } + return e; +} + +template +int +Hashtable::CompareEntries(const HashtableEntry & left, const HashtableEntry & right, KeyCompareFunc optKeyFunc, ValueCompareFunc optValueFunc, void * cookie) const +{ + return optValueFunc ? optValueFunc(left._value, right._value, cookie) : (optKeyFunc ? optKeyFunc(left._key, right._key, cookie) : 0); +} + +// Linked-list MergeSort adapted from Simon Tatham's C code at http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.c +template +status_t +Hashtable::SortByAux(KeyCompareFunc optKeyFunc, ValueCompareFunc optValueFunc, void * cookie) +{ + if ((optKeyFunc)||(optValueFunc)) + { + if (_iterHead) + { + for (uint32 mergeSize = 1; /* empty */; mergeSize *= 2) + { + HashtableEntry * p = _iterHead; + _iterHead = _iterTail = NULL; + + uint32 numMerges = 0; /* count number of merges we do in this pass */ + while(p) + { + numMerges++; /* there exists a merge to be done */ + + /* step `mergeSize' places along from p */ + HashtableEntry * q = p; + uint32 psize = 0; + for (uint32 i=0; i_iterNext; + if (!q) break; + } + + /* now we have two lists; merge them */ + for (uint32 qsize=mergeSize; ((psize > 0)||((qsize > 0)&&(q))); /* empty */) + { + HashtableEntry * e; + + /* decide whether next element of the merge comes from p or q */ + if (psize == 0) {e = q; q = q->_iterNext; qsize--;} + else if ((qsize == 0)||(!q)) {e = p; p = p->_iterNext; psize--;} + else if (CompareEntries(*p,*q,optKeyFunc,optValueFunc,cookie) <= 0) {e = p; p = p->_iterNext; psize--;} + else {e = q; q = q->_iterNext; qsize--;} + + /* append to our new more-sorted list */ + if (_iterTail) _iterTail->_iterNext = e; + else _iterHead = e; + e->_iterPrev = _iterTail; + _iterTail = e; + } + + p = q; /* now p has stepped `mergeSize' places along, and q has too */ + } + _iterTail->_iterNext = NULL; + if (numMerges <= 1) return B_NO_ERROR; + } + } + return B_NO_ERROR; // it's easy to sort an empty list :^) + } + return B_ERROR; +} + +template +status_t +Hashtable::EnsureSize(uint32 requestedSize) +{ + if (_tableSize >= requestedSize) return B_NO_ERROR; // no need to do anything if we're already big enough! + // 1. Initialize the scratch space for our active iterators. + { + HashtableIterator * nextIter = _iterList; + while(nextIter) + { + nextIter->_scratchSpace[0] = nextIter->_scratchSpace[1] = NULL; // these will hold our switch-to-on-success values + nextIter = nextIter->_nextIter; + } + } + + // 2. Create a new, bigger table, and fill it with a copy of all of our data. + Hashtable biggerTable(NextPrime(muscleMax(_count, requestedSize))); + biggerTable.SetKeyCompareFunction(_userKeyCompareFunc); + biggerTable.SetValueCompareFunction(_userValueCompareFunc); + biggerTable.SetCompareCookie(_compareCookie); + biggerTable.SetAutoSortMode(_autoSortMode); + { + HashtableEntry * next = _iterHead; + while(next) + { + HashtableEntry * hisClone = biggerTable.PutAux(next->_hash, next->_key, next->_value, NULL, NULL); + if (hisClone) + { + // Mark any iterators that will need to be redirected to point to the new nodes. + HashtableIterator * nextIter = _iterList; + while(nextIter) + { + if (nextIter->_nextKeyCookie == next) nextIter->_scratchSpace[0] = hisClone; + if (nextIter->_nextValueCookie == next) nextIter->_scratchSpace[1] = hisClone; + nextIter = nextIter->_nextIter; + } + } + else return B_ERROR; // oops, out of mem, too bad. + + next = next->_iterNext; + } + } + + // 3. Swap contents with the bigger table, but don't swap iterator lists (we want to keep ours!) + { + HashtableIterator * temp = _iterList; + _iterList = NULL; + SwapContents(biggerTable); + _iterList = temp; + } + + // 4. Lastly, fix up our iterators to point to their new entries. + { + HashtableIterator * nextIter = _iterList; + while(nextIter) + { + nextIter->_nextKeyCookie = nextIter->_scratchSpace[0]; + nextIter->_nextValueCookie = nextIter->_scratchSpace[1]; + nextIter = nextIter->_nextIter; + } + } + + return B_NO_ERROR; +} + +template +void +Hashtable::SwapContents(Hashtable & swapMe) +{ + muscleSwap(_count, swapMe._count); + muscleSwap(_tableSize, swapMe._tableSize); + muscleSwap(_table, swapMe._table); + muscleSwap(_iterHead, swapMe._iterHead); + muscleSwap(_iterTail, swapMe._iterTail); + muscleSwap(_freeHead, swapMe._freeHead); + muscleSwap(_userKeyCompareFunc, swapMe._userKeyCompareFunc); + muscleSwap(_userValueCompareFunc, swapMe._userValueCompareFunc); + muscleSwap(_autoSortMode, swapMe._autoSortMode); + muscleSwap(_compareCookie, swapMe._compareCookie); + muscleSwap(_iterList, swapMe._iterList); + + // Lastly, swap the owners of all iterators, so that they will unregister from the correct table when they die + { + HashtableIterator * next = _iterList; + while(next) + { + next->_owner = &swapMe; + next = next->_nextIter; + } + } + { + HashtableIterator * next = swapMe._iterList; + while(next) + { + next->_owner = this; + next = next->_nextIter; + } + } +} + +template +status_t +Hashtable::MoveToFront(const KeyType & moveMe) +{ + HashtableEntry * e = (_count>0)?GetEntry(ComputeHash(moveMe), moveMe):NULL; + if (e == NULL) return B_ERROR; + if (e->_iterPrev) + { + RemoveIterationEntry(e); + InsertIterationEntry(e, NULL); + } + return B_NO_ERROR; +} + +template +status_t +Hashtable::MoveToBack(const KeyType & moveMe) +{ + HashtableEntry * e = (_count>0)?GetEntry(ComputeHash(moveMe), moveMe):NULL; + if (e == NULL) return B_ERROR; + if (e->_iterNext) + { + RemoveIterationEntry(e); + InsertIterationEntry(e, _iterTail); + } + return B_NO_ERROR; +} + +template +status_t +Hashtable::MoveToBefore(const KeyType & moveMe, const KeyType & toBeforeMe) +{ + if (_count > 0) + { + HashtableEntry * e = GetEntry(ComputeHash(moveMe), moveMe); + HashtableEntry * f = GetEntry(ComputeHash(toBeforeMe), toBeforeMe); + if ((e == NULL)||(f == NULL)||(e == f)) return B_ERROR; + if (e->_iterNext != f) + { + RemoveIterationEntry(e); + InsertIterationEntry(e, f->_iterPrev); + } + return B_NO_ERROR; + } + else return B_ERROR; +} + +template +status_t +Hashtable::MoveToBehind(const KeyType & moveMe, const KeyType & toBehindMe) +{ + if (_count > 0) + { + HashtableEntry * d = GetEntry(ComputeHash(toBehindMe), toBehindMe); + HashtableEntry * e = GetEntry(ComputeHash(moveMe), moveMe); + if ((d == NULL)||(e == NULL)||(d == e)) return B_ERROR; + if (e->_iterPrev != d) + { + RemoveIterationEntry(e); + InsertIterationEntry(e, d); + } + return B_NO_ERROR; + } + else return B_ERROR; +} + +// Adds (e) to the end of our iteration linked list, or to an appropriate location to maintain sorting, if a sorting function is specified. +template +void +Hashtable::InsertSortedIterationEntry(HashtableEntry * e, KeyCompareFunc optKeyFunc, ValueCompareFunc optValueFunc, void * cookie) +{ + HashtableEntry * insertAfter = _iterTail; // default to appending to the end of the list + if ((_iterHead)&&((optKeyFunc)||(optValueFunc))) + { + // We're in sorted mode, so we'll try to place this guy in the correct position. + if (CompareEntries(*e, *_iterHead, optKeyFunc, optValueFunc, cookie) < 0) insertAfter = NULL; // easy; append to the head of the list + else if (CompareEntries(*e, *_iterTail, optKeyFunc, optValueFunc, cookie) < 0) // only iterate through if we're before the tail, otherwise the tail is fine + { + HashtableEntry * prev = _iterHead; + HashtableEntry * next = _iterHead->_iterNext; // more difficult; find where to insert into the middle + while(next) + { + if (CompareEntries(*e, *next, optKeyFunc, optValueFunc, cookie) < 0) + { + insertAfter = prev; + break; + } + else + { + prev = next; + next = next->_iterNext; + } + } + } + } + InsertIterationEntry(e, insertAfter); +} + +// Adds (e) to the our iteration linked list, behind (optBehindThis), or at the head if (optBehindThis) is NULL. +template +void +Hashtable::InsertIterationEntry(HashtableEntry * e, HashtableEntry * optBehindThis) +{ + e->_iterPrev = optBehindThis; + e->_iterNext = optBehindThis ? optBehindThis->_iterNext : _iterHead; + if (e->_iterPrev) e->_iterPrev->_iterNext = e; + else _iterHead = e; + if (e->_iterNext) e->_iterNext->_iterPrev = e; + else _iterTail = e; +} + +// Remove (e) from our iteration linked list +template +void +Hashtable::RemoveIterationEntry(HashtableEntry * e) +{ + // Update any iterators that were pointing at (e), so that they now point to the entry after e. + HashtableIterator * next = _iterList; + while(next) + { + if (next->_nextKeyCookie == e) (void) next->GetNextKey(); + if (next->_nextValueCookie == e) (void) next->GetNextValue(); + next = next->_nextIter; + } + + if (_iterHead == e) _iterHead = e->_iterNext; + if (_iterTail == e) _iterTail = e->_iterPrev; + if (e->_iterPrev) e->_iterPrev->_iterNext = e->_iterNext; + if (e->_iterNext) e->_iterNext->_iterPrev = e->_iterPrev; + e->_iterPrev = e->_iterNext = NULL; +} + +template +typename Hashtable::HashtableEntry * +Hashtable::PutAux(uint32 hash, const KeyType& key, const ValueType& value, ValueType * optSetPreviousValue, bool * optReplacedFlag) +{ + if (optReplacedFlag) *optReplacedFlag = false; + + if (_table == NULL) // demand-allocate this + { + _freeHead = _table = HashtableEntry::CreateEntriesArray(_tableSize); + if (_table == NULL) return NULL; + } + + // If we already have an entry for this key in the table, we can just replace its contents + HashtableEntry * e = GetEntry(hash, key); + if (e) + { + if (optSetPreviousValue) *optSetPreviousValue = e->_value; + if (optReplacedFlag) *optReplacedFlag = true; + e->_value = value; + if ((_autoSortMode == AUTOSORT_BY_VALUE)&&(_userValueCompareFunc)) + { + // If our new value has changed our position in the sort-order, then adjust the traversal list + if ((e->_iterPrev)&&(_userValueCompareFunc(e->_value, e->_iterPrev->_value, _compareCookie) < 0)) + { + const HashtableEntry * moveToBefore = e->_iterPrev; + while((moveToBefore->_iterPrev)&&(_userValueCompareFunc(e->_value, moveToBefore->_iterPrev->_value, _compareCookie) < 0)) moveToBefore = moveToBefore->_iterPrev; + (void) MoveToBefore(e->_key, moveToBefore->_key); + } + else if ((e->_iterNext)&&(_userValueCompareFunc(e->_value, e->_iterNext->_value, _compareCookie) > 0)) + { + const HashtableEntry * moveToBehind = e->_iterNext; + while((moveToBehind->_iterNext)&&(_userValueCompareFunc(e->_value, moveToBehind->_iterNext->_value, _compareCookie) > 0)) moveToBehind = moveToBehind->_iterNext; + (void) MoveToBehind(e->_key, moveToBehind->_key); + } + } + return e; + } + + // Rehash the table if the threshold is exceeded + if (_count == _tableSize) return (EnsureSize(_tableSize*2) == B_NO_ERROR) ? PutAux(hash, key, value, optSetPreviousValue, optReplacedFlag) : NULL; + + HashtableEntry * slot = _table[hash%_tableSize].GetMapTo(); + if (IsBucketHead(slot)) + { + // This slot's chain is already present -- so just create a new entry in the chain's linked list to hold our item + e = _freeHead; + _freeHead = e->RemoveFromFreeList(_freeHead); + e->_hash = hash; + e->_key = key; + e->_value = value; + + // insert e into the list immediately after (slot) + e->_bucketPrev = slot; + e->_bucketNext = slot->_bucketNext; + if (e->_bucketNext) e->_bucketNext->_bucketPrev = e; + slot->_bucketNext = e; + + InsertSortedIterationEntry(e, (_autoSortMode == AUTOSORT_BY_KEY) ? _userKeyCompareFunc : NULL, (_autoSortMode == AUTOSORT_BY_VALUE) ? _userValueCompareFunc : NULL, _compareCookie); + } + else + { + if (slot->_hash != MUSCLE_HASHTABLE_INVALID_HASH_CODE) + { + // Hey, some other bucket is using my starter-slot! + // To get around this, we'll swap my starter-slot for an empty one and use that instead. + slot->GetMappedFrom()->SwapMaps(_freeHead->GetMappedFrom()); + slot = _freeHead; + } + _freeHead = slot->RemoveFromFreeList(_freeHead); + + // First entry in slot; just copy data over + slot->_hash = hash; + slot->_key = key; + slot->_value = value; + + slot->_bucketPrev = slot->_bucketNext = NULL; + e = slot; + InsertSortedIterationEntry(slot, (_autoSortMode == AUTOSORT_BY_KEY) ? _userKeyCompareFunc : NULL, (_autoSortMode == AUTOSORT_BY_VALUE) ? _userValueCompareFunc : NULL, _compareCookie); + } + + _count++; + + return e; +} + +template +status_t +Hashtable::RemoveAux(const KeyType& key, ValueType * optSetValue) +{ + HashtableEntry * e = (_count>0)?GetEntry(ComputeHash(key), key):NULL; + if (e) + { + RemoveIterationEntry(e); + if (optSetValue) *optSetValue = e->_value; + + HashtableEntry * prev = e->_bucketPrev; + HashtableEntry * next = e->_bucketNext; + if (prev) + { + prev->_bucketNext = next; + if (next) next->_bucketPrev = prev; + } + else if (next) + { + next->_bucketPrev = NULL; + e->GetMappedFrom()->SwapMaps(next->GetMappedFrom()); + } + + e->ReturnToFreeList(KeyType(), ValueType(), &_freeHead); + + _count--; + return B_NO_ERROR; + } + return B_ERROR; +} + +template +void +Hashtable::Clear(bool releaseCachedBuffers) +{ + // First go through our list of active iterators, and let them all know they are now invalid + while(_iterList) + { + HashtableIterator * next = _iterList->_nextIter; + _iterList->_owner = NULL; + _iterList->_nextKeyCookie = _iterList-> _nextValueCookie = NULL; + _iterList->_prevIter = _iterList->_nextIter = NULL; + _iterList = next; + } + + if (_count > 0) + { + if (releaseCachedBuffers == false) + { + // Go through our list of valid entries and reset them all to their default state + // This is important since sometimes they may be holding on to large allocated memory buffers, etc + KeyType blankKey = KeyType(); + ValueType blankValue = ValueType(); + while(_iterHead) + { + HashtableEntry * next = _iterHead->_iterNext; // save for later + _iterHead->ReturnToFreeList(blankKey, blankValue, &_freeHead); + _iterHead = next; + } + } + _iterHead = _iterTail = NULL; + _count = 0; + } + if (releaseCachedBuffers) + { + delete [] _table; + _table = NULL; + _freeHead = NULL; + _tableSize = _initialCapacity; + } +} + +template +uint32 +Hashtable::NextPrime(uint32 start) const +{ + if (start % 2 == 0) start++; + uint32 i; + for (; ; start += 2) + { + for (i = 3; i * i <= start; i += 2) if (start % i == 0) break; + if (i * i > start) return start; + } +} + +//=============================================================== +// Implementation of HashtableIterator +//=============================================================== + +template +HashtableIterator::HashtableIterator() : _nextKeyCookie(NULL), _nextValueCookie(NULL), _owner(NULL) +{ + // empty +} + +template +HashtableIterator::HashtableIterator(const HashtableIterator & rhs) : _owner(NULL) +{ + *this = rhs; +} + +template +HashtableIterator::HashtableIterator(const Hashtable & table, bool backwards) : _owner(NULL) +{ + table.InitializeIterator(*this, backwards); +} + +template +HashtableIterator::HashtableIterator(const Hashtable & table, const KeyType & startAt, bool backwards) : _owner(NULL) +{ + table.InitializeIteratorAt(*this, startAt, backwards); +} + +template +HashtableIterator::~HashtableIterator() +{ + if (_owner) _owner->UnregisterIterator(this); +} + +template +void +HashtableIterator::SetOwner(const Hashtable * table) +{ + if (_owner != table) + { + if (_owner) _owner->UnregisterIterator(this); + _owner = table; + if (_owner) _owner->RegisterIterator(this); + } +} + +template +HashtableIterator & +HashtableIterator:: operator=(const HashtableIterator & rhs) +{ + if (this != &rhs) + { + SetOwner(rhs._owner); + _backwards = rhs._backwards; + _nextKeyCookie = rhs._nextKeyCookie; + _nextValueCookie = rhs._nextValueCookie; + } + return *this; +} + + +template +status_t +HashtableIterator::GetNextKey(KeyType& key) +{ + const KeyType * ret = GetNextKey(); + if (ret) + { + key = *ret; + return B_NO_ERROR; + } + else return B_ERROR; +} + +template +status_t +HashtableIterator::GetNextValue(ValueType& val) +{ + ValueType * ret = GetNextValue(); + if (ret) + { + val = *ret; + return B_NO_ERROR; + } + else return B_ERROR; +} + +template +status_t +HashtableIterator::PeekNextKey(KeyType& key) const +{ + const KeyType * ret = PeekNextKey(); + if (ret) + { + key = *ret; + return B_NO_ERROR; + } + else return B_ERROR; +} + +template +status_t +HashtableIterator::PeekNextValue(ValueType& val) const +{ + ValueType * ret = PeekNextValue(); + if (ret) + { + val = *ret; + return B_NO_ERROR; + } + else return B_ERROR; +} + +template +ValueType * +HashtableIterator::GetNextValue() +{ + ValueType * val = PeekNextValue(); + if (val) + { + _owner->IterateCookie(&_nextValueCookie, _backwards); + return val; + } + return NULL; +} + +template +const KeyType * +HashtableIterator::GetNextKey() +{ + const KeyType * ret = PeekNextKey(); + if (ret) + { + _owner->IterateCookie(&_nextKeyCookie, _backwards); + return ret; + } + return NULL; +} + +template +ValueType * +HashtableIterator::PeekNextValue() const +{ + return (_owner) ? _owner->GetValueFromCookie(_nextValueCookie) : NULL; +} + +template +const KeyType * +HashtableIterator::PeekNextKey() const +{ + return (_owner) ? _owner->GetKeyFromCookie(_nextKeyCookie) : NULL; +} + +template +status_t +HashtableIterator::GetNextKeyAndValue(KeyType & setKey, ValueType & setValue) +{ + return (GetNextKey(setKey) == B_NO_ERROR) ? GetNextValue(setValue) : B_ERROR; +} + +template +status_t +HashtableIterator::GetNextKeyAndValue(KeyType & setKey, ValueType * & setValuePtr) +{ + return ((setValuePtr = GetNextValue()) != NULL) ? GetNextKey(setKey) : B_ERROR; +} + +template +status_t +HashtableIterator::GetNextKeyAndValue(KeyType & setKey, const ValueType * & setValuePtr) +{ + return ((setValuePtr = GetNextValue()) != NULL) ? GetNextKey(setKey) : B_ERROR; +} + +template +status_t +HashtableIterator::GetNextKeyAndValue(const KeyType * & setKeyPtr, ValueType & setValue) +{ + return ((setKeyPtr = GetNextKey()) != NULL) ? GetNextValue(setValue) : B_ERROR; +} + +template +status_t +HashtableIterator::GetNextKeyAndValue(const KeyType * & setKeyPtr, ValueType * & setValuePtr) +{ + return (((setKeyPtr = GetNextKey()) != NULL)&&((setValuePtr = GetNextValue()) != NULL)) ? B_NO_ERROR : B_ERROR; +} + +template +status_t +HashtableIterator::GetNextKeyAndValue(const KeyType * & setKeyPtr, const ValueType * & setValuePtr) +{ + return (((setKeyPtr = GetNextKey()) != NULL)&&((setValuePtr = GetNextValue()) != NULL)) ? B_NO_ERROR : B_ERROR; +} + +END_NAMESPACE(muscle); + +#endif diff --git a/library/libfunky/extra/Queue.h b/library/libfunky/extra/Queue.h new file mode 100644 index 0000000..05afc70 --- /dev/null +++ b/library/libfunky/extra/Queue.h @@ -0,0 +1,1058 @@ +/* This file is Copyright 2005 Level Control Systems. See the included LICENSE.txt file for details. */ + +#ifndef MuscleQueue_h +#define MuscleQueue_h + +#include "support/MuscleSupport.h" + +BEGIN_NAMESPACE(muscle); + +#ifndef SMALL_QUEUE_SIZE +# define SMALL_QUEUE_SIZE 3 +#endif + +/** This class implements a templated double-ended queue data structure. + * Adding or removing items from the head or tail of a Queue is (on average) + * an O(1) operation. A Queue also makes for a nice Vector, if that's all you need. + */ +template class Queue +{ +public: + /** Constructor. + * @param initialSlots Specifies how many slots to pre-allocate. Defaults to (SMALL_QUEUE_SIZE). + */ + Queue(uint32 initialSlots = SMALL_QUEUE_SIZE); + + /** Copy constructor. */ + Queue(const Queue& copyMe); + + /** Destructor. */ + virtual ~Queue(); + + /** Assigment operator. */ + Queue &operator=(const Queue &from); + + /** Equality operator. Queues are equal if they are the same length, and + * every nth item in this queue is == to the corresponding item in (rhs). */ + bool operator==(const Queue &rhs) const; + + /** Returns the negation of the equality operator */ + bool operator!=(const Queue &rhs) const {return !(*this == rhs);} + + /** Appends (item) to the end of the queue. Queue size grows by one. + * @param item The item to append. + * @return B_NO_ERROR on success, B_ERROR on failure (out of memory) + */ + status_t AddTail(const ItemType & item = ItemType()); + + /** Appends some or all items in (queue) to the end of our queue. Queue size + * grows by (queue.GetNumItems()). + * For example: + * Queue a; // contains 1, 2, 3, 4 + * Queue b; // contains 5, 6, 7, 8 + * a.AddTail(b); // a now contains 1, 2, 3, 4, 5, 6, 7, 8 + * @param queue The queue to append to our queue. + * @param startIndex Index in (queue) to start adding at. Default to zero. + * @param numItems Number of items to add. If this number is too large, it will be capped appropriately. Default is to add all items. + * @return B_NO_ERROR on success, B_ERROR on failure (out of memory) + */ + status_t AddTail(const Queue & queue, uint32 startIndex = 0, uint32 numItems = (uint32)-1); + + /** Adds the given array of items to the tail of the Queue. Equivalent + * to adding them to the tail of the Queue one at a time, but somewhat + * more efficient. On success, the queue size grows by (numItems). + * @param items Pointer to an array of items to add to the Queue. + * @param numItems Number of items in the array + * @return B_NO_ERROR on success, or B_ERROR on failure (out of memory) + */ + status_t AddTail(const ItemType * items, uint32 numItems); + + /** Prepends (item) to the head of the queue. Queue size grows by one. + * @param item The item to prepend. + * @return B_NO_ERROR on success, B_ERROR on failure (out of memory) + */ + status_t AddHead(const ItemType &item = ItemType()); + + /** Concatenates (queue) to the head of our queue. + * Our queue size grows by (queue.GetNumItems()). + * For example: + * Queue a; // contains 1, 2, 3, 4 + * Queue b; // contains 5, 6, 7, 8 + * a.AddHead(b); // a now contains 5, 6, 7, 8, 1, 2, 3, 4 + * @param queue The queue to prepend to our queue. + * @param startIndex Index in (queue) to start adding at. Default to zero. + * @param numItems Number of items to add. If this number is too large, it will be capped appropriately. Default is to add all items. + * @return B_NO_ERROR on success, B_ERROR on failure (out of memory) + */ + status_t AddHead(const Queue & queue, uint32 startIndex = 0, uint32 numItems = (uint32)-1); + + /** Concatenates the given array of items to the head of the Queue. + * The semantics are the same as for AddHead(const Queue &). + * @param items Pointer to an array of items to add to the Queue. + * @param numItems Number of items in the array + * @return B_NO_ERROR on success, or B_ERROR on failure (out of memory) + */ + status_t AddHead(const ItemType * items, uint32 numItems); + + /** Removes the item at the head of the queue. + * @return B_NO_ERROR on success, B_ERROR if the queue was empty. + */ + status_t RemoveHead(); + + /** Removes the item at the head of the queue and places it into (returnItem). + * @param returnItem On success, the removed item is copied into this object. + * @return B_NO_ERROR on success, B_ERROR if the queue was empty + */ + status_t RemoveHead(ItemType & returnItem); + + /** Removes the item at the tail of the queue. + * @return B_NO_ERROR on success, B_ERROR if the queue was empty. + */ + status_t RemoveTail(); + + /** Removes the item at the tail of the queue and places it into (returnItem). + * @param returnItem On success, the removed item is copied into this object. + * @return B_NO_ERROR on success, B_ERROR if the queue was empty + */ + status_t RemoveTail(ItemType & returnItem); + + /** Removes the item at the (index)'th position in the queue. + * @param index Which item to remove--can range from zero + * (head of the queue) to GetNumItems()-1 (tail of the queue). + * @return B_NO_ERROR on success, B_ERROR on failure (i.e. bad index) + * Note that this method is somewhat inefficient for indices that + * aren't at the head or tail of the queue (i.e. O(n) time) + */ + status_t RemoveItemAt(uint32 index); + + /** Removes the item at the (index)'th position in the queue, and copies it into (returnItem). + * @param index Which item to remove--can range from zero + * (head of the queue) to (GetNumItems()-1) (tail of the queue). + * @param returnItem On success, the removed item is copied into this object. + * @return B_NO_ERROR on success, B_ERROR on failure (i.e. bad index) + */ + status_t RemoveItemAt(uint32 index, ItemType & returnItem); + + /** Copies the (index)'th item into (returnItem). + * @param index Which item to get--can range from zero + * (head of the queue) to (GetNumItems()-1) (tail of the queue). + * @param returnItem On success, the retrieved item is copied into this object. + * @return B_NO_ERROR on success, B_ERROR on failure (e.g. bad index) + */ + status_t GetItemAt(uint32 index, ItemType & returnItem) const; + + /** Returns a pointer to an item in the array (i.e. no copying of the item is done). + * Included for efficiency; be careful with this: modifying the queue can invalidate + * the returned pointer! + * @param index Index of the item to return a pointer to. + * @return a pointer to the internally held item, or NULL if (index) was invalid. + */ + ItemType * GetItemAt(uint32 index) const; + + /** Replaces the (index)'th item in the queue with (newItem). + * @param index Which item to replace--can range from zero + * (head of the queue) to (GetNumItems()-1) (tail of the queue). + * @param newItem The item to place into the queue at the (index)'th position. + * @return B_NO_ERROR on success, B_ERROR on failure (e.g. bad index) + */ + status_t ReplaceItemAt(uint32 index, const ItemType & newItem = ItemType()); + + /** Inserts (item) into the (nth) slot in the array. InsertItemAt(0) + * is the same as AddHead(item), InsertItemAt(GetNumItems()) is the same + * as AddTail(item). Other positions will involve an O(n) shifting of contents. + * @param index The position at which to insert the new item. + * @param newItem The item to insert into the queue. + * @return B_NO_ERROR on success, B_ERROR on failure (i.e. bad index). + */ + status_t InsertItemAt(uint32 index, const ItemType & newItem = ItemType()); + + /** Removes all items from the queue. + * @param releaseCachedBuffers If true, we will immediately free any buffers that we may be holding. Otherwise + * we will keep them around so that they can be re-used in the future. + */ + void Clear(bool releaseCachedBuffers = false); + + /** Returns the number of items in the queue. (This number does not include pre-allocated space) */ + uint32 GetNumItems() const {return _itemCount;} + + /** Returns the number of item-slots we have allocated space for. Note that this is NOT + * the same as the value returned by GetNumItems() -- it is generally larger, since we pre-allocate + * additional slots in advance to cut down on the number of re-allocations we need to do. + */ + uint32 GetNumAllocatedItemSlots() const {return _queueSize;} + + /** Returns true iff their are no items in the queue. */ + bool IsEmpty() const {return (_itemCount == 0);} + + /** Returns a read-only reference the head item in the queue. You must not call this when the queue is empty! */ + const ItemType & Head() const {return *GetItemAt(0);} + + /** Returns a read-only reference the tail item in the queue. You must not call this when the queue is empty! */ + const ItemType & Tail() const {return *GetItemAt(_itemCount-1);} + + /** Returns a writable reference the head item in the queue. You must not call this when the queue is empty! */ + ItemType & Head() {return *GetItemAt(0);} + + /** Returns a writable reference the tail item in the queue. You must not call this when the queue is empty! */ + ItemType & Tail() {return *GetItemAt(_itemCount-1);} + + /** Returns a pointer to the first item in the queue, or NULL if the queue is empty */ + ItemType * HeadPointer() const {return (_itemCount > 0) ? GetItemAt(0) : NULL;} + + /** Returns a pointer to the last item in the queue, or NULL if the queue is empty */ + ItemType * TailPointer() const {return (_itemCount > 0) ? GetItemAt(_itemCount-1) : NULL;} + + /** Convenient read-only array-style operator (be sure to only use valid indices!) */ + const ItemType & operator [](uint32 Index) const; + + /** Convenient read-write array-style operator (be sure to only use valid indices!) */ + ItemType & operator [](uint32 Index); + + /** Deprecated synonym for GetItemAt(). Don't call this method in new code, call GetItemAt() instead! + * @deprecated + */ + ItemType * GetItemPointer(uint32 index) const {return GetItemAt(index);} + + /** Makes sure there is enough space allocated for at least (numSlots) items. + * You only need to call this if you wish to minimize the number of data re-allocations done, + * or wish to add or remove a large number of default items at once (by specifying setNumItems=true). + * @param numSlots the minimum amount of items to pre-allocate space for in the Queue. + * @param setNumItems If true, the length of the Queue will be altered by adding or removing + * items to (from) the tail of the Queue until the Queue is the specified size. + * If false (the default), more slots may be pre-allocated, but the + * number of items officially in the Queue remains the same as before. + * @param extraReallocItems If we have to do an array reallocation, this many extra slots will be + * added to the newly allocated array, above and beyond what is strictly + * necessary. That way the likelihood of another reallocation being necessary + * in the near future is reduced. Default value is zero, indicating that + * no extra slots will be allocated. This argument is ignored if (setNumItems) is true. + * @returns B_NO_ERROR on success, or B_ERROR on failure (out of memory) + */ + status_t EnsureSize(uint32 numSlots, bool setNumItems = false, uint32 extraReallocItems = 0); + + /** Returns the last index of the given (item), or -1 if (item) is + * not found in the list. O(n) search time. + * @param item The item to look for. + * @return The index of (item), or -1 if no such item is present. + */ + int32 IndexOf(const ItemType & item) const; + + /** + * Swaps the values of the two items at the given indices. This operation + * will involve three copies of the held items. + * @param fromIndex First index to swap. + * @param toIndex Second index to swap. + */ + void Swap(uint32 fromIndex, uint32 toIndex); + + /** + * Reverses the ordering of the items in the given subrange. + * (e.g. if the items were A,B,C,D,E, this would change them to E,D,C,B,A) + * @param from Index of the start of the subrange. Defaults to zero. + * @param to Index of the next item after the end of the subrange. If greater than + * the number of items currently in the queue, this value will be clipped + * to be equal to that number. Defaults to the largest possible uint32. + */ + void ReverseItemOrdering(uint32 from=0, uint32 to = ((uint32)-1)); + + /** + * This is the signature of the type of callback function that you must pass + * into the Sort() method. This function should work like strcmp(), returning + * a negative value if (item1) is less than item2, or zero if the items are + * equal, or a positive value if (item1) is greater than item2. + * @param item1 The first item + * @param item2 The second item + * @param cookie A user-defined value that was passed in to the Sort() method. + * @return A value indicating which item is "larger", as defined above. + */ + typedef int (*ItemCompareFunc)(const ItemType & item1, const ItemType & item2, void * cookie); + + /** + * Does an in-place, stable sort on a subrange of the contents of this Queue. + * (The sort algorithm is a smart, in-place merge sort). + * @param compareFunc A function that compares two items in this queue and returns + * a value indicating which is "larger". (negative indicates + * that the second parameter is larger, positive indicate that the + * first is larger, and zero indicates that the two parameters are equal) + * @param from Index of the start of the subrange. Defaults to zero. + * @param to Index of the next item after the end of the subrange. + * If greater than the number of items currently in the queue, + * the subrange will extend to the last item. Defaults to the largest possible uint32. + * @param optCookie A user-defined value that will be passed to the (compareFunc). + */ + void Sort(ItemCompareFunc compareFunc, uint32 from=0, uint32 to = ((uint32)-1), void * optCookie = NULL); + + /** + * Swaps our contents with the contents of (that), in an efficient manner. + * @param that The queue whose contents are to be swapped with our own. + */ + void SwapContents(Queue & that); + + /** + * Goes through the array and removes every item that is equal to (val). + * @param val the item to look for and remove + * @return The number of instances of (val) that were found and removed during this operation. + */ + uint32 RemoveAllInstancesOf(const ItemType & val); + + /** + * Goes through the array and removes the first item that is equal to (val). + * @param val the item to look for and remove + * @return B_NO_ERROR if a matching item was found and removed, or B_ERROR if it wasn't found. + */ + status_t RemoveFirstInstanceOf(const ItemType & val); + + /** + * Goes through the array and removes the last item that is equal to (val). + * @param val the item to look for and remove + * @return B_NO_ERROR if a matching item was found and removed, or B_ERROR if it wasn't found. + */ + status_t RemoveLastInstanceOf(const ItemType & val); + + /** Returns true iff the first item in our queue is equal to (prefix). */ + bool StartsWith(const ItemType & prefix) const {return ((GetNumItems()>0)&&(Head() == prefix));} + + /** Returns true iff the (prefixQueue) is a prefix of this queue. */ + bool StartsWith(const Queue & prefixQueue) const; + + /** Returns true iff the last item in our queue is equal to (suffix). */ + bool EndsWith(const ItemType & suffix) const {return ((GetNumItems()>0)&&(Tail() == suffix));} + + /** Returns true iff the (suffixQueue) is a suffix of this queue. */ + bool EndsWith(const Queue & suffixQueue) const; + + /** + * Returns a pointer to the nth internally-held contiguous-Item-sub-array, to allow efficient + * array-style access to groups of items in this Queue. In the current implementation + * there may be as many as two such sub-arrays present, depending on the internal state of the Queue. + * @param whichArray Index of the internal array to return a pointer to. Typically zero or one. + * @param retLength On success, the number of items in the returned sub-array will be written here. + * @return Pointer to the first item in the sub-array on success, or NULL on failure. + * Note that this array is only guaranteed valid as long as no items are + * added or removed from the Queue. + */ + ItemType * GetArrayPointer(uint32 whichArray, uint32 & retLength) {return const_cast(GetArrayPointerAux(whichArray, retLength));} + + /** Read-only version of the above */ + const ItemType * GetArrayPointer(uint32 whichArray, uint32 & retLength) const {return GetArrayPointerAux(whichArray, retLength);} + +private: + const ItemType * GetArrayPointerAux(uint32 whichArray, uint32 & retLength) const; + void SwapContentsAux(Queue & that); + + inline uint32 NextIndex(uint32 idx) const {return (idx >= _queueSize-1) ? 0 : idx+1;} + inline uint32 PrevIndex(uint32 idx) const {return (idx == 0) ? _queueSize-1 : idx-1;} + + // Translates a user-index into an index into the _queue array. + inline uint32 InternalizeIndex(uint32 idx) const {return (_headIndex + idx) % _queueSize;} + + // Helper methods, used for sorting (stolen from http://www-ihm.lri.fr/~thomas/VisuTri/inplacestablesort.html) + void Merge(ItemCompareFunc compareFunc, uint32 from, uint32 pivot, uint32 to, uint32 len1, uint32 len2, void * cookie); + uint32 Lower(ItemCompareFunc compareFunc, uint32 from, uint32 to, const ItemType & val, void * cookie) const; + uint32 Upper(ItemCompareFunc compareFunc, uint32 from, uint32 to, const ItemType & val, void * cookie) const; + + ItemType _smallQueue[SMALL_QUEUE_SIZE]; // small queues can be stored inline in this array + ItemType * _queue; // points to _smallQueue, or to a dynamically alloc'd array + uint32 _queueSize; // number of slots in the _queue array + uint32 _itemCount; // number of valid items in the array + uint32 _headIndex; // index of the first filled slot (meaningless if _itemCount is zero) + uint32 _tailIndex; // index of the last filled slot (meaningless if _itemCount is zero) + const uint32 _initialSize; // as specified in ctor +}; + +template +Queue::Queue(uint32 initialSize) + : _queue(NULL), _queueSize(0), _itemCount(0), _initialSize(initialSize) +{ + // empty +} + +template +Queue::Queue(const Queue& rhs) + : _queue(NULL), _queueSize(0), _itemCount(0), _initialSize(rhs._initialSize) +{ + *this = rhs; +} + +template +bool +Queue::operator ==(const Queue& rhs) const +{ + if (this == &rhs) return true; + if (GetNumItems() != rhs.GetNumItems()) return false; + + for (int i = GetNumItems()-1; i>=0; i--) if (((*this)[i] == rhs[i]) == false) return false; + + return true; +} + + +template +Queue & +Queue::operator =(const Queue& rhs) +{ + if (this != &rhs) + { + uint32 numItems = rhs.GetNumItems(); + if (EnsureSize(numItems, true) == B_NO_ERROR) for (uint32 i=0; i +ItemType & +Queue::operator[](uint32 i) +{ + MASSERT(i<_itemCount, "Invalid index to Queue::[]"); + return _queue[InternalizeIndex(i)]; +} + +template +const ItemType & +Queue::operator[](uint32 i) const +{ + MASSERT(i<_itemCount, "Invalid index to Queue::[]"); + return _queue[InternalizeIndex(i)]; +} + +template +ItemType * +Queue::GetItemAt(uint32 i) const +{ + return &_queue[InternalizeIndex(i)]; +} + +template +Queue::~Queue() +{ + if (_queue != _smallQueue) delete [] _queue; +} + +template +status_t +Queue:: +AddTail(const ItemType &item) +{ + if (EnsureSize(_itemCount+1, false, _itemCount+1) == B_ERROR) return B_ERROR; + if (_itemCount == 0) _headIndex = _tailIndex = 0; + else _tailIndex = NextIndex(_tailIndex); + _queue[_tailIndex] = item; + _itemCount++; + return B_NO_ERROR; +} + +template +status_t +Queue:: +AddTail(const Queue &queue, uint32 startIndex, uint32 numNewItems) +{ + uint32 hisSize = queue.GetNumItems(); + numNewItems = muscleMin(numNewItems, (startIndex < hisSize) ? (hisSize-startIndex) : 0); + + uint32 mySize = GetNumItems(); + uint32 newSize = mySize+numNewItems; + + if (EnsureSize(newSize, true) != B_NO_ERROR) return B_ERROR; + for (uint32 i=mySize; i +status_t +Queue:: +AddTail(const ItemType * items, uint32 numItems) +{ + uint32 mySize = GetNumItems(); + uint32 newSize = mySize+numItems; + uint32 rhs = 0; + + if (EnsureSize(newSize, true) != B_NO_ERROR) return B_ERROR; + for (uint32 i=mySize; i +status_t +Queue:: +AddHead(const ItemType &item) +{ + if (EnsureSize(_itemCount+1, false, _itemCount+1) == B_ERROR) return B_ERROR; + if (_itemCount == 0) _headIndex = _tailIndex = 0; + else _headIndex = PrevIndex(_headIndex); + _queue[_headIndex] = item; + _itemCount++; + return B_NO_ERROR; +} + +template +status_t +Queue:: +AddHead(const Queue &queue, uint32 startIndex, uint32 numNewItems) +{ + uint32 hisSize = queue.GetNumItems(); + numNewItems = muscleMin(numNewItems, (startIndex < hisSize) ? (hisSize-startIndex) : 0); + + if (EnsureSize(numNewItems+GetNumItems()) != B_NO_ERROR) return B_ERROR; + for (int i=((int)startIndex+numNewItems)-1; i>=(int32)startIndex; i--) if (AddHead(queue[i]) == B_ERROR) return B_ERROR; + return B_NO_ERROR; +} + +template +status_t +Queue:: +AddHead(const ItemType * items, uint32 numItems) +{ + if (EnsureSize(_itemCount+numItems) != B_NO_ERROR) return B_ERROR; + for (int i=((int)numItems)-1; i>=0; i--) if (AddHead(items[i]) == B_ERROR) return B_ERROR; + return B_NO_ERROR; +} + +template +status_t +Queue:: +RemoveHead(ItemType & returnItem) +{ + if (_itemCount == 0) return B_ERROR; + returnItem = _queue[_headIndex]; + return RemoveHead(); +} + +template +status_t +Queue:: +RemoveHead() +{ + if (_itemCount == 0) return B_ERROR; + int oldHeadIndex = _headIndex; + _headIndex = NextIndex(_headIndex); + _itemCount--; + _queue[oldHeadIndex] = ItemType(); // this must be done last, as queue state must be coherent when we do this + return B_NO_ERROR; +} + +template +status_t +Queue:: +RemoveTail(ItemType & returnItem) +{ + if (_itemCount == 0) return B_ERROR; + returnItem = _queue[_tailIndex]; + return RemoveTail(); +} + +template +status_t +Queue:: +RemoveTail() +{ + if (_itemCount == 0) return B_ERROR; + int removedItemIndex = _tailIndex; + _tailIndex = PrevIndex(_tailIndex); + _itemCount--; + _queue[removedItemIndex] = ItemType(); // this must be done last, as queue state must be coherent when we do this + return B_NO_ERROR; +} + +template +status_t +Queue:: +GetItemAt(uint32 index, ItemType & returnItem) const +{ + if (index >= _itemCount) return B_ERROR; + returnItem = _queue[InternalizeIndex(index)]; + return B_NO_ERROR; +} + +template +status_t +Queue:: +RemoveItemAt(uint32 index, ItemType & returnItem) +{ + if (index >= _itemCount) return B_ERROR; + returnItem = _queue[InternalizeIndex(index)]; + return RemoveItemAt(index); +} + +template +status_t +Queue:: +RemoveItemAt(uint32 index) +{ + if (index >= _itemCount) return B_ERROR; + + uint32 internalizedIndex = InternalizeIndex(index); + uint32 indexToClear; + + if (index < _itemCount/2) + { + // item is closer to the head: shift everything forward one, ending at the head + while(internalizedIndex != _headIndex) + { + uint32 prev = PrevIndex(internalizedIndex); + _queue[internalizedIndex] = _queue[prev]; + internalizedIndex = prev; + } + indexToClear = _headIndex; + _headIndex = NextIndex(_headIndex); + } + else + { + // item is closer to the tail: shift everything back one, ending at the tail + while(internalizedIndex != _tailIndex) + { + uint32 next = NextIndex(internalizedIndex); + _queue[internalizedIndex] = _queue[next]; + internalizedIndex = next; + } + indexToClear = _tailIndex; + _tailIndex = PrevIndex(_tailIndex); + } + + _itemCount--; + _queue[indexToClear] = ItemType(); // this must be done last, as queue state must be coherent when we do this + return B_NO_ERROR; +} + +template +status_t +Queue:: +ReplaceItemAt(uint32 index, const ItemType & newItem) +{ + if (index >= _itemCount) return B_ERROR; + _queue[InternalizeIndex(index)] = newItem; + return B_NO_ERROR; +} + +template +status_t +Queue:: +InsertItemAt(uint32 index, const ItemType & newItem) +{ + // Simple cases + if (index > _itemCount) return B_ERROR; + if (index == _itemCount) return AddTail(newItem); + if (index == 0) return AddHead(newItem); + + // Harder case: inserting into the middle of the array + if (index < _itemCount/2) + { + // Add a space at the front, and shift things back + if (AddHead() != B_NO_ERROR) return B_ERROR; // allocate an extra slot + for (uint32 i=0; i((int32)index); i--) ReplaceItemAt(i, *GetItemAt(i-1)); + } + return ReplaceItemAt(index, newItem); +} + +template +void +Queue:: +Clear(bool releaseCachedBuffers) +{ + if ((releaseCachedBuffers)&&(_queue != _smallQueue)) + { + delete [] _queue; + _queue = NULL; + _queueSize = 0; + _itemCount = 0; + } + else while(RemoveTail() == B_NO_ERROR) {/* empty */} +} + +template +status_t +Queue:: +EnsureSize(uint32 size, bool setNumItems, uint32 extraPreallocs) +{ + if ((_queue == NULL)||(_queueSize < size)) + { + const uint32 sqLen = ARRAYITEMS(_smallQueue); + uint32 temp = size + extraPreallocs; + uint32 newQLen = muscleMax(_initialSize, ((setNumItems)||(temp <= sqLen)) ? muscleMax(sqLen,temp) : temp); + + ItemType * newQueue = ((_queue == _smallQueue)||(newQLen > sqLen)) ? newnothrow_array(ItemType,newQLen) : _smallQueue; + if (newQueue == NULL) {WARN_OUT_OF_MEMORY; return B_ERROR;} + if (newQueue == _smallQueue) newQLen = sqLen; + + for (uint32 i=0; i<_itemCount; i++) (void) GetItemAt(i, newQueue[i]); // we know that (_itemCount < size) + if (setNumItems) _itemCount = size; + _headIndex = 0; + _tailIndex = _itemCount-1; + + if (_queue == _smallQueue) + { + ItemType blank = ItemType(); + for (uint32 i=0; i size) (void) RemoveTail(); // Gotta overwrite the "removed" items, so this is a bit slower + } + + return B_NO_ERROR; +} + +template +int32 +Queue:: +IndexOf(const ItemType & item) const +{ + if (_queue) for (int i=((int)GetNumItems())-1; i>=0; i--) if (*GetItemAt(i) == item) return i; + return -1; +} + + +template +void +Queue:: +Swap(uint32 fromIndex, uint32 toIndex) +{ + ItemType temp = *(GetItemAt(fromIndex)); + ReplaceItemAt(fromIndex, *(GetItemAt(toIndex))); + ReplaceItemAt(toIndex, temp); +} + +template +void +Queue:: +Sort(ItemCompareFunc compareFunc, uint32 from, uint32 to, void * cookie) +{ + uint32 size = GetNumItems(); + if (to > size) to = size; + if (to > from) + { + if (to < from+12) + { + // too easy, just do a bubble sort (base case) + if (to > from+1) + { + for (uint32 i=from+1; ifrom; j--) + { + int ret = compareFunc(*(GetItemAt(j)), *(GetItemAt(j-1)), cookie); + if (ret < 0) Swap(j, j-1); + else break; + } + } + } + } + else + { + // Okay, do the real thing + uint32 middle = (from + to)/2; + Sort(compareFunc, from, middle, cookie); + Sort(compareFunc, middle, to, cookie); + Merge(compareFunc, from, middle, to, middle-from, to-middle, cookie); + } + } +} + +template +void +Queue:: +ReverseItemOrdering(uint32 from, uint32 to) +{ + uint32 size = GetNumItems(); + if (size > 0) + { + to--; // make it inclusive + if (to >= size) to = size-1; + while (from < to) Swap(from++, to--); + } +} + +template +status_t +Queue:: +RemoveFirstInstanceOf(const ItemType & val) +{ + uint32 ni = GetNumItems(); + for (uint32 i=0; i +status_t +Queue:: +RemoveLastInstanceOf(const ItemType & val) +{ + for (int32 i=((int32)GetNumItems())-1; i>=0; i--) if ((*this)[i] == val) return RemoveItemAt(i); + return B_ERROR; +} + +template +uint32 +Queue:: +RemoveAllInstancesOf(const ItemType & val) +{ + // Efficiently collapse all non-matching slots up to the top of the list + uint32 ret = 0; + uint32 writeTo = 0; + uint32 origSize = GetNumItems(); + for(uint32 readFrom=0; readFrom writeTo) (*this)[writeTo] = nextRead; + writeTo++; + } + } + + // Now get rid of any now-surplus slots + for (; writeTo +void +Queue:: +Merge(ItemCompareFunc compareFunc, uint32 from, uint32 pivot, uint32 to, uint32 len1, uint32 len2, void * cookie) +{ + if ((len1)&&(len2)) + { + if (len1+len2 == 2) + { + if (compareFunc(*(GetItemAt(pivot)), *(GetItemAt(from)), cookie) < 0) Swap(pivot, from); + } + else + { + uint32 first_cut, second_cut; + uint32 len11, len22; + if (len1 > len2) + { + len11 = len1/2; + first_cut = from + len11; + second_cut = Lower(compareFunc, pivot, to, *GetItemAt(first_cut), cookie); + len22 = second_cut - pivot; + } + else + { + len22 = len2/2; + second_cut = pivot + len22; + first_cut = Upper(compareFunc, from, pivot, *GetItemAt(second_cut), cookie); + len11 = first_cut - from; + } + + // do a rotation + if ((pivot!=first_cut)&&(pivot!=second_cut)) + { + // find the greatest common denominator of (pivot-first_cut) and (second_cut-first_cut) + uint32 n = pivot-first_cut; + { + uint32 m = second_cut-first_cut; + while(n!=0) + { + uint32 t = m % n; + m=n; + n=t; + } + n = m; + } + + while(n--) + { + const ItemType val = *GetItemAt(first_cut+n); + uint32 shift = pivot - first_cut; + uint32 p1 = first_cut+n; + uint32 p2 = p1+shift; + while (p2 != first_cut + n) + { + ReplaceItemAt(p1, *GetItemAt(p2)); + p1 = p2; + if (second_cut - p2 > shift) p2 += shift; + else p2 = first_cut + (shift - (second_cut - p2)); + } + ReplaceItemAt(p1, val); + } + } + + uint32 new_mid = first_cut+len22; + Merge(compareFunc, from, first_cut, new_mid, len11, len22, cookie); + Merge(compareFunc, new_mid, second_cut, to, len1 - len11, len2 - len22, cookie); + } + } +} + + +template +uint32 +Queue:: +Lower(ItemCompareFunc compareFunc, uint32 from, uint32 to, const ItemType & val, void * cookie) const +{ + if (to > from) + { + uint32 len = to - from; + while (len > 0) + { + uint32 half = len/2; + uint32 mid = from + half; + if (compareFunc(*(GetItemAt(mid)), val, cookie) < 0) + { + from = mid+1; + len = len - half - 1; + } + else len = half; + } + } + return from; +} + +template +uint32 +Queue:: +Upper(ItemCompareFunc compareFunc, uint32 from, uint32 to, const ItemType & val, void * cookie) const +{ + if (to > from) + { + uint32 len = to - from; + while (len > 0) + { + uint32 half = len/2; + uint32 mid = from + half; + if (compareFunc(val, *(GetItemAt(mid)), cookie) < 0) len = half; + else + { + from = mid+1; + len = len - half -1; + } + } + } + return from; +} + +template +const ItemType * +Queue :: GetArrayPointerAux(uint32 whichArray, uint32 & retLength) const +{ + if (_itemCount > 0) + { + switch(whichArray) + { + case 0: + retLength = (_headIndex <= _tailIndex) ? (_tailIndex-_headIndex)+1 : (_queueSize-_headIndex); + return &_queue[_headIndex]; + break; + + case 1: + if (_headIndex > _tailIndex) + { + retLength = _tailIndex+1; + return &_queue[0]; + } + break; + } + } + return NULL; +} + +template +void +Queue::SwapContents(Queue & that) +{ + bool thisSmall = (_queue == _smallQueue); + bool thatSmall = (that._queue == that._smallQueue); + + if ((thisSmall)&&(thatSmall)) + { + // First, move any extra items from the longer queue to the shorter one... + uint32 commonSize = muscleMin(GetNumItems(), that.GetNumItems()); + int32 sizeDiff = ((int32)GetNumItems())-((int32)that.GetNumItems()); + Queue & copyTo = (sizeDiff > 0) ? that : *this; + Queue & copyFrom = (sizeDiff > 0) ? *this : that; + (void) copyTo.AddTail(copyFrom, commonSize); // guaranteed not to fail + (void) copyFrom.EnsureSize(commonSize, true); // remove the copied items from (copyFrom) + + // Then just swap the elements that are present in both arrays + for (uint32 i=0; i +void +Queue::SwapContentsAux(Queue & largeThat) +{ + // First, copy over our (small) contents to his static buffer + uint32 ni = GetNumItems(); + for (uint32 i=0; i 0) + { + largeThat._queue = largeThat._smallQueue; + largeThat._queueSize = ARRAYITEMS(largeThat._smallQueue); + largeThat._headIndex = 0; + largeThat._tailIndex = ni-1; + } + else + { + largeThat._queue = NULL; + largeThat._queueSize = 0; + // headIndex and tailIndex are undefined in this case anyway + } + + muscleSwap(_itemCount, largeThat._itemCount); +} + +template +bool +Queue::StartsWith(const Queue & prefixQueue) const +{ + if (prefixQueue.GetNumItems() > GetNumItems()) return false; + uint32 prefixQueueLen = prefixQueue.GetNumItems(); + for (uint32 i=0; i +bool +Queue::EndsWith(const Queue & suffixQueue) const +{ + if (suffixQueue.GetNumItems() > GetNumItems()) return false; + int32 lastToCheck = GetNumItems()-suffixQueue.GetNumItems(); + for (int32 i=GetNumItems()-1; i>=lastToCheck; i--) if (!(suffixQueue[i] == (*this)[i])) return false; + return true; +} + +END_NAMESPACE(muscle); + +#endif + diff --git a/library/libfunky/extra/ReflowingTextView.cpp b/library/libfunky/extra/ReflowingTextView.cpp new file mode 100644 index 0000000..0384f99 --- /dev/null +++ b/library/libfunky/extra/ReflowingTextView.cpp @@ -0,0 +1,255 @@ +#include "ReflowingTextView.h" +#include "ShareConstants.h" + +namespace beshare { + +const bigtime_t RTV_HIDE_DELAY = 1500000; +const bigtime_t RTV_SHOW_DELAY = 750000; + +enum { + RTV_SHOW_TOOLTIP = 0x1000, + RTV_HIDE_TOOLTIP +}; + +ReflowingTextView :: ReflowingTextView(BRect frame, const char *name, BRect textRect, uint32 resizeMask, uint32 flags) : BTextView(frame, name, textRect, resizeMask, flags), _showTipRunner(NULL), _canShow(false), _urlTip(NULL), _currentLinkStart(-1) +{ + // empty +} + +ReflowingTextView :: ~ReflowingTextView() +{ + if ((_urlTip)&&(_urlTip->Lock())) _urlTip->Quit(); + delete _showTipRunner; +} + +void ReflowingTextView :: AttachedToWindow() +{ + BTextView::AttachedToWindow(); + FixTextRect(); +} + +void ReflowingTextView :: FrameResized(float w, float h) +{ + BTextView::FrameResized(w, h); + FixTextRect(); +} + +void ReflowingTextView :: MouseMoved(BPoint where, uint32 code, const BMessage * msg) +{ + const URLLink * link = NULL; + if (code == B_INSIDE_VIEW) + { + link = GetURLAt(where); +#ifdef B_BEOS_VERSION_5 + SetViewCursor((link != NULL) ? B_CURSOR_SYSTEM_DEFAULT : B_CURSOR_I_BEAM); +#else + be_app->SetCursor((link != NULL) ? B_HAND_CURSOR : B_I_BEAM_CURSOR); +#endif + } + + String scratch; + const String * urlString = link ? &link->GetURL() : &scratch; + if ((link)&&(urlString->Length() == 0)) + { + char * buf = new char[link->GetLength()+1]; + GetText(link->GetStart(), link->GetLength(), buf); + buf[link->GetLength()] = '\0'; + scratch = buf; + delete [] buf; + urlString = &scratch; + } + + int32 linkStart = link ? (int32)link->GetStart() : -1; + if (linkStart != _currentLinkStart) + { + _currentLinkStart = linkStart; + _currentURLString = *urlString; + if (linkStart >= 0) + { + if ((_canShow == false)&&((_showTipRunner == NULL)||(_runnerWillHide))) + { + // Schedule unsetting the show flag + delete _showTipRunner; + _runnerWillHide = false; + _showTipRunner = new BMessageRunner(this, new BMessage(RTV_SHOW_TOOLTIP), RTV_SHOW_DELAY, 1); + } + } + else + { + if (_canShow) + { + // schedule a delayed show + delete _showTipRunner; + _runnerWillHide = true; + _showTipRunner = new BMessageRunner(this, new BMessage(RTV_HIDE_TOOLTIP), RTV_HIDE_DELAY, 1); + } + else if ((_showTipRunner)&&(_runnerWillHide == false)) + { + delete _showTipRunner; // cancel the pending show! + _showTipRunner = NULL; + } + } + UpdateToolTip(); + } + BTextView::MouseMoved(where, code, msg); +} + +void ReflowingTextView :: MessageReceived(BMessage * msg) +{ + switch(msg->what) + { + case RTV_SHOW_TOOLTIP: + delete _showTipRunner; _showTipRunner = NULL; + _canShow = true; + UpdateToolTip(); + break; + + case RTV_HIDE_TOOLTIP: + delete _showTipRunner; _showTipRunner = NULL; + _canShow = false; + UpdateToolTip(); + break; + + default: + BTextView::MessageReceived(msg); + break; + } +} + +void ReflowingTextView :: UpdateToolTip() +{ + if ((_canShow)&&(_currentLinkStart >= 0)) + { + if (_urlTip == NULL) + { + _urlTip = new BWindow(BRect(0,0,5,5), NULL, B_NO_BORDER_WINDOW_LOOK, B_FLOATING_ALL_WINDOW_FEEL, B_NOT_MOVABLE|B_NOT_CLOSABLE|B_NOT_ZOOMABLE|B_NOT_MINIMIZABLE|B_AVOID_FOCUS); + BView * blackBorder = new BView(_urlTip->Bounds(), NULL, B_FOLLOW_ALL_SIDES, 0); + const rgb_color black = {0,0,0,255}; + blackBorder->SetViewColor(black); + _urlTip->AddChild(blackBorder); + + const rgb_color hiliteYellow = {255,255,200,255}; + BRect inset = blackBorder->Bounds(); inset.InsetBy(1,1); + BView * yellowInterior = new BView(inset, NULL, B_FOLLOW_ALL_SIDES, 0); + yellowInterior->SetLowColor(hiliteYellow); + yellowInterior->SetViewColor(hiliteYellow); + blackBorder->AddChild(yellowInterior); + + _urlStringView = new BStringView(yellowInterior->Bounds(), NULL, "", B_FOLLOW_ALL_SIDES); + _urlStringView->SetLowColor(hiliteYellow); + _urlStringView->SetViewColor(hiliteYellow); + yellowInterior->AddChild(_urlStringView); + } + if (_urlTip->Lock()) + { + font_height ttfh; _urlStringView->GetFontHeight(&ttfh); + float urlHeight = 20.0f; + BPoint pt = PointAt(_currentLinkStart, &urlHeight); + _urlTip->MoveTo(ConvertToScreen(pt)+BPoint(15.0f, -(ttfh.ascent+ttfh.descent+3.0f))); + + _urlTip->ResizeTo(muscleMin(_urlStringView->StringWidth(_currentURLString())+4.0f, 400.0f), ttfh.ascent+ttfh.descent+2.0f); + _urlStringView->SetText(_currentURLString()); + _urlTip->SetWorkspaces(B_CURRENT_WORKSPACE); + if (_urlTip->IsHidden()) _urlTip->Show(); + _urlTip->Unlock(); + } + } + else if (_urlTip) + { + if (_urlTip->Lock()) + { + if (_urlTip->IsHidden() == false) _urlTip->Hide(); + _urlTip->Unlock(); + } + } +} + +void ReflowingTextView :: MouseDown(BPoint where) +{ + if (IsFocus() == false) MakeFocus(); + const URLLink * url = GetURLAt(where); + if (url) + { + char * allocBuf = NULL; + const char * buf = url->GetURL()(); + if (buf[0] == '\0') + { + buf = allocBuf = new char[url->GetLength()+1]; + GetText(url->GetStart(), url->GetLength(), allocBuf); + allocBuf[url->GetLength()] = '\0'; + } + + if (strncasecmp(buf, "beshare://", 10) == 0) + { + char * argv[] = {(char *) &buf[10]}; + be_roster->Launch(BESHARE_MIME_TYPE, ARRAYITEMS(argv), argv); + } + else if (strncasecmp(buf, "beshare:", 8) == 0) + { + BMessage msg(_queryMessage); + msg.AddString("query", &buf[8]); + _commandTarget.SendMessage(&msg); + } + else if (strncasecmp(buf, "share:", 6) == 0) + { + BMessage msg(_queryMessage); + msg.AddString("query", &buf[6]); + _commandTarget.SendMessage(&msg); + } + else if (strncasecmp(buf, "priv:", 5) == 0) + { + BMessage msg(_privMessage); + msg.AddString("users", &buf[5]); + _commandTarget.SendMessage(&msg); + } + else if (strncasecmp(buf, "audio://", 8) == 0) + { + BMessage msg(B_REFS_RECEIVED); + String temp("http://"); + temp += &buf[8]; + msg.AddString("be:url", temp()); + be_roster->Launch("audio/x-scpls", &msg); + } + else be_roster->Launch(strncasecmp(buf, "mailto:", 7) ? "application/x-vnd.Be.URL.http" : "text/x-email", 1, const_cast(&buf)); + + delete [] allocBuf; + } + BTextView::MouseDown(where); +} + +void ReflowingTextView :: FixTextRect() +{ + BRect t(Frame()); + SetTextRect(t); +} + +void ReflowingTextView :: Clear() +{ + Delete(0, TextLength()-1); + _urls.Clear(); +} + +void ReflowingTextView :: AddURLRegion(uint32 start, uint32 len, const String & optHiddenURL) +{ + _urls.AddTail(URLLink(start, len, optHiddenURL)); +} + +void ReflowingTextView :: SetCommandURLTarget(const BMessenger & target, const BMessage & queryMsg, const BMessage & privMsg) +{ + _commandTarget = target; + _queryMessage = queryMsg; + _privMessage = privMsg; +} + +const ReflowingTextView::URLLink * ReflowingTextView :: GetURLAt(BPoint pt) const +{ + uint32 offset = (uint32) OffsetAt(pt); + for (int i=_urls.GetNumItems()-1; i>=0; i--) + { + const URLLink & url = _urls[i]; + if ((offset >= url.GetStart())&&(offset < url.GetStart() + url.GetLength())) return &url; + } + return NULL; +} + +}; // end namespace beshare diff --git a/library/libfunky/extra/ReflowingTextView.h b/library/libfunky/extra/ReflowingTextView.h new file mode 100644 index 0000000..9f5e7f4 --- /dev/null +++ b/library/libfunky/extra/ReflowingTextView.h @@ -0,0 +1,83 @@ +#ifndef REFLOWING_TEXT_VIEW_H +#define REFLOWING_TEXT_VIEW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util/Queue.h" +#include "util/String.h" +#include "BeShareNameSpace.h" + +namespace beshare { + +/* Subsclass of BTextView that automatically reflows the text when it is resized */ +class ReflowingTextView : public BTextView +{ +public: + ReflowingTextView(BRect frame, const char *name, BRect textRect, uint32 resizeMask, uint32 flags = B_WILL_DRAW | B_PULSE_NEEDED); + virtual ~ReflowingTextView(); + + virtual void AttachedToWindow(); + + virtual void FrameResized(float w, float h); + + virtual void MessageReceived(BMessage * msg); + + virtual void MouseMoved(BPoint where, uint32 code, const BMessage * msg); + + virtual void MouseDown(BPoint where); + + void FixTextRect(); + + void Clear(); + + void AddURLRegion(uint32 start, uint32 len, const String & optHiddenURL); + + void SetCommandURLTarget(const BMessenger & target, const BMessage & queryMsg, const BMessage & privMsg); + +private: + void UpdateToolTip(); + + /* A simple little data class that remembers stuff we need to remember about hyperlinks in the text view */ + class URLLink + { + public: + URLLink() : _start(0), _len(0) {/* empty */} + URLLink(uint32 start, uint32 len, const String & optURL) : _start(start), _len(len), _url(optURL) {/* empty */} + + inline uint32 GetStart() const {return _start;} + inline uint32 GetLength() const {return _len;} + const String & GetURL() const {return _url;} + + private: + uint32 _start; + uint32 _len; + String _url; + }; + + const URLLink * GetURLAt(BPoint pt) const; + + Queue _urls; + BMessenger _commandTarget; + BMessage _queryMessage; + BMessage _privMessage; + BMessageRunner * _showTipRunner; + bool _runnerWillHide; // If true, the runner is a hide-runner. + bool _canShow; + BWindow * _urlTip; + BStringView * _urlStringView; + int32 _currentLinkStart; + String _currentURLString; +}; + +}; // end namespace beshare + +#endif diff --git a/library/libfunky/extra/String.cpp b/library/libfunky/extra/String.cpp new file mode 100644 index 0000000..690fda7 --- /dev/null +++ b/library/libfunky/extra/String.cpp @@ -0,0 +1,674 @@ +/* This file is Copyright 2005 Level Control Systems. See the included LICENSE.txt file for details. */ + +#include "util/String.h" +#include "system/GlobalMemoryAllocator.h" +#include + +BEGIN_NAMESPACE(muscle); + +String :: ~String() +{ + if (_buffer != _smallBuffer) muscleFree(_buffer); +} + +status_t +String::SetFromString(const String & s, uint32 firstChar, uint32 afterLastChar) +{ + afterLastChar = muscleMin(afterLastChar, s.Length()); + uint32 len = (afterLastChar > firstChar) ? (afterLastChar-firstChar) : 0; + if (len > 0) + { + if (EnsureBufferSize(len+1, false) != B_NO_ERROR) return B_ERROR; + if (&s == this) memmove(_buffer, s()+firstChar, len); + else memcpy( _buffer, s()+firstChar, len); + _buffer[len] = '\0'; + _length = len; + } + else Clear(); + + return B_NO_ERROR; +} + +status_t +String::SetCstr(const char * str, uint32 maxLen) +{ + // If (str)'s got a NUL byte before maxLen, make (maxLen) smaller. + // We can't call strlen(str) because we don't have any guarantee that the NUL + // byte even exists! Without a NUL byte, strlen() could run off into the weeds... + uint32 sLen = 0; + if (str) {while((sLen 0) + { + if (str[maxLen-1] != '\0') maxLen++; // make room to add the NUL byte if necessary + if (EnsureBufferSize(maxLen, false) != B_NO_ERROR) return B_ERROR; + if (muscleInRange((char *)str, _buffer, &_buffer[_length])) memmove(_buffer, str, maxLen-1); + else memcpy(_buffer, str, maxLen-1); + _buffer[maxLen-1] = '\0'; + _length = maxLen-1; + } + else Clear(); + + return B_NO_ERROR; +} + +String & +String::operator-=(const char aChar) +{ + int idx = LastIndexOf(aChar); + if (idx >= 0) + { + String temp = Substring(idx+1); + (*this) = this->Substring(0, idx); + (*this) += temp; + } + return *this; +} + +String & +String::operator+=(const String &other) +{ + uint32 otherLen = other.Length(); + if ((otherLen > 0)&&(EnsureBufferSize(Length() + otherLen + 1, true) == B_NO_ERROR)) + { + memcpy(&_buffer[_length], other(), other.Length()+1); + _length += otherLen; + } + return *this; +} + +String & +String::operator+=(const char * other) +{ + if (other == NULL) other = ""; + uint32 otherLen = strlen(other); + if (otherLen > 0) + { + if (muscleInRange(other, (const char *)_buffer, (const char *)(_buffer+_length))) return operator+=(String(other)); // avoid self-entanglement + else if (EnsureBufferSize(Length() + otherLen + 1, true) == B_NO_ERROR) + { + memcpy(&_buffer[_length], other, otherLen+1); + _length += otherLen; + } + } + return *this; +} + +String & +String::operator-=(const String &other) +{ + if (*this == other) *this = ""; + else + { + int idx = LastIndexOf(other); + if (idx >= 0) + { + String temp = Substring(idx+other.Length()); + (*this) = Substring(0, idx); + (*this) += temp; + } + } + return *this; +} + +String & +String::operator<<(int rhs) +{ + char buff[64]; + sprintf(buff, "%d", rhs); + return *this << buff; +} + +String & +String::operator<<(float rhs) +{ + char buff[64]; + sprintf(buff, "%.2f", rhs); + return *this << buff; +} + +String & +String::operator<<(bool rhs) +{ + const char* val = rhs ? "true" : "false"; + return *this << val; +} + +void +String::Reverse() +{ + if ((_buffer)&&(Length() > 0)) + { + uint32 from = 0; + uint32 to = Length()-1; + while(from 0) + { + // If we are replacing a shorter string with a longer string, we'll have to do a copy-and-swap + uint32 numInstances = GetNumInstancesOf(replaceMe); + if (numInstances == 0) return 0; // no changes necessary! + if (temp.Prealloc(Length()+(perInstanceDelta*numInstances)) != B_NO_ERROR) return -1; + } + + // This code works for both the in-place and the copy-over modes! + int32 ret = 0; + const char * readPtr = Cstr(); + char * writePtr = (perInstanceDelta > 0) ? temp._buffer : NULL; + while(1) + { + char * nextReplaceMe = strstr((char *) readPtr, (char *) replaceMe()); + if (nextReplaceMe) + { + ret++; + if (writePtr) + { + uint32 numBytes = nextReplaceMe-readPtr; + if (perInstanceDelta != 0) memmove(writePtr, readPtr, numBytes); + writePtr += numBytes; + } + else writePtr = nextReplaceMe; + + memcpy(writePtr, withMe(), withMe.Length()); + readPtr = nextReplaceMe + replaceMe.Length(); + writePtr += withMe.Length(); + } + else + { + if (writePtr) + { + // Finish up + uint32 numBytes = Cstr()+Length()-readPtr; + if (perInstanceDelta != 0) memmove(writePtr, readPtr, numBytes); + writePtr += numBytes; + *writePtr = '\0'; + if (perInstanceDelta > 0) + { + temp._length = writePtr-temp(); + SwapContents(temp); + } + else _length = writePtr-Cstr(); + } + return ret; + } + } + return ret; // just to shut the compiler up; we never actually get here +} + +void +String::SwapContents(String & s) +{ + TCHECKPOINT; + + if (&s != this) + { + bool thisSmall = ( _buffer == _smallBuffer); + bool sSmall = (s._buffer == s._smallBuffer); + + if ((sSmall)&&(thisSmall)) + { + for (int32 i=muscleMax(_length, s._length); i>=0; i--) muscleSwap(_smallBuffer[i], s._smallBuffer[i]); + } + else if (thisSmall) + { + _buffer = s._buffer; + _bufferLen = s._bufferLen; + s._buffer = s._smallBuffer; + s._bufferLen = sizeof(s._smallBuffer); + memcpy(s._smallBuffer, _smallBuffer, _length+1); + } + else if (sSmall) + { + s._buffer = _buffer; + s._bufferLen = _bufferLen; + _buffer = _smallBuffer; + _bufferLen = sizeof(_smallBuffer); + memcpy(_smallBuffer, s._smallBuffer, s._length+1); + } + else + { + muscleSwap(_buffer, s._buffer); + muscleSwap(_bufferLen, s._bufferLen); + } + + muscleSwap(_length, s._length); // always do this + } +} + +int +String::LastIndexOf(const String &s2, uint32 fromIndex) const +{ + TCHECKPOINT; + + if (s2.Length() == 0) return Length()-1; + if (fromIndex >= Length()) return -1; + for (int i=fromIndex; i>=0; i--) if (strncmp(Cstr()+i, s2.Cstr(), s2.Length()) == 0) return i; + return -1; +} + +int +String::LastIndexOf(const char * s2, uint32 fromIndex) const +{ + TCHECKPOINT; + + if (s2 == NULL) s2 = ""; + uint32 s2Len = strlen(s2); + if (s2Len == 0) return Length()-1; + if (fromIndex >= Length()) return -1; + for (int i=fromIndex; i>=0; i--) if (strncmp(Cstr()+i, s2, s2Len) == 0) return i; + return -1; +} + +String +String::ToLowerCase() const +{ + String ret(*this); + if (ret._buffer) for (uint32 i=0; istartIdx; endIdx--) if (!IsSpaceChar(s[endIdx])) break; + return String(*this, (uint32)startIdx, (uint32)(endIdx+1)); +} + +uint32 String :: FlattenedSize() const +{ + return Length()+1; +} + +void String :: Flatten(uint8 *buffer) const +{ + memcpy((char *)buffer, Cstr(), Length()+1); +} + +status_t String :: Unflatten(const uint8 *buf, uint32 size) +{ + return SetCstr((const char *)buf, size); +} + +uint32 String :: GetNumInstancesOf(char ch) const +{ + uint32 ret = 0; + for (const char * s = Cstr(); (*s != '\0'); s++) if (*s == ch) ret++; + return ret; +} + +uint32 String :: GetNumInstancesOf(const String & substring) const +{ + TCHECKPOINT; + + uint32 ret = 0; + if (substring.Length() > 0) + { + uint32 lastIdx = 0; + int32 idx; + while((idx = IndexOf(substring, lastIdx)) >= 0) + { + ret++; + lastIdx = idx + substring.Length(); + } + } + return ret; +} + +uint32 String :: GetNumInstancesOf(const char * substring) const +{ + TCHECKPOINT; + + if (substring == NULL) substring = ""; + uint32 ret = 0; + uint32 substringLength = strlen(substring); + if (substringLength > 0) + { + uint32 lastIdx = 0; + int32 idx; + while((idx = IndexOf(substring, lastIdx)) >= 0) + { + ret++; + lastIdx = idx + substringLength; + } + } + return ret; +} + +String String :: Prepend(const String & str, uint32 count) const +{ + TCHECKPOINT; + + String ret; + uint32 newLen = (count*str.Length())+Length(); + if (ret.Prealloc(newLen) == B_NO_ERROR) + { + char * b = ret._buffer; + + if (str.Length() > 0) + { + for (uint32 i=0; i 0) + { + memcpy(b, Cstr(), Length()); + b += Length(); + } + ret._length = (b-ret._buffer); + ret._buffer[ret._length] = '\0'; // terminate the string + } + return ret; +} + +String String :: Prepend(const char * str, uint32 count) const +{ + TCHECKPOINT; + + if (muscleInRange(str, (const char *)_buffer, (const char *)(_buffer+Length()))) return Prepend(String(str), count); // avoid self-entanglement! + else + { + if (str == NULL) str = ""; + uint32 sLen = strlen(str); + String ret; + uint32 newLen = (count*sLen)+Length(); + if (ret.Prealloc(newLen) == B_NO_ERROR) + { + char * b = ret._buffer; + + if (sLen > 0) + { + for (uint32 i=0; i 0) + { + memcpy(b, Cstr(), Length()); + b += Length(); + } + ret._length = (b-ret._buffer); + ret._buffer[ret._length] = '\0'; // terminate the string + } + return ret; + } +} + +String String :: Append(const String & str, uint32 count) const +{ + TCHECKPOINT; + + String ret; + uint32 newLen = Length()+(count*str.Length()); + if (ret.Prealloc(newLen) == B_NO_ERROR) + { + char * b = ret._buffer; + if (Length() > 0) + { + memcpy(b, Cstr(), Length()); + b += Length(); + } + if (str.Length() > 0) + { + for (uint32 i=0; i 0) + { + memcpy(b, Cstr(), Length()); + b += Length(); + } + if (sLen > 0) + { + for (uint32 i=0; i _bufferLen) + { + if (requestedBufLen <= sizeof(_smallBuffer)) // guaranteed only to be true the very first time we are called! + { + // For small initial requests, we can just set up our buffer pointer to point to our static-buffer area. Cheap! + _buffer = _smallBuffer; + _bufferLen = sizeof(_smallBuffer); + } + else + { + // If we're doing a first-time allocation, allocate exactly the number of the bytes requested. + // If it's a re-allocation, allocate more than requested as it's more likely to happen yet another time... + uint32 newBufLen = (_buffer == NULL) ? requestedBufLen : (requestedBufLen * 2); + if (retainValue) + { + if ((_buffer)&&(_buffer != _smallBuffer)) + { + // We can call muscleRealloc() to hopefully avoid data copying + char * newBuf = (char *)muscleRealloc(_buffer, newBufLen); + if (newBuf) + { + _buffer = newBuf; + _bufferLen = newBufLen; + } + else + { + WARN_OUT_OF_MEMORY; + return B_ERROR; + } + } + else + { + // Oops, muscleRealloc() won't do.... we'll just have to copy the bytes over + char * newBuf = (char *) muscleAlloc(newBufLen); + if (newBuf == NULL) + { + WARN_OUT_OF_MEMORY; + return B_ERROR; + } + if (_buffer) memcpy(newBuf, _buffer, Length()+1); + if (_buffer != _smallBuffer) muscleFree(_buffer); + _buffer = newBuf; + _bufferLen = newBufLen; + } + } + else + { + // If the caller doesn't care about retaining the value, then it's + // probably cheaper just to free our buffer and get a new one. + char * newBuf = (char *) muscleAlloc(newBufLen); + if (newBuf == NULL) + { + WARN_OUT_OF_MEMORY; + return B_ERROR; + } + if (_buffer != _smallBuffer) muscleFree(_buffer); + _buffer = newBuf; + _bufferLen = newBufLen; + } + } + } + return B_NO_ERROR; +} + +String String :: Pad(uint32 minLength, bool padOnRight, char padChar) const +{ + if (Length() < minLength) + { + uint32 padLen = minLength-Length(); + String temp; temp += padChar; + return (padOnRight) ? Append(temp, padLen) : Prepend(temp, padLen); + } + else return *this; +} + +#define ARG_IMPLEMENTATION \ + char buf[256]; \ + sprintf(buf, fmt, value); \ + return ArgAux(buf) + +String String :: Arg(int8 value, const char * fmt) const {ARG_IMPLEMENTATION;} +String String :: Arg(uint8 value, const char * fmt) const {ARG_IMPLEMENTATION;} +String String :: Arg(int16 value, const char * fmt) const {ARG_IMPLEMENTATION;} +String String :: Arg(uint16 value, const char * fmt) const {ARG_IMPLEMENTATION;} +String String :: Arg(int32 value, const char * fmt) const {ARG_IMPLEMENTATION;} +String String :: Arg(uint32 value, const char * fmt) const {ARG_IMPLEMENTATION;} +String String :: Arg(int64 value, const char * fmt) const {ARG_IMPLEMENTATION;} +String String :: Arg(uint64 value, const char * fmt) const {ARG_IMPLEMENTATION;} +String String :: Arg(double value, const char * fmt) const {ARG_IMPLEMENTATION;} +String String :: Arg(const String & value) const {return ArgAux(value());} +String String :: Arg(const char * value) const {return ArgAux(value);} + +String String :: ArgAux(const char * buf) const +{ + TCHECKPOINT; + + int32 lowestArg = -1; + const char * s = Cstr(); + while(*s != '\0') + { + if (*s == '%') + { + s++; + if (muscleInRange(*s, '0', '9')) + { + int32 val = atol(s); + lowestArg = (lowestArg < 0) ? val : muscleMin(val, lowestArg); + while(muscleInRange(*s, '0', '9')) s++; + } + } + else s++; + } + + if (lowestArg >= 0) + { + char token[64]; + sprintf(token, "%%%li", lowestArg); + String ret(*this); + (void) ret.Replace(token, buf); + return ret; + } + else return *this; +} + +const String & GetEmptyString() +{ + static const String _empty; + return _empty; +} + +/*--- ElfHash --------------------------------------------------- + * The published hash algorithm used in the UNIX ELF format + * for object files. Accepts a pointer to a string to be hashed + * and returns an unsigned long. + * jaf: stolen from: http://www.ddj.com/articles/1996/9604/9604b/9604b.htm?topic=algorithms + *-------------------------------------------------------------*/ +uint32 CStringHashFunc(const char * n) +{ + uint32 h = 0, g; + const unsigned char * name = (const unsigned char *) n; + while (*name) + { + h = (h << 4) + *name++; + if ((g = h & 0xF0000000) != 0) h ^= g >> 24; + h &= ~g; + } + return h; +} + +int CStringCompareFunc(const char * const & s1, const char * const & s2, void *) +{ + return strcmp(s1, s2); +} + +int StringCompareFunc(const String & s1, const String & s2, void *) +{ + return muscleCompare(s1, s2); +} + +END_NAMESPACE(muscle); diff --git a/library/libfunky/extra/String.h b/library/libfunky/extra/String.h new file mode 100644 index 0000000..119971e --- /dev/null +++ b/library/libfunky/extra/String.h @@ -0,0 +1,672 @@ +/* This file is Copyright 2005 Level Control Systems. See the included LICENSE.txt file for details. */ +/* This class was derived from the String class written by Michael Olivero (mike95@mike95.com) */ + +/* NOTE TO MACOS/X X-CODE USERS: If you are trying to #include + * and X-Code is "helpfully" pulling in this file instead (because the + * OS/X filesystem is case-insensitive), you can get around that problem + * by adding "USE_HEADERMAP = NO" to your X-Code target settings. + * ref: http://lists.apple.com/archives/xcode-users/2004/Aug/msg00934.html + * --Jeremy + */ + +#ifndef MuscleString_h +#define MuscleString_h + +#include +#include +#include "support/Flattenable.h" + +BEGIN_NAMESPACE(muscle); + +#ifndef SMALL_MUSCLE_STRING_LENGTH +# define SMALL_MUSCLE_STRING_LENGTH 7 // strings shorter than this length can be stored inline, without requiring an extra new[]. +#endif + +/** A nice hashing function for use with (const char *)'s */ +uint32 CStringHashFunc(const char * str); + +/** A character string class. Represents a dynamically resizable NUL-terminated string. */ +class String : public Flattenable { +public: + /** Constructor. + * @param str If non-NULL, the initial value for this String. + * @param maxLen The maximum number of characters to place into + * this String (not including the NUL terminator byte). + * Default is unlimited (i.e. scan the entire string no matter how long it is) + */ + String(const char * str = NULL, uint32 maxLen = ((uint32)-1)) : Flattenable(), _buffer(NULL), _bufferLen(0), _length(0) {if (str) (void) SetCstr(str, maxLen);} + + /** Copy Constructor. + * @param str String to become a copy of. + */ + String(const String & str) : Flattenable(), _buffer(NULL), _bufferLen(0), _length(0) {(void) SetFromString(str);} + + /** This constructor sets this String to be a substring of the specified String. + * @param str String to become a copy of. + * @param beginIndex Index of the first character in (str) to include. + * @param endIndex Index after the last character in (str) to include. + * Defaults to a very large number, so that by default the entire remainder of the string is included. + */ + String(const String & str, uint32 beginIndex, uint32 endIndex=((uint32)-1)) : Flattenable(), _buffer(NULL), _bufferLen(0), _length(0) {(void) SetFromString(str, beginIndex, endIndex);} + + /** Destructor. */ + virtual ~String(); + + /** Assignment Operator. Sets this string to be a one-character string + * @param val The character that should be the sole character in this String. + */ + String & operator = (char val) {(void) SetCstr(&val, 1); return *this;} + + /** Assignment Operator. + * @param val Pointer to the C-style string to copy from. If NULL, this string will become "". + */ + String & operator = (const char * val) {(void) SetCstr(val); return *this;} + + /** Assignment Operator. + * @param rhs String to become a copy of. + */ + String & operator = (const String &rhs) {(void) SetFromString(rhs); return *this;} + + /** Append Operator. + * @param rhs A string to append to this string. + */ + String & operator += (const String &rhs); + + /** Append Operator. + * @param rhs A string to append to this string. If NULL, this operation is a no-op. + */ + String & operator += (const char * rhs); + + /** Append Operator. + * @param ch A character to append to this string. + */ + String & operator += (const char ch) + { + if (EnsureBufferSize(Length()+2, true) == B_NO_ERROR) + { + _buffer[_length++] = ch; + _buffer[_length] = '\0'; + } + return *this; + } + + /** Remove Operator. + * @param rhs A substring to remove from this string; the + * last instance of the substring will be cut out. + * If (rhs) is not found, there is no effect. + */ + String & operator -= (const String &rhs); + + /** Remove Operator. + * @param ch A character to remove from this string; the last + * instance of this char will be cut out. If (ch) is + * not found, there is no effect. + */ + String & operator -= (const char ch); + + /** Append 'Stream' Operator. + * @param rhs A String to append to this string. + * @return a non const String refrence to 'this' so you can chain appends. + */ + String & operator << (const String& rhs) {return (*this += rhs);} + + /** Append 'Stream' Operator. + * @param rhs A const char* to append to this string. + * @return a non const String refrence to 'this' so you can chain appends. + */ + String & operator << (const char* rhs) {return (*this += rhs);} + + /** Append 'Stream' Operator. + * @param rhs An int to append to this string. + * @return a non const String refrence to 'this' so you can chain appends. + */ + String & operator << (int rhs); + + /** Append 'Stream' Operator. + * @param rhs A float to append to this string. Formatting is set at 2 decimals of precision. + * @return a non const String refrence to 'this' so you can chain appends. + */ + String & operator << (float rhs); + + /** Append 'Stream' Operator. + * @param rhs A bool to append to this string. Converts to 'true' and 'false' strings appropriately. + * @return a non const String refrence to 'this' so you can chain appends. + */ + String & operator << (bool rhs); + + /** Comparison Operator. Returns true if the two strings are equal (as determined by strcmp()) + * @param rhs A string to compare ourself with + */ + bool operator == (const String &rhs) const {return ((this == &rhs)||((Length() == rhs.Length())&&(strcmp(Cstr(), rhs.Cstr()) == 0)));} + + /** Comparison Operator. Returns true if the two strings are equal (as determined by strcmp()) + * @param rhs Pointer to a C string to compare with. NULL pointers are considered a synonym for "". + */ + bool operator == (const char * rhs) const {return (strcmp(Cstr(), rhs?rhs:"") == 0);} + + /** Comparison Operator. Returns true if the two strings are not equal (as determined by strcmp()) + * @param rhs A string to compare ourself with + */ + bool operator != (const String &rhs) const {return !(*this == rhs);} + + /** Comparison Operator. Returns true if the two strings are not equal (as determined by strcmp()) + * @param rhs Pointer to a C string to compare to. NULL pointers are considered a synonym for "". + */ + bool operator != (const char * rhs) const {return (strcmp(Cstr(), rhs?rhs:"") != 0);} + + /** Comparison Operator. Returns true if this string comes before (rhs) lexically. + * @param rhs A string to compare ourself with + */ + bool operator < (const String &rhs) const {return (this == &rhs) ? false : (strcmp(Cstr(), rhs.Cstr()) < 0);} + + /** Comparison Operator. Returns true if this string comes before (rhs) lexically. + * @param rhs Pointer to a C string to compare to. NULL pointers are considered a synonym for "". + */ + bool operator < (const char * rhs) const {return (strcmp(Cstr(), rhs?rhs:"") < 0);} + + /** Comparison Operator. Returns true if this string comes after (rhs) lexically. + * @param rhs A string to compare ourself with + */ + bool operator > (const String &rhs) const {return (this == &rhs) ? false : (strcmp(Cstr(), rhs.Cstr()) > 0);} + + /** Comparison Operator. Returns true if this string comes after (rhs) lexically. + * @param rhs Pointer to a C string to compare to. NULL pointers are considered a synonym for "". + */ + bool operator > (const char * rhs) const {return (strcmp(Cstr(), rhs?rhs:"") > 0);} + + /** Comparison Operator. Returns true if the two strings are equal, or this string comes before (rhs) lexically. + * @param rhs A string to compare ourself with + */ + bool operator <= (const String &rhs) const {return (this == &rhs) ? true : (strcmp(Cstr(), rhs.Cstr()) <= 0);} + + /** Comparison Operator. Returns true if the two strings are equal, or this string comes before (rhs) lexically. + * @param rhs Pointer to a C string to compare to. NULL pointers are considered a synonym for "". + */ + bool operator <= (const char * rhs) const {return (strcmp(Cstr(), rhs?rhs:"") <= 0);} + + /** Comparison Operator. Returns true if the two strings are equal, or this string comes after (rhs) lexically. + * @param rhs A string to compare ourself with + */ + bool operator >= (const String &rhs) const {return (this == &rhs) ? true : (strcmp(Cstr(), rhs.Cstr()) >= 0);} + + /** Comparison Operator. Returns true if the two strings are equal, or this string comes after (rhs) lexically. + * @param rhs Pointer to a C string to compare to. NULL pointers are considered a synonym for "". + */ + bool operator >= (const char * rhs) const {return (strcmp(Cstr(), rhs?rhs:"") >= 0);} + + /** Array Operator. Used to get easy access to the characters that make up this string. + * @param index Index of the character to return. Be sure to only use valid indices! + */ + char operator [] (uint32 index) const {VerifyIndex(index); return _buffer[index];} + + /** Array Operator. Used to get easy access to the characters that make up this string. + * @param index Index of the character to set. Be sure to only use valid indices! + */ + char & operator [] (uint32 index) {VerifyIndex(index); return _buffer[index];} + + /** Returns the character at the (index)'th position in the string. + * @param index A value between 0 and (Length()-1), inclusive. + * @return A character value. + */ + char CharAt(uint32 index) const {return operator[](index);} + + /** Compares this string to another string using strcmp() + * @param rhs A string to compare ourself with + */ + int CompareTo(const String & rhs) const {return strcmp(Cstr(), rhs.Cstr());} + + /** Compares this string to a C string using strcmp() + * @param rhs Pointer to a C string to compare to. NULL pointers are considered a synonym for "". + */ + int CompareTo(const char * rhs) const {return strcmp(Cstr(), rhs?rhs:"");} + + /** Returns a read-only C-style pointer to our held character string. */ + const char * Cstr() const {return _buffer ? _buffer : "";} + + /** Convenience synonym for Cstr(). */ + const char * operator()() const {return Cstr();} + + /** Clears this string so that it contains no characters. Equivalent to setting it to "". */ + void Clear() {if (_buffer) _buffer[0] = '\0'; _length = 0;} + + /** Sets our state from the given C-style string. + * @param str The new string to copy from. If maxLen is negative, this may be NULL. + * @param maxLen If set, the number of characters to copy (not including the NUL + * terminator byte). By default, the number of characters is determined + * automatically by scanning the string. + */ + status_t SetCstr(const char * str, uint32 maxLen = ((uint32)-1)); + + /** Sets our state from the given String. This is similar to the copy constructor, except + * that it allows you to optionally specify a maximum length, and it allows you to detect + * out-of-memory errors. + * @param str The new string to copy from. + * @param beginIndex Index of the first character in (str) to include. + * @param endIndex Index after the last character in (str) to include. + * Defaults to a very large number, so that by default the entire remainder of the string is included. + * @returns B_NO_ERROR on success, or B_ERROR on failure (out of memory?) + */ + status_t SetFromString(const String & str, uint32 firstChar = 0, uint32 maxLen = ((uint32)-1)); + + /** Returns true iff this string starts with (prefix) + * @param c a character to check for at the end of this String. + */ + bool EndsWith(char c) const {return (_length > 0)&&(_buffer[_length-1] == c);} + + /** Returns true iff this string ends with (suffix) + * @param suffix a String to check for at the end of this String. + */ + bool EndsWith(const String &suffix) const {return (Length() < suffix.Length()) ? false : (strcmp(Cstr()+(Length()-suffix.Length()), suffix.Cstr()) == 0);} + + /** Returns true iff this string ends with (suffix) + * @param suffix a String to check for at the end of this String. NULL pointers are treated as a synonym for "". + */ + bool EndsWith(const char * suffix) const + { + if (suffix == NULL) suffix = ""; + uint32 suffixLen = strlen(suffix); + return (Length() < suffixLen) ? false : (strcmp(Cstr()+(Length()-suffixLen), suffix) == 0); + } + + /** Returns true iff this string is equal to (string), as determined by strcmp(). + * @param str a String to compare this String with. + */ + bool Equals(const String & str) const {return (*this == str);} + + /** Returns true iff this string is equal to (str), as determined by strcmp(). + * @param str Pointer to a C string to compare to. NULL pointers are considered a synonym for "". + */ + bool Equals(const char * str) const {return (*this == str);} + + /** Returns true iff this string contains a single character (c). + * @param c a character to compare this String with. + */ + bool Equals(char c) const {return (_length == 1)&&(_buffer[0] == c);} + + /** Returns the first index of (ch) in this string starting at or after (fromIndex), or -1 if not found. + * @param ch A character to look for in this string. + * @param fromIndex Index of the first character to start searching at in this String. Defaults to zero (i.e. start from the first character) + */ + int IndexOf(char ch, uint32 fromIndex = 0) const + { + const char * temp = (fromIndex < Length()) ? strchr(Cstr()+fromIndex, ch) : NULL; + return temp ? (temp - Cstr()) : -1; + } + + /** Returns the first index of substring (str) in this string starting at or after (fromIndex), or -1 if not found. + * @param str A String to look for in this string. + * @param fromIndex Index of the first character to start searching at in this String. Defaults to zero (i.e. start from the first character) + */ + int IndexOf(const String &str, uint32 fromIndex = 0) const + { + const char * temp = (fromIndex < Length()) ? strstr(Cstr()+fromIndex, str()) : NULL; + return temp ? (temp - Cstr()) : -1; + } + + /** Returns the first index of substring (str) in this string starting at or after (fromIndex), or -1 if not found. + * @param str Pointer to a C string to compare to. NULL pointers are considered a synonym for "". + * @param fromIndex Index of the first character to start searching at in this String. Defaults to zero (i.e. start from the first character) + */ + int IndexOf(const char * str, uint32 fromIndex = 0) const + { + const char * temp = (fromIndex < Length()) ? strstr(Cstr()+fromIndex, str?str:"") : NULL; + return temp ? (temp - Cstr()) : -1; + } + + /** Returns the last index of (ch) in this string starting at or after (fromIndex), or -1 if not found. + * @param ch A character to look for in this string. + * @param fromIndex Index of the first character to start searching at in this String. Defaults to zero (i.e. start from the first character) + */ + int LastIndexOf(char ch, uint32 fromIndex = 0) const + { + const char * lio = (fromIndex < Length()) ? strrchr(Cstr()+fromIndex, ch) : NULL; + return lio ? (lio - Cstr()) : -1; + } + + /** Returns the last index of substring (str) in this string + * @param str A String to look for in this string. + * @param fromIndex Index of the first character to start searching at in this String. Defaults to zero (i.e. start from the first character) + */ + int LastIndexOf(const String &str) const {return (str.Length() <= Length()) ? LastIndexOf(str, Length()-str.Length()) : -1;} + + /** Returns the last index of substring (str) in this string + * @param str Pointer to a C string to compare to. NULL pointers are considered a synonym for "". + */ + int LastIndexOf(const char * str) const + { + if (str == NULL) str = ""; + uint32 strLen = strlen(str); + return (strLen <= Length()) ? LastIndexOf(str, Length()-strLen) : -1; + } + + /** Returns the last index of substring (str) in this string starting at or after (fromIndex), or -1 if not found. + * @param str A String to look for in this string. + * @param fromIndex Index of the first character to start searching at in this String. Defaults to zero (i.e. start from the first character) + */ + int LastIndexOf(const String &str, uint32 fromIndex) const; + + /** Returns the last index of substring (str) in this string starting at or after (fromIndex), or -1 if not found. + * @param str Pointer to a C string to compare to. NULL pointers are considered a synonym for "". + * @param fromIndex Index of the first character to start searching at in this String. Defaults to zero (i.e. start from the first character) + */ + int LastIndexOf(const char * str, uint32 fromIndex) const; + + /** Returns the number of characters in the string (not including the terminating NUL byte) */ + uint32 Length() const {return _length;} + + /** Returns the number of instances of (c) in this string. */ + uint32 GetNumInstancesOf(char ch) const; + + /** Returns the number of instances of (substring) in this string. */ + uint32 GetNumInstancesOf(const String & substring) const; + + /** Returns the number of instances of (substring) in this string. */ + uint32 GetNumInstancesOf(const char * substring) const; + + /** Returns true iff this string starts with (prefix) */ + bool StartsWith(char c) const {return (_length > 0)&&(_buffer[0] == c);} + + /** Returns true iff this string starts with (prefix) */ + bool StartsWith(const String &str) const {return ((Length() >= str.Length())&&(strncmp(Cstr(), str(), str.Length()) == 0));} + + /** Returns true iff this string starts with (prefix) + * @param str Pointer to a C string to compare to. NULL pointers are considered a synonym for "". + */ + bool StartsWith(const char * prefix) const + { + if (prefix == NULL) prefix = ""; + uint32 prefixLen = strlen(prefix); + return (Length() < prefixLen) ? false : (strncmp(Cstr(), prefix, prefixLen) == 0); + } + + /** Returns true iff this string starts with the first (offset) characters of (prefix) */ + bool StartsWith(const String &prefix, uint32 offset) const {return ((offset+prefix.Length()<=Length())&&(strncmp(Cstr()+offset, prefix.Cstr(), prefix.Length()) == 0));} + + /** Returns true iff this string starts with the first (offset) characters of (prefix) + * @param str Pointer to a C string to compare to. NULL pointers are considered a synonym for "". + */ + bool StartsWith(const char * prefix, uint32 offset) const + { + if (prefix == NULL) prefix = ""; + uint32 prefixLen = strlen(prefix); + return ((offset+prefixLen<=Length())&&(strncmp(Cstr()+offset, prefix, prefixLen) == 0)); + } + + /** Returns a string that consists of (count) copies of (str), followed by this string. */ + String Prepend(const String & str, uint32 count = 1) const; + + /** Returns a string that consists of (count) copies of (str), followed by this string. + * @param str Pointer to a C string to compare to. NULL pointers are considered a synonym for "". + * @param count How many instances of (str) should be prepended to this string. Defaults to 1. + */ + String Prepend(const char * str, uint32 count = 1) const; + + /** Returns a string that consists of this string followed by (count) copies of (str). */ + String Append(const String & str, uint32 count = 1) const; + + /** Returns a string that consists of this string followed by (count) copies of (str). + * @param str Pointer to a C string to compare to. NULL pointers are considered a synonym for "". + * @param count How many instances of (str) should be appended to this string. Defaults to 1. + */ + String Append(const char * str, uint32 count = 1) const; + + /** Returns a string that is like this string, but padded out to the specified minimum length with (padChar). + * @param minLength Minimum length that the returned string should be. + * @param padOnRight If true, (padChar)s will be added to the right; if false (the default), they will be added on the left. + * @param padChar The character to pad out the string with. Defaults to ' '. + * @returns the new, padded String. + */ + String Pad(uint32 minLength, bool padOnRight = false, char padChar = ' ') const; + + /** Returns a string that consists of only the last part of this string, starting with index (beginIndex). Does not modify the string it is called on. */ + String Substring(uint32 beginIndex) const {return String(*this, beginIndex);} + + /** Returns a string that consists of only the characters in this string from range (beginIndex) to (endIndex-1). Does not modify the string it is called on. */ + String Substring(uint32 beginIndex, uint32 endIndex) const {return String(*this, beginIndex, endIndex);} + + /** Returns a string that consists of only the last part of this string, starting with the first character after the last instance of (markerString). + * If (markerString) is not found in the string, then this entire String is returned. + * For example, String("this is a test").Substring("is a") returns " test". + * Does not modify the string it is called on. + */ + String Substring(const String & markerString) const + { + int idx = LastIndexOf(markerString); + return (idx >= 0) ? String(*this, idx+markerString.Length()) : *this; + } + + /** See the Substring(const String &) documentation for details. */ + String Substring(const char * markerString) const + { + int idx = LastIndexOf(markerString); + return (idx >= 0) ? String(*this, idx+strlen(markerString)) : *this; // if (idx >= 0), then we know markerString is non-NULL + } + + /** Returns a string that consists of only the characters in the string from range (beginIndex) until the character just before + * the first character in (markerString). If (markerString) is not found, then the entire substring starting at (beginIndex) is returned. + * For example, String("this is a test").Substring(1, "is a") returns "his ". + * Does not modify the string it is called on. + */ + String Substring(uint32 beginIndex, const String & markerString) const {return String(*this, beginIndex, (uint32) IndexOf(markerString, beginIndex));} + + /** See the Substring(uint32, const String &) documentation for details. */ + String Substring(uint32 beginIndex, const char * markerString) const {return String(*this, beginIndex, (uint32) IndexOf(markerString, beginIndex));} + + /** Returns an all lower-case version of this string. Does not modify the string it is called on. */ + String ToLowerCase() const; + + /** Returns an all upper-case version of this string. Does not modify the string it is called on. */ + String ToUpperCase() const; + + /** Returns an version of this string that has all leading and trailing whitespace removed. Does not modify the string it is called on. */ + String Trim() const; + + /** Swaps the state of this string with (swapWithMe). Very efficient since little or no data copying is required. */ + void SwapContents(String & swapWithMe); + + /** Like CompareTo(), but case insensitive. */ + int CompareToIgnoreCase(const String &s) const {return ToLowerCase().CompareTo(s.ToLowerCase());} + + /** Like EndsWith(), but case insensitive. */ + bool EndsWithIgnoreCase(char c) const {return (_length > 0)&&(tolower(_buffer[_length-1]) == tolower(c));} + + /** Like EndsWith(), but case insensitive. */ + bool EndsWithIgnoreCase(const String &s) const {return ToLowerCase().EndsWith(s.ToLowerCase());} + + /** Like Equals(), but case insensitive. */ + bool EqualsIgnoreCase(const String &s) const {return ToLowerCase().Equals(s.ToLowerCase());} + + /** Like Equals(), but case insensitive. */ + bool EqualsIgnoreCase(char c) const {return (_length==1)&&(tolower(_buffer[0])==tolower(c));} + + /** Like IndexOf(), but case insensitive. */ + int IndexOfIgnoreCase(const String &s) const {return ToLowerCase().IndexOf(s.ToLowerCase());} + + /** Like IndexOf(), but case insensitive. */ + int IndexOfIgnoreCase(const String &s, uint32 f) const {return ToLowerCase().IndexOf(s.ToLowerCase(),f);} + + /** Like IndexOf(), but case insensitive. */ + int IndexOfIgnoreCase(char ch) const {return ToLowerCase().IndexOf((char)tolower(ch));} + + /** Like IndexOf(), but case insensitive. */ + int IndexOfIgnoreCase(char ch, uint32 f) const {return ToLowerCase().IndexOf((char)tolower(ch),f);} + + /** Like LastIndexOf(), but case insensitive. */ + int LastIndexOfIgnoreCase(const String &s) const {return ToLowerCase().LastIndexOf(s.ToLowerCase());} + + /** Like LastIndexOf(), but case insensitive. */ + int LastIndexOfIgnoreCase(const String &s, uint32 f) const {return ToLowerCase().LastIndexOf(s.ToLowerCase(),f);} + + /** Like LastIndexOf(), but case insensitive. */ + int LastIndexOfIgnoreCase(char ch) const {return ToLowerCase().LastIndexOf((char)tolower(ch));} + + /** Like LastIndexOf(), but case insensitive. */ + int LastIndexOfIgnoreCase(char ch, uint32 f) const {return ToLowerCase().LastIndexOf((char)tolower(ch),f);} + + /** Like EndsWith(), but case insensitive. */ + bool StartsWithIgnoreCase(char c) const {return (_length > 0)&&(tolower(_buffer[0]) == tolower(c));} + + /** Like StartsWith(), but case insensitive. */ + bool StartsWithIgnoreCase(const String &s) const {return ToLowerCase().StartsWith(s.ToLowerCase());} + + /** Like StartsWith(), but case insensitive. */ + bool StartsWithIgnoreCase(const String &s, uint32 o) const {return ToLowerCase().StartsWith(s.ToLowerCase(),o);} + + /** Returns a hash code for this string */ + inline uint32 HashCode() const {return CStringHashFunc(Cstr());} + + /** Replaces all instances of (oldChar) in this string with (newChar). + * @param replaceMe The character to search for. + * @param withMe The character to replace all occurrences of (replaceMe) with. + * @returns The number of characters that were successfully replaced. + */ + uint32 Replace(char replaceMe, char withMe); + + /** Replaces all instances of (replaceMe) in this string with (withMe). + * @param replaceMe The substring to search for. + * @param withMe The substring to replace all occurrences of (replaceMe) with. + * @returns The number of substrings that were successfully replaced, or -1 + * if the operation failed (out of memory, or (replaceMe) was of length zero) + */ + int32 Replace(const String & replaceMe, const String & withMe); + + /** Reverses the order of all characters in the string, so that e.g. "string" becomes "gnirts" */ + void Reverse(); + + /** Part of the Flattenable interface. + * @return false + */ + virtual bool IsFixedSize() const {return false;} + + /** Part of the Flattenable interface. + * @return B_STRING_TYPE + */ + virtual uint32 TypeCode() const {return B_STRING_TYPE;} + + /** Part of the Flattenable interface. + * @return Length()+1 (the +1 is for the terminating NUL byte) + */ + virtual uint32 FlattenedSize() const; + + /** Part of the Flattenable interface. Flattens our string into (buffer). + * @param buffer A byte array to receive the flattened version of this string. + * There must be at least FlattenedSize() bytes available in this array. + * The clever secret here is that a flattened String is just a C-style + * null-terminated character array, and can be used interchangably as such. + */ + virtual void Flatten(uint8 *buffer) const; + + /** Unflattens a String from (buf). + * @param buf an array of (size) bytes. + * @param size the number of bytes in (buf). + * @return B_NO_ERROR (never fails!) + */ + virtual status_t Unflatten(const uint8 *buf, uint32 size); + + /** Makes sure that we have pre-allocated enough space for a NUL-terminated string + * at least (numChars) bytes long (not including the NUL byte). + * If not, this method will try to allocate the space. + * @param numChars How much space to pre-allocate, in ASCII characters. + * @returns B_NO_ERROR on success, or B_ERROR on failure (out of memory). + */ + status_t Prealloc(uint32 numChars) {return EnsureBufferSize(numChars+1, true);} + + /** Returns a string like this string, but with the appropriate %# tokens + * replaced with a textual representation of the values passed in as (value). + * For example, String("%1 is a %2").Arg(13).Arg("bakers dozen") would return + * the string "13 is a bakers dozen". + * @param value The value to replace in the string. + * @param fmt The format parameter to pass to sprintf(). Note that if you supply your + * own format string, you'll need to be careful since a badly chosen format + * string could lead to a crash or out-of-bounds memory overwrite. In particular, + * the format string should match the type specified, and should not lead to + * more than 256 bytes being written. + * @returns a new String with the appropriate tokens replaced. + */ + String Arg(int8 value, const char * fmt = "%i") const; + + /** As above, but for uint8 values. */ + String Arg(uint8 value, const char * fmt = "%u") const; + + /** As above, but for int16 values. */ + String Arg(int16 value, const char * fmt = "%i") const; + + /** As above, but for uint16 values. */ + String Arg(uint16 value, const char * fmt = "%u") const; + + /** As above, but for int32 values. */ + String Arg(int32 value, const char * fmt = "%li") const; + + /** As above, but for uint32 values. */ + String Arg(uint32 value, const char * fmt = "%lu") const; + + /** As above, but for int64 values. */ + String Arg(int64 value, const char * fmt = INT64_FORMAT_SPEC) const; + + /** As above, but for uint64 values. */ + String Arg(uint64 value, const char * fmt = UINT64_FORMAT_SPEC) const; + + /** As above, but for double values. */ + String Arg(double value, const char * fmt = "%f") const; + + /** As above, but for string values. */ + String Arg(const String & value) const; + String Arg(const char * value) const; + +private: + bool IsSpaceChar(char c) const {return ((c==' ')||(c=='\t')||(c=='\r')||(c=='\n'));} + status_t EnsureBufferSize(uint32 newBufLen, bool retainValue); + String ArgAux(const char * buf) const; + + char _smallBuffer[SMALL_MUSCLE_STRING_LENGTH+1]; // store very small strings in-line, to avoid dynamic allocation + char * _buffer; // Stores the chars. May point at (_smallBuffer), or a dynamically allocated buffer + uint32 _bufferLen; // Number of bytes pointed to by (_buffer) + uint32 _length; // cached strlen(_buffer) + + void VerifyIndex(uint32 index) const + { +#ifdef MUSCLE_AVOID_ASSERTIONS + (void) index; // avoid compiler warnings +#else + MASSERT(index < _length, "Index Out Of Bounds Exception"); +#endif + } +}; + +/** Convenience method: returns a string with no characters in it (a.k.a. "") */ +const String & GetEmptyString(); + +template class HashFunctor; + +template <> +class HashFunctor +{ +public: + uint32 operator () (const String & x) const {return CStringHashFunc(x());} +}; + +template <> +class HashFunctor +{ +public: + uint32 operator () (const char * x) const {return CStringHashFunc(x);} +}; + +/** A function for comparing (const String &)'s -- calls the String operators */ +int StringCompareFunc(const String &, const String &, void *); + +/** A function for comparing (const char *)'s -- calls strcmp() */ +int CStringCompareFunc(const char * const &, const char * const &, void *); + +inline String operator+(const String & lhs, const String &rhs) {String ret(lhs); ret += rhs; return ret;} +inline String operator+(const String & lhs, const char *rhs) {String ret(lhs); ret += rhs; return ret;} +inline String operator+(const char * lhs, const String & rhs) {String ret(lhs); ret += rhs; return ret;} +inline String operator+(const String & lhs, char rhs) {String ret(lhs); ret += rhs; return ret;} +inline String operator-(const String & lhs, const String &rhs) {String ret(lhs); ret -= rhs; return ret;} +inline String operator-(const String & lhs, const char *rhs) {String ret(lhs); ret -= rhs; return ret;} +inline String operator-(const char *lhs, const String &rhs) {String ret(lhs); ret -= rhs; return ret;} +inline String operator-(const String & lhs, char rhs) {String ret(lhs); ret -= rhs; return ret;} + +END_NAMESPACE(muscle); + +#endif diff --git a/library/libfunky/include/Colors.h b/library/libfunky/include/Colors.h new file mode 100644 index 0000000..42a582f --- /dev/null +++ b/library/libfunky/include/Colors.h @@ -0,0 +1,53 @@ +//Useful until be gets around to making these sorts of things +//globals akin to be_plain_font, etc. + + +#ifndef _SGB_COLORS_H_ +#define _SGB_COLORS_H_ + + +//****************************************************************************************************** +//**** SYSTEM HEADER FILES +//****************************************************************************************************** +#include + + +//****************************************************************************************************** +//**** CONSTANT DEFINITIONS +//****************************************************************************************************** +//Be standard UI colors +const rgb_color BeBackgroundGrey = {216,216,216, 255}; +const rgb_color BeInactiveControlGrey = {240,240,240, 255}; +const rgb_color BeFocusBlue = {0, 0, 229, 255}; +const rgb_color BeHighlight = {255,255,255, 255}; +const rgb_color BeShadow = {152,152,152, 255}; +const rgb_color BeDarkShadow = {108,108,108, 255}; +const rgb_color BeLightShadow = {194,194,194, 255}; +const rgb_color BeButtonGrey = {232,232,232, 255}; +const rgb_color BeInactiveGrey = {127,127,127, 255}; +const rgb_color BeListSelectGrey = {178,178,178, 255}; +const rgb_color BeTitleBarYellow = {255,203,0, 255}; + +//Other colors +const rgb_color Black = {0, 0, 0, 255}; +const rgb_color White = {255,255,255, 255}; +const rgb_color Red = {255,0, 0, 255}; +const rgb_color Green = {0, 167,0, 255}; +const rgb_color LightGreen = {90, 240,90, 255}; +const rgb_color Blue = {49, 61, 225, 255}; +const rgb_color LightBlue = {64, 162,255, 255}; +const rgb_color Purple = {144,64, 221, 255}; +const rgb_color LightPurple = {166,74, 255, 255}; +const rgb_color Lavender = {193,122,255, 255}; +const rgb_color Yellow = {255,203,0, 255}; +const rgb_color Orange = {255,163,0, 255}; +const rgb_color Flesh = {255,231,186, 255}; +const rgb_color Tan = {208,182,121, 255}; +const rgb_color Brown = {154,110,45, 255}; +const rgb_color Grey = {200,200,200, 255}; +const rgb_color LightMetallicBlue = {143,166,240, 255}; +const rgb_color MedMetallicBlue = {75, 96, 154, 255}; +const rgb_color DarkMetallicBlue = {78, 89, 126, 255}; + + +#endif diff --git a/library/libfunky/include/ImageCache.h b/library/libfunky/include/ImageCache.h new file mode 100644 index 0000000..47c28d1 --- /dev/null +++ b/library/libfunky/include/ImageCache.h @@ -0,0 +1,52 @@ +#ifndef ImageCache_H +#define ImageCache_H + + /** + * ImageCache. + * @author Andrea Anzani. + */ + +class BBitmap; + +#include +#include +#include "KeyMap.h" + +class ImageCache +{ + +protected: // Constructor/Destructor + + ImageCache(); + + ~ImageCache(); + +public: // Operations + + /** Returns the image corresponding to the which constant */ + static BBitmap * GetImage( BString which ,BString name); + + + static void AddImage(BString name,BBitmap* which); + static void DeleteImage(BString name); + + /** Frees the singleton instance of the cache; + Call this when app quits + */ + static void Release(); + +private: + + static BBitmap * LoadImage( const char *resourceName,const char *); + // Class Data + + static ImageCache * m_instance; + +private: // Instance Data + + + KeyMap m_bitmaps; + +}; + +#endif /* __C_ImageCache_H__ */ diff --git a/library/libfunky/include/KeyMap.h b/library/libfunky/include/KeyMap.h new file mode 100644 index 0000000..0406536 --- /dev/null +++ b/library/libfunky/include/KeyMap.h @@ -0,0 +1,207 @@ +#ifndef __Keymap_h__ +#define __Keymap_h__ + +#include +#include + +using namespace std; + +template +class KeyMap +{ +public: + + bool AddItem( T1 const & key, T2 const & value); + bool RemoveItemFor( T1 const & key); + + T2 ValueFor(T1 key,bool* found = NULL); + T2 ValueAt(int32 position); + + T1 KeyAt(int32 position); + void RemoveItemAt(int32 position); + + uint32 CountItems(); + + void PrintToStream(); + bool MakeEmpty(); + bool IsEmpty(); + +private: + + bool getValue( T1 const & key, T2 *value); //returns value + bool getIndex( T2 const & value, T1 *key ); //returns key + + bool getFirst( T1 *key, T2 *value ); + bool getNext( T1 *key, T2 *value ); + + typename std::map::iterator begin(); + typename std::map::iterator end(); + + std::map m_Map; + typename std::map::iterator m_pPos; +}; + +template +bool KeyMap::AddItem( T1 const & key, T2 const & value) +{ + + std::pair::iterator,bool> result = m_Map.insert( make_pair(key, value) ); + if (!result.second) { + return false; + } + + return true; +} + +template +bool KeyMap::RemoveItemFor( T1 const & key ) +{ + m_Map.erase( key ); + return true; +} + +template +bool KeyMap::IsEmpty() +{ + return m_Map.empty(); +} + + +template +bool KeyMap::MakeEmpty() +{ + m_Map.clear(); + return true; +} + + + +template +bool KeyMap::getIndex( T2 const & value, T1 *key ) +{ + //do something with all elements having a certain value + typename std::map::iterator pos; + for (pos = m_Map.begin(); pos != m_Map.end(); ++pos) { + if (pos->second == value) { + *key = (pos->first); + return true; + } + } + return false; +} + +template +bool KeyMap::getFirst( T1 *key, T2 *value ) +{ + if (m_Map.empty() ) { + return false; + } + //do something with all elements having a certain value + typename std::map::iterator pos; + m_pPos= m_Map.begin(); + *key = m_pPos->first; + *value= m_pPos->second; + return true; +} + +template +bool KeyMap::getNext( T1 *key, T2 *value ) +{ + if ( m_Map.empty() ) { + return false; + } + if ( ++m_pPos == m_Map.end() ) { + return false; + } + *key = m_pPos->first; + *value= m_pPos->second; + return true; +} + +template +bool KeyMap::getValue(T1 const & key, T2 *value) +{ + typename std::map::iterator pos; + pos = m_Map.find(key); + if (m_Map.end() != pos) { + *value = pos->second; + return true; + } + return false; +} + +template +T2 KeyMap::ValueFor(T1 key, bool* found) +{ + T2 pointer; + if (found) + { + *found = getValue(key, &pointer); + return ((*found) ? pointer : NULL); + } + bool f = getValue(key, &pointer); + return (f ? pointer : NULL); +} + +template +T2 KeyMap::ValueAt(int32 position) +{ + typename std::map::iterator i = begin(); + std::advance(i, position); + if(i == end()) + return NULL; + else + return i->second; +} + +template +T1 KeyMap::KeyAt(int32 position) +{ + typename std::map::iterator i = begin(); + std::advance(i, position); + if(i == end()) + return NULL; + else + return i->first; +} + +template +void KeyMap::RemoveItemAt(int32 position) +{ + typename std::map::iterator i = begin(); + std::advance(i, position); + RemoveItemFor(i->first); +} + + +template +uint32 KeyMap::CountItems() +{ + return m_Map.size(); +} + +template +void KeyMap::PrintToStream() +{ + typename std::map::iterator pos; + cout << std::endl << " -- KeyMap::PrintToStream --" << std::endl; + for (pos = m_Map.begin(); pos != m_Map.end(); ++pos) { + cout << pos->first <<" : " << pos->second << std::endl; + } +} + +template +typename std::map::iterator KeyMap::begin() +{ + m_pPos = m_Map.begin(); + return m_pPos; +} + +template +typename std::map::iterator KeyMap::end() +{ + m_pPos = m_Map.end(); + return m_pPos; +} + +#endif // __Keymap_h__ diff --git a/library/libfunky/include/ObjectList.h b/library/libfunky/include/ObjectList.h new file mode 100644 index 0000000..bfa1832 --- /dev/null +++ b/library/libfunky/include/ObjectList.h @@ -0,0 +1,866 @@ +/* +Open Tracker License + +Terms and Conditions + +Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice applies to all licensees +and shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Be Incorporated shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from Be Incorporated. + +Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks +of Be Incorporated in the United States and other countries. Other brand product +names are registered trademarks or trademarks of their respective holders. +All rights reserved. +*/ + +/**************************************************************************** +** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ** +** ** +** DANGER, WILL ROBINSON! ** +** ** +** The interfaces contained here are part of BeOS's ** +** ** +** >> PRIVATE NOT FOR PUBLIC USE << ** +** ** +** implementation. ** +** ** +** These interfaces WILL CHANGE in future releases. ** +** If you use them, your app WILL BREAK at some future time. ** +** ** +** (And yes, this does mean that binaries built from OpenTracker will not ** +** be compatible with some future releases of the OS. When that happens, ** +** we will provide an updated version of this file to keep compatibility.) ** +** ** +** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ** +****************************************************************************/ + +// +// ObjectList is a wrapper around BList that adds type safety, +// optional object ownership, search, insert operations, etc. +// + +#ifndef __OBJECT_LIST__ +#define __OBJECT_LIST__ + +#ifndef _BE_H +#include +#endif + +#include + + +template class BObjectList; + +template +struct UnaryPredicate { + + virtual int operator()(const T *) const + // virtual could be avoided here if FindBinaryInsertionIndex, + // etc. were member template functions + { return 0; } + +private: + static int _unary_predicate_glue(const void *item, void *context); + +friend class BObjectList; +}; + +template +int +UnaryPredicate::_unary_predicate_glue(const void *item, void *context) +{ + return ((UnaryPredicate *)context)->operator()((const T *)item); +} + + +class _PointerList_ : public BList { +public: + _PointerList_(const _PointerList_ &list); + _PointerList_(int32 itemsPerBlock = 20, bool owning = false); + ~_PointerList_(); + + typedef void *(* GenericEachFunction)(void *, void *); + typedef int (* GenericCompareFunction)(const void *, const void *); + typedef int (* GenericCompareFunctionWithState)(const void *, const void *, + void *); + typedef int (* UnaryPredicateGlue)(const void *, void *); + + void *EachElement(GenericEachFunction, void *); + void SortItems(GenericCompareFunction); + void SortItems(GenericCompareFunctionWithState, void *state); + void HSortItems(GenericCompareFunction); + void HSortItems(GenericCompareFunctionWithState, void *state); + + void *BinarySearch(const void *, GenericCompareFunction) const; + void *BinarySearch(const void *, GenericCompareFunctionWithState, void *state) const; + + int32 BinarySearchIndex(const void *, GenericCompareFunction) const; + int32 BinarySearchIndex(const void *, GenericCompareFunctionWithState, void *state) const; + int32 BinarySearchIndexByPredicate(const void *, UnaryPredicateGlue) const; + + bool Owning() const; + bool ReplaceItem(int32, void *); + +protected: + bool owning; + +}; + +template +class BObjectList : private _PointerList_ { +public: + + // iteration and sorting + typedef T *(* EachFunction)(T *, void *); + typedef const T *(* ConstEachFunction)(const T *, void *); + typedef int (* CompareFunction)(const T *, const T *); + typedef int (* CompareFunctionWithState)(const T *, const T *, void *state); + + BObjectList(int32 itemsPerBlock = 20, bool owning = false); + BObjectList(const BObjectList &list); + // clones list; if list is owning, makes copies of all + // the items + + virtual ~BObjectList(); + + BObjectList &operator=(const BObjectList &list); + // clones list; if list is owning, makes copies of all + // the items + + // adding and removing + // ToDo: + // change Add calls to return const item + bool AddItem(T *); + bool AddItem(T *, int32); + bool AddList(BObjectList *); + bool AddList(BObjectList *, int32); + + bool RemoveItem(T *, bool deleteIfOwning = true); + // if owning, deletes the removed item + T *RemoveItemAt(int32); + // returns the removed item + + void MakeEmpty(bool deleteIfOwning = true); + + // item access + T *ItemAt(int32) const; + + bool ReplaceItem(int32 index, T *); + // if list is owning, deletes the item at first + T *SwapWithItem(int32 index, T *newItem); + // same as ReplaceItem, except does not delete old item at , + // returns it instead + + T *FirstItem() const; + T *LastItem() const; + + // misc. getters + int32 IndexOf(const T *) const; + bool HasItem(const T *) const; + bool IsEmpty() const; + int32 CountItems() const; + + T *EachElement(EachFunction, void *); + const T *EachElement(ConstEachFunction, void *) const; + + void SortItems(CompareFunction); + void SortItems(CompareFunctionWithState, void *state); + void HSortItems(CompareFunction); + void HSortItems(CompareFunctionWithState, void *state); + + // linear search, returns first item that matches predicate + const T *FindIf(const UnaryPredicate &) const; + T *FindIf(const UnaryPredicate &); + + // list must be sorted with CompareFunction for these to work + T *BinarySearch(const T &, CompareFunction) const; + T *BinarySearch(const T &, CompareFunctionWithState, void *state) const; + + template + T *BinarySearchByKey(const Key &key, int (*compare)(const Key *, const T *)) + const; + + template + T *BinarySearchByKey(const Key &key, + int (*compare)(const Key *, const T *, void *), void *state) const; + + int32 BinarySearchIndex(const T &item, CompareFunction compare) const; + int32 BinarySearchIndex(const T &item, CompareFunctionWithState compare, + void *state) const; + + template + int32 BinarySearchIndexByKey(const Key &key, + int (*compare)(const Key *, const T *)) const; + + // Binary insertion - list must be sorted with CompareFunction for + // these to work + + // simple insert + bool BinaryInsert(T *, CompareFunction); + bool BinaryInsert(T *, CompareFunctionWithState, void *state); + bool BinaryInsert(T *, const UnaryPredicate &); + + // unique insert, returns false if item already in list + bool BinaryInsertUnique(T *, CompareFunction); + bool BinaryInsertUnique(T *, CompareFunctionWithState, void *state); + bool BinaryInsertUnique(T *, const UnaryPredicate &); + + // insert a copy of the item, returns new inserted item + T *BinaryInsertCopy(const T ©This, CompareFunction); + T *BinaryInsertCopy(const T ©This, CompareFunctionWithState, void *state); + + // insert a copy of the item if not in list already + // returns new inserted item or existing item in case of a conflict + T *BinaryInsertCopyUnique(const T ©This, CompareFunction); + T *BinaryInsertCopyUnique(const T ©This, CompareFunctionWithState, void *state); + + int32 FindBinaryInsertionIndex(const UnaryPredicate &, bool *alreadyInList = 0) const; + // returns either the index into which a new item should be inserted + // or index of an existing item that matches the predicate + + // deprecated API, will go away + BList *AsBList() + { return this; } + const BList *AsBList() const + { return this; } +private: + void SetItem(int32, T *); +}; + +template +Result +WhileEachListItem(BObjectList *list, Result (Item::*func)(Param1), Param1 p1) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (list->ItemAt(index)->*func)(p1)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (*func)(Item *, Param1), Param1 p1) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (*func)(list->ItemAt(index), p1)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (Item::*func)(Param1, Param2), + Param1 p1, Param2 p2) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (list->ItemAt(index)->*func)(p1, p2)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (*func)(Item *, Param1, Param2), + Param1 p1, Param2 p2) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (*func)(list->ItemAt(index), p1, p2)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (*func)(Item *, Param1, Param2, + Param3, Param4), Param1 p1, Param2 p2, Param3 p3, Param4 p4) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (*func)(list->ItemAt(index), p1, p2, p3, p4)) != 0) + break; + + return result; +} + +template +void +EachListItemIgnoreResult(BObjectList *list, Result (Item::*func)()) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (list->ItemAt(index)->*func)(); +} + +template +void +EachListItem(BObjectList *list, void (*func)(Item *, Param1), Param1 p1) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1); +} + +template +void +EachListItem(BObjectList *list, void (Item::*func)(Param1, Param2), + Param1 p1, Param2 p2) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (list->ItemAt(index)->*func)(p1, p2); +} + +template +void +EachListItem(BObjectList *list, void (*func)(Item *,Param1, Param2), + Param1 p1, Param2 p2) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1, p2); +} + +template +void +EachListItem(BObjectList *list, void (*func)(Item *,Param1, Param2, + Param3), Param1 p1, Param2 p2, Param3 p3) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1, p2, p3); +} + + +template +void +EachListItem(BObjectList *list, void (*func)(Item *,Param1, Param2, + Param3, Param4), Param1 p1, Param2 p2, Param3 p3, Param4 p4) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1, p2, p3, p4); +} + +// inline code + +inline bool +_PointerList_::Owning() const +{ + return owning; +} + +template +BObjectList::BObjectList(int32 itemsPerBlock, bool owning) + : _PointerList_(itemsPerBlock, owning) +{ +} + +template +BObjectList::BObjectList(const BObjectList &list) + : _PointerList_(list) +{ + owning = list.owning; + if (owning) { + // make our own copies in an owning list + int32 count = list.CountItems(); + for (int32 index = 0; index < count; index++) { + T *item = list.ItemAt(index); + if (item) + item = new T(*item); + SetItem(index, item); + } + } +} + +template +BObjectList::~BObjectList() +{ + if (Owning()) + // have to nuke elements first + MakeEmpty(); +} + +template +BObjectList & +BObjectList::operator=(const BObjectList &list) +{ + owning = list.owning; + BObjectList &result = (BObjectList &)_PointerList_::operator=(list); + if (owning) { + // make our own copies in an owning list + int32 count = list.CountItems(); + for (int32 index = 0; index < count; index++) { + T *item = list.ItemAt(index); + if (item) + item = new T(*item); + SetItem(index, item); + } + } + return result; +} + +template +bool +BObjectList::AddItem(T *item) +{ + // need to cast to void * to make T work for const pointers + return _PointerList_::AddItem((void *)item); +} + +template +bool +BObjectList::AddItem(T *item, int32 atIndex) +{ + return _PointerList_::AddItem((void *)item, atIndex); +} + +template +bool +BObjectList::AddList(BObjectList *newItems) +{ + return _PointerList_::AddList(newItems); +} + +template +bool +BObjectList::AddList(BObjectList *newItems, int32 atIndex) +{ + return _PointerList_::AddList(newItems, atIndex); +} + + +template +bool +BObjectList::RemoveItem(T *item, bool deleteIfOwning) +{ + bool result = _PointerList_::RemoveItem((void *)item); + + if (result && Owning() && deleteIfOwning) + delete item; + + return result; +} + +template +T * +BObjectList::RemoveItemAt(int32 index) +{ + return (T *)_PointerList_::RemoveItem(index); +} + +template +inline T * +BObjectList::ItemAt(int32 index) const +{ + return (T *)_PointerList_::ItemAt(index); +} + +template +bool +BObjectList::ReplaceItem(int32 index, T *item) +{ + if (owning) + delete ItemAt(index); + return _PointerList_::ReplaceItem(index, (void *)item); +} + +template +T * +BObjectList::SwapWithItem(int32 index, T *newItem) +{ + T *result = ItemAt(index); + _PointerList_::ReplaceItem(index, (void *)newItem); + return result; +} + +template +void +BObjectList::SetItem(int32 index, T *newItem) +{ + _PointerList_::ReplaceItem(index, (void *)newItem); +} + +template +int32 +BObjectList::IndexOf(const T *item) const +{ + return _PointerList_::IndexOf((void *)item); +} + +template +T * +BObjectList::FirstItem() const +{ + return (T *)_PointerList_::FirstItem(); +} + +template +T * +BObjectList::LastItem() const +{ + return (T *)_PointerList_::LastItem(); +} + +template +bool +BObjectList::HasItem(const T *item) const +{ + return _PointerList_::HasItem((void *)item); +} + +template +bool +BObjectList::IsEmpty() const +{ + return _PointerList_::IsEmpty(); +} + +template +int32 +BObjectList::CountItems() const +{ + return _PointerList_::CountItems(); +} + +template +void +BObjectList::MakeEmpty(bool deleteIfOwning) +{ + if (owning && deleteIfOwning) { + int32 count = CountItems(); + for (int32 index = 0; index < count; index++) + delete ItemAt(index); + } + _PointerList_::MakeEmpty(); +} + +template +T * +BObjectList::EachElement(EachFunction func, void *params) +{ + return (T *)_PointerList_::EachElement((GenericEachFunction)func, params); +} + + +template +const T * +BObjectList::EachElement(ConstEachFunction func, void *params) const +{ + return (const T *) + const_cast *>(this)->_PointerList_::EachElement( + (GenericEachFunction)func, params); +} + +template +const T * +BObjectList::FindIf(const UnaryPredicate &predicate) const +{ + int32 count = CountItems(); + for (int32 index = 0; index < count; index++) + if (predicate.operator()(ItemAt(index)) == 0) + return ItemAt(index); + return 0; +} + +template +T * +BObjectList::FindIf(const UnaryPredicate &predicate) +{ + int32 count = CountItems(); + for (int32 index = 0; index < count; index++) + if (predicate.operator()(ItemAt(index)) == 0) + return ItemAt(index); + return 0; +} + + +template +void +BObjectList::SortItems(CompareFunction function) +{ + _PointerList_::SortItems((GenericCompareFunction)function); +} + +template +void +BObjectList::SortItems(CompareFunctionWithState function, void *state) +{ + _PointerList_::SortItems((GenericCompareFunctionWithState)function, state); +} + +template +void +BObjectList::HSortItems(CompareFunction function) +{ + _PointerList_::HSortItems((GenericCompareFunction)function); +} + +template +void +BObjectList::HSortItems(CompareFunctionWithState function, void *state) +{ + _PointerList_::HSortItems((GenericCompareFunctionWithState)function, state); +} + +template +T * +BObjectList::BinarySearch(const T &key, CompareFunction func) const +{ + return (T*)_PointerList_::BinarySearch(&key, + (GenericCompareFunction)func); +} + +template +T * +BObjectList::BinarySearch(const T &key, CompareFunctionWithState func, void *state) const +{ + return (T*)_PointerList_::BinarySearch(&key, + (GenericCompareFunctionWithState)func, state); +} + + +template +template +T * +BObjectList::BinarySearchByKey(const Key &key, + int (*compare)(const Key *, const T *)) const +{ + return (T*)_PointerList_::BinarySearch(&key, + (GenericCompareFunction)compare); +} + + +template +template +T * +BObjectList::BinarySearchByKey(const Key &key, + int (*compare)(const Key *, const T *, void *), void *state) const +{ + return (T*)_PointerList_::BinarySearch(&key, + (GenericCompareFunctionWithState)compare, state); +} + + +template +int32 +BObjectList::BinarySearchIndex(const T &item, CompareFunction compare) const +{ + return _PointerList_::BinarySearchIndex(&item, + (GenericCompareFunction)compare); +} + + +template +int32 +BObjectList::BinarySearchIndex(const T &item, + CompareFunctionWithState compare, void *state) const +{ + return _PointerList_::BinarySearchIndex(&item, + (GenericCompareFunctionWithState)compare, state); +} + + +template +template +int32 +BObjectList::BinarySearchIndexByKey(const Key &key, + int (*compare)(const Key *, const T *)) const +{ + return _PointerList_::BinarySearchIndex(&key, + (GenericCompareFunction)compare); +} + + +template +bool +BObjectList::BinaryInsert(T *item, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunction)func); + if (index >= 0) { + // already in list, add after existing + return AddItem(item, index + 1); + } + + return AddItem(item, -index - 1); +} + +template +bool +BObjectList::BinaryInsert(T *item, CompareFunctionWithState func, void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunctionWithState)func, state); + if (index >= 0) { + // already in list, add after existing + return AddItem(item, index + 1); + } + + return AddItem(item, -index - 1); +} + +template +bool +BObjectList::BinaryInsertUnique(T *item, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunction)func); + if (index >= 0) + return false; + + return AddItem(item, -index - 1); +} + +template +bool +BObjectList::BinaryInsertUnique(T *item, CompareFunctionWithState func, void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunctionWithState)func, state); + if (index >= 0) + return false; + + return AddItem(item, -index - 1); +} + + +template +T * +BObjectList::BinaryInsertCopy(const T ©This, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunction)func); + + if (index >= 0) + index++; + else + index = -index - 1; + + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +T * +BObjectList::BinaryInsertCopy(const T ©This, CompareFunctionWithState func, void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunctionWithState)func, state); + + if (index >= 0) + index++; + else + index = -index - 1; + + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +T * +BObjectList::BinaryInsertCopyUnique(const T ©This, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunction)func); + if (index >= 0) + return ItemAt(index); + + index = -index - 1; + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +T * +BObjectList::BinaryInsertCopyUnique(const T ©This, CompareFunctionWithState func, + void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunctionWithState)func, state); + if (index >= 0) + return ItemAt(index); + + index = -index - 1; + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +int32 +BObjectList::FindBinaryInsertionIndex(const UnaryPredicate &pred, bool *alreadyInList) + const +{ + int32 index = _PointerList_::BinarySearchIndexByPredicate(&pred, + (UnaryPredicateGlue)&UnaryPredicate::_unary_predicate_glue); + + if (alreadyInList) + *alreadyInList = index >= 0; + + if (index < 0) + index = -index - 1; + + return index; +} + +template +bool +BObjectList::BinaryInsert(T *item, const UnaryPredicate &pred) +{ + return AddItem(item, FindBinaryInsertionIndex(pred)); +} + +template +bool +BObjectList::BinaryInsertUnique(T *item, const UnaryPredicate &pred) +{ + bool alreadyInList; + int32 index = FindBinaryInsertionIndex(pred, &alreadyInList); + if (alreadyInList) + return false; + + AddItem(item, index); + return true; +} + +#endif /* __OBJECT_LIST__ */ diff --git a/library/libfunky/include/PBox.h b/library/libfunky/include/PBox.h new file mode 100644 index 0000000..b5710db --- /dev/null +++ b/library/libfunky/include/PBox.h @@ -0,0 +1,59 @@ +#ifndef PBox_H +#define PBox_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ObjectList.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +class BBox; +class BButton; + +class PBox : public BBox { + enum { + LISTCHANGED, + SAVE, + REVERT + }; + + public: + + PBox(BRect rect,BMessage fTemplate, BMessage fData,const char* settings_name); + + void AttachedToWindow(); + virtual void MessageReceived(BMessage *msg); + + void GetData(BMessage* data); + + const char* GetSettingsName(){ return fSName.String();} + private: + + float BuildGUI(BMessage viewTemplate, BMessage settings,BView *view); + + BView *fView; + + BView* fPrefView; + + BMessage fTemplate; + BMessage fData; + float fFontHeight; + BString fSName; + +}; + +#endif diff --git a/library/libfunky/include/Setting.h b/library/libfunky/include/Setting.h new file mode 100644 index 0000000..2debf94 --- /dev/null +++ b/library/libfunky/include/Setting.h @@ -0,0 +1,24 @@ +#ifndef Setting_H_ +#define Setting_H_ + +#include +#include + +class Setting : public BMessage { + + public: + + Setting(const char* name); + + void Store(); + void Retrive(); + + BString SettingPath(); + + private: + BString filename; +}; + +#endif + +//.. diff --git a/library/libfunky/include/SettingsTextView.h b/library/libfunky/include/SettingsTextView.h new file mode 100644 index 0000000..d16b54b --- /dev/null +++ b/library/libfunky/include/SettingsTextView.h @@ -0,0 +1,25 @@ +#ifndef SettingsTextView_H_ +#define SettingsTextView_H_ + +#include +#include +#include + + +class SettingsTextView : public BView +{ + public: + SettingsTextView(BRect frame, char *name, BString testo); + void AttachedToWindow(); + void Draw(BRect updateRect); + void SetText(const char*text){fText.SetTo(text);}; + BString Text(){ return fText; } + private: + BString fText; + + + + +}; + +#endif diff --git a/library/libfunky/include/Utils.h b/library/libfunky/include/Utils.h new file mode 100644 index 0000000..e8fbac0 --- /dev/null +++ b/library/libfunky/include/Utils.h @@ -0,0 +1,39 @@ +#ifndef _Utils_H_ +#define _Utils_H_ + +#include +#include +#include +#include + + +BString GetAppRelativePath(); +BString GetAppFilename(); +bool CheckMIME(BString mime,BNode* node); + +BBitmap* LoadIcon(const char* name); +void AddIcon(const char* name,BBitmap*); + + + +status_t ReadAttributeData(BNode* node,const char *name, char **buffer, int32 *size); + +status_t ReadAttributeString(BNode* node,const char *name, char **buffer, int32 *size); +BString ReadAttributeString(BNode* node,const char *name); + +status_t ReadAttributeInt32(BNode* node,const char *name, int32 *dest); +int32 ReadAttributeInt32(BNode* node,const char *name); + +status_t WriteAttributeInt32(BNode* node,const char *name, int32 dest); +status_t WriteAttributeString(BNode* node,const char *name, const char* string); + +status_t WriteAttributeMessage(BNode* node,const char* name,BMessage*); +status_t ReadAttributeMessage(BNode* node,const char* name,BMessage*); + +BString ReadableSize(off_t bytes); +BString ReadableSpeed(float speed); + +void BPDrawString(const char* string, BView* parent, BRect rect,alignment ali,float kTextMargin = 0.0); + + +#endif diff --git a/library/librunview/Jamfile b/library/librunview/Jamfile new file mode 100644 index 0000000..bb763d6 --- /dev/null +++ b/library/librunview/Jamfile @@ -0,0 +1,30 @@ + +SubDir TOP librunview ; + +if $(OSPLAT) = X86 { + C++FLAGS += -Wno-sign-compare -Wno-overloaded-virtual ; +} + + +SAVED_DEFINES = $(DEFINES) ; + +DEFINES = $(SAVED_DEFINES) ; + +SubDirSysHdrs /boot/home/config/include ; +SubDirSysHdrs $(TOP)/librunview/include ; +SubDirSysHdrs /boot/beos/etc/develop/zeta-r1-gcc2-x86/headers/be/locale ; + + +LINKFLAGS += -L/boot/home/config/lib ; +LINKFLAGS += -L$(TOP)/libs ; +LINKFLAGS += -L/boot/develop/headers/be ; + +# +StaticLibrary librunview.a : + RunView.cpp + Theme.cpp + URLCrunch.cpp + Utilities.cpp + ; +# + diff --git a/library/librunview/NormalTextRender.h b/library/librunview/NormalTextRender.h new file mode 100644 index 0000000..52d92da --- /dev/null +++ b/library/librunview/NormalTextRender.h @@ -0,0 +1,42 @@ +#ifndef _NormalTextRender_H_ +#define _NormalTextRender_H_ + +#include "TextRender.h" +#include +#include + +#include + +class NormalTextRender : public TextRender +{ + public: + + NormalTextRender(BFont f):TextRender(){ + font=f; + } + + ~NormalTextRender() {}; + + void Render(BView *target,const char* txt,int16 num,BPoint pos,BRect drawRect) { + + target->SetFont(&font); + target->DrawString(txt,num,pos); + + + }; + + + float Size(float maxwidth){ return font.Size();} + + void GetHeight(font_height *height){ font.GetHeight(height); }; + + + void GetEscapements(const char charArray[], int32 numChars,float escapementArray[]){ + font.GetEscapements(charArray,numChars,escapementArray); + } + + private: + BFont font; + +}; +#endif diff --git a/library/librunview/ObjectList.h b/library/librunview/ObjectList.h new file mode 100644 index 0000000..bfa1832 --- /dev/null +++ b/library/librunview/ObjectList.h @@ -0,0 +1,866 @@ +/* +Open Tracker License + +Terms and Conditions + +Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice applies to all licensees +and shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Be Incorporated shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from Be Incorporated. + +Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks +of Be Incorporated in the United States and other countries. Other brand product +names are registered trademarks or trademarks of their respective holders. +All rights reserved. +*/ + +/**************************************************************************** +** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ** +** ** +** DANGER, WILL ROBINSON! ** +** ** +** The interfaces contained here are part of BeOS's ** +** ** +** >> PRIVATE NOT FOR PUBLIC USE << ** +** ** +** implementation. ** +** ** +** These interfaces WILL CHANGE in future releases. ** +** If you use them, your app WILL BREAK at some future time. ** +** ** +** (And yes, this does mean that binaries built from OpenTracker will not ** +** be compatible with some future releases of the OS. When that happens, ** +** we will provide an updated version of this file to keep compatibility.) ** +** ** +** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ** +****************************************************************************/ + +// +// ObjectList is a wrapper around BList that adds type safety, +// optional object ownership, search, insert operations, etc. +// + +#ifndef __OBJECT_LIST__ +#define __OBJECT_LIST__ + +#ifndef _BE_H +#include +#endif + +#include + + +template class BObjectList; + +template +struct UnaryPredicate { + + virtual int operator()(const T *) const + // virtual could be avoided here if FindBinaryInsertionIndex, + // etc. were member template functions + { return 0; } + +private: + static int _unary_predicate_glue(const void *item, void *context); + +friend class BObjectList; +}; + +template +int +UnaryPredicate::_unary_predicate_glue(const void *item, void *context) +{ + return ((UnaryPredicate *)context)->operator()((const T *)item); +} + + +class _PointerList_ : public BList { +public: + _PointerList_(const _PointerList_ &list); + _PointerList_(int32 itemsPerBlock = 20, bool owning = false); + ~_PointerList_(); + + typedef void *(* GenericEachFunction)(void *, void *); + typedef int (* GenericCompareFunction)(const void *, const void *); + typedef int (* GenericCompareFunctionWithState)(const void *, const void *, + void *); + typedef int (* UnaryPredicateGlue)(const void *, void *); + + void *EachElement(GenericEachFunction, void *); + void SortItems(GenericCompareFunction); + void SortItems(GenericCompareFunctionWithState, void *state); + void HSortItems(GenericCompareFunction); + void HSortItems(GenericCompareFunctionWithState, void *state); + + void *BinarySearch(const void *, GenericCompareFunction) const; + void *BinarySearch(const void *, GenericCompareFunctionWithState, void *state) const; + + int32 BinarySearchIndex(const void *, GenericCompareFunction) const; + int32 BinarySearchIndex(const void *, GenericCompareFunctionWithState, void *state) const; + int32 BinarySearchIndexByPredicate(const void *, UnaryPredicateGlue) const; + + bool Owning() const; + bool ReplaceItem(int32, void *); + +protected: + bool owning; + +}; + +template +class BObjectList : private _PointerList_ { +public: + + // iteration and sorting + typedef T *(* EachFunction)(T *, void *); + typedef const T *(* ConstEachFunction)(const T *, void *); + typedef int (* CompareFunction)(const T *, const T *); + typedef int (* CompareFunctionWithState)(const T *, const T *, void *state); + + BObjectList(int32 itemsPerBlock = 20, bool owning = false); + BObjectList(const BObjectList &list); + // clones list; if list is owning, makes copies of all + // the items + + virtual ~BObjectList(); + + BObjectList &operator=(const BObjectList &list); + // clones list; if list is owning, makes copies of all + // the items + + // adding and removing + // ToDo: + // change Add calls to return const item + bool AddItem(T *); + bool AddItem(T *, int32); + bool AddList(BObjectList *); + bool AddList(BObjectList *, int32); + + bool RemoveItem(T *, bool deleteIfOwning = true); + // if owning, deletes the removed item + T *RemoveItemAt(int32); + // returns the removed item + + void MakeEmpty(bool deleteIfOwning = true); + + // item access + T *ItemAt(int32) const; + + bool ReplaceItem(int32 index, T *); + // if list is owning, deletes the item at first + T *SwapWithItem(int32 index, T *newItem); + // same as ReplaceItem, except does not delete old item at , + // returns it instead + + T *FirstItem() const; + T *LastItem() const; + + // misc. getters + int32 IndexOf(const T *) const; + bool HasItem(const T *) const; + bool IsEmpty() const; + int32 CountItems() const; + + T *EachElement(EachFunction, void *); + const T *EachElement(ConstEachFunction, void *) const; + + void SortItems(CompareFunction); + void SortItems(CompareFunctionWithState, void *state); + void HSortItems(CompareFunction); + void HSortItems(CompareFunctionWithState, void *state); + + // linear search, returns first item that matches predicate + const T *FindIf(const UnaryPredicate &) const; + T *FindIf(const UnaryPredicate &); + + // list must be sorted with CompareFunction for these to work + T *BinarySearch(const T &, CompareFunction) const; + T *BinarySearch(const T &, CompareFunctionWithState, void *state) const; + + template + T *BinarySearchByKey(const Key &key, int (*compare)(const Key *, const T *)) + const; + + template + T *BinarySearchByKey(const Key &key, + int (*compare)(const Key *, const T *, void *), void *state) const; + + int32 BinarySearchIndex(const T &item, CompareFunction compare) const; + int32 BinarySearchIndex(const T &item, CompareFunctionWithState compare, + void *state) const; + + template + int32 BinarySearchIndexByKey(const Key &key, + int (*compare)(const Key *, const T *)) const; + + // Binary insertion - list must be sorted with CompareFunction for + // these to work + + // simple insert + bool BinaryInsert(T *, CompareFunction); + bool BinaryInsert(T *, CompareFunctionWithState, void *state); + bool BinaryInsert(T *, const UnaryPredicate &); + + // unique insert, returns false if item already in list + bool BinaryInsertUnique(T *, CompareFunction); + bool BinaryInsertUnique(T *, CompareFunctionWithState, void *state); + bool BinaryInsertUnique(T *, const UnaryPredicate &); + + // insert a copy of the item, returns new inserted item + T *BinaryInsertCopy(const T ©This, CompareFunction); + T *BinaryInsertCopy(const T ©This, CompareFunctionWithState, void *state); + + // insert a copy of the item if not in list already + // returns new inserted item or existing item in case of a conflict + T *BinaryInsertCopyUnique(const T ©This, CompareFunction); + T *BinaryInsertCopyUnique(const T ©This, CompareFunctionWithState, void *state); + + int32 FindBinaryInsertionIndex(const UnaryPredicate &, bool *alreadyInList = 0) const; + // returns either the index into which a new item should be inserted + // or index of an existing item that matches the predicate + + // deprecated API, will go away + BList *AsBList() + { return this; } + const BList *AsBList() const + { return this; } +private: + void SetItem(int32, T *); +}; + +template +Result +WhileEachListItem(BObjectList *list, Result (Item::*func)(Param1), Param1 p1) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (list->ItemAt(index)->*func)(p1)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (*func)(Item *, Param1), Param1 p1) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (*func)(list->ItemAt(index), p1)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (Item::*func)(Param1, Param2), + Param1 p1, Param2 p2) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (list->ItemAt(index)->*func)(p1, p2)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (*func)(Item *, Param1, Param2), + Param1 p1, Param2 p2) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (*func)(list->ItemAt(index), p1, p2)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (*func)(Item *, Param1, Param2, + Param3, Param4), Param1 p1, Param2 p2, Param3 p3, Param4 p4) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (*func)(list->ItemAt(index), p1, p2, p3, p4)) != 0) + break; + + return result; +} + +template +void +EachListItemIgnoreResult(BObjectList *list, Result (Item::*func)()) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (list->ItemAt(index)->*func)(); +} + +template +void +EachListItem(BObjectList *list, void (*func)(Item *, Param1), Param1 p1) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1); +} + +template +void +EachListItem(BObjectList *list, void (Item::*func)(Param1, Param2), + Param1 p1, Param2 p2) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (list->ItemAt(index)->*func)(p1, p2); +} + +template +void +EachListItem(BObjectList *list, void (*func)(Item *,Param1, Param2), + Param1 p1, Param2 p2) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1, p2); +} + +template +void +EachListItem(BObjectList *list, void (*func)(Item *,Param1, Param2, + Param3), Param1 p1, Param2 p2, Param3 p3) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1, p2, p3); +} + + +template +void +EachListItem(BObjectList *list, void (*func)(Item *,Param1, Param2, + Param3, Param4), Param1 p1, Param2 p2, Param3 p3, Param4 p4) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1, p2, p3, p4); +} + +// inline code + +inline bool +_PointerList_::Owning() const +{ + return owning; +} + +template +BObjectList::BObjectList(int32 itemsPerBlock, bool owning) + : _PointerList_(itemsPerBlock, owning) +{ +} + +template +BObjectList::BObjectList(const BObjectList &list) + : _PointerList_(list) +{ + owning = list.owning; + if (owning) { + // make our own copies in an owning list + int32 count = list.CountItems(); + for (int32 index = 0; index < count; index++) { + T *item = list.ItemAt(index); + if (item) + item = new T(*item); + SetItem(index, item); + } + } +} + +template +BObjectList::~BObjectList() +{ + if (Owning()) + // have to nuke elements first + MakeEmpty(); +} + +template +BObjectList & +BObjectList::operator=(const BObjectList &list) +{ + owning = list.owning; + BObjectList &result = (BObjectList &)_PointerList_::operator=(list); + if (owning) { + // make our own copies in an owning list + int32 count = list.CountItems(); + for (int32 index = 0; index < count; index++) { + T *item = list.ItemAt(index); + if (item) + item = new T(*item); + SetItem(index, item); + } + } + return result; +} + +template +bool +BObjectList::AddItem(T *item) +{ + // need to cast to void * to make T work for const pointers + return _PointerList_::AddItem((void *)item); +} + +template +bool +BObjectList::AddItem(T *item, int32 atIndex) +{ + return _PointerList_::AddItem((void *)item, atIndex); +} + +template +bool +BObjectList::AddList(BObjectList *newItems) +{ + return _PointerList_::AddList(newItems); +} + +template +bool +BObjectList::AddList(BObjectList *newItems, int32 atIndex) +{ + return _PointerList_::AddList(newItems, atIndex); +} + + +template +bool +BObjectList::RemoveItem(T *item, bool deleteIfOwning) +{ + bool result = _PointerList_::RemoveItem((void *)item); + + if (result && Owning() && deleteIfOwning) + delete item; + + return result; +} + +template +T * +BObjectList::RemoveItemAt(int32 index) +{ + return (T *)_PointerList_::RemoveItem(index); +} + +template +inline T * +BObjectList::ItemAt(int32 index) const +{ + return (T *)_PointerList_::ItemAt(index); +} + +template +bool +BObjectList::ReplaceItem(int32 index, T *item) +{ + if (owning) + delete ItemAt(index); + return _PointerList_::ReplaceItem(index, (void *)item); +} + +template +T * +BObjectList::SwapWithItem(int32 index, T *newItem) +{ + T *result = ItemAt(index); + _PointerList_::ReplaceItem(index, (void *)newItem); + return result; +} + +template +void +BObjectList::SetItem(int32 index, T *newItem) +{ + _PointerList_::ReplaceItem(index, (void *)newItem); +} + +template +int32 +BObjectList::IndexOf(const T *item) const +{ + return _PointerList_::IndexOf((void *)item); +} + +template +T * +BObjectList::FirstItem() const +{ + return (T *)_PointerList_::FirstItem(); +} + +template +T * +BObjectList::LastItem() const +{ + return (T *)_PointerList_::LastItem(); +} + +template +bool +BObjectList::HasItem(const T *item) const +{ + return _PointerList_::HasItem((void *)item); +} + +template +bool +BObjectList::IsEmpty() const +{ + return _PointerList_::IsEmpty(); +} + +template +int32 +BObjectList::CountItems() const +{ + return _PointerList_::CountItems(); +} + +template +void +BObjectList::MakeEmpty(bool deleteIfOwning) +{ + if (owning && deleteIfOwning) { + int32 count = CountItems(); + for (int32 index = 0; index < count; index++) + delete ItemAt(index); + } + _PointerList_::MakeEmpty(); +} + +template +T * +BObjectList::EachElement(EachFunction func, void *params) +{ + return (T *)_PointerList_::EachElement((GenericEachFunction)func, params); +} + + +template +const T * +BObjectList::EachElement(ConstEachFunction func, void *params) const +{ + return (const T *) + const_cast *>(this)->_PointerList_::EachElement( + (GenericEachFunction)func, params); +} + +template +const T * +BObjectList::FindIf(const UnaryPredicate &predicate) const +{ + int32 count = CountItems(); + for (int32 index = 0; index < count; index++) + if (predicate.operator()(ItemAt(index)) == 0) + return ItemAt(index); + return 0; +} + +template +T * +BObjectList::FindIf(const UnaryPredicate &predicate) +{ + int32 count = CountItems(); + for (int32 index = 0; index < count; index++) + if (predicate.operator()(ItemAt(index)) == 0) + return ItemAt(index); + return 0; +} + + +template +void +BObjectList::SortItems(CompareFunction function) +{ + _PointerList_::SortItems((GenericCompareFunction)function); +} + +template +void +BObjectList::SortItems(CompareFunctionWithState function, void *state) +{ + _PointerList_::SortItems((GenericCompareFunctionWithState)function, state); +} + +template +void +BObjectList::HSortItems(CompareFunction function) +{ + _PointerList_::HSortItems((GenericCompareFunction)function); +} + +template +void +BObjectList::HSortItems(CompareFunctionWithState function, void *state) +{ + _PointerList_::HSortItems((GenericCompareFunctionWithState)function, state); +} + +template +T * +BObjectList::BinarySearch(const T &key, CompareFunction func) const +{ + return (T*)_PointerList_::BinarySearch(&key, + (GenericCompareFunction)func); +} + +template +T * +BObjectList::BinarySearch(const T &key, CompareFunctionWithState func, void *state) const +{ + return (T*)_PointerList_::BinarySearch(&key, + (GenericCompareFunctionWithState)func, state); +} + + +template +template +T * +BObjectList::BinarySearchByKey(const Key &key, + int (*compare)(const Key *, const T *)) const +{ + return (T*)_PointerList_::BinarySearch(&key, + (GenericCompareFunction)compare); +} + + +template +template +T * +BObjectList::BinarySearchByKey(const Key &key, + int (*compare)(const Key *, const T *, void *), void *state) const +{ + return (T*)_PointerList_::BinarySearch(&key, + (GenericCompareFunctionWithState)compare, state); +} + + +template +int32 +BObjectList::BinarySearchIndex(const T &item, CompareFunction compare) const +{ + return _PointerList_::BinarySearchIndex(&item, + (GenericCompareFunction)compare); +} + + +template +int32 +BObjectList::BinarySearchIndex(const T &item, + CompareFunctionWithState compare, void *state) const +{ + return _PointerList_::BinarySearchIndex(&item, + (GenericCompareFunctionWithState)compare, state); +} + + +template +template +int32 +BObjectList::BinarySearchIndexByKey(const Key &key, + int (*compare)(const Key *, const T *)) const +{ + return _PointerList_::BinarySearchIndex(&key, + (GenericCompareFunction)compare); +} + + +template +bool +BObjectList::BinaryInsert(T *item, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunction)func); + if (index >= 0) { + // already in list, add after existing + return AddItem(item, index + 1); + } + + return AddItem(item, -index - 1); +} + +template +bool +BObjectList::BinaryInsert(T *item, CompareFunctionWithState func, void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunctionWithState)func, state); + if (index >= 0) { + // already in list, add after existing + return AddItem(item, index + 1); + } + + return AddItem(item, -index - 1); +} + +template +bool +BObjectList::BinaryInsertUnique(T *item, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunction)func); + if (index >= 0) + return false; + + return AddItem(item, -index - 1); +} + +template +bool +BObjectList::BinaryInsertUnique(T *item, CompareFunctionWithState func, void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunctionWithState)func, state); + if (index >= 0) + return false; + + return AddItem(item, -index - 1); +} + + +template +T * +BObjectList::BinaryInsertCopy(const T ©This, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunction)func); + + if (index >= 0) + index++; + else + index = -index - 1; + + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +T * +BObjectList::BinaryInsertCopy(const T ©This, CompareFunctionWithState func, void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunctionWithState)func, state); + + if (index >= 0) + index++; + else + index = -index - 1; + + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +T * +BObjectList::BinaryInsertCopyUnique(const T ©This, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunction)func); + if (index >= 0) + return ItemAt(index); + + index = -index - 1; + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +T * +BObjectList::BinaryInsertCopyUnique(const T ©This, CompareFunctionWithState func, + void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunctionWithState)func, state); + if (index >= 0) + return ItemAt(index); + + index = -index - 1; + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +int32 +BObjectList::FindBinaryInsertionIndex(const UnaryPredicate &pred, bool *alreadyInList) + const +{ + int32 index = _PointerList_::BinarySearchIndexByPredicate(&pred, + (UnaryPredicateGlue)&UnaryPredicate::_unary_predicate_glue); + + if (alreadyInList) + *alreadyInList = index >= 0; + + if (index < 0) + index = -index - 1; + + return index; +} + +template +bool +BObjectList::BinaryInsert(T *item, const UnaryPredicate &pred) +{ + return AddItem(item, FindBinaryInsertionIndex(pred)); +} + +template +bool +BObjectList::BinaryInsertUnique(T *item, const UnaryPredicate &pred) +{ + bool alreadyInList; + int32 index = FindBinaryInsertionIndex(pred, &alreadyInList); + if (alreadyInList) + return false; + + AddItem(item, index); + return true; +} + +#endif /* __OBJECT_LIST__ */ diff --git a/library/librunview/RunView.cpp b/library/librunview/RunView.cpp new file mode 100644 index 0000000..3d9f8b6 --- /dev/null +++ b/library/librunview/RunView.cpp @@ -0,0 +1,2842 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Vision. + * + * The Initial Developer of the Original Code is The Vision Team. + * Portions created by The Vision Team are + * Copyright (C) 1999, 2000, 2001 The Vision Team. All Rights + * Reserved. + * + * Contributor(s): Rene Gollent + * Todd Lair + * Alan Ellis + */ + +#define FORE_WHICH 0 +#define BACK_WHICH 1 +#define FONT_WHICH 2 + +#define MARGIN_WIDTH 10.0 +#define MARGIN_INDENT 10.0 + +#define OFFVIEW_TIMER (10000LL) +#define ABS(x) (x * ((x<0) ? -1 : 1)) +#define SOFTBREAK_STEP 5 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ObjectList.h" +#include "Theme.h" +#include "RunView.h" +#include "URLCrunch.h" +#include "Utilities.h" +#include "RVAction.h" + +#ifdef ZETA +#include +#else +#define _T(str) (str) +#endif + +// cursor data for hovering over URLs + +static unsigned char URLCursorData[] = {16,1,2,2, + 0,0,0,0,56,0,36,0,36,0,19,224,18,92,9,42, + 8,1,60,33,76,49,66,121,48,125,12,253,2,0,1,0, + 0,0,0,0,56,0,60,0,60,0,31,224,31,252,15,254, + 15,255,63,255,127,255,127,255,63,255,15,255,3,254,1,248 +}; + +struct SoftBreak +{ + int16 fOffset; + float fHeight; + float fAscent; +}; + +struct URL +{ + int32 fOffset; + int32 fLength; + BString fUrl; + + URL (const char *address, int32 off, int32 len) : + fOffset (off), + fLength (len), + fUrl (address) + { } +}; + +typedef BObjectList urllist; + +struct SoftBreakEnd +{ + int16 fOffset; + + SoftBreakEnd (int16 offset) + : fOffset (offset) + { } +}; + +struct FontColor +{ + int16 fOffset; + // G++ is stupid. We only need 2 bits + // for fWhich, but the compiler has a bug + // and warns us against fWhich == 2 + int16 fWhich : 3; + int16 fIndex : 13; +}; + +struct Line +{ + char *fText; + time_t fStamp; + urllist *fUrls; + int16 *fSpaces; + int16 *fEdges; + FontColor *fFcs; + SoftBreak *fSofties; + float fTop; + float fBottom; + + int16 fLength; + int16 fSpace_count; + int16 fEdge_count; + int16 fFc_count; + int16 fSoftie_size; + int16 fSoftie_used; + + Line ( + const char *buffer, + int16 fLength, + float top, + float width, + Theme *fTheme, + const char *fStamp_format, + int16 fore, + int16 back, + int16 font); + + ~Line (void); + + void Append ( + const char *buffer, + int16 len, + float width, + Theme *fTheme, + int16 fore, + int16 back, + int16 font); + + void FigureSpaces (void); + + void FigureFontColors ( + int16 pos, + int16 fore, + int16 back, + int16 font); + + void FigureEdges ( + Theme *fTheme, + float width); + + void SoftBreaks ( + Theme * fTheme, + float width); + + void AddSoftBreak (SoftBreakEnd , float &, + uint16 &, int16 &, float &, float &, Theme *); + + int16 CountChars (int16 pos, int16 len); + size_t SetStamp (const char *, bool); + + void SelectWord (int16 *, int16 *); +}; + +inline int32 +UTF8_CHAR_LEN (uchar c) +{ + return (((0xE5000000 >> (((c) >> 3) & 0x1E)) & 3) + 1); +} + +RunView::RunView ( + BRect frame, + const char *name, + Theme *theme, + uint32 resizingMode, + uint32 flags) + : BView ( + frame, + name, + resizingMode, + flags | B_WILL_DRAW | B_FRAME_EVENTS), + fScroller (NULL), + fTheme (theme), + fWorking (NULL), + fLine_count (0), + fStamp_format (NULL), + fClipping_name (NULL), + fSp_start (0, 0), + fSp_end (0, 0), + fTracking (0), + fTrack_offset (0, 0), + fOff_view_runner (NULL), + fOff_view_time (0), + fResizedirty (false), + fFontsdirty (false), + fMyPopUp (NULL), + fLastClick (0,0), + fLastClickTime (0), + fIndent(false) +{ + Theme::TimestampFore = C_TIMESTAMP_DUMMY; + Theme::TimestampBack = C_TIMESTAMP_DUMMY; + Theme::TimespaceFore = MAX_COLORS; + Theme::TimespaceBack = MAX_COLORS; + Theme::TimespaceFont = MAX_FONTS; + Theme::TimestampFont = F_TIMESTAMP_DUMMY; + Theme::NormalFore = C_TEXT; + Theme::NormalBack = C_TEXT; + Theme::NormalFont = F_TEXT; + Theme::SelectionBack = C_SELECTION; + + + memset (fLines, 0, sizeof (fLines)); + fURLCursor = new BCursor (URLCursorData); + + fTheme->ReadLock(); + + BView::SetViewColor (B_TRANSPARENT_COLOR); + BView::SetLowColor (fTheme->BackgroundAt (Theme::NormalBack)); + BView::SetHighColor (fTheme->ForegroundAt (Theme::NormalFore)); + + fTheme->ReadUnlock(); + + SetDefaultOpenURLAction(NULL); +} + +RunView::~RunView (void) +{ + for (int16 i = 0; i < fLine_count; ++i) + delete fLines[i]; + + delete fWorking; + delete fURLCursor; + delete [] fStamp_format; + delete [] fClipping_name; +} + +void +RunView::AttachedToWindow (void) +{ + BView::AttachedToWindow(); +#if B_BEOS_VERSION_DANO + SetDoubleBuffering (B_UPDATE_INVALIDATED | B_UPDATE_SCROLLED | B_UPDATE_EXPOSED | B_UPDATE_RESIZED); +#endif + RecalcScrollBar (false); + fTheme->WriteLock(); + fTheme->AddView (this); + fTheme->WriteUnlock(); +} + +void +RunView::DetachedFromWindow (void) +{ + fTheme->WriteLock(); + fTheme->RemoveView (this); + fTheme->WriteUnlock(); +} + +void +RunView::FrameResized (float start_width, float height) +{ + BView::FrameResized (start_width, height); + + if (IsHidden()) + { + fResizedirty = true; + return; + } + ResizeRecalc(); +} + +void +RunView::TargetedByScrollView (BScrollView *s) +{ + fScroller = s; + BView::TargetedByScrollView (fScroller); +} + +void +RunView::Show (void) +{ + if (fFontsdirty) + { + FontChangeRecalc(); + // this effectively does the same thing as resize so if both have changed, only + // do the fonts recalculation + fFontsdirty = false; + fResizedirty = false; + } + else if (fResizedirty) + { + ResizeRecalc(); + fResizedirty = false; + } + BView::Show(); +} + + +void +RunView::Draw (BRect frame) +{ + TextRender *tr=NULL; + + Window()->DisableUpdates(); + Window()->BeginViewTransaction(); + + rgb_color low_color, hi_color, view_color, sel_color, sel_fText; + float height (frame.bottom); + BRect bounds (Bounds()); + BRegion clipper; + bool drawSelection (false); + bool checkSelection (fSp_start != fSp_end); + + clipper.Set (frame); + ConstrainClippingRegion (&clipper); + + fTheme->ReadLock(); + view_color = fTheme->BackgroundAt (Theme::NormalBack); + + sel_color = fTheme->BackgroundAt (Theme::SelectionBack); + if (((sel_color.red + sel_color.blue + sel_color.green) / 3) >= 127) + { + sel_fText.red = sel_fText.green = sel_fText.blue = 0; + sel_fText.alpha = 255; + } + else + { + sel_fText.red = sel_fText.green = sel_fText.blue = sel_fText.alpha = 255; + } + BRect remains; + if (fLine_count == 0) + remains = frame; + else if (frame.bottom >= fLines[fLine_count - 1]->fBottom + 1.0) + remains.Set ( + frame.left, + fLines[fLine_count - 1]->fBottom + 1.0, + frame.right, + frame.bottom); + + if (remains.IsValid()) + { + SetLowColor (view_color); + FillRect (remains, B_SOLID_LOW); + } + + for (int16 i = fLine_count - 1; i >= 0; --i) + { + Line *line (fLines[i]); + if (line->fBottom < frame.top) + break; + + BRect r (bounds.left, line->fTop, bounds.right, line->fBottom); + + if (!frame.Intersects (r)) + continue; + + float indent (ceil (MARGIN_WIDTH / 2.0)); + int16 place (0); + + int16 fore (0); + int16 back (0); + int16 font (0); + + height = line->fTop; + + for (int16 sit = 0; sit < line->fSoftie_used; /*++sit*/sit++) + { + int16 last_len (UTF8_CHAR_LEN (line->fText[line->fSofties[sit].fOffset])); + float left (indent); + float start (0.0); + + // Fill indentation + SetLowColor (view_color); + + SetDrawingMode (B_OP_COPY); + r.Set (0.0, height, indent - 1.0, height + line->fSofties[sit].fHeight - 1.0); + FillRect (r, B_SOLID_LOW); + + if (sit) + { + int16 j (place); + + while (--j >= 0) + if ((start = line->fEdges[j]) != 0) + break; + } + + while (place < line->fSofties[sit].fOffset + last_len) + { + // Get current foreground color and set + while (fore < line->fFc_count) + { + if (line->fFcs[fore].fWhich == FORE_WHICH) + { + if (line->fFcs[fore].fOffset > place) + break; + + hi_color = fTheme->ForegroundAt (line->fFcs[fore].fIndex); + } + + ++fore; + } + + // Get current background color and set + while (back < line->fFc_count) + { + if (line->fFcs[back].fWhich == BACK_WHICH) + { + if (line->fFcs[back].fOffset > place) + break; + + + low_color = fTheme->BackgroundAt (line->fFcs[back].fIndex); + } + + ++back; + } + + // Get current font and set + while (font < line->fFc_count) + { + if (line->fFcs[font].fWhich == FONT_WHICH) + { + if (line->fFcs[font].fOffset > place) + break; + + //const BFont &f (fTheme->FontAt (line->fFcs[font].fIndex)); + tr = fTheme->TextRenderAt (line->fFcs[font].fIndex); + //SetFont (&f); + } + + ++font; + } + + int16 fLength (line->fSofties[sit].fOffset - place + last_len); + + if (fore < line->fFc_count + && line->fFcs[fore].fOffset - place < fLength) + fLength = line->fFcs[fore].fOffset - place; + + if (back < line->fFc_count + && line->fFcs[back].fOffset - place < fLength) + fLength = line->fFcs[back].fOffset - place; + + if (font < line->fFc_count + && line->fFcs[font].fOffset - place < fLength) + fLength = line->fFcs[font].fOffset - place; + + if (checkSelection) + { + // case 1: current line marks beginning of selection + if (i == fSp_start.fLine) + { + // if we're just prior to the selection, clip fLength to only + // draw up to the selection start + if (place + fLength >= fSp_start.fOffset && place < fSp_start.fOffset) + { + fLength = fSp_start.fOffset - place; + drawSelection = false; + } + // we're at the selection, switch drawing color mode + else if (place >= fSp_start.fOffset) + { + if (fSp_end.fLine == fSp_start.fLine) + { + if (place < fSp_end.fOffset) + { + drawSelection = true; + if ((fSp_end.fOffset - place) < fLength) + fLength = fSp_end.fOffset - place; + } + else + drawSelection = false; + } + else + drawSelection = true; + } + else + drawSelection = false; + + } + // case 2: line in between beginning and end of selection, + // highlight entire line + else if (i > fSp_start.fLine && i < fSp_end.fLine) + drawSelection = true; + // case 3: last line of selection, with multiple fLines in between + else if (i == fSp_end.fLine && i != fSp_start.fLine) + { + if (place < (fSp_end.fOffset)) + { + if (fSp_end.fOffset - place < fLength) + fLength = (fSp_end.fOffset - place); + drawSelection = true; + } + else + drawSelection = false; + } + else + drawSelection = false; + } + + if (place + fLength == line->fLength) + --fLength; + + int16 k (place + fLength - 1); + while (line->fEdges[k] == 0) + --k; + + r.Set ( + left, + height, + line->fEdges[k] + indent - start, + height + line->fSofties[sit].fHeight - 1.0); + + SetDrawingMode (B_OP_COPY); + if (drawSelection) + SetLowColor (sel_color); + else + SetLowColor (low_color); + SetHighColor (hi_color); + FillRect (r, B_SOLID_LOW); + + if (drawSelection) + SetHighColor (sel_fText); + + SetDrawingMode (B_OP_OVER); + +// if(tr) + if ( sit >= line->fSoftie_used ) + { + printf("bah. sit is %d and fSoftie_used is %d\n", sit, line->fSoftie_used); + } else + { +// printf("ooh. sit is %d and fSoftie_used is %d\n", sit, line->fSoftie_used); + tr->Render(this, + line->fText + place, + min_c (fLength, line->fLength - place - 1), + BPoint (left, height + line->fSofties[sit].fAscent), + r); + //debug: StrokeLine(BPoint (left, height),BPoint (left, height+2)); + } + +/* DrawString ( + line->fText + place, + min_c (fLength, line->fLength - place - 1), + BPoint (left, height + line->fSofties[sit].fAscent)); +*/ + left = line->fEdges[k] + indent - start; + + if ((place += fLength) + 1 >= line->fLength) + ++place; + } + + BRect margin( + left + 1.0, + height, + bounds.right, // - indent, + height + line->fSofties[sit].fHeight - 1.0); + + if(tr!=NULL) { + + tr->MarginAfterTheText(this,view_color,margin); + /*margin.left = bounds.right-indent; + margin.right = bounds.right; + SetDrawingMode (B_OP_COPY); + //SetLowColor (view_color); + SetLowColor (255,0,0); + FillRect (margin,B_SOLID_LOW); + */ + } + else { + // Margin after fText + SetDrawingMode (B_OP_COPY); + SetLowColor (view_color); + FillRect (margin,B_SOLID_LOW); + } + + height += line->fSofties[sit].fHeight; + + if (sit == 0 && fIndent) + indent += (MARGIN_INDENT / 2.0); + } + } + + fTheme->ReadUnlock(); + Window()->EndViewTransaction(); + Window()->EnableUpdates(); + ConstrainClippingRegion (NULL); +} + +void +RunView::SetViewColor (rgb_color color) +{ + assert (memcmp (&color, &B_TRANSPARENT_COLOR, sizeof (rgb_color)) != 0); + BView::SetViewColor (color); +} + +void +RunView::BuildPopUp (BPoint point) +{ + // This function checks certain criteria (fText is selected, + // TextView is editable, etc) to determine fWhich MenuItems + // to enable and disable + + bool enablecopy (true), + enableselectall (true), + enablelookup (false); + BString querystring (""); + + if (fSp_start == fSp_end) + enablecopy = false; // no selection + + if (!fLine_count) + enableselectall = false; + + if (enablecopy) + { + enablelookup = true; // has a selection less than 32 chars long + GetSelectionText(querystring); + } + + fMyPopUp = new BPopUpMenu ("Context Menu", false, false); + + BMenuItem *item; + + BMessage *lookup; + lookup = new BMessage (M_LOOKUP_WEBSTER); + lookup->AddString ("string", querystring); + item = new BMenuItem(_T("Lookup (Dictionary)"), lookup); + item->SetEnabled (enablelookup); + item->SetTarget(this); + fMyPopUp->AddItem (item); + + lookup = new BMessage (M_LOOKUP_GOOGLE); + lookup->AddString ("string", querystring); + item = new BMenuItem(_T("Lookup (Google)"), lookup); + item->SetEnabled (enablelookup); + item->SetTarget(this); + fMyPopUp->AddItem (item); + + lookup = new BMessage (M_LOOKUP_ACRONYM); + lookup->AddString ("string", querystring); + item = new BMenuItem(_T("Lookup (Acronym Finder)"), lookup); + item->SetEnabled (enablelookup); + item->SetTarget(this); + fMyPopUp->AddItem (item); + + fMyPopUp->AddSeparatorItem(); + BString aurl = GetURL(point); + if(aurl != ""){ + BMessage* url = new BMessage ('cour'); + url->AddString("url",aurl); + item = new BMenuItem(_T("Copy URL"), url); + item->SetEnabled (true); + item->SetTarget (this); + fMyPopUp->AddItem (item); + + url = new BMessage ('opur'); + url->AddString("url",aurl); + item = new BMenuItem(_T("Open URL"), url); + item->SetEnabled (true); + item->SetTarget (this); + fMyPopUp->AddItem (item); + + fMyPopUp->AddSeparatorItem(); + } + + item = new BMenuItem(_T("Copy"), new BMessage (B_COPY), 'C'); + item->SetEnabled (enablecopy); + item->SetTarget (this); + fMyPopUp->AddItem (item); + + item = new BMenuItem(_T("Select All"), new BMessage (B_SELECT_ALL), 'A'); + item->SetEnabled (enableselectall); + item->SetTarget (this); + fMyPopUp->AddItem (item); + + /*fMyPopUp->AddSeparatorItem(); + + item = new BMenuItem(_T("Clear"), new BMessage(M_CLEAR)); + item->SetTarget(this); + fMyPopUp->AddItem(item); + */ + + fMyPopUp->SetFont (be_plain_font); +} + +bool +RunView::CheckClickBounds (const SelectPos &s, const BPoint &point) const +{ + return ((point.x <= fLines[s.fLine]->fEdges[fLines[s.fLine]->fLength - 1]) + && (point.y <= fLines[s.fLine]->fBottom)); +} + +void +RunView::MouseDown (BPoint point) +{ + if (!fLine_count) + return; + + MakeFocus(); + + BMessage *msg (Window()->CurrentMessage()); + uint32 buttons; + uint32 mouseModifiers; + bigtime_t sysTime; + msg->FindInt64 ("when", &sysTime); + uint16 clicks = CheckClickCount (point, fLastClick, sysTime, fLastClickTime, fClickCount) % 3; + msg->FindInt32 ("buttons", reinterpret_cast(&buttons)); + msg->FindInt32 ("modifiers", reinterpret_cast(&mouseModifiers)); + + SelectPos s (PositionAt (point)); + bool inBounds (CheckClickBounds (s, point)); + + if (buttons == B_SECONDARY_MOUSE_BUTTON + && (mouseModifiers & B_SHIFT_KEY) == 0 + && (mouseModifiers & B_COMMAND_KEY) == 0 + && (mouseModifiers & B_CONTROL_KEY) == 0 + && (mouseModifiers & B_OPTION_KEY) == 0 + && (mouseModifiers & B_MENU_KEY) == 0) + { + SelectPos start (s), + end (s); + + // select word + if (inBounds && !IntersectSelection (s,s)) + { + fLines[s.fLine]->SelectWord (&start.fOffset, &end.fOffset); + + Select (start, end); + } + + BuildPopUp(point); + fMyPopUp->Go ( + ConvertToScreen (point), + true, + false); + + delete fMyPopUp; + fMyPopUp = 0; + return; + } + + if (buttons == B_PRIMARY_MOUSE_BUTTON + && (mouseModifiers & B_SHIFT_KEY) == 0 + && (mouseModifiers & B_COMMAND_KEY) == 0 + && (mouseModifiers & B_CONTROL_KEY) == 0 + && (mouseModifiers & B_OPTION_KEY) == 0 + && (mouseModifiers & B_MENU_KEY) == 0) + { + SelectPos start (s), + end (s); + + switch (clicks) + { + case 2: + { + if (inBounds) + { + // select word + fLines[s.fLine]->SelectWord (&start.fOffset, &end.fOffset); + + Select (start, end); + return; + } + } + break; + + case 0: + { + if (inBounds) + { + start.fOffset = 0; + end.fOffset = fLines[s.fLine]->fLength - 1; + Select (start, end); + return; + } + } + break; + + default: + { + if (!inBounds || !IntersectSelection (s, s)) + Select (s,s); + SetMouseEventMask (B_POINTER_EVENTS); + fTracking = 1; + fTrack_offset = s; + return; + } + } + } + else if (buttons == B_PRIMARY_MOUSE_BUTTON + && (mouseModifiers & B_SHIFT_KEY) != 0 + && (mouseModifiers & B_COMMAND_KEY) == 0 + && (mouseModifiers & B_CONTROL_KEY) == 0 + && (mouseModifiers & B_OPTION_KEY) == 0 + && (mouseModifiers & B_MENU_KEY) == 0) + { + if (s.fLine < fSp_start.fLine || s.fOffset < fSp_start.fOffset) + { + Select (s, fSp_end); + fTrack_offset = SelectPos (fSp_end.fLine, (fSp_end.fOffset > 0) ? fSp_end.fOffset - 1 : fSp_end.fOffset); + } + else + { + Select (fSp_start, s); + fTrack_offset = fSp_start; + } + + SetMouseEventMask (B_POINTER_EVENTS); + fTracking = 2; + } +} + +bool +RunView::CheckURL(BPoint point) //by xeD +{ + if (!fLine_count) + return false; + + SelectPos s = PositionAt (point); + + if (!fLines[s.fLine]->fUrls) + { + // if there aren't any URLs in the current line, go back to default + return false; + } + Line *curline (fLines[s.fLine]); + + for (int32 i = 0; i < curline->fUrls->CountItems(); i++) + { + URL *current = curline->fUrls->ItemAt(i); + if ((s.fOffset >= current->fOffset) + && (s.fOffset <= current->fOffset + current->fLength)) + { + return true; + } + } + + return false; +} + +BString +RunView::GetURL(BPoint point){ + if (!fLine_count) + return ""; + + SelectPos s = PositionAt (point); + + if (!fLines[s.fLine]->fUrls) + { + // if there aren't any URLs in the current line, go back to default + return ""; + } + Line *curline (fLines[s.fLine]); + + for (int32 i = 0; i < curline->fUrls->CountItems(); i++) + { + URL *current = curline->fUrls->ItemAt(i); + if ((s.fOffset >= current->fOffset) + && (s.fOffset <= current->fOffset + current->fLength)) + { + + return current->fUrl; + + } + } + + return ""; +} + +void +RunView::CheckURLCursor (BPoint point) +{ + if (CheckURL(point)) + SetViewCursor (fURLCursor); // if there aren't any URLs in the current line, go back to default + else + SetViewCursor (B_CURSOR_SYSTEM_DEFAULT); // no URLs found, set back to default + +} + +void +RunView::MouseMoved (BPoint point, uint32 transit, const BMessage *msg) +{ + if (fTracking == 0 + && fLine_count + && (transit == B_ENTERED_VIEW + || transit == B_INSIDE_VIEW)) + CheckURLCursor (point); + + + if (!fLine_count || fTracking == 0) + { + BView::MouseMoved (point, transit, msg); + return; + } + + switch (transit) + { + case B_ENTERED_VIEW: + if (fOff_view_runner) + { + delete fOff_view_runner; + fOff_view_runner = 0; + } + + if (fTracking == 1 || fTracking == 2) + ExtendTrackingSelect (point); + + break; + + case B_EXITED_VIEW: + if (fTracking == 1 || fTracking == 2) + ShiftTrackingSelect (point, true, OFFVIEW_TIMER); + break; + + case B_OUTSIDE_VIEW: + + if (fTracking == 1 || fTracking == 2) + { + bigtime_t now (system_time()); + + ShiftTrackingSelect ( + point, + false, + max_c (0LL, min_c (OFFVIEW_TIMER, OFFVIEW_TIMER - (now - fOff_view_time)))); + } + break; + + case B_INSIDE_VIEW: + + if ((fTracking == 1) && (fSp_start != fSp_end)) + { + BMessage *drag = new BMessage(B_MIME_DATA); + + // Add originator and action + drag->AddPointer("be:originator", this); + drag->AddInt32("be_actions", B_TRASH_TARGET); + + BString fText; + GetSelectionText (fText); + + // add the text + drag->AddData("text/plain", B_MIME_TYPE, fText.String(), + fText.Length()); + + + BRect frame ( + fLines[fSp_start.fLine]->fEdges[fSp_start.fOffset], + fLines[fSp_start.fLine]->fTop, + fLines[fSp_end.fLine]->fEdges[fSp_end.fOffset], + fLines[fSp_end.fLine]->fBottom); + + if (fSp_start.fLine != fSp_end.fLine) + { + frame.left = 0.0; + frame.right = Bounds().right; + } + // selection lies within the bounds of a line, check + // if it fLines on one of the wrapped subfLines and calculate rectangle + // appropriately + else + { + Line *line (fLines[fSp_start.fLine]); + float left (line->fEdges[fSp_start.fOffset]), + top (line->fTop), + right (line->fEdges[fSp_end.fOffset]), + bottom (line->fBottom); + int top_softie (0), bottom_softie (0); + bool start_found (false); + bool end_found (false); + + if (line->fSoftie_used) + { + if (fSp_start.fOffset < line->fSofties[0].fOffset) + start_found = true; + + if (fSp_end.fOffset < line->fSofties[0].fOffset) + end_found = true; + } + + if (!end_found) + for (int16 sit = 1; sit < line->fSoftie_used; ++sit) + { + if (!start_found && fSp_start.fOffset < line->fSofties[sit].fOffset) + { + left = line->fEdges[fSp_start.fOffset] - + line->fEdges[line->fSofties[sit-1].fOffset]; + + top += (sit) * line->fSofties[sit].fHeight; + top_softie = sit; + start_found = true; + } + + if (fSp_end.fOffset < line->fSofties[sit].fOffset) + { + right = line->fEdges[fSp_end.fOffset] - + line->fEdges[line->fSofties[sit-1].fOffset]; + + bottom = top + (sit - top_softie + 1) * line->fSofties[sit].fHeight; + bottom_softie = sit; + end_found = true; + break; + } + } + if (!end_found) + { + int32 soft_count = (line->fSoftie_used >= 2) ? + line->fSoftie_used - 2 : 0; + right = line->fEdges[line->fLength - 1] - + line->fEdges[line->fSofties[soft_count].fOffset]; + bottom_softie = soft_count - 2; + + } + if (right < left || (bottom_softie - top_softie) > 0) + { + left = 0.0; + right = Bounds().right; + } + + frame.Set (left, top, right, bottom); + frame.OffsetBy (MARGIN_WIDTH / 2.0, 0.0); + } + + if (frame.Height() > Bounds().Height()) + frame = Bounds(); + + DragMessage (drag, frame); + + fTracking = 3; + } + else if (fTracking == 1 || fTracking == 2) + ExtendTrackingSelect (point); + break; + } +} + +void +RunView::MouseUp (BPoint point) +{ + SelectPos s (PositionAt (point)); + bool url_handle (false); + + if (!fLine_count) + { + fTracking = 0; + return; + } + + if (fTracking == 1) + { + Line *curline (fLines[s.fLine]); + if (curline->fUrls) + { + for (int32 i = 0; i < curline->fUrls->CountItems(); i++) + { + URL *current = curline->fUrls->ItemAt(i); + if ((s.fOffset >= current->fOffset) + && (s.fOffset <= current->fOffset + current->fLength)) + { + + LoadURL (current->fUrl.String()); + url_handle = true; + break; + } + } + } + if (!url_handle && s == fTrack_offset) + Select (s, s); + } + + if (fOff_view_runner) + { + delete fOff_view_runner; + fOff_view_runner = 0; + } + + fTracking = 0; + +} + +void +RunView::ExtendTrackingSelect (BPoint point) +{ + SelectPos s (PositionAt (point)); + + if (s.fLine < fTrack_offset.fLine || (s.fLine == fTrack_offset.fLine && s.fOffset < fTrack_offset.fOffset)) + { + Select (s, fTrack_offset); + fTracking = 2; + } + else if (s.fLine > fTrack_offset.fLine || (s.fLine == fTrack_offset.fLine && s.fOffset > fTrack_offset.fOffset)) + { + Select (fTrack_offset, s); + fTracking = 2; + } +} + +void +RunView::ShiftTrackingSelect (BPoint point, bool move, bigtime_t timer) +{ + BRect bounds (Bounds()); + + if (fOff_view_runner) + { + delete fOff_view_runner; + fOff_view_runner = 0; + } + + if (point.y < bounds.top) + { + if (bounds.top > 0.0) + { + float delta (bounds.top - point.y); + + if (fOff_view_runner == 0) + { + BMessage *msg (new BMessage (M_OFFVIEW_SELECTION)); + + msg->AddFloat ("delta", delta); + msg->AddBool ("bottom", false); + msg->AddPoint ("point", point); + + fOff_view_runner = new BMessageRunner ( + BMessenger (this), + msg, + timer == 0LL ? OFFVIEW_TIMER : timer); + + } + + if (move || timer == 0) + { + delta = max_c (ABS (ceil (delta / 2.0)), 10.0); + delta = min_c (delta, Bounds().Height()); + + if (bounds.top - delta < 0.0) + delta = bounds.top; + + ScrollBy (0.0, -delta); + fOff_view_time = system_time(); + } + } + + point.x = 0.0; + point.y = Bounds().top; + ExtendTrackingSelect (point); + } + + if (point.y > bounds.bottom) + { + Line *line (fLines[fLine_count-1]); + if (line + && line->fBottom > bounds.bottom) + { + float delta (point.y - bounds.bottom); + + if (fOff_view_runner == 0) + { + BMessage *msg (new BMessage (M_OFFVIEW_SELECTION)); + + msg->AddFloat ("delta", delta); + msg->AddBool ("bottom", true); + msg->AddPoint ("point", point); + + fOff_view_runner = new BMessageRunner ( + BMessenger (this), + msg, + timer == 0LL ? OFFVIEW_TIMER : timer); + + } + + if (move || timer == 0) + { + delta = max_c (ABS (ceil (delta / 2.0)), 10.0); + delta = min_c (delta, Bounds().Height()); + + if (bounds.bottom + delta > line->fBottom) + delta = line->fBottom - bounds.bottom; + + ScrollBy (0.0, delta); + fOff_view_time = system_time(); + } + } + + point.x = Bounds().right; + point.y = Bounds().bottom; + ExtendTrackingSelect (point); + } + else + ExtendTrackingSelect (point); +} + +void +RunView::MessageReceived (BMessage *msg) +{ + switch (msg->what) + { + + case M_THEME_FOREGROUND_CHANGE: + case M_THEME_BACKGROUND_CHANGE: + if (!IsHidden()) + Invalidate (Bounds()); + break; + + case M_THEME_FONT_CHANGE: + { + Theme *save (fTheme); + + fTheme = NULL; + SetTheme (save); + break; + } + + case B_SELECT_ALL: + SelectAll(); + break; + + case B_COPY: + if (fSp_start != fSp_end + && be_clipboard->Lock()) + { + BString fText; + GetSelectionText (fText); + + be_clipboard->Clear(); + + BMessage *msg (be_clipboard->Data()); + msg->AddData ("text/plain", B_MIME_TYPE, fText.String(), fText.Length()); + + be_clipboard->Commit(); + be_clipboard->Unlock(); + } + break; + case 'cour': //Copy URL + if (be_clipboard->Lock()) + { + BString fText; + msg->FindString("url",&fText); + + BString map; + if(urls.FindString(fText.String(),&map) == B_OK) + fText.SetTo(map); + if(fText.IFindFirst("action:") == 0) return; + + be_clipboard->Clear(); + + BMessage *msgD (be_clipboard->Data()); + msgD->AddData ("text/plain", B_MIME_TYPE, fText.String(), fText.Length()); + + be_clipboard->Commit(); + be_clipboard->Unlock(); + } + break; + case 'opur': //Open URL + { + BString url; + if(msg->FindString("url",&url)==B_OK) + LoadURL(url.String()); + + } + break; + case M_OFFVIEW_SELECTION: + { + BPoint point; + float delta; + bool bottom; + + msg->FindPoint ("point", &point); + msg->FindBool ("bottom", &bottom); + msg->FindFloat ("delta", &delta); + + if (bottom) + point.y = Bounds().bottom + delta; + else + point.y = Bounds().top - delta; + + ShiftTrackingSelect (point, true, OFFVIEW_TIMER); + break; + } + + case M_LOOKUP_WEBSTER: + { + BString lookup; + msg->FindString ("string", &lookup); + lookup = StringToURI (lookup.String()); + lookup.Prepend ("http://www.m-w.com/cgi-bin/dictionary?va="); + LoadURL (lookup.String()); + } + break; + + case M_LOOKUP_GOOGLE: + { + BString lookup; + msg->FindString ("string", &lookup); + lookup = StringToURI (lookup.String()); + lookup.Prepend ("http://www.google.com/search?q="); + LoadURL (lookup.String()); + } + break; + + case M_LOOKUP_ACRONYM: + { + BString lookup; + msg->FindString ("string", &lookup); + lookup = StringToURI (lookup.String()); + lookup.Prepend ("http://www.acronymfinder.com/af-query.asp?String=exact&Acronym="); + lookup.Append ("&Find=Find"); + LoadURL (lookup.String()); + } + break; + + case M_CLEAR: + { + Clear(); + } + break; + + default: + BView::MessageReceived (msg); + } +} + +void +RunView::ResizeRecalc (void) +{ + float width (Bounds().Width() - MARGIN_WIDTH); + int16 fSoftie_size (0), fSoftie_used (0); + SoftBreak *fSofties (NULL); + BRect bounds (Bounds()); + BRegion region; + float top (0.0); + + fTheme->ReadLock(); + for (int16 i = 0; i < fLine_count; ++i) + { + float old_top (fLines[i]->fTop), old_bottom (fLines[i]->fBottom); + if (fSoftie_size < fLines[i]->fSoftie_used) + { + delete [] fSofties; + fSofties = new SoftBreak [fSoftie_size = fLines[i]->fSoftie_size]; + } + + fSoftie_used = fLines[i]->fSoftie_used; + memcpy (fSofties, fLines[i]->fSofties, (fSoftie_used * sizeof (SoftBreak))); + + fLines[i]->fTop = top; + fLines[i]->SoftBreaks (fTheme, width); + top = fLines[i]->fBottom + 1.0; + + BRect r (0.0, fLines[i]->fTop, bounds.right, fLines[i]->fBottom); + + if (bounds.Intersects (r) + && (old_top != fLines[i]->fTop + || old_bottom != fLines[i]->fBottom + || fSoftie_used != fLines[i]->fSoftie_used + || memcmp (fSofties, fLines[i]->fSofties, fSoftie_used * sizeof (SoftBreak)))) + region.Include (r); + } + + fTheme->ReadUnlock(); + + + if (Window()) + { + if (RecalcScrollBar (true)) + Invalidate (Bounds()); + else + { + int32 count (region.CountRects()), j; + + for (j = 0; j < count; ++j) + Invalidate (region.RectAt (j)); + + if (top <= bounds.bottom) + { + BRect r (bounds); + + r.top = top; + Invalidate (r); + } + } + + Window()->Sync(); + } + + if (fWorking) fWorking->fTop = top; + delete [] fSofties; +} + +void +RunView::FontChangeRecalc (void) +{ + float width (Bounds().Width() - MARGIN_WIDTH); + float top (0.0); + + for (int16 i = 0; i < fLine_count; ++i) + { + fLines[i]->fTop = top; + + fLines[i]->FigureSpaces(); + fLines[i]->FigureEdges (fTheme, width); + + top = fLines[i]->fBottom + 1.0; + } + + if (fWorking) + fWorking->fTop = top; + + RecalcScrollBar (false); + if (!IsHidden()) + Invalidate (Bounds()); + if (Window()) Window()->UpdateIfNeeded(); +} + +bool +RunView::RecalcScrollBar (bool constrain) +{ + BScrollBar *bar; + + if (fScroller == NULL + || (bar = fScroller->ScrollBar (B_VERTICAL)) == NULL) + return false; + + float value (bar->Value()); + BRect bounds (Bounds()); + bool changed (false); + float bottom (0.0); + float scrollMin, scrollMax; + + + bar->GetRange (&scrollMin, &scrollMax); + + if (fLine_count) + TextResized(BRect(0,value,0,fLines[fLine_count - 1]->fBottom)); + else + TextResized(BRect(0,0,0,0)); + + + if (fLine_count + && (bounds.Contains (BPoint (0.0, 0.0)) == false + || bounds.Contains (BPoint (0.0, fLines[fLine_count - 1]->fBottom + ExtraTextSize() )) == false)) + { + + bottom = fLines[fLine_count - 1]->fBottom + ExtraTextSize() + 5.0; + bar->SetProportion (bounds.Height() / bottom); + bar->SetSteps (10.0, bounds.Height()); + + bottom -= bounds.Height(); + } + + // We don't want the bar to cause a draw/copybits, so we restrict the + // clipping region to nothing + + if (constrain) + { + BRegion region; + ConstrainClippingRegion (®ion); + } + + if (scrollMax != bottom) + { + bar->SetRange (0.0, bottom); + + if (value == scrollMax || scrollMin == scrollMax) + { + bar->SetValue (bottom); + changed = true; + } + } + + if (constrain) + ConstrainClippingRegion (NULL); + + return changed; +} + +void +RunView::Append ( + const char *buffer, + int16 fore, + int16 back, + int16 font) +{ + Append (buffer, strlen (buffer), fore, back, font); +} + +void +RunView::AppendURL(const char * text,const char *url,int16 font){ + urls.AddString(text,url); + Append(text,C_URL,C_URL,font); +} + +void +RunView::AppendURL(const char * text,const char * url,int16 back,int16 font){ + urls.AddString(text,url); + Append(text,C_URL,back,font); +} + +void +RunView::Append ( + const char *buffer, + int32 len, + int16 fore, + int16 back, + int16 font) +{ + if (buffer == NULL) + return; + float width (Bounds().Width() - 10); + int32 place (0); + + assert (fore != Theme::TimestampFore); + assert (back != Theme::TimestampBack); + assert (font != Theme::TimestampFont); + assert (fore != Theme::TimespaceFore); + assert (back != Theme::TimespaceBack); + assert (font != Theme::TimespaceFont); + assert (back != Theme::SelectionBack); + + fTheme->ReadLock(); + + while (place < len) + { + int32 end (place); + + while (end < len && buffer[end] != '\n') + ++end; + + if (end < len) ++end; + + if (fWorking) + { + + URLCrunch crunch (buffer + place, end - place); + BString temp; + int32 url_offset (0), + last_offset (0); + + + while ((url_offset = crunch.Crunch (&temp)) != B_ERROR) + { + fWorking->Append (buffer + place, + (url_offset - last_offset), + width, + fTheme, + fore, + back, + font); + + fWorking->Append (temp.String(), + temp.Length(), + width, + fTheme, + C_URL, + back, + F_URL); + + place += (url_offset - last_offset) + temp.Length(); + last_offset = url_offset + temp.Length(); + } + + if (place < end) + fWorking->Append ( + buffer + place, + end - place, + width, + fTheme, + fore, + back, + font); + } + else + { + float top (0.0); + + if (fLine_count > 0) + top = fLines[fLine_count - 1]->fBottom + 1.0; + + + fWorking = new Line ( + buffer + place, + 0, + top, + width, + fTheme, + fStamp_format, + fore, + back, + font); + + URLCrunch crunch (buffer + place, end - place); + BString temp; + int32 url_offset (0), + last_offset (0); + + while ((url_offset = crunch.Crunch (&temp)) != B_ERROR) + { + fWorking->Append (buffer + place, + (url_offset - last_offset), + width, + fTheme, + fore, + back, + font); + fWorking->Append (temp.String(), + temp.Length(), + width, + fTheme, + C_URL, + back, + F_URL); + + place += (url_offset - last_offset) + temp.Length(); + last_offset = url_offset + temp.Length(); + } + + if (place < end) + fWorking->Append (buffer + place, + end - place, + width, + fTheme, + fore, + back, + font); + } + + if (fWorking->fLength + && fWorking->fText[fWorking->fLength - 1] == '\n') + { + bool chopped; + + if (Window()) Window()->DisableUpdates(); + + if ((chopped = (fLine_count == LINE_COUNT))) + { + Line *first (fLines[0]); + float shift (first->fBottom + 1); + + for (int16 i = 1; i < LINE_COUNT; ++i) + { + fLines[i]->fTop -= shift; + fLines[i]->fBottom -= shift; + + fLines[i - 1] = fLines[i]; + } + + fWorking->fTop -= shift; + fWorking->fBottom -= shift; + + delete first; + + if (fSp_start.fLine > 0) + fSp_start.fLine--; + else + fSp_start.fOffset = 0; + + if (fSp_end.fLine > 0) + fSp_end.fLine--; + else + fSp_end.fOffset = 0; + + // Recalc the scrollbar so that we have clean drawing + // after the line has been removed + --fLine_count; + RecalcScrollBar (true); + } + + fLines[fLine_count++] = fWorking; + RecalcScrollBar (true); + + Invalidate (Bounds()); + + if (Window()) + { + Window()->EnableUpdates(); + Window()->UpdateIfNeeded(); + } + + fWorking = NULL; + } + + place = end; + } + + fTheme->ReadUnlock(); +} + +void +RunView::Clear (void) +{ + for (int16 i = 0; i < fLine_count; ++i) + delete fLines[i]; + + fLine_count = 0; + RecalcScrollBar (true); + Invalidate(); + + fSp_start.fLine = 0; + fSp_start.fOffset = 0; + fSp_end = fSp_start; + + if (fWorking) + fWorking->fTop = 0.0; + + urls.MakeEmpty(); +} + +int16 +RunView::LineCount (void) const +{ + return fLine_count; +} + +const char * +RunView::LineAt (int16 which) const +{ + if (which < 0 || which >= fLine_count) + return NULL; + + return fLines[which]->fText; +} + +void +RunView::SetTimeStampFormat (const char *format) +{ + if ((format == NULL + && fStamp_format == NULL) + || (format != NULL + && fStamp_format != NULL + && strcmp (format, fStamp_format) == 0)) + return; + + bool was_on (false); + + if (fStamp_format) + { + delete [] fStamp_format; + fStamp_format = NULL; + was_on = true; + } + + if (format) + fStamp_format = strcpy (new char [strlen (format) + 1], format); + + float width (Bounds().Width() - MARGIN_WIDTH); + float top (0.0); + + fTheme->ReadLock(); + for (int16 i = 0; i < fLine_count; ++i) + { + fLines[i]->fTop = top; + + fLines[i]->SetStamp (fStamp_format, was_on); + fLines[i]->FigureSpaces(); + fLines[i]->FigureEdges(fTheme, width); + + top = fLines[i]->fBottom + 1.0; + } + fTheme->ReadUnlock(); + + if (fWorking) + { + fWorking->fTop = top; + fWorking->SetStamp (fStamp_format, was_on); + } + + RecalcScrollBar (false); + Invalidate (Bounds()); + if (Window()) Window()->UpdateIfNeeded(); +} + +void +RunView::SetTheme (Theme *t) +{ + if (t == NULL || fTheme == t) + return; + + fTheme = t; + + if (IsHidden()) + { + fFontsdirty = true; + return; + } + FontChangeRecalc(); +} + +SelectPos +RunView::PositionAt (BPoint point) const +{ + int16 i, lfIndex (0); + SelectPos pos (-1, 0); + + if (fLine_count == 0) + return pos; + + // find the line + for (i = 0; i < fLine_count; ++i) + { + if (fLines[i]->fTop > point.y) + break; + lfIndex = i; + } + + // check to make sure we actually did find a line and not just run into fLine_count + if (fLines[lfIndex]->fBottom < point.y) + { + pos.fLine = fLine_count - 1; + pos.fOffset = fLines[fLine_count - 1]->fLength; + return pos; + } + + float height (fLines[lfIndex]->fTop); + int16 sfIndex (0); + + for (i = 0; i < fLines[lfIndex]->fSoftie_used; ++i) + { + if (height > point.y) + break; + + sfIndex = i; + height += fLines[lfIndex]->fSofties[i].fHeight; + } + + float margin (MARGIN_WIDTH / 2.0); + float width (0); + int16 start (0); + + if (sfIndex) + { + int16 offset (fLines[lfIndex]->fSofties[sfIndex - 1].fOffset); + + width = fLines[lfIndex]->fEdges[offset]; + start = offset + UTF8_CHAR_LEN (fLines[lfIndex]->fText[offset]); + } + + for (i = start; i <= fLines[lfIndex]->fSofties[sfIndex].fOffset; ++i) + if (fLines[lfIndex]->fEdges[i] + margin - width >= point.x) + break; + + pos.fLine = lfIndex; + pos.fOffset = min_c (i, fLines[lfIndex]->fSofties[sfIndex].fOffset); + if (pos.fOffset > 0) pos.fOffset += UTF8_CHAR_LEN (fLines[pos.fLine]->fText[pos.fOffset]); + + return pos; +} + +BPoint +RunView::PointAt (SelectPos s) const +{ + return BPoint(fLines[s.fLine]->fTop + fLines[s.fLine]->fBottom / 2.0, fLines[s.fLine]->fEdges[s.fOffset]); +} + +void +RunView::GetSelectionText (BString &string) const +{ + /* + for (int32 i = 0; i < curline->fUrls->CountItems(); i++) + { + URL *current = curline->fUrls->ItemAt(i); + if ((s.fOffset >= current->fOffset) + && (s.fOffset <= current->fOffset + current->fLength)) + { + SetViewCursor (fURLCursor); + return; + } + } + */ + if (fSp_start == fSp_end) + return; + + if (fSp_start.fLine == fSp_end.fLine) + { + const char *line (LineAt (fSp_start.fLine)); + string.Append (line + fSp_start.fOffset, fSp_end.fOffset - fSp_start.fOffset); + return; + } + + for (int32 i = fSp_start.fLine; i <= fSp_end.fLine; i++) + { + const char *line (LineAt (i)); + if (i == fSp_start.fLine) + { + line += fSp_start.fOffset; + string.Append (line); + } + else if (i == fSp_end.fLine) + { + string.Append (line, fSp_end.fOffset); + break; + } + else + string.Append (line); + } +} + +bool +RunView::IntersectSelection (const SelectPos &start, const SelectPos &end) const +{ + if (fSp_start.fLine == fSp_end.fLine) + { + if (start.fLine == fSp_start.fLine && start.fOffset >= fSp_start.fOffset && start.fOffset < fSp_end.fOffset) + return true; + if (end.fLine == fSp_start.fLine && end.fOffset >= fSp_start.fOffset && end.fOffset < fSp_end.fOffset) + return true; + } + else + { + if (start.fLine > fSp_start.fLine && start.fLine < fSp_end.fLine) + return true; + if (end.fLine > fSp_start.fLine && end.fLine < fSp_end.fLine) + return true; + if (start.fLine == fSp_start.fLine && start.fOffset >= fSp_start.fOffset) + return true; + if (end.fLine == fSp_start.fLine && end.fOffset >= fSp_start.fOffset) + return true; + if (start.fLine == fSp_end.fLine && start.fOffset < fSp_end.fOffset) + return true; + if (end.fLine == fSp_end.fLine && end.fOffset < fSp_end.fOffset) + return true; + } + + return false; +} + +BRect +RunView::GetTextFrame(const SelectPos &start, const SelectPos &end) const +{ + return BRect (0.0, fLines[(start.fLine > 0) ? (start.fLine - 1) : 0]->fTop, + Bounds().Width(), fLines[end.fLine]->fBottom); +} + +void +RunView::Select (const SelectPos &start, const SelectPos &end) +{ + if (fSp_start != fSp_end) + { + if (start == end || !IntersectSelection (start, end)) + { + BRect frame (GetTextFrame (fSp_start, fSp_end)); + + fSp_start = start; + fSp_end = start; + Invalidate (frame); + } + else + { + if (fSp_start.fLine < start.fLine || (fSp_start.fLine == start.fLine && fSp_start.fOffset < start.fOffset)) + { + BRect frame (GetTextFrame (fSp_start, start)); + + fSp_start = start; + Invalidate (frame); + } + + if (end.fLine < fSp_end.fLine || (fSp_end.fLine == end.fLine && end.fOffset < fSp_end.fOffset)) + { + BRect frame (GetTextFrame (end, fSp_end)); + + fSp_end = end; + Invalidate (frame); + } + } + } + + if (fSp_start == fSp_end) + { + fSp_start = start; + fSp_end = end; + + if (fSp_start != fSp_end) + { + BRect frame (GetTextFrame (start, end)); + + Invalidate (frame); + } + } + else // extension + { + if (start.fLine < fSp_start.fLine || (start.fLine == fSp_start.fLine && start.fOffset < fSp_start.fOffset)) + { + BRect frame (GetTextFrame (start, fSp_start)); + + fSp_start = start; + Invalidate (frame); + } + + if (end.fLine > fSp_end.fLine || (end.fLine == fSp_end.fLine && end.fOffset > fSp_end.fOffset)) + { + BRect frame (GetTextFrame (fSp_end, end)); + + fSp_end = end; + Invalidate (frame); + } + } +} + +void +RunView::SelectAll (void) +{ + if (fLine_count) + { + fSp_start = SelectPos (0, 0); + fSp_end = SelectPos (fLine_count-1, fLines[fLine_count-1]->fLength); + Invalidate(Bounds()); + } +} + +void +RunView::SetClippingName (const char *name) +{ + delete [] fClipping_name; + fClipping_name = new char[strlen(name) + 1]; + memcpy (fClipping_name, name, strlen(name)); + fClipping_name[strlen(name)] = '\0'; +} + +Line::Line ( + const char *buffer, + int16 len, + float top, + float width, + Theme *theme, + const char *stamp_format, + int16 fore, + int16 back, + int16 font) + : fText (NULL), + fStamp (time(NULL)), + fUrls (NULL), + fSpaces (NULL), + fEdges (NULL), + fFcs (NULL), + fSofties (NULL), + fTop (top), + fBottom (0.0), + fLength (len), + fSpace_count (0), + fEdge_count (0), + fFc_count (0), + fSoftie_size (0), + fSoftie_used (0) +{ + // Very important to call SetStamp before Append, It would look real funny otherwise! + SetStamp( stamp_format, false ); + + Append( buffer, len, width, theme, fore, back, font ); +} + +Line::~Line (void) +{ + delete [] fSpaces; + delete [] fEdges; + delete [] fFcs; + delete [] fText; + delete [] fSofties; + + if (fUrls) + { + while (fUrls->CountItems() > 0) + delete fUrls->RemoveItemAt(0L); + delete fUrls; + } +} + +void +Line::Append ( + const char *buffer, + int16 len, + float width, + Theme *theme, + int16 fore, + int16 back, + int16 font) +{ + int16 save (fLength); + char *new_fText; + + new_fText = new char [fLength + len + 1]; + + if (fText != NULL) + { + memcpy (new_fText, fText, fLength); + delete [] fText; + } + + memcpy (new_fText + fLength, buffer, len); + fLength += len; + new_fText[fLength] = '\0'; + + // replace Tab chars with spaces. + // todo: This should be temp until RunView can properly + // display tabs. + for( char* pos = new_fText + save; *pos; ++pos ) + { + if( '\t' == *pos ) + { + *pos = ' '; + } + } + + fText = new_fText; + + FigureFontColors (save, fore, back, font); + + if (fore == C_URL) + { + if (!fUrls) + fUrls = new urllist; + fUrls->AddItem (new URL (buffer, save, len)); + } + + if (fText[fLength - 1] == '\n') + { + FigureSpaces(); + FigureEdges (theme, width); + } +} + +void +Line::FigureSpaces (void) +{ + const char spacers[] = " \t\n-\\/"; + const char *buffer (fText); + size_t offset (0), n; + int16 count (0); + + delete [] fSpaces; + fSpace_count = 0; + while ((n = strcspn (buffer + offset, spacers)) < fLength - offset) + { + ++count; + offset += n + 1; + } + + fSpaces = new int16 [count]; + + offset = 0; + while ((n = strcspn (buffer + offset, spacers)) < fLength - offset) + { + fSpaces[fSpace_count++] = n + offset; + offset += n + 1; + } +} + +void +Line::FigureFontColors ( + int16 pos, + int16 fore, + int16 back, + int16 font) +{ + if (fFc_count) + { + int16 last_fore = -1; + int16 last_back = -1; + int16 last_font = -1; + int16 i; + + // we have fFcs, so we backtrack for last of each fWhich + for (i = fFc_count - 1; i >= 0; --i) + { + if (last_fore < 0 + && fFcs[i].fWhich == FORE_WHICH) + last_fore = i; + else if (last_back < 0 + && fFcs[i].fWhich == BACK_WHICH) + last_back = i; + else if (last_font < 0 + && fFcs[i].fWhich == FONT_WHICH) + last_font = i; + + if (last_fore >= 0 + && last_back >= 0 + && last_font >= 0) + break; + } + + // now figure out how many more we need + int16 count = 0; + if (fFcs[last_fore].fIndex != fore) + ++count; + if (fFcs[last_back].fIndex != back) + ++count; + if (fFcs[last_font].fIndex != font) + ++count; + + if (count) + { + FontColor *new_fFcs; + new_fFcs = new FontColor [fFc_count + count]; + memcpy (new_fFcs, fFcs, fFc_count * sizeof (FontColor)); + delete [] fFcs; + fFcs = new_fFcs; + + if (fFcs[last_fore].fIndex != fore) + { + fFcs[fFc_count].fWhich = FORE_WHICH; + fFcs[fFc_count].fOffset = pos; + fFcs[fFc_count].fIndex = fore; + ++fFc_count; + } + + if (fFcs[last_back].fIndex != back) + { + fFcs[fFc_count].fWhich = BACK_WHICH; + fFcs[fFc_count].fOffset = pos; + fFcs[fFc_count].fIndex = back; + ++fFc_count; + } + + if (fFcs[last_font].fIndex != font) + { + fFcs[fFc_count].fWhich = FONT_WHICH; + fFcs[fFc_count].fOffset = pos; + fFcs[fFc_count].fIndex = font; + ++fFc_count; + } + } + } + else + { + fFcs = new FontColor [fFc_count = 3]; + fFcs[0].fWhich = FORE_WHICH; + fFcs[0].fOffset = 0; + fFcs[0].fIndex = fore; + fFcs[1].fWhich = BACK_WHICH; + fFcs[1].fOffset = 0; + fFcs[1].fIndex = back; + fFcs[2].fWhich = FONT_WHICH; + fFcs[2].fOffset = 0; + fFcs[2].fIndex = font; + } +} + +void +Line::FigureEdges ( + Theme *theme, + float width) +{ + delete [] fEdges; + fEdges = new int16 [fLength]; + + int16 cur_fFcs (0), next_fFcs (0), cur_font (0); + + fEdge_count = 0; + while (cur_fFcs < fFc_count) + { + if (fFcs[cur_fFcs].fWhich == FONT_WHICH) + { + cur_font = cur_fFcs; + break; + } + + ++cur_fFcs; + } + + while (cur_fFcs < fFc_count) + { + int16 last_offset (fFcs[cur_fFcs].fOffset); + next_fFcs = cur_fFcs + 1; + + while (next_fFcs < fFc_count) + { + // We want to break at every difference + // but, we want to break on a font if available + if (fFcs[next_fFcs].fOffset > last_offset) + { + while (next_fFcs < fFc_count + && fFcs[next_fFcs].fWhich != FONT_WHICH + && next_fFcs + 1 < fFc_count + && fFcs[next_fFcs + 1].fOffset == fFcs[next_fFcs].fOffset) + ++next_fFcs; + + break; + } + ++next_fFcs; + } + + if (fFcs[cur_fFcs].fWhich == FONT_WHICH) + cur_font = cur_fFcs; + + int16 ccount; + int16 seglen; + + if (next_fFcs == fFc_count) + { + ccount = CountChars (fFcs[cur_fFcs].fOffset, fLength - fFcs[cur_fFcs].fOffset); + seglen = fLength - fFcs[cur_fFcs].fOffset; + } + else + { + ccount = CountChars ( + fFcs[cur_fFcs].fOffset, + fFcs[next_fFcs].fOffset - fFcs[cur_fFcs].fOffset); + seglen = fFcs[next_fFcs].fOffset - fFcs[cur_fFcs].fOffset; + } + + // const BFont &f (theme->FontAt (fFcs[cur_font].fIndex)); + TextRender *tr=theme->TextRenderAt (fFcs[cur_font].fIndex); + +#ifdef __INTEL__ + float eshift[ccount]; +#else + float *eshift = new float[ccount]; +#endif + + /* f.GetEscapements ( + fText + fFcs[cur_fFcs].fOffset, + ccount, + eshift);*/ + +// if(tr) + tr->GetEscapements ( + fText + fFcs[cur_fFcs].fOffset, + ccount, + eshift); + + // This is not perfect, because we are including the left edge, + // but BFont::GetEdges doesn't seem to work as we'd like + + int16 i; + float size=0; + +// if(tr) + size=tr->Size(width); + + + float incrementor = (fEdge_count > 0) ? fEdges[fEdge_count - 1] : 0; + + for (i = 0; i < ccount; ++i) + { + incrementor += eshift[i] * size; + + fEdges[fEdge_count+i] = (int16) incrementor; + + // this little backfTracking routine is necessary in the case where an fFcs change + // comes immediately after a UTF8-char, since all but the first edge will be 0 + // and thus the new edge's starting position will be thrown off if we don't + // backtrack to the beginning of the char + if ((fEdge_count + i > 0) && fEdges[fEdge_count + i - 1] == 0) + { + int32 temp = fEdge_count + i - 1; + while (fEdges[--temp] == 0); + fEdges[fEdge_count + i] += fEdges[temp]; + } + } + + for (i = fFcs[cur_fFcs].fOffset; i < fFcs[cur_fFcs].fOffset + seglen;) + { + int32 len (UTF8_CHAR_LEN (fText[i]) - 1); + + if (len) + { + int16 k; + for (k = fEdge_count + ccount - 1; k > i; --k) + fEdges[k + len] = fEdges[k]; + + for (k = 1; k <= len; ++k) + fEdges[i + k] = 0; + + ccount += len; + } + + i += len + 1; + } + + cur_fFcs = next_fFcs; + fEdge_count += ccount; +#ifndef __INTEL__ + delete [] eshift; +#endif + } + + SoftBreaks (theme, width); +} + + +void +Line::AddSoftBreak (SoftBreakEnd sbe, float &start, uint16 &fText_place, + int16 &font, float &width, float &start_width, Theme *theme) +{ + fText_place = sbe.fOffset; + + if (fSoftie_size < fSoftie_used + 1) + { + SoftBreak *new_softies; + + new_softies = new SoftBreak [fSoftie_size += SOFTBREAK_STEP]; + + if (fSofties) + { + memcpy (new_softies, fSofties, sizeof (SoftBreak) * fSoftie_used); + delete [] fSofties; + } + + fSofties = new_softies; + } + + // consume whitespace + while (fText_place + 1 < fLength + && isspace (fText[fText_place + 1])) + ++fText_place; + + fSofties[fSoftie_used].fOffset = fText_place; + fSofties[fSoftie_used].fHeight = 0.0; + fSofties[fSoftie_used].fAscent = 0.0; + + int16 last (font); + while (font < fFc_count) + { + //const BFont &f (theme->FontAt (fFcs[font].fIndex)); + TextRender *tr=theme->TextRenderAt (fFcs[font].fIndex); + + font_height fh; + float height; + + tr->GetHeight (&fh); + + height = ceil (fh.ascent + fh.descent + fh.leading); + if (fSofties[fSoftie_used].fHeight < height) + fSofties[fSoftie_used].fHeight = height; + if (fSofties[fSoftie_used].fAscent < fh.ascent) + fSofties[fSoftie_used].fAscent = fh.ascent; + + // now try and find next + while (++font < fFc_count) + if (fFcs[font].fWhich == FONT_WHICH) + break; + + if (font == fFc_count + || fFcs[font].fOffset > fText_place) + { + font = last; + break; + } + + last = font; + } + + if (fText_place < fLength) + start = fEdges[fText_place]; + + fBottom += fSofties[fSoftie_used++].fHeight; + fText_place += UTF8_CHAR_LEN (fText[fText_place]); + width = start_width - MARGIN_INDENT; +} + +void +Line::SoftBreaks (Theme *theme, float start_width) +{ + float margin (ceil (MARGIN_WIDTH / 2.0)); + float width (start_width); + float start (0.0); + uint16 fText_place (0); + int16 space_place (0); + int16 font (0); + + fSoftie_used = 0; + fBottom = fTop; + + // find first font + while (font < fFc_count && fFcs[font].fWhich != FONT_WHICH) + ++font; + + while (fText_place < fLength) + { + while (space_place < fSpace_count) + { + if (fEdges[fSpaces[space_place]] - start > width) + break; + + ++space_place; + } + + // we've reached the end of the line (but it might not all fit) + // or we only have one space, so we check if we need to split the word + if (space_place == fSpace_count + || space_place == 0 + || fSpaces[space_place - 1] < fText_place) + { + // everything fits.. how wonderful (but we want at least one softbreak) + if (fEdge_count == 0) + { + AddSoftBreak (SoftBreakEnd(fLength - 1), start, fText_place, font, width, start_width, theme); + break; + } + + int16 i (fEdge_count - 1); + + while (fEdges[i] == 0) + --i; + + if (fEdges[i] - start <= width) + { + AddSoftBreak (SoftBreakEnd(fLength - 1), start, fText_place, font, width, start_width, theme); + continue; + } + + // we force at least one character + // your font may be a little too large for your window! + fText_place += UTF8_CHAR_LEN (fText[fText_place]); + while (fText_place < fLength) + { + if (fEdges[fText_place] - start > width - margin) + break; + + fText_place += UTF8_CHAR_LEN (fText[fText_place]); + } + AddSoftBreak (SoftBreakEnd(fText_place), start, fText_place, font, width, start_width, theme); + continue; + } + + // we encountered more than one space, so we rule out having to + // split the word, if the current word will fit within the bounds + int16 ccount1, ccount2; + --space_place; + + ccount1 = fSpaces[space_place]; + ccount2 = fSpaces[space_place+1] - ccount1; + + int16 i (ccount1 - 1); + while (fEdges[i] == 0) + --i; + + if (fEdges[ccount1 + ccount2] - fEdges[i] < width - margin) + { + AddSoftBreak (SoftBreakEnd(fSpaces[space_place]), start, fText_place, font, width, start_width, theme); + continue; + } + + // We need to break up the really long word + fText_place = fSpaces[space_place]; + while (fText_place < fEdge_count) + { + if ((fEdges[fText_place] - start) > width) + break; + + fText_place += UTF8_CHAR_LEN (fText[fText_place]); + } + } + + fBottom -= 1.0; +} + +int16 +Line::CountChars (int16 pos, int16 len) +{ + int16 ccount (0); + + if (pos >= fLength) + return ccount; + + if (pos + len > fLength) + len = fLength - pos; + + register int16 i = pos; + while (i < pos + len) + { + i += UTF8_CHAR_LEN(fText[i]); + ++ccount; + } + + return ccount; +} + +size_t +Line::SetStamp (const char *format, bool was_on) +{ + size_t size (0); + int32 i (0); + + if (was_on) + { + int16 offset (fFcs[4].fOffset + 1); + + if (fUrls) + { + for (i = 0; i < fUrls->CountItems(); i++) + fUrls->ItemAt(i)->fOffset -= offset; + } + memmove (fText, fText + offset, fLength - offset); + fText[fLength -= offset] = '\0'; + + for (i = 6; i < fFc_count; ++i) + { + fFcs[i].fOffset -= offset; + fFcs[i - 6] = fFcs[i]; + } + + fFc_count -= 6; + } + + if (format) + { + char buffer[1024]; + struct tm curTime; + + localtime_r (&fStamp, &curTime); + size = strftime (buffer, 1023, format, &curTime); + if (fUrls) + { + for (i = 0; i < fUrls->CountItems(); i++) + fUrls->ItemAt(i)->fOffset += size; + } + + char *new_fText; + + new_fText = new char [fLength + size + 2]; + memcpy (new_fText, buffer, size); + new_fText[size++] = ' '; + new_fText[size] = '\0'; + + if (fText) + { + memcpy (new_fText + size, fText, fLength); + delete [] fText; + } + + fText = new_fText; + fText[fLength += size] = '\0'; + + FontColor *new_fFcs; + new_fFcs = new FontColor [fFc_count + 6]; + + if (fFcs) + { + memcpy ( + new_fFcs + 6, + fFcs, + fFc_count * sizeof (FontColor)); + delete [] fFcs; + } + fFcs = new_fFcs; + fFc_count += 6; + + fFcs[0].fWhich = FORE_WHICH; + fFcs[0].fIndex = Theme::TimestampFore; + fFcs[0].fOffset = 0; + fFcs[1].fWhich = BACK_WHICH; + fFcs[1].fIndex = Theme::TimestampBack; + fFcs[1].fOffset = 0; + fFcs[2].fWhich = FONT_WHICH; + fFcs[2].fIndex = Theme::TimestampFont; + fFcs[2].fOffset = 0; + + fFcs[3].fWhich = FORE_WHICH; + fFcs[3].fIndex = Theme::TimespaceFore; + fFcs[3].fOffset = size - 1; + fFcs[4].fWhich = BACK_WHICH; + fFcs[4].fIndex = Theme::TimespaceBack; + fFcs[4].fOffset = size - 1; + fFcs[5].fWhich = FONT_WHICH; + fFcs[5].fIndex = Theme::TimespaceFont; + fFcs[5].fOffset = size - 1; + + for (i = 6; i < fFc_count; ++i) + fFcs[i].fOffset += size; + } + + return size; +} + +void +Line::SelectWord (int16 *start, int16 *end) +{ + int16 start_tmp (*start), end_tmp (*end); + + while(start_tmp > 0 && fText[start_tmp-1] != ' ') + start_tmp--; + + while ((end_tmp - 1) < fLength && fText[end_tmp] != ' ') + end_tmp++; + + while (end_tmp >= fLength) + --end_tmp; + + *start = start_tmp; + *end = end_tmp; +} + +bool +RunView::FindText(const char *text) +{ + bool result (false); + if (text != NULL) + { + for (int32 i = 0; i < fLine_count; i++) + { + char *offset (NULL); + if ((offset = strstr((const char *)fLines[i], text)) != NULL) + { + SelectPos start (i, offset - text), + end (i, (offset - text) + strlen(text)); + Select(start, end); + ScrollTo(0.0, fLines[i]->fTop); + result = true; + break; + } + } + } + return result; +} + +void RunView::LoadURL(const char *url) { + BString argument (url); + + if (argument.FindFirst ("://") == B_ERROR) + { + + if (argument.IFindFirst ("www") == 0) + argument.Prepend ("http://"); + + else if (argument.IFindFirst ("ftp") == 0) + argument.Prepend ("ftp://"); + + else + { //by xeD + BString map; + if(urls.FindString(url,&map) == B_OK) + argument.SetTo(map); + + } + + } + + const char *args[] = { argument.String(), 0 }; + + if (argument.IFindFirst ("file:") == 0) + { + // The URL is guaranteed to be at least "file:/" + BString file(argument.String() + 5); + + // todo: Should probably see if the file exists before going through + // all this, but, oh well... ;) + file.Prepend("/boot/beos/system/Tracker "); + file += " &"; // just in case + + system(file.String()); + } + else if (argument.IFindFirst ("mailto:") == 0) + { + be_roster->Launch ("text/x-email", 1, const_cast(args)); + } + else //by xeD + if (argument.IFindFirst ("action:") == 0) + { + InvokeAction(argument.String()); + } + else + if(fDefaultURLAction){ + //printf("fDefaultURLAction\n"); + fDefaultURLAction->Perform(BString(argument.String())); + } + else{ + //printf("no fDefaultURLAction!\n"); + be_roster->Launch ("text/html", 1, const_cast(args)); + } +} + +void RunView::ScrollToBottom(void) { + if (fLine_count != 0) { + BScrollBar *scroll = fScroller->ScrollBar(B_VERTICAL); + if (scroll != NULL) scroll->SetValue(fLines[fLine_count - 1]->fBottom); + ScrollTo(0.0, fLines[fLine_count - 1]->fBottom); + }; +}; + +void RunView::ScrollToSelection(void) { + if (fLine_count == 0) return; + + if (fSp_start != fSp_end) + ScrollTo(0.0, fLines[fSp_start.fLine]->fTop); + +}; + +//by xed +void +RunView::ClearActions(){ + actions.MakeEmpty(); +} + +void +RunView::AddAction(const char* symbolicName,RVAction* action){ + actions.AddPointer(symbolicName,(void*)action); +} + +void +RunView::SetDefaultOpenURLAction(RVAction* action){ + fDefaultURLAction=action; +} + +RVAction* +RunView::FindAction(const char* symbolicName){ + RVAction* action=NULL; + actions.FindPointer(symbolicName,(void**)&action); + return action; +} + +//should be private.. +void +RunView::InvokeAction(BString mangledName){ + mangledName.RemoveFirst("action://"); + int from = mangledName.FindFirst("("); + + BString actionName; + actionName.SetTo(mangledName,from); + + mangledName.Remove(0,from+1); + int to = mangledName.FindFirst(")"); + + BString param; + param.SetTo(mangledName,to); + + RVAction* action=FindAction(actionName.String()); + if(action) + action->Perform(param); + else + debugger(actionName.String()); +} + +//-- diff --git a/library/librunview/SmileTextRender.h b/library/librunview/SmileTextRender.h new file mode 100644 index 0000000..9e83173 --- /dev/null +++ b/library/librunview/SmileTextRender.h @@ -0,0 +1,66 @@ +#ifndef _SmileTextRender_H_ +#define _SmileTextRender_H_ + +#include "TextRender.h" +#include +#include + +#include +#include +#include +#include + +#include "Emoticor.h" + +extern float gEmoticonSize; + +class SmileTextRender : public TextRender +{ + public: + SmileTextRender():TextRender(){}; + + virtual ~SmileTextRender() {}; + + virtual void Render(BView *target,const char* txt,int16 num,BPoint pos) { + + BBitmap *pointer=NULL; + BString f(txt,num); + + if(emoticor->config->FindPointer(f.String(),(void**)&pointer)==B_OK) + { + target->SetDrawingMode( B_OP_ALPHA ); + target->DrawBitmapAsync( pointer,BPoint(pos.x, pos.y- (gEmoticonSize/2)) ); + target->SetDrawingMode( B_OP_OVER ); + +/* BRect r = pointer->Bounds(); + r.OffsetTo(pos); + r.OffsetBy(0, - (gEmoticonSize/2 + 2) ); + r.InsetBy(-1,-1); + + rgb_color oldCol = target->HighColor(); + target->SetHighColor( 255,0,0 ); + target->StrokeRect( r ); + target->SetHighColor( oldCol ); +*/ + } + }; + + + virtual float Size(){ return gEmoticonSize;} + + virtual void GetHeight(font_height *h) + { + h->ascent=gEmoticonSize/2; + h->descent=gEmoticonSize/2; + h->leading=0; + }; + + virtual void + GetEscapements(const char * /*charArray*/, int32 numChars,float escapementArray[]) + { + //font.GetEscapements(charArray,numChars,escapementArray); + escapementArray[0]=1; + for(int i=1;i +#include +#include +#include +#include +#include + +#include "Theme.h" +#include "NormalTextRender.h" + +int16 Theme::TimestampFore = 0; +int16 Theme::TimestampBack = 0; +int16 Theme::TimestampFont = 0; +int16 Theme::TimespaceFore = 1; +int16 Theme::TimespaceBack = 1; +int16 Theme::TimespaceFont = 1; +int16 Theme::NormalFore = 2; +int16 Theme::NormalBack = 2; +int16 Theme::NormalFont = 2; +int16 Theme::SelectionBack = 3; + +//at least we use a 'normal' text render + + +Theme::Theme ( + const char *n, + int16 foreCount, + int16 backCount, + int16 renderCount) + : name (NULL), + fores (NULL), + backs (NULL), + text_renders (NULL), + fore_count (max_c (foreCount, 4)), + back_count (max_c (backCount, 4)), + render_count (max_c (renderCount, 4)) +{ + name = strcpy (new char [strlen (n) + 1], n); + + fores = new rgb_color [fore_count]; + backs = new rgb_color [back_count]; + + normal_textrender = new NormalTextRender(be_plain_font); + + text_renders = (TextRender**)malloc(render_count*sizeof(TextRender*)); + for ( int i=0; i= fore_count || which < 0) + return color; + + return fores[which]; +} + +const rgb_color +Theme::BackgroundAt (int16 which) const +{ + rgb_color color = {255, 255, 255, 255}; + + if (which >= back_count || which < 0) + return color; + + return backs[which]; +} +/* +const BFont & +Theme::FontAt (int16 which) const +{ + if (which >= font_count || which < 0) + return *be_plain_font; + + return fonts[which]; +} +*/ + +TextRender* +Theme::TextRenderAt (int16 which) +{ + if ( which < 0 ){ + //printf("Theme::TextRenderAt(): which < 0 (%d)\n", which); + return normal_textrender; + } + if ( which >= render_count ){ + //printf("Theme::TextRenderAt(): which >= render_count (%d, %d)\n", which, render_count); + return normal_textrender; + } + + return text_renders[which]; +} + +bool +Theme::SetForeground (int16 which, const rgb_color color) +{ + if (which >= fore_count || which < 0) + return false; + + fores[which] = color; + return true; +} + +bool +Theme::SetBackground (int16 which, const rgb_color color) +{ + if (which >= back_count || which < 0) + return false; + + backs[which] = color; + return true; +} + + +bool +Theme::SetTextRender(int16 which,TextRender *trender) +{ + + + if (which >= render_count || which < 0 || !trender) + return false; + + text_renders[which] = trender; + return true; +} + +void +Theme::AddView (BView *view) +{ + list.AddItem (view); +} + +void +Theme::RemoveView (BView *view) +{ + list.RemoveItem (view); +} + diff --git a/library/librunview/URLCrunch.cpp b/library/librunview/URLCrunch.cpp new file mode 100644 index 0000000..c8aaf7e --- /dev/null +++ b/library/librunview/URLCrunch.cpp @@ -0,0 +1,99 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Vision. + * + * The Initial Developer of the Original Code is The Vision Team. + * Portions created by The Vision Team are + * Copyright (C) 1999, 2000, 2001 The Vision Team. All Rights + * Reserved. + * + * Contributor(s): Rene Gollent + * Todd Lair + */ + +#include + +#include "URLCrunch.h" + +URLCrunch::URLCrunch (const char *data, int32 len) + : buffer (""), + current_pos (0) +{ + buffer.Append (data, len); +} + +URLCrunch::~URLCrunch (void) +{ +} + +int32 +URLCrunch::Crunch (BString *url) +{ + if (current_pos >= buffer.Length()) + return B_ERROR; + + const int32 tagNum = 7; + const char *tags[tagNum] = + { + "http://", + "https://", + "www.", + "ftp://", + "ftp.", + "file:/", + "mailto:" + }; + + int32 marker (buffer.Length()); + int32 pos (current_pos); + int32 url_length (0); + int32 markers[tagNum]; + int32 i(0); + + for (i = 0; i < tagNum; ++i) + markers[i] = buffer.IFindFirst (tags[i], pos); + + for (i = 0; i < tagNum; ++i) + + if (markers[i] != B_ERROR + && markers[i] < marker) + { + url_length = markers[i] + strlen(tags[i]); + + url_length += strcspn (buffer.String() + url_length, " \t\n|\\<>\")(][}{;'*^"); + + + int len (strlen (tags[i])); + + if (url_length - markers[i] > len + && (isdigit (buffer[markers[i] + len]) + || isalpha (buffer[markers[i] + len]))) + { + marker = markers[i]; + pos = url_length + 1; + url_length -= marker; + } + else + pos = markers[i] + 1; + } + + if (marker < buffer.Length()) + { + *url = ""; + + url->Append (buffer.String() + marker, url_length); + } + + current_pos = pos; + + return marker < buffer.Length() ? marker : B_ERROR; +} diff --git a/library/librunview/URLCrunch.h b/library/librunview/URLCrunch.h new file mode 100644 index 0000000..e410e16 --- /dev/null +++ b/library/librunview/URLCrunch.h @@ -0,0 +1,40 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Vision. + * + * The Initial Developer of the Original Code is The Vision Team. + * Portions created by The Vision Team are + * Copyright (C) 1999, 2000, 2001 The Vision Team. All Rights + * Reserved. + * + * Contributor(s): Todd Lair + * + */ + +#ifndef URLCRUNCH_H_ +#define URLCRUNCH_H_ + +#include + +class URLCrunch +{ + BString buffer; + int32 current_pos; + + public: + + URLCrunch (const char *, int32); + ~URLCrunch (void); + int32 Crunch (BString *); +}; + +#endif diff --git a/library/librunview/Utilities.cpp b/library/librunview/Utilities.cpp new file mode 100644 index 0000000..18e6394 --- /dev/null +++ b/library/librunview/Utilities.cpp @@ -0,0 +1,378 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Vision. + * + * The Initial Developer of the Original Code is The Vision Team. + * Portions created by The Vision Team are + * Copyright (C) 1999, 2000, 2001 The Vision Team. All Rights + * Reserved. + * + * Contributor(s): Wade Majors + * Todd Lair + * Andrew Bazan + */ + +#include +#include + +#include +#include +#include +#include +#include + +const float doubleClickThresh = 6; + +BString +GetWord (const char *cData, int32 wordNeeded) +{ + /* + * Function purpose: Get word number {wordNeeded} from {cData} + * (space delimited) + */ + + BString data (cData); + BString buffer ("-9z99"); + int32 wordAt (1), place (0); + + while (wordAt != wordNeeded && place != B_ERROR) + { + if ((place = data.FindFirst ('\x20', place)) != B_ERROR) + if (++place < data.Length() + && data[place] != '\x20') + ++wordAt; + } + + if (wordAt == wordNeeded + && place != B_ERROR + && place < data.Length()) + { + int32 end (data.FindFirst ('\x20', place)); + + if (end == B_ERROR) + end = data.Length(); + + data.CopyInto (buffer, place, end - place); + } + + return buffer; +} + +BString +GetWordColon (const char *cData, int32 wordNeeded) +{ + /* + * Function purpose: Get word number {wordNeeded} from {cData} + * (colon delimited) + */ + + BString data (cData); + BString buffer ("-9z99"); + int32 wordAt (1), place (0); + + while (wordAt != wordNeeded && place != B_ERROR) + { + if ((place = data.FindFirst (':', place)) != B_ERROR) + if (++place < data.Length() + && data[place] != ':') + ++wordAt; + } + + if (wordAt == wordNeeded + && place != B_ERROR + && place < data.Length()) + { + int32 end (data.FindFirst (':', place)); + + if (end == B_ERROR) + end = data.Length(); + + data.CopyInto (buffer, place, end - place); + } + + return buffer; +} + +BString +RestOfString (const char *cData, int32 wordStart) +{ + /* + * Function purpose: Get word number {wordStart} from {cData} + * append the rest of the string after {wordStart} + * (space delimited) + */ + + BString data (cData); + int32 wordAt (1), place (0); + BString buffer ("-9z99"); + + while (wordAt != wordStart && place != B_ERROR) + { + if ((place = data.FindFirst ('\x20', place)) != B_ERROR) + if (++place < data.Length() + && data[place] != '\x20') + ++wordAt; + } + + if (wordAt == wordStart + && place != B_ERROR + && place < data.Length()) + data.CopyInto (buffer, place, data.Length() - place); + + return buffer; +} + +BString +GetNick (const char *cData) +{ + /* + * Function purpose: Get nickname from {cData} + * + * Expected format: nickname!user@host.name + */ + + BString data (cData); + BString theNick; + + for (int32 i = 1; i < data.Length() && data[i] != '!' && data[i] != '\x20'; ++i) + theNick += data[i]; + + return theNick; +} + +BString +GetIdent (const char *cData) +{ + /* + * Function purpose: Get identname/username from {cData} + * + * Expected format: nickname!user@host.name + */ + + BString data (GetWord(cData, 1)); + BString theIdent; + int32 place[2]; + + if ((place[0] = data.FindFirst ('!')) != B_ERROR + && (place[1] = data.FindFirst ('@')) != B_ERROR) + { + ++(place[0]); + data.CopyInto (theIdent, place[0], place[1] - place[0]); + } + + return theIdent; +} + +BString +GetAddress (const char *cData) +{ + /* + * Function purpose: Get address/hostname from {cData} + * + * Expected format: nickname!user@host.name + */ + + BString data (GetWord(cData, 1)); + BString address; + int32 place; + + if ((place = data.FindFirst ('@')) != B_ERROR) + { + int32 length (data.FindFirst ('\x20', place)); + + if (length == B_ERROR) + length = data.Length(); + + ++place; + data.CopyInto (address, place, length - place); + } + + return address; +} + +BString +TimeStamp() +{ + /* + * Function purpose: Return the timestamp string + * + */ + +// if(!vision_app->GetBool ("timestamp")) +// return ""; + +// const char *ts_format (vision_app->GetString ("timestamp_format")); + const char *ts_format = "[%H:%M]"; + + time_t myTime (time (0)); + tm curTime; + localtime_r (&myTime, &curTime); + + char tempTime[32]; + tempTime[strftime (tempTime, 31, ts_format, &curTime)] = '\0'; + + return BString (tempTime).Append('\x20', 1); +} + + +BString +ExpandKeyed ( + const char *incoming, + const char *keys, + const char **expansions) +{ + BString buffer; + + while (incoming && *incoming) + { + if (*incoming == '$') + { + const char *place; + + ++incoming; + + if ((place = strchr (keys, *incoming)) != 0) + buffer += expansions[place - keys]; + else + buffer += *incoming; + } + else + buffer += *incoming; + + ++incoming; + } + + buffer += "\n"; + + return buffer; +} + +BString +StringToURI (const char *string) +{ + /* + * Function purpose: Converts {string} to a URI safe format + * + */ + + BString buffer (string); + buffer.ToLower(); + buffer.ReplaceAll ("%", "%25"); // do this first! + buffer.ReplaceAll ("\n", "%20"); + buffer.ReplaceAll (" ", "%20"); + buffer.ReplaceAll ("\"", "%22"); + buffer.ReplaceAll ("#", "%23"); + buffer.ReplaceAll ("@", "%40"); + buffer.ReplaceAll ("`", "%60"); + buffer.ReplaceAll (":", "%3A"); + buffer.ReplaceAll ("<", "%3C"); + buffer.ReplaceAll (">", "%3E"); + buffer.ReplaceAll ("[", "%5B"); + buffer.ReplaceAll ("\\", "%5C"); + buffer.ReplaceAll ("]", "%5D"); + buffer.ReplaceAll ("^", "%5E"); + buffer.ReplaceAll ("{", "%7B"); + buffer.ReplaceAll ("|", "%7C"); + buffer.ReplaceAll ("}", "%7D"); + buffer.ReplaceAll ("~", "%7E"); + return buffer; +} + +BString +DurationString (int64 value) +{ + /* + * Function purpose: Return a duration string based on {value} + * + */ + + BString duration; + bigtime_t micro = value; + bigtime_t milli = micro/1000; + bigtime_t sec = milli/1000; + bigtime_t min = sec/60; + bigtime_t hours = min/60; + bigtime_t days = hours/24; + + char message[512] = ""; + if (days) + sprintf(message, "%Ld day%s ",days,days!=1?"s":""); + + if (hours%24) + sprintf(message, "%s%Ld hr%s ",message, hours%24,(hours%24)!=1?"s":""); + + if (min%60) + sprintf(message, "%s%Ld min%s ",message, min%60, (min%60)!=1?"s":""); + + sprintf(message, "%s%Ld.%Ld sec%s",message, sec%60, (milli%1000), (sec%60)!=1?"s":""); + + duration += message; + + return duration; +} + + +const char * +RelToAbsPath (const char *append_) +{ + app_info ai; + be_app->GetAppInfo (&ai); + + BEntry entry (&ai.ref); + BPath path; + entry.GetPath (&path); + path.GetParent (&path); + path.Append (append_); + + return path.Path(); +} + + +int32 +Get440Len (const char *cData) +{ + BString data (cData); + + if (data.Length() < 440) + return data.Length(); + else + { + int32 place (data.FindLast ('\x20', 440)); + if (place == B_ERROR) + return 440; + return place; + } +} + +uint16 +CheckClickCount(BPoint point, BPoint &lastClick, bigtime_t sysTime, bigtime_t &lastClickTime, int16 &clickCount) +{ + // check time and proximity + BPoint delta = point - lastClick; + + bigtime_t timeDelta = sysTime - lastClickTime; + + bigtime_t doubleClickSpeed; + get_click_speed(&doubleClickSpeed); + + lastClickTime = sysTime; + + if (timeDelta < doubleClickSpeed + && fabs(delta.x) < doubleClickThresh + && fabs(delta.y) < doubleClickThresh) + return (++clickCount); + + lastClick = point; + clickCount = 1; + return clickCount; +} + diff --git a/library/librunview/Utilities.h b/library/librunview/Utilities.h new file mode 100644 index 0000000..80af0ca --- /dev/null +++ b/library/librunview/Utilities.h @@ -0,0 +1,70 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Vision. + * + * The Initial Developer of the Original Code is The Vision Team. + * Portions created by The Vision Team are + * Copyright (C) 1999, 2000, 2001 The Vision Team. All Rights + * Reserved. + * + * Contributor(s): Wade Majors + * Todd Lair + * Andrew Bazan + */ + +#ifndef _UTILITIES_H +#define _UTILITIES_H_ + +#include + +template class AutoDestructor { + public: + AutoDestructor(T *t) + { + fObject = t; + } + + virtual ~AutoDestructor(void) + { + delete fObject; + } + + void SetTo(T *t) + { + delete fObject; + fObject = t; + } + + private: + T *fObject; +}; + + +class BMessage; +class BPoint; + +BString GetWord (const char *, int32); +BString RestOfString (const char *, int32); +BString GetNick (const char *); +BString GetIdent (const char *); +BString GetAddress (const char *); +BString TimeStamp (void); +BString ExpandKeyed (const char *, const char *, const char **); +BString DurationString (int64); +BString StringToURI (const char *); +const char *RelToAbsPath (const char *); +BString GetWordColon (const char *, int32); +int32 Get440Len (const char *); +uint16 CheckClickCount(BPoint, BPoint &, bigtime_t, bigtime_t &, int16 &); + + +#endif diff --git a/library/librunview/include/RVAction.h b/library/librunview/include/RVAction.h new file mode 100644 index 0000000..4bbeebb --- /dev/null +++ b/library/librunview/include/RVAction.h @@ -0,0 +1,15 @@ +#ifndef _RVAction_h_ +#define _RVAction_h_ + +class RVAction +{ + public: + + virtual ~RVAction(){}; + + virtual status_t Perform(BString param) = 0; + virtual BString GetDescription() = 0; + +}; + +#endif diff --git a/library/librunview/include/RunView.h b/library/librunview/include/RunView.h new file mode 100644 index 0000000..8cb55d6 --- /dev/null +++ b/library/librunview/include/RunView.h @@ -0,0 +1,249 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Vision. + * + * The Initial Developer of the Original Code is The Vision Team. + * Portions created by The Vision Team are + * Copyright (C) 1999, 2000, 2001 The Vision Team. All Rights + * Reserved. + * + * Contributor(s): Rene Gollent + * Todd Lair + */ + +#ifndef RUNVIEW_H_ +#define RUNVIEW_H_ + +#define LINE_COUNT 1000 + +#include + + +//#include "main.h" + +struct Line; +class RVAction; //by xeD +class Theme; +class RunView; +class BScrollView; +class BCursor; +class BMessageRunner; +class BPopUpMenu; + + +const uint32 kResizeMessage = 'irsz'; +const uint32 M_LOOKUP_WEBSTER = 'rvlw'; +const uint32 M_LOOKUP_GOOGLE = 'rvlg'; +const uint32 M_LOOKUP_ACRONYM = 'rvla'; +const uint32 M_CLEAR = 'rvcl'; + +const uint32 M_OFFVIEW_SELECTION = 'rvos'; +const uint32 M_THEME_FOREGROUND_CHANGE = 'rvtf'; +const uint32 M_THEME_BACKGROUND_CHANGE = 'rvtb'; +const uint32 M_THEME_FONT_CHANGE = 'rvto'; + +#define C_URL 0 +#define C_TIMESTAMP 1 +#define C_TEXT 2 +#define C_OWNNICK 3 +#define C_OTHERNICK 4 +#define C_ACTION 5 +#define C_SELECTION 6 +#define C_TIMESTAMP_DUMMY 7 // Needed to fake a TS +#define MAX_COLORS 8 + +/* +#define F_URL 0 +#define F_TEXT 1 +#define F_TIMESTAMP 2 +#define F_ACTION 3 +#define F_EMOTICON 4 // new style by xeD ;) +#define F_STYLE_0 4 // new style by xeD ;) +#define F_TIMESTAMP_DUMMY 5 // Needed to fake TS +#define MAX_FONTS 6 +*/ + +enum { + F_URL = 0, + F_TEXT, + F_TIMESTAMP, + F_ACTION, + F_EMOTICON, + F_STYLE_0, + F_STYLE_1, + F_STYLE_2, + F_TIMESTAMP_DUMMY, //DON'T TOUCH NOT USE + MAX_FONTS //DON'T TOUCH NOT USE +}; + +class SelectPos +{ + public: + + int16 fLine; + int16 fOffset; + + SelectPos ( + int16 selLine = 0, + int16 selOffset = 0) + : fLine (selLine), + fOffset (selOffset) + { } + + SelectPos (const SelectPos &pos) + : fLine (pos.fLine), + fOffset (pos.fOffset) + { } + + ~SelectPos (void) + { } + + SelectPos &operator = (const SelectPos &pos) + { + fLine = pos.fLine; + fOffset = pos.fOffset; + + return *this; + } + + inline int operator == (const SelectPos &rhs) const + { + return ((fLine == rhs.fLine) && (fOffset == rhs.fOffset)); + } + + inline int operator != (const SelectPos &rhs) const + { + return (!(*this == rhs)); + } + + +}; + +class RunView : public BView +{ + BScrollView *fScroller; + BCursor *fURLCursor; + Theme *fTheme; + + Line *fWorking; + Line *fLines[LINE_COUNT]; + int16 fLine_count, + fClickCount; + + char *fStamp_format; + char *fClipping_name; + + SelectPos fSp_start, fSp_end; + + int32 fTracking; + SelectPos fTrack_offset; + BMessageRunner *fOff_view_runner; + bigtime_t fOff_view_time; + + bool fResizedirty; + bool fFontsdirty; + BPopUpMenu *fMyPopUp; + BPoint fLastClick; + bigtime_t fLastClickTime; + + BMessage urls; //by xeD + BMessage actions; //by xeD + + bool fIndent; //by xeD + + RVAction* fDefaultURLAction; //by xeD + + RVAction* FindAction(const char* symbolicName); //by xeD + void InvokeAction(BString mangledName); //by xeD + + bool RecalcScrollBar (bool constrain); + void ResizeRecalc (void); + void FontChangeRecalc (void); + void ExtendTrackingSelect (BPoint); + void ShiftTrackingSelect (BPoint, bool, bigtime_t); + void CheckURLCursor (BPoint); + bool CheckURL(BPoint); //by xeD + BString GetURL(BPoint); + + void BuildPopUp (BPoint point); + + bool CheckClickBounds (const SelectPos &, const BPoint &) const; + void LoadURL(const char *url); + + public: + + RunView ( + BRect, + const char *, + Theme *, + uint32 = B_FOLLOW_LEFT | B_FOLLOW_TOP, + uint32 = 0UL); + virtual ~RunView (void); + + virtual void AttachedToWindow (void); + virtual void DetachedFromWindow (void); + virtual void FrameResized (float, float); + + virtual void TextResized(BRect /*r*/){}; //by xeD Callback when text bounds changed. + virtual float ExtraTextSize(){ return 0;}; //by xeD does we use more Vert space than the text? + + virtual void TargetedByScrollView (BScrollView *); + virtual void Show (); + virtual void Draw (BRect); + virtual void MessageReceived (BMessage *); + + virtual void SetViewColor (rgb_color); + void SetViewColor (uchar red, uchar green, uchar blue, uchar alpha = 255) + { rgb_color color = {red, green, blue, alpha}; SetViewColor (color); } + + + virtual void MouseDown (BPoint); + virtual void MouseMoved (BPoint, uint32, const BMessage *); + virtual void MouseUp (BPoint); + + //by xeD + void SetIndentWrappedLine(bool val){ fIndent = val;} + + void Append (const char *, int32, int16, int16, int16); + void Append (const char *, int16, int16, int16); + void AppendURL(const char *,const char *,int16 font); + void AppendURL(const char *,const char *,int16 back,int16 font); + + void ClearActions(); //by xeD + void AddAction(const char* symbolicName,RVAction*); //by xeD + void SetDefaultOpenURLAction(RVAction*); //by xeD + + void Clear (void); + + int16 LineCount (void) const; + const char *LineAt (int16) const; + + void SetTimeStampFormat (const char *); + void SetTheme (Theme *); + + SelectPos PositionAt (BPoint) const; + BPoint PointAt (SelectPos) const; + + BRect GetTextFrame (const SelectPos &, const SelectPos &) const; + bool IntersectSelection (const SelectPos &, const SelectPos &) const; + void GetSelectionText (BString &) const; + void Select (const SelectPos &, const SelectPos &); + void SelectAll (void); + void SetClippingName (const char *); + bool FindText(const char *); + + void ScrollToBottom(void); + void ScrollToSelection(void); + +}; + +#endif diff --git a/library/librunview/include/TextRender.h b/library/librunview/include/TextRender.h new file mode 100644 index 0000000..700fcc3 --- /dev/null +++ b/library/librunview/include/TextRender.h @@ -0,0 +1,25 @@ +#ifndef _TextRender_H_ +#define _TextRender_H_ + +class TextRender +{ + public: + TextRender(){}; + virtual ~TextRender() {}; + + virtual void Render(BView *target,const char*,int16 num,BPoint pos,BRect drawRect) = 0; + + virtual void GetHeight(font_height *height) = 0; + virtual void GetEscapements(const char charArray[], int32 numChars,float escapementArray[])=0; + virtual float Size(float maxwidth) = 0; + + virtual void MarginAfterTheText(BView *target,rgb_color view_color, BRect rect){ + // Margin after fText + target->SetDrawingMode (B_OP_COPY); + target->SetLowColor (view_color); + target->FillRect (rect, B_SOLID_LOW); + } + // + +}; +#endif diff --git a/library/librunview/include/Theme.h b/library/librunview/include/Theme.h new file mode 100644 index 0000000..762be7d --- /dev/null +++ b/library/librunview/include/Theme.h @@ -0,0 +1,109 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Vision. + * + * The Initial Developer of the Original Code is The Vision Team. + * Portions created by The Vision Team are + * Copyright (C) 1999, 2000, 2001 The Vision Team. All Rights + * Reserved. + * + * Contributor(s): Rene Gollent + * Todd Lair + */ + +#ifndef THEME_H_ +#define THEME_H_ + +#include +#include +#include + +#include "TextRender.h" + +class BView; +class NormalTextRender; + +class Theme +{ + char *name; + rgb_color *fores; + rgb_color *backs; + //BFont *fonts; + TextRender **text_renders; //FIX!! + + int16 fore_count; + int16 back_count; + int16 render_count; + + BList list; + sem_id sid; + + public: + + static int16 TimestampFore; + static int16 TimestampBack; + static int16 TimestampFont; + static int16 TimespaceFore; + static int16 TimespaceBack; + static int16 TimespaceFont; + static int16 NormalFore; + static int16 NormalBack; + static int16 NormalFont; + static int16 SelectionBack; + + Theme ( + const char *, + int16, + int16, + int16); + virtual ~Theme (void); + + const char *Name (void) const + { return name; } + + void ReadLock (void); + void ReadUnlock (void); + void WriteLock (void); + void WriteUnlock (void); + + int16 CountForegrounds (void) const; + int16 CountBackgrounds (void) const; +// int16 CountFonts (void) const; + int16 CountTextRenders (void) const; + + const rgb_color ForegroundAt (int16) const; + const rgb_color BackgroundAt (int16) const; + + //const BFont &FontAt (int16) const; + + TextRender* TextRenderAt(int16); + + bool SetForeground (int16, const rgb_color); + bool SetForeground (int16 w, uchar r, uchar g, uchar b, uchar a = 255) + { rgb_color color = {r, g, b, a}; return SetForeground (w, color); } + bool SetBackground (int16, const rgb_color); + bool SetBackground (int16 w, uchar r, uchar g, uchar b, uchar a = 255) + { rgb_color color = {r, g, b, a}; return SetBackground (w, color); } + + //bool SetFont (int16, const BFont &); + bool SetTextRender(int16, TextRender *); + + + + + void AddView (BView *); + void RemoveView (BView *); + + NormalTextRender *normal_textrender; +}; + +#endif diff --git a/release/Language/Dictionaries/BePodder.blBY b/release/Language/Dictionaries/BePodder.blBY new file mode 100644 index 0000000..296dac8 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.blBY @@ -0,0 +1,604 @@ + +# Locale file for BePodder. +# Modified: 4/18/2006 +# Author: BePodderTeam +# E-mail: bepodder.team@gmail.com + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" + +"Web Site" "Web Site" + +"Can't connect!" "Can't connect!" +"Http port failed!" "Http port failed!" +"Can't resolve host!" "Can't resolve host!" +"Not found!" "Not found!" +"Bad resume!" "Bad resume!" +"Aborted by Callback!" "Aborted by Callback!" +"Can't resume! (range error)" "Can't resume! (range error)" +"Access Denied!" "Access Denied!" +"User or Password Incorrect!" "User or Password Incorrect!" +"Other error (cUrl code: " "Other error (cUrl code: " +"cUrl init error!" "cUrl init error!" +"Can't open file!" "Can't open file!" +"Other error (status code: " "Other error (status code: " +"Downloading" "Downloading" + + +### MENUBAR ----------------------------------- + +"File" "File" +"About..." "About..." +"Close!" "Close!" +"Quit" "Quit" + +"Settings" "Settings" +"Preferences..." "Preferences..." + +"Subscriptions" "Subscriptions" + +"Episodes" "Episodes" + +"Lists" "Lists" +"Podcast List" "Podcast List" +"Podcast directory list" "Podcast directory list" +"Videoblog List" "Videoblog List" +"Videoblog directory list" "Videoblog directory list" +"Imagefeeds List" "Imagefeeds List" +"Imagefeeds directory list" "Imagefeeds directory list" +"Newsfeeds List" "Newsfeeds List" +"Newsfeeds directory list" "Newsfeeds directory list" +"BitTorrentfeeds List" "BitTorrentfeeds List" +"BitTorrentfeeds directory list" "BitTorrentfeeds directory list" +"Internationalfeeds List" "Internationalfeeds List" +"Internationalfeeds directory list" "Internationalfeeds directory list" + +"View" "View" +"Full Screen" "Full Screen" +"Toolbar" "Toolbar" +"Subscriptions View" "Subscriptions View" +"Small Items" "Small Items" +"Big Items" "Big Items" +"Move BePodder on workspace:" "Move BePodder on workspace:" + +"Help" "Help" +"Getting Started" "Getting Started" +"Keyboard Shortcuts" "Keyboard Shortcuts" +"Tutorials" "Tutorials" +"Online Support" "Online Support" + + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "Insert the rss feed url!" +"Add" "Add" +"Paste" "Paste" + +# Buttons directory list window +"Collapse All" "Collapse All" +"Preview" "Preview" +"Subscribe" "Subscribe" + + +# Buttons help window +"Next" "Next" +"Prev" "Prev" +"Close" "Close" +"Index" "Index" + + +# Buttons remove windows +"Cancel" "Cancel" +"Delete" "Delete" +"Archive" "Archive" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Add the podcast to the Subscriptions list" +"Delete the podcast from the Subscriptions list" "Delete the podcast from the Subscriptions list" +"Check the selected podcast for new items" "Check the selected podcast for new items" +"Show the podcast homepage" "Show the podcast homepage" + +"Delete the item and the enclosure" "Delete the item and the enclosure" +"Stop the item download" "Stop the item download" +"Download the selected episode" "Download the selected episode" +"Play the selected episode" "Play the selected episode" + +"Submit bug and idea" "Submit bug and idea" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Collapse all categories in the directory list" +"Add the selected podcast to the Subscription list" "Add the selected podcast to the Subscription list" +"Checkout a podcast before downloading it" "Checkout a podcast before downloading it" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Show Channel Image" +"XML Feed Link" "XML Feed Link" + +"Show Episode info" "Show Episode info" +"Show Subscription info" "Show Subscription info" +"Show Downloads info" "Show Downloads info" + +"Enclosure: " "Enclosure: " + +"Lookup (Dictionary)" "Lookup (Dictionary)" +"Lookup (Google)" "Lookup (Google)" +"Lookup (Acronym Finder)" "Lookup (Acronym Finder)" +"Copy" "Copy" +"Select All" "Select All" +"Copy URL" "Copy URL" +"Open URL" "Open URL" +"Subscription" "Subscription" + + +### PREFERENCES ----------------------------------- + +"Preferences" "Preferences" + +"Proxy" "Proxy" +"Enable Proxy" "Enable Proxy" +"Address" "Address" +"Port" "Port" +"Username" "Username" +"Password" "Password" + +"Max Downloads" "Max Downloads" + +"FileType" "FileType" +"Browser" "Browser" +"Player" "Player" + +"Channels" "Channels" +"Check all channels on startup" "Check all channels on startup" +"Check the channel every" "Check the channel every" + +"never" "never" +"5 minutes" "5 minutes" +"15 minutes" "15 minutes" +"30 minutes" "30 minutes" +"1 hour" "1 hour" +"2 hour" "2 hour" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 new item" +"%d new items" "%d new items" +"new" "new" +"error" "error" +"not down" "not down" +"enquequed" "enquequed" +"downloading" "downloading" +"downloaded" "downloaded" +"connecting" "connecting" +"not found" "not found" +"stopped" "stopped" +"can't connect" "can't connect" +"invalid format" "invalid format" + +"Icon" "Icon" +"Title" "Title" +"Date" "Date" +"Size" "Size" +"Status" "Status" +"Download" "Download" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "Add Channel" +"Remove Channel" "Remove Channel" +"Check Channel" "Check Channel" +"Open Homepage" "Open Homepage" + +"Open Web Page" "Open Web Page" +"Open Enclosures folder" "Open Enclosures folder" +"Check All Channels" "Check All Channels" + +"Show Channel Image" "Show Channel Image" + +"Play enclosure" "Play enclosure" +"(Re)start download" "(Re)start download" +"Stop download" "Stop download" +"Remove Item" "Remove Item" + +"Find this Item" "Find this Item" +"Remove from this list" "Remove from this list" + + + +### ALERT ----------------------------------- + +"\nRemoving.." "\nRemoving.." +"\nAn error occured while removing!" "\nAn error occured while removing!" +"Check all the podcasts for new items" "Check all the podcasts for new items" + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" + + +"Can't open the selected file with:\n\n" "Can't open the selected file with:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nPlease check if the application is installed in the right way.\n" +"Download it!" "Download it!" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +You are going to remove the selected item. + +Are you sure? +(you will lost the enclosure file if any)" + + +_key="alert2a" + _value=" +You are going to remove the channel: + +" + +_key="alert2b" + _value=" + +Would you like just to archive this +channel (keeping all the files and +enclosures downloaded so far) or +do you want to DELETE the whole + channel from you computer?" + +_key="alert3" + _value=" +Parsing archive.." + +_key="alert_3gp" + _value=" +3GP is a multimedia container format defined by the Third Generation Partnership Project (3GPP) for use on 3G mobile phones. It stores video streams as MPEG-4 or H.263, and audio streams as AMR-NB or AAC-LC. + +VideoLAN still doesn't support the audio AMR (3GPP)" + +_key="alert_swf" + _value=" +SWF is a proprietary vector graphics file format produced by the Flash software from Adobe (formerly Macromedia). + +Currently Flash support in BeOS/Haiku/Zeta is limited to the old standalone Flash player version 4.1015, there isn't a modern Flash player" + + + + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Introduction" +"The User Interface" "The User Interface" +"Menu Bar" "Menu Bar" +"Toolbar Buttons" "Toolbar Buttons" +"First time with BePodder" "First time with BePodder" +"Download Podcast's enclosure files" "Download Podcast's enclosure files" +"Settings Overview" "Settings Overview" +"Directory lists" "Directory lists" +"Loading Help..." "Loading Help..." +"Register your copy" "Register your copy" +"Starting point" "Starting point" + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value="Welcome to the BePodder Getting Started Guide." + +_key="help1-1" + _value="If you are already familiar with podcasts and RSS/Atom feeds you can immediately go to BePodder by closing this window." + +_key="help1-2" +_value="If not, this is a short introduction providing you everything you'll need to know on how to get started with BePodder. Use the buttons below to navigate through this tutorial." + + +_key="help2-0" +_value="Podcasting is a method for publishing audio and video broadcasts via the Internet; links to free audio and video files are enclosed in RSS and Atom feeds." + +_key="help2-1" +_value="Therefore Podcasting is simply a type of online media delivery; users can subscribe to a podcast using a feed (such as RSS 'Really Simple Syndication' or Atom)." + +_key="help2-2" +_value="An aggregator (or podcatcher) like BePodder, is a piece of software that allows you to subscribe to a RSS feed and periodically check for and download new content; with BePodder you can check for new Podcast items (Episodes) of your subscribed Channels. Any item can contain an enclosure, just like an Email can contain an attachment." + + + +_key="help3-0" +_value="BePodder has an easy to use yet powerful Graphical User Interface. The main window is split into tree panels:" + +_key="help3-1" +_value="1) The Subscription list (the panel with the number 1 in the screenshot) with the list of the podcasts that you have subscribed to. When you click on a Channel you can see in the panel 2 the list of the channel's items." + +_key="help3-2" +_value="2) The Episodes list with all the items available." + +_key="help3-3" +_value="3) The Info panel show: episode info, channel info or Downloads info; you can select an info panel by clicking one of the below three buttons." + + + +_key="help4-0" +_value="At the very top of the BePodder main window is the menubar with seven menus available: File, Settings, Subscriptions, Episodes, Lists, View and Help. Some menu commands are followed by a right pointing arrow that indicates a submenu of related commands. As you explore each menu, be sure to take a look at the submenus as well. Click on a menus to show its commands:" + +_key="help4-1" +_value="File: contains commands to close the application and to show information about BePodder" + +_key="help4-2" +_value="Settings: contains command to open the Preferences window that allows you to customize various BePodder settings." + +_key="help4-3" +_value="Subscriptions: contains commands that perform actions on the selected channel of your subscriptions list." + +_key="help4-4" +_value="Episodes: contains commands that perform actions on the selected item (episode) of the channel's episode list." + +_key="help4-5" +_value="Lists: contains commands to open BePodder's OPML directories." + +_key="help4-6" +_value="View: contains commands and controls for the BePodder window." + +_key="help4-7" +_value="Help: contains commands to open BePodder's 'Getting Started Guide' and the 'Keyboard Shortcuts List'." + + + +_key="help5-0" + _value="Add Button: opens the Add Window to add a feed url (e.g. http://www.newpodcast.com/rss.xml) usually given on the podcast homepage; looks for text or graphic link that says something like 'XML', 'RSS' or 'Podcast Feed' on it." + +_key="help5-1" + _value="Channel Remove Button: opens a window in which you can select how remove the channel: just archive the select channel (keeping all the files and eclosure downloaded so far) or delete the whole channel from your computer." + +_key="help5-2" + _value="Check Button: checks the selected channel and updates the list of the available items for that podcast adding the new items." + +_key="help5-3" + _value="Web Button: shows the channel homepage in the browser. To select your favorite browser open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select your favorite browser." + +_key="help5-4" + _value="Play Button: with this button you can view or listen the file enclosure of the selected item(episode). To select your favorite player open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select you favorite player." + +_key="help5-5" + _value="Download Button: downloads the file enclosure of the selected item (episode); you can see the download info by clicking on the third button over the info panel." + +_key="help5-6" + _value="Stop Button: stops to download the file enclosure of the selected item (episode); to resume the download double-click the item (episode) or select the item and click the Download Button" + +_key="help5-7" + _value="Item Remove Button: deletes the selected item (you will loose the enclosure file)." + + + +_key="help6-0" + _value="Getting started with BePodder is easy." + +_key="help6-1" + _value="On the left of the main window you can see the 'Subscription List' with all your feed subscriptions. We have added some subscriptions for you, and you can always add your own in two ways:" + +_key="help6-2" + _value="1) click the Add Button, then insert the feed url (example: http://www.newpodcast.com/rss.xml) and click add." + +_key="help6-3" + _value="2) in the menubar select 'Directory' and then 'Podcast list' or another list, choose a podcast and click 'Subscribe'." + +_key="help6-4" + _value="If you select a Podcast in the subscriptions list and use the check button, BePodder adds the new items to the 'Episodes list' (below on the right); you can check all your podcasts by right-clicking and selecting 'Check All Channels' in the context menu." + +_key="help6-5" + _value="Look at the screenshot above, there are 3 new items indicated by a black dot in the first column of the 'Episodes list'." + +_key="help6-6" + _value="In the second column there are icons that indicate the state of the item:" + +_key="help6-7" + _value="- the Episode 4 has an icon that indicates an error" + +_key="help6-8" + _value="- the Episode 3 has an icon that indicates that the item's enclosure download request is enquequed" + +_key="help6-9" + _value="- the Episode 2 has an icon that indicates that BePodder is downloading the item's enclosure file" + +_key="help6-10" + _value="- the Episode 1 have an icon that indicates that BePodder have just downloaded the item's enclosure file" + + + +_key="help7-0" + _value="Select an item in the 'Episodes list' and then double-click on it (or click the Download Button) to start downloading the enclosed file; you can always stop the download by clicking on the Stop Button." + +_key="help7-1" + _value="When you click on the Subscribed Podcasts in the 'Subscriptions List' the software shows you, in the 'List of episodes', all the items available in that Subscription. Select an item and then click play (Play Button) to view or listen to the file." + +_key="help7-2" + _value="You can access the Enclosures Folder by clicking on the folder icon in the Info Pannel or by right-clicking your mouse on an item and select 'Open Enclosures Folder' in the context menu." + + + +_key="help8-0" + _value="Preferences can be accessed by clicking in the menu-bar Settings>Preferences. You can select a category from the left list of the preferences dialog: FileType, Channels, Download and Proxy." + +_key="help8-1" + _value="- FileType: to specify the default browser and player. " + +_key="help8-2" + _value="- Channels: to specify preferences that control the operation to check channels new items; you can choose to Check all channels on startup or check the channel every desired minutes." + +_key="help8-3" + _value="- Download: to specify the max number of item's files to download at the same time," + +_key="help8-4" + _value="- Proxy: to set up a proxy server to work with BePodder; a proxy server acts as a security barrier between your internal network and the Internet, keeping others on the Internet from accessing information on your internal network." + + + +_key="help9-0" + _value="BePodder has built-in podcast, videoblog, imagefeeds, newsfeeds, bittorrentfeeds and internationalfeeds OPML directories with thousands of feeds grouped by category." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) is an XML-based format that allows exchange of outline-structured information between applications." + +_key="help9-2" + _value="OPML directory can be accessed by clicking in the menu-bar 'Lists' and thenselecting a list. To browse the opml directory for a feed, expand the list by clicking the arrow of the category that you are interested in (see image); using this method, you can expand the opml directory until you find the desired feed. Once you have selected it, you can add it to the subscription list by clicking the button 'Subscribe', you can also collapse all categories in the directory list by clicking the button 'Collapse All'." + +_key="help_shortcut1" +_value="This page describes the keyboard shortcuts that can be used in BePodder. The shortcuts are grouped here by function." + +_key="help_shortcut2" +_value="means that you can use either alt or control (es. Alt+Q or Ctrl+Q Quit the application), which way you have set it in the Deskbar menu preferences under Keyboard (the default shortcut key is Alt)." + +_key="help_shortcut3" + _value="General shortcuts" + +_key="help_shortcut4" + _value="Quit the application" + +_key="help_shortcut5" + _value="Shows the Preferences window" + +_key="help_shortcut6" + _value="Shows the Podcast directory list" + +_key="help_shortcut7" + _value="Shows the Videoblog directory list" + +_key="help_shortcut8" + _value="Shows the Imagefeeds directory list" + +_key="help_shortcut9" + _value="Shows the Newsfeeds directory list" + +_key="help_shortcut9b" + _value="Shows the BitTorrentfeeds directory list" + +_key="help_shortcut9c" + _value="Shows the Internationalfeeds directory list" + +_key="help_shortcut10" + _value="Fullscreen" + +_key="help_shortcut11" + _value="Shows/Hides the toolbar" + +_key="help_shortcut12" + _value="Shows the Getting Started Help" + +_key="help_shortcut13" + _value="Shows this keyboard shortcuts page" + +_key="help_shortcut14" + _value="Channels shortcuts" + +_key="help_shortcut15" + _value="Add a podcast to the subscriptions list" + +_key="help_shortcut16" + _value="Delete the selected podcast from the subscriptions list" + +_key="help_shortcut17" + _value="Check the selected podcast for new episodes (items)" + +_key="help_shortcut18" + _value="Check all podcasts for new episodes (items)" + +_key="help_shortcut19" + _value="Shows the podcast homepage" + +_key="help_shortcut20" + _value="Open enclosures folder" + +_key="help_shortcut21" + _value="Episodes shortcuts" + +_key="help_shortcut22" + _value="Play enclosure" + +_key="help_shortcut23" + _value="(Re)start download the selected episodes (items)" + +_key="help_shortcut24" + _value="Stop the episode (item) download" + +_key="help_shortcut25" + _value="Delete the selected episode (item)" + +_key="help_shortcut26" + _value="Shows the podcast episode (item) page " + +_key="help_shortcut27" + _value="Open enclosures folder" + +_key="help_buy1" + _value="BePodder Light is the basic version (free download and no time limited), the registered version adds some more nice features: unlimited number of channels, small Channel view, proxy support, automatic channels check, up to 5 enclosure downloads at the same time (multithreading)." + +_key="help_buy2" + _value="Please pay the shareware fee, it's only 15 euro (Kagi add tax in some countries), BePodder licence can be purchased online from Kagi." + +_key="help_buy3" + _value="Buy at www.funkyideasoft.com" + +_key="help_buy4" + _value="After purchasing, an email will be sent to you with a keyfile and instruction on how to install it. It's just a matter of unzipping a file and moving it to a certain directory." + +_key="help_buy5" + _value="There is no problem updating BePodder when a new version becomes available. The keyfile will unlock all downloadable packages unless otherwise notified." + + +### USELESS ######## + +"Opml Editor" "Opml Editor" +"name:" "name:" +"Add a category" "Add a category" +"Add a new Broadcast" "Add a new Broadcast" +"feed:" "feed:" +"url:" "url:" +"Test podcast" "Test podcast" +"Del a category" "Del a category" +"Add a category" "Add a category" +"Select the podcast category:" "Select the podcast category:" +"Check all" "Check all" +"Check" "Check" +"Refresh the list" "Refresh the list" +"Load" "Load" +"Load the list" "Load the list" +"Save" "Save" +"Save the list" "Save the list" +"Revert" "Revert" +"Apply" "Apply" + + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.czCZ b/release/Language/Dictionaries/BePodder.czCZ new file mode 100644 index 0000000..296dac8 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.czCZ @@ -0,0 +1,604 @@ + +# Locale file for BePodder. +# Modified: 4/18/2006 +# Author: BePodderTeam +# E-mail: bepodder.team@gmail.com + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" + +"Web Site" "Web Site" + +"Can't connect!" "Can't connect!" +"Http port failed!" "Http port failed!" +"Can't resolve host!" "Can't resolve host!" +"Not found!" "Not found!" +"Bad resume!" "Bad resume!" +"Aborted by Callback!" "Aborted by Callback!" +"Can't resume! (range error)" "Can't resume! (range error)" +"Access Denied!" "Access Denied!" +"User or Password Incorrect!" "User or Password Incorrect!" +"Other error (cUrl code: " "Other error (cUrl code: " +"cUrl init error!" "cUrl init error!" +"Can't open file!" "Can't open file!" +"Other error (status code: " "Other error (status code: " +"Downloading" "Downloading" + + +### MENUBAR ----------------------------------- + +"File" "File" +"About..." "About..." +"Close!" "Close!" +"Quit" "Quit" + +"Settings" "Settings" +"Preferences..." "Preferences..." + +"Subscriptions" "Subscriptions" + +"Episodes" "Episodes" + +"Lists" "Lists" +"Podcast List" "Podcast List" +"Podcast directory list" "Podcast directory list" +"Videoblog List" "Videoblog List" +"Videoblog directory list" "Videoblog directory list" +"Imagefeeds List" "Imagefeeds List" +"Imagefeeds directory list" "Imagefeeds directory list" +"Newsfeeds List" "Newsfeeds List" +"Newsfeeds directory list" "Newsfeeds directory list" +"BitTorrentfeeds List" "BitTorrentfeeds List" +"BitTorrentfeeds directory list" "BitTorrentfeeds directory list" +"Internationalfeeds List" "Internationalfeeds List" +"Internationalfeeds directory list" "Internationalfeeds directory list" + +"View" "View" +"Full Screen" "Full Screen" +"Toolbar" "Toolbar" +"Subscriptions View" "Subscriptions View" +"Small Items" "Small Items" +"Big Items" "Big Items" +"Move BePodder on workspace:" "Move BePodder on workspace:" + +"Help" "Help" +"Getting Started" "Getting Started" +"Keyboard Shortcuts" "Keyboard Shortcuts" +"Tutorials" "Tutorials" +"Online Support" "Online Support" + + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "Insert the rss feed url!" +"Add" "Add" +"Paste" "Paste" + +# Buttons directory list window +"Collapse All" "Collapse All" +"Preview" "Preview" +"Subscribe" "Subscribe" + + +# Buttons help window +"Next" "Next" +"Prev" "Prev" +"Close" "Close" +"Index" "Index" + + +# Buttons remove windows +"Cancel" "Cancel" +"Delete" "Delete" +"Archive" "Archive" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Add the podcast to the Subscriptions list" +"Delete the podcast from the Subscriptions list" "Delete the podcast from the Subscriptions list" +"Check the selected podcast for new items" "Check the selected podcast for new items" +"Show the podcast homepage" "Show the podcast homepage" + +"Delete the item and the enclosure" "Delete the item and the enclosure" +"Stop the item download" "Stop the item download" +"Download the selected episode" "Download the selected episode" +"Play the selected episode" "Play the selected episode" + +"Submit bug and idea" "Submit bug and idea" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Collapse all categories in the directory list" +"Add the selected podcast to the Subscription list" "Add the selected podcast to the Subscription list" +"Checkout a podcast before downloading it" "Checkout a podcast before downloading it" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Show Channel Image" +"XML Feed Link" "XML Feed Link" + +"Show Episode info" "Show Episode info" +"Show Subscription info" "Show Subscription info" +"Show Downloads info" "Show Downloads info" + +"Enclosure: " "Enclosure: " + +"Lookup (Dictionary)" "Lookup (Dictionary)" +"Lookup (Google)" "Lookup (Google)" +"Lookup (Acronym Finder)" "Lookup (Acronym Finder)" +"Copy" "Copy" +"Select All" "Select All" +"Copy URL" "Copy URL" +"Open URL" "Open URL" +"Subscription" "Subscription" + + +### PREFERENCES ----------------------------------- + +"Preferences" "Preferences" + +"Proxy" "Proxy" +"Enable Proxy" "Enable Proxy" +"Address" "Address" +"Port" "Port" +"Username" "Username" +"Password" "Password" + +"Max Downloads" "Max Downloads" + +"FileType" "FileType" +"Browser" "Browser" +"Player" "Player" + +"Channels" "Channels" +"Check all channels on startup" "Check all channels on startup" +"Check the channel every" "Check the channel every" + +"never" "never" +"5 minutes" "5 minutes" +"15 minutes" "15 minutes" +"30 minutes" "30 minutes" +"1 hour" "1 hour" +"2 hour" "2 hour" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 new item" +"%d new items" "%d new items" +"new" "new" +"error" "error" +"not down" "not down" +"enquequed" "enquequed" +"downloading" "downloading" +"downloaded" "downloaded" +"connecting" "connecting" +"not found" "not found" +"stopped" "stopped" +"can't connect" "can't connect" +"invalid format" "invalid format" + +"Icon" "Icon" +"Title" "Title" +"Date" "Date" +"Size" "Size" +"Status" "Status" +"Download" "Download" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "Add Channel" +"Remove Channel" "Remove Channel" +"Check Channel" "Check Channel" +"Open Homepage" "Open Homepage" + +"Open Web Page" "Open Web Page" +"Open Enclosures folder" "Open Enclosures folder" +"Check All Channels" "Check All Channels" + +"Show Channel Image" "Show Channel Image" + +"Play enclosure" "Play enclosure" +"(Re)start download" "(Re)start download" +"Stop download" "Stop download" +"Remove Item" "Remove Item" + +"Find this Item" "Find this Item" +"Remove from this list" "Remove from this list" + + + +### ALERT ----------------------------------- + +"\nRemoving.." "\nRemoving.." +"\nAn error occured while removing!" "\nAn error occured while removing!" +"Check all the podcasts for new items" "Check all the podcasts for new items" + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" + + +"Can't open the selected file with:\n\n" "Can't open the selected file with:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nPlease check if the application is installed in the right way.\n" +"Download it!" "Download it!" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +You are going to remove the selected item. + +Are you sure? +(you will lost the enclosure file if any)" + + +_key="alert2a" + _value=" +You are going to remove the channel: + +" + +_key="alert2b" + _value=" + +Would you like just to archive this +channel (keeping all the files and +enclosures downloaded so far) or +do you want to DELETE the whole + channel from you computer?" + +_key="alert3" + _value=" +Parsing archive.." + +_key="alert_3gp" + _value=" +3GP is a multimedia container format defined by the Third Generation Partnership Project (3GPP) for use on 3G mobile phones. It stores video streams as MPEG-4 or H.263, and audio streams as AMR-NB or AAC-LC. + +VideoLAN still doesn't support the audio AMR (3GPP)" + +_key="alert_swf" + _value=" +SWF is a proprietary vector graphics file format produced by the Flash software from Adobe (formerly Macromedia). + +Currently Flash support in BeOS/Haiku/Zeta is limited to the old standalone Flash player version 4.1015, there isn't a modern Flash player" + + + + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Introduction" +"The User Interface" "The User Interface" +"Menu Bar" "Menu Bar" +"Toolbar Buttons" "Toolbar Buttons" +"First time with BePodder" "First time with BePodder" +"Download Podcast's enclosure files" "Download Podcast's enclosure files" +"Settings Overview" "Settings Overview" +"Directory lists" "Directory lists" +"Loading Help..." "Loading Help..." +"Register your copy" "Register your copy" +"Starting point" "Starting point" + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value="Welcome to the BePodder Getting Started Guide." + +_key="help1-1" + _value="If you are already familiar with podcasts and RSS/Atom feeds you can immediately go to BePodder by closing this window." + +_key="help1-2" +_value="If not, this is a short introduction providing you everything you'll need to know on how to get started with BePodder. Use the buttons below to navigate through this tutorial." + + +_key="help2-0" +_value="Podcasting is a method for publishing audio and video broadcasts via the Internet; links to free audio and video files are enclosed in RSS and Atom feeds." + +_key="help2-1" +_value="Therefore Podcasting is simply a type of online media delivery; users can subscribe to a podcast using a feed (such as RSS 'Really Simple Syndication' or Atom)." + +_key="help2-2" +_value="An aggregator (or podcatcher) like BePodder, is a piece of software that allows you to subscribe to a RSS feed and periodically check for and download new content; with BePodder you can check for new Podcast items (Episodes) of your subscribed Channels. Any item can contain an enclosure, just like an Email can contain an attachment." + + + +_key="help3-0" +_value="BePodder has an easy to use yet powerful Graphical User Interface. The main window is split into tree panels:" + +_key="help3-1" +_value="1) The Subscription list (the panel with the number 1 in the screenshot) with the list of the podcasts that you have subscribed to. When you click on a Channel you can see in the panel 2 the list of the channel's items." + +_key="help3-2" +_value="2) The Episodes list with all the items available." + +_key="help3-3" +_value="3) The Info panel show: episode info, channel info or Downloads info; you can select an info panel by clicking one of the below three buttons." + + + +_key="help4-0" +_value="At the very top of the BePodder main window is the menubar with seven menus available: File, Settings, Subscriptions, Episodes, Lists, View and Help. Some menu commands are followed by a right pointing arrow that indicates a submenu of related commands. As you explore each menu, be sure to take a look at the submenus as well. Click on a menus to show its commands:" + +_key="help4-1" +_value="File: contains commands to close the application and to show information about BePodder" + +_key="help4-2" +_value="Settings: contains command to open the Preferences window that allows you to customize various BePodder settings." + +_key="help4-3" +_value="Subscriptions: contains commands that perform actions on the selected channel of your subscriptions list." + +_key="help4-4" +_value="Episodes: contains commands that perform actions on the selected item (episode) of the channel's episode list." + +_key="help4-5" +_value="Lists: contains commands to open BePodder's OPML directories." + +_key="help4-6" +_value="View: contains commands and controls for the BePodder window." + +_key="help4-7" +_value="Help: contains commands to open BePodder's 'Getting Started Guide' and the 'Keyboard Shortcuts List'." + + + +_key="help5-0" + _value="Add Button: opens the Add Window to add a feed url (e.g. http://www.newpodcast.com/rss.xml) usually given on the podcast homepage; looks for text or graphic link that says something like 'XML', 'RSS' or 'Podcast Feed' on it." + +_key="help5-1" + _value="Channel Remove Button: opens a window in which you can select how remove the channel: just archive the select channel (keeping all the files and eclosure downloaded so far) or delete the whole channel from your computer." + +_key="help5-2" + _value="Check Button: checks the selected channel and updates the list of the available items for that podcast adding the new items." + +_key="help5-3" + _value="Web Button: shows the channel homepage in the browser. To select your favorite browser open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select your favorite browser." + +_key="help5-4" + _value="Play Button: with this button you can view or listen the file enclosure of the selected item(episode). To select your favorite player open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select you favorite player." + +_key="help5-5" + _value="Download Button: downloads the file enclosure of the selected item (episode); you can see the download info by clicking on the third button over the info panel." + +_key="help5-6" + _value="Stop Button: stops to download the file enclosure of the selected item (episode); to resume the download double-click the item (episode) or select the item and click the Download Button" + +_key="help5-7" + _value="Item Remove Button: deletes the selected item (you will loose the enclosure file)." + + + +_key="help6-0" + _value="Getting started with BePodder is easy." + +_key="help6-1" + _value="On the left of the main window you can see the 'Subscription List' with all your feed subscriptions. We have added some subscriptions for you, and you can always add your own in two ways:" + +_key="help6-2" + _value="1) click the Add Button, then insert the feed url (example: http://www.newpodcast.com/rss.xml) and click add." + +_key="help6-3" + _value="2) in the menubar select 'Directory' and then 'Podcast list' or another list, choose a podcast and click 'Subscribe'." + +_key="help6-4" + _value="If you select a Podcast in the subscriptions list and use the check button, BePodder adds the new items to the 'Episodes list' (below on the right); you can check all your podcasts by right-clicking and selecting 'Check All Channels' in the context menu." + +_key="help6-5" + _value="Look at the screenshot above, there are 3 new items indicated by a black dot in the first column of the 'Episodes list'." + +_key="help6-6" + _value="In the second column there are icons that indicate the state of the item:" + +_key="help6-7" + _value="- the Episode 4 has an icon that indicates an error" + +_key="help6-8" + _value="- the Episode 3 has an icon that indicates that the item's enclosure download request is enquequed" + +_key="help6-9" + _value="- the Episode 2 has an icon that indicates that BePodder is downloading the item's enclosure file" + +_key="help6-10" + _value="- the Episode 1 have an icon that indicates that BePodder have just downloaded the item's enclosure file" + + + +_key="help7-0" + _value="Select an item in the 'Episodes list' and then double-click on it (or click the Download Button) to start downloading the enclosed file; you can always stop the download by clicking on the Stop Button." + +_key="help7-1" + _value="When you click on the Subscribed Podcasts in the 'Subscriptions List' the software shows you, in the 'List of episodes', all the items available in that Subscription. Select an item and then click play (Play Button) to view or listen to the file." + +_key="help7-2" + _value="You can access the Enclosures Folder by clicking on the folder icon in the Info Pannel or by right-clicking your mouse on an item and select 'Open Enclosures Folder' in the context menu." + + + +_key="help8-0" + _value="Preferences can be accessed by clicking in the menu-bar Settings>Preferences. You can select a category from the left list of the preferences dialog: FileType, Channels, Download and Proxy." + +_key="help8-1" + _value="- FileType: to specify the default browser and player. " + +_key="help8-2" + _value="- Channels: to specify preferences that control the operation to check channels new items; you can choose to Check all channels on startup or check the channel every desired minutes." + +_key="help8-3" + _value="- Download: to specify the max number of item's files to download at the same time," + +_key="help8-4" + _value="- Proxy: to set up a proxy server to work with BePodder; a proxy server acts as a security barrier between your internal network and the Internet, keeping others on the Internet from accessing information on your internal network." + + + +_key="help9-0" + _value="BePodder has built-in podcast, videoblog, imagefeeds, newsfeeds, bittorrentfeeds and internationalfeeds OPML directories with thousands of feeds grouped by category." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) is an XML-based format that allows exchange of outline-structured information between applications." + +_key="help9-2" + _value="OPML directory can be accessed by clicking in the menu-bar 'Lists' and thenselecting a list. To browse the opml directory for a feed, expand the list by clicking the arrow of the category that you are interested in (see image); using this method, you can expand the opml directory until you find the desired feed. Once you have selected it, you can add it to the subscription list by clicking the button 'Subscribe', you can also collapse all categories in the directory list by clicking the button 'Collapse All'." + +_key="help_shortcut1" +_value="This page describes the keyboard shortcuts that can be used in BePodder. The shortcuts are grouped here by function." + +_key="help_shortcut2" +_value="means that you can use either alt or control (es. Alt+Q or Ctrl+Q Quit the application), which way you have set it in the Deskbar menu preferences under Keyboard (the default shortcut key is Alt)." + +_key="help_shortcut3" + _value="General shortcuts" + +_key="help_shortcut4" + _value="Quit the application" + +_key="help_shortcut5" + _value="Shows the Preferences window" + +_key="help_shortcut6" + _value="Shows the Podcast directory list" + +_key="help_shortcut7" + _value="Shows the Videoblog directory list" + +_key="help_shortcut8" + _value="Shows the Imagefeeds directory list" + +_key="help_shortcut9" + _value="Shows the Newsfeeds directory list" + +_key="help_shortcut9b" + _value="Shows the BitTorrentfeeds directory list" + +_key="help_shortcut9c" + _value="Shows the Internationalfeeds directory list" + +_key="help_shortcut10" + _value="Fullscreen" + +_key="help_shortcut11" + _value="Shows/Hides the toolbar" + +_key="help_shortcut12" + _value="Shows the Getting Started Help" + +_key="help_shortcut13" + _value="Shows this keyboard shortcuts page" + +_key="help_shortcut14" + _value="Channels shortcuts" + +_key="help_shortcut15" + _value="Add a podcast to the subscriptions list" + +_key="help_shortcut16" + _value="Delete the selected podcast from the subscriptions list" + +_key="help_shortcut17" + _value="Check the selected podcast for new episodes (items)" + +_key="help_shortcut18" + _value="Check all podcasts for new episodes (items)" + +_key="help_shortcut19" + _value="Shows the podcast homepage" + +_key="help_shortcut20" + _value="Open enclosures folder" + +_key="help_shortcut21" + _value="Episodes shortcuts" + +_key="help_shortcut22" + _value="Play enclosure" + +_key="help_shortcut23" + _value="(Re)start download the selected episodes (items)" + +_key="help_shortcut24" + _value="Stop the episode (item) download" + +_key="help_shortcut25" + _value="Delete the selected episode (item)" + +_key="help_shortcut26" + _value="Shows the podcast episode (item) page " + +_key="help_shortcut27" + _value="Open enclosures folder" + +_key="help_buy1" + _value="BePodder Light is the basic version (free download and no time limited), the registered version adds some more nice features: unlimited number of channels, small Channel view, proxy support, automatic channels check, up to 5 enclosure downloads at the same time (multithreading)." + +_key="help_buy2" + _value="Please pay the shareware fee, it's only 15 euro (Kagi add tax in some countries), BePodder licence can be purchased online from Kagi." + +_key="help_buy3" + _value="Buy at www.funkyideasoft.com" + +_key="help_buy4" + _value="After purchasing, an email will be sent to you with a keyfile and instruction on how to install it. It's just a matter of unzipping a file and moving it to a certain directory." + +_key="help_buy5" + _value="There is no problem updating BePodder when a new version becomes available. The keyfile will unlock all downloadable packages unless otherwise notified." + + +### USELESS ######## + +"Opml Editor" "Opml Editor" +"name:" "name:" +"Add a category" "Add a category" +"Add a new Broadcast" "Add a new Broadcast" +"feed:" "feed:" +"url:" "url:" +"Test podcast" "Test podcast" +"Del a category" "Del a category" +"Add a category" "Add a category" +"Select the podcast category:" "Select the podcast category:" +"Check all" "Check all" +"Check" "Check" +"Refresh the list" "Refresh the list" +"Load" "Load" +"Load the list" "Load the list" +"Save" "Save" +"Save the list" "Save the list" +"Revert" "Revert" +"Apply" "Apply" + + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.daDK b/release/Language/Dictionaries/BePodder.daDK new file mode 100644 index 0000000..296dac8 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.daDK @@ -0,0 +1,604 @@ + +# Locale file for BePodder. +# Modified: 4/18/2006 +# Author: BePodderTeam +# E-mail: bepodder.team@gmail.com + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" + +"Web Site" "Web Site" + +"Can't connect!" "Can't connect!" +"Http port failed!" "Http port failed!" +"Can't resolve host!" "Can't resolve host!" +"Not found!" "Not found!" +"Bad resume!" "Bad resume!" +"Aborted by Callback!" "Aborted by Callback!" +"Can't resume! (range error)" "Can't resume! (range error)" +"Access Denied!" "Access Denied!" +"User or Password Incorrect!" "User or Password Incorrect!" +"Other error (cUrl code: " "Other error (cUrl code: " +"cUrl init error!" "cUrl init error!" +"Can't open file!" "Can't open file!" +"Other error (status code: " "Other error (status code: " +"Downloading" "Downloading" + + +### MENUBAR ----------------------------------- + +"File" "File" +"About..." "About..." +"Close!" "Close!" +"Quit" "Quit" + +"Settings" "Settings" +"Preferences..." "Preferences..." + +"Subscriptions" "Subscriptions" + +"Episodes" "Episodes" + +"Lists" "Lists" +"Podcast List" "Podcast List" +"Podcast directory list" "Podcast directory list" +"Videoblog List" "Videoblog List" +"Videoblog directory list" "Videoblog directory list" +"Imagefeeds List" "Imagefeeds List" +"Imagefeeds directory list" "Imagefeeds directory list" +"Newsfeeds List" "Newsfeeds List" +"Newsfeeds directory list" "Newsfeeds directory list" +"BitTorrentfeeds List" "BitTorrentfeeds List" +"BitTorrentfeeds directory list" "BitTorrentfeeds directory list" +"Internationalfeeds List" "Internationalfeeds List" +"Internationalfeeds directory list" "Internationalfeeds directory list" + +"View" "View" +"Full Screen" "Full Screen" +"Toolbar" "Toolbar" +"Subscriptions View" "Subscriptions View" +"Small Items" "Small Items" +"Big Items" "Big Items" +"Move BePodder on workspace:" "Move BePodder on workspace:" + +"Help" "Help" +"Getting Started" "Getting Started" +"Keyboard Shortcuts" "Keyboard Shortcuts" +"Tutorials" "Tutorials" +"Online Support" "Online Support" + + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "Insert the rss feed url!" +"Add" "Add" +"Paste" "Paste" + +# Buttons directory list window +"Collapse All" "Collapse All" +"Preview" "Preview" +"Subscribe" "Subscribe" + + +# Buttons help window +"Next" "Next" +"Prev" "Prev" +"Close" "Close" +"Index" "Index" + + +# Buttons remove windows +"Cancel" "Cancel" +"Delete" "Delete" +"Archive" "Archive" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Add the podcast to the Subscriptions list" +"Delete the podcast from the Subscriptions list" "Delete the podcast from the Subscriptions list" +"Check the selected podcast for new items" "Check the selected podcast for new items" +"Show the podcast homepage" "Show the podcast homepage" + +"Delete the item and the enclosure" "Delete the item and the enclosure" +"Stop the item download" "Stop the item download" +"Download the selected episode" "Download the selected episode" +"Play the selected episode" "Play the selected episode" + +"Submit bug and idea" "Submit bug and idea" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Collapse all categories in the directory list" +"Add the selected podcast to the Subscription list" "Add the selected podcast to the Subscription list" +"Checkout a podcast before downloading it" "Checkout a podcast before downloading it" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Show Channel Image" +"XML Feed Link" "XML Feed Link" + +"Show Episode info" "Show Episode info" +"Show Subscription info" "Show Subscription info" +"Show Downloads info" "Show Downloads info" + +"Enclosure: " "Enclosure: " + +"Lookup (Dictionary)" "Lookup (Dictionary)" +"Lookup (Google)" "Lookup (Google)" +"Lookup (Acronym Finder)" "Lookup (Acronym Finder)" +"Copy" "Copy" +"Select All" "Select All" +"Copy URL" "Copy URL" +"Open URL" "Open URL" +"Subscription" "Subscription" + + +### PREFERENCES ----------------------------------- + +"Preferences" "Preferences" + +"Proxy" "Proxy" +"Enable Proxy" "Enable Proxy" +"Address" "Address" +"Port" "Port" +"Username" "Username" +"Password" "Password" + +"Max Downloads" "Max Downloads" + +"FileType" "FileType" +"Browser" "Browser" +"Player" "Player" + +"Channels" "Channels" +"Check all channels on startup" "Check all channels on startup" +"Check the channel every" "Check the channel every" + +"never" "never" +"5 minutes" "5 minutes" +"15 minutes" "15 minutes" +"30 minutes" "30 minutes" +"1 hour" "1 hour" +"2 hour" "2 hour" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 new item" +"%d new items" "%d new items" +"new" "new" +"error" "error" +"not down" "not down" +"enquequed" "enquequed" +"downloading" "downloading" +"downloaded" "downloaded" +"connecting" "connecting" +"not found" "not found" +"stopped" "stopped" +"can't connect" "can't connect" +"invalid format" "invalid format" + +"Icon" "Icon" +"Title" "Title" +"Date" "Date" +"Size" "Size" +"Status" "Status" +"Download" "Download" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "Add Channel" +"Remove Channel" "Remove Channel" +"Check Channel" "Check Channel" +"Open Homepage" "Open Homepage" + +"Open Web Page" "Open Web Page" +"Open Enclosures folder" "Open Enclosures folder" +"Check All Channels" "Check All Channels" + +"Show Channel Image" "Show Channel Image" + +"Play enclosure" "Play enclosure" +"(Re)start download" "(Re)start download" +"Stop download" "Stop download" +"Remove Item" "Remove Item" + +"Find this Item" "Find this Item" +"Remove from this list" "Remove from this list" + + + +### ALERT ----------------------------------- + +"\nRemoving.." "\nRemoving.." +"\nAn error occured while removing!" "\nAn error occured while removing!" +"Check all the podcasts for new items" "Check all the podcasts for new items" + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" + + +"Can't open the selected file with:\n\n" "Can't open the selected file with:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nPlease check if the application is installed in the right way.\n" +"Download it!" "Download it!" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +You are going to remove the selected item. + +Are you sure? +(you will lost the enclosure file if any)" + + +_key="alert2a" + _value=" +You are going to remove the channel: + +" + +_key="alert2b" + _value=" + +Would you like just to archive this +channel (keeping all the files and +enclosures downloaded so far) or +do you want to DELETE the whole + channel from you computer?" + +_key="alert3" + _value=" +Parsing archive.." + +_key="alert_3gp" + _value=" +3GP is a multimedia container format defined by the Third Generation Partnership Project (3GPP) for use on 3G mobile phones. It stores video streams as MPEG-4 or H.263, and audio streams as AMR-NB or AAC-LC. + +VideoLAN still doesn't support the audio AMR (3GPP)" + +_key="alert_swf" + _value=" +SWF is a proprietary vector graphics file format produced by the Flash software from Adobe (formerly Macromedia). + +Currently Flash support in BeOS/Haiku/Zeta is limited to the old standalone Flash player version 4.1015, there isn't a modern Flash player" + + + + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Introduction" +"The User Interface" "The User Interface" +"Menu Bar" "Menu Bar" +"Toolbar Buttons" "Toolbar Buttons" +"First time with BePodder" "First time with BePodder" +"Download Podcast's enclosure files" "Download Podcast's enclosure files" +"Settings Overview" "Settings Overview" +"Directory lists" "Directory lists" +"Loading Help..." "Loading Help..." +"Register your copy" "Register your copy" +"Starting point" "Starting point" + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value="Welcome to the BePodder Getting Started Guide." + +_key="help1-1" + _value="If you are already familiar with podcasts and RSS/Atom feeds you can immediately go to BePodder by closing this window." + +_key="help1-2" +_value="If not, this is a short introduction providing you everything you'll need to know on how to get started with BePodder. Use the buttons below to navigate through this tutorial." + + +_key="help2-0" +_value="Podcasting is a method for publishing audio and video broadcasts via the Internet; links to free audio and video files are enclosed in RSS and Atom feeds." + +_key="help2-1" +_value="Therefore Podcasting is simply a type of online media delivery; users can subscribe to a podcast using a feed (such as RSS 'Really Simple Syndication' or Atom)." + +_key="help2-2" +_value="An aggregator (or podcatcher) like BePodder, is a piece of software that allows you to subscribe to a RSS feed and periodically check for and download new content; with BePodder you can check for new Podcast items (Episodes) of your subscribed Channels. Any item can contain an enclosure, just like an Email can contain an attachment." + + + +_key="help3-0" +_value="BePodder has an easy to use yet powerful Graphical User Interface. The main window is split into tree panels:" + +_key="help3-1" +_value="1) The Subscription list (the panel with the number 1 in the screenshot) with the list of the podcasts that you have subscribed to. When you click on a Channel you can see in the panel 2 the list of the channel's items." + +_key="help3-2" +_value="2) The Episodes list with all the items available." + +_key="help3-3" +_value="3) The Info panel show: episode info, channel info or Downloads info; you can select an info panel by clicking one of the below three buttons." + + + +_key="help4-0" +_value="At the very top of the BePodder main window is the menubar with seven menus available: File, Settings, Subscriptions, Episodes, Lists, View and Help. Some menu commands are followed by a right pointing arrow that indicates a submenu of related commands. As you explore each menu, be sure to take a look at the submenus as well. Click on a menus to show its commands:" + +_key="help4-1" +_value="File: contains commands to close the application and to show information about BePodder" + +_key="help4-2" +_value="Settings: contains command to open the Preferences window that allows you to customize various BePodder settings." + +_key="help4-3" +_value="Subscriptions: contains commands that perform actions on the selected channel of your subscriptions list." + +_key="help4-4" +_value="Episodes: contains commands that perform actions on the selected item (episode) of the channel's episode list." + +_key="help4-5" +_value="Lists: contains commands to open BePodder's OPML directories." + +_key="help4-6" +_value="View: contains commands and controls for the BePodder window." + +_key="help4-7" +_value="Help: contains commands to open BePodder's 'Getting Started Guide' and the 'Keyboard Shortcuts List'." + + + +_key="help5-0" + _value="Add Button: opens the Add Window to add a feed url (e.g. http://www.newpodcast.com/rss.xml) usually given on the podcast homepage; looks for text or graphic link that says something like 'XML', 'RSS' or 'Podcast Feed' on it." + +_key="help5-1" + _value="Channel Remove Button: opens a window in which you can select how remove the channel: just archive the select channel (keeping all the files and eclosure downloaded so far) or delete the whole channel from your computer." + +_key="help5-2" + _value="Check Button: checks the selected channel and updates the list of the available items for that podcast adding the new items." + +_key="help5-3" + _value="Web Button: shows the channel homepage in the browser. To select your favorite browser open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select your favorite browser." + +_key="help5-4" + _value="Play Button: with this button you can view or listen the file enclosure of the selected item(episode). To select your favorite player open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select you favorite player." + +_key="help5-5" + _value="Download Button: downloads the file enclosure of the selected item (episode); you can see the download info by clicking on the third button over the info panel." + +_key="help5-6" + _value="Stop Button: stops to download the file enclosure of the selected item (episode); to resume the download double-click the item (episode) or select the item and click the Download Button" + +_key="help5-7" + _value="Item Remove Button: deletes the selected item (you will loose the enclosure file)." + + + +_key="help6-0" + _value="Getting started with BePodder is easy." + +_key="help6-1" + _value="On the left of the main window you can see the 'Subscription List' with all your feed subscriptions. We have added some subscriptions for you, and you can always add your own in two ways:" + +_key="help6-2" + _value="1) click the Add Button, then insert the feed url (example: http://www.newpodcast.com/rss.xml) and click add." + +_key="help6-3" + _value="2) in the menubar select 'Directory' and then 'Podcast list' or another list, choose a podcast and click 'Subscribe'." + +_key="help6-4" + _value="If you select a Podcast in the subscriptions list and use the check button, BePodder adds the new items to the 'Episodes list' (below on the right); you can check all your podcasts by right-clicking and selecting 'Check All Channels' in the context menu." + +_key="help6-5" + _value="Look at the screenshot above, there are 3 new items indicated by a black dot in the first column of the 'Episodes list'." + +_key="help6-6" + _value="In the second column there are icons that indicate the state of the item:" + +_key="help6-7" + _value="- the Episode 4 has an icon that indicates an error" + +_key="help6-8" + _value="- the Episode 3 has an icon that indicates that the item's enclosure download request is enquequed" + +_key="help6-9" + _value="- the Episode 2 has an icon that indicates that BePodder is downloading the item's enclosure file" + +_key="help6-10" + _value="- the Episode 1 have an icon that indicates that BePodder have just downloaded the item's enclosure file" + + + +_key="help7-0" + _value="Select an item in the 'Episodes list' and then double-click on it (or click the Download Button) to start downloading the enclosed file; you can always stop the download by clicking on the Stop Button." + +_key="help7-1" + _value="When you click on the Subscribed Podcasts in the 'Subscriptions List' the software shows you, in the 'List of episodes', all the items available in that Subscription. Select an item and then click play (Play Button) to view or listen to the file." + +_key="help7-2" + _value="You can access the Enclosures Folder by clicking on the folder icon in the Info Pannel or by right-clicking your mouse on an item and select 'Open Enclosures Folder' in the context menu." + + + +_key="help8-0" + _value="Preferences can be accessed by clicking in the menu-bar Settings>Preferences. You can select a category from the left list of the preferences dialog: FileType, Channels, Download and Proxy." + +_key="help8-1" + _value="- FileType: to specify the default browser and player. " + +_key="help8-2" + _value="- Channels: to specify preferences that control the operation to check channels new items; you can choose to Check all channels on startup or check the channel every desired minutes." + +_key="help8-3" + _value="- Download: to specify the max number of item's files to download at the same time," + +_key="help8-4" + _value="- Proxy: to set up a proxy server to work with BePodder; a proxy server acts as a security barrier between your internal network and the Internet, keeping others on the Internet from accessing information on your internal network." + + + +_key="help9-0" + _value="BePodder has built-in podcast, videoblog, imagefeeds, newsfeeds, bittorrentfeeds and internationalfeeds OPML directories with thousands of feeds grouped by category." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) is an XML-based format that allows exchange of outline-structured information between applications." + +_key="help9-2" + _value="OPML directory can be accessed by clicking in the menu-bar 'Lists' and thenselecting a list. To browse the opml directory for a feed, expand the list by clicking the arrow of the category that you are interested in (see image); using this method, you can expand the opml directory until you find the desired feed. Once you have selected it, you can add it to the subscription list by clicking the button 'Subscribe', you can also collapse all categories in the directory list by clicking the button 'Collapse All'." + +_key="help_shortcut1" +_value="This page describes the keyboard shortcuts that can be used in BePodder. The shortcuts are grouped here by function." + +_key="help_shortcut2" +_value="means that you can use either alt or control (es. Alt+Q or Ctrl+Q Quit the application), which way you have set it in the Deskbar menu preferences under Keyboard (the default shortcut key is Alt)." + +_key="help_shortcut3" + _value="General shortcuts" + +_key="help_shortcut4" + _value="Quit the application" + +_key="help_shortcut5" + _value="Shows the Preferences window" + +_key="help_shortcut6" + _value="Shows the Podcast directory list" + +_key="help_shortcut7" + _value="Shows the Videoblog directory list" + +_key="help_shortcut8" + _value="Shows the Imagefeeds directory list" + +_key="help_shortcut9" + _value="Shows the Newsfeeds directory list" + +_key="help_shortcut9b" + _value="Shows the BitTorrentfeeds directory list" + +_key="help_shortcut9c" + _value="Shows the Internationalfeeds directory list" + +_key="help_shortcut10" + _value="Fullscreen" + +_key="help_shortcut11" + _value="Shows/Hides the toolbar" + +_key="help_shortcut12" + _value="Shows the Getting Started Help" + +_key="help_shortcut13" + _value="Shows this keyboard shortcuts page" + +_key="help_shortcut14" + _value="Channels shortcuts" + +_key="help_shortcut15" + _value="Add a podcast to the subscriptions list" + +_key="help_shortcut16" + _value="Delete the selected podcast from the subscriptions list" + +_key="help_shortcut17" + _value="Check the selected podcast for new episodes (items)" + +_key="help_shortcut18" + _value="Check all podcasts for new episodes (items)" + +_key="help_shortcut19" + _value="Shows the podcast homepage" + +_key="help_shortcut20" + _value="Open enclosures folder" + +_key="help_shortcut21" + _value="Episodes shortcuts" + +_key="help_shortcut22" + _value="Play enclosure" + +_key="help_shortcut23" + _value="(Re)start download the selected episodes (items)" + +_key="help_shortcut24" + _value="Stop the episode (item) download" + +_key="help_shortcut25" + _value="Delete the selected episode (item)" + +_key="help_shortcut26" + _value="Shows the podcast episode (item) page " + +_key="help_shortcut27" + _value="Open enclosures folder" + +_key="help_buy1" + _value="BePodder Light is the basic version (free download and no time limited), the registered version adds some more nice features: unlimited number of channels, small Channel view, proxy support, automatic channels check, up to 5 enclosure downloads at the same time (multithreading)." + +_key="help_buy2" + _value="Please pay the shareware fee, it's only 15 euro (Kagi add tax in some countries), BePodder licence can be purchased online from Kagi." + +_key="help_buy3" + _value="Buy at www.funkyideasoft.com" + +_key="help_buy4" + _value="After purchasing, an email will be sent to you with a keyfile and instruction on how to install it. It's just a matter of unzipping a file and moving it to a certain directory." + +_key="help_buy5" + _value="There is no problem updating BePodder when a new version becomes available. The keyfile will unlock all downloadable packages unless otherwise notified." + + +### USELESS ######## + +"Opml Editor" "Opml Editor" +"name:" "name:" +"Add a category" "Add a category" +"Add a new Broadcast" "Add a new Broadcast" +"feed:" "feed:" +"url:" "url:" +"Test podcast" "Test podcast" +"Del a category" "Del a category" +"Add a category" "Add a category" +"Select the podcast category:" "Select the podcast category:" +"Check all" "Check all" +"Check" "Check" +"Refresh the list" "Refresh the list" +"Load" "Load" +"Load the list" "Load the list" +"Save" "Save" +"Save the list" "Save the list" +"Revert" "Revert" +"Apply" "Apply" + + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.deDE b/release/Language/Dictionaries/BePodder.deDE new file mode 100644 index 0000000..c6e1c59 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.deDE @@ -0,0 +1,603 @@ + +# Locale file for BePodder. +# Modified: 12/23/2005 +# Author: Maurice Kalinowski +# E-mail: maurice.kalinowski@yellowtab.com + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Shareware Anwendung!\n\nBitte unterstütze uns!\n\nKaufe eine Software Lizenz\nMehr Informationen auf unserer Webseite\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "Diese BePodder Kopie ist abgelaufen!\nBitte kaufe die Schlüsseldatei und unterstütze uns.\n" + +"Web Site" "Webseite" + +"Can't connect!" "Can't connect!" +"Http port failed!" "Http port failed!" +"Can't resolve host!" "Can't resolve host!" +"Not found!" "Not found!" +"Bad resume!" "Bad resume!" +"Aborted by Callback!" "Aborted by Callback!" +"Can't resume! (range error)" "Can't resume! (range error)" +"Access Denied!" "Access Denied!" +"User or Password Incorrect!" "User or Password Incorrect!" +"Other error (cUrl code: " "Other error (cUrl code: " +"cUrl init error!" "cUrl init error!" +"Can't open file!" "Can't open file!" +"Other error (status code: " "Other error (status code: " +"Downloading" "Downloading" + + +### MENUBAR ----------------------------------- + +"File" "Datei" +"About..." "Über..." +"Close!" "Schließen!" +"Quit" "Beenden" + +"Settings" "Einstellungen" +"Preferences..." "Präferenzen..." + +"Subscriptions" "Bestellungen" + +"Episodes" "Folgen" + +"Lists" "Listen" +"Podcast List" "Podcast Liste" +"Podcast directory list" "Verzeichnisliste der Podcasts" +"Videoblog List" "Videoblog Liste" +"Videoblog directory list" "Verzeichnisliste der Videoblogs" +"Imagefeeds List" "Bildeinspeisungsliste" +"Imagefeeds directory list" "Verzeichnisliste der Bildeinspeisungen" +"Newsfeeds List" "Nachrichteneinspeisungsliste" +"Newsfeeds directory list" "Verzeichnisliste der Nachrichteneinspeisungen" +"BitTorrentfeeds List" "BitTorrentfeeds Liste" +"BitTorrentfeeds directory list" "Verzeichnisliste der BitTorrentfeeds" +"Internationalfeeds List" "Internationalfeeds Liste" +"Internationalfeeds directory list" "Verzeichnisliste der Internationalfeeds" + +"View" "Ansicht" +"Full Screen" "Vollbild" +"Toolbar" "Werkzeugleiste" +"Subscriptions View" "Bestellübersicht" +"Small Items" "Kleine Einträge" +"Big Items" "Große Einträge" +"Move BePodder on workspace:" "Verschiebe BePodder auf dem Arbeitsplatz:" + +"Help" "Hilfe" +"Getting Started" "Einführung" +"Keyboard Shortcuts" "Tastaturkürzel" +"Online Support" "Online Hilfe" + + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "RSS URL einspeisen!" +"Add" "Hinzufügen" +"Paste" "Einfügen" + +# Buttons directory list window +"Collapse All" "Collapse All" +"Preview" "Vorschau" +"Subscribe" "Bestellen" + + +# Buttons help window +"Next" "Weiter" +"Prev" "Zurück" +"Close" "Schließen" +"Index" "Index" + + +# Buttons remove windows +"Cancel" "Abbruch" +"Delete" "Löschen" +"Archive" "Ablegen" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Füge Podcast zur Anmeldungsliste hinzu" +"Delete the podcast from the Subscriptions list" "Entferne Podcast von der Anmeldeliste" +"Check the selected podcast for new items" "Prüfe ausgewählten Podcast nach neuen Einträgen" +"Show the podcast homepage" "Zeige die Podcast Homepage" + +"Delete the item and the enclosure" "Delete the item and the enclosure" +"Stop the item download" "Unterbreche den Download des Eintrages" +"Download the selected episode" "Lade die ausgewählte Folge herunter" +"Play the selected episode" "Spiele die ausgewählte Folge ab" + +"Submit bug and idea" "Teile Vorschläge und Fehler mit" + + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Collapse all categories in the directory list" +"Add the selected podcast to the Subscription list" "Füge ausgewählten Podcast zur Anmeldeliste hinzu" +"Checkout a podcast before downloading it" "Überprüfe den Podcast vor dem Download" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Zeige Kanal Abbild" +"XML Feed Link" "Link zur XML Einspeisung" + +"Show Episode info" "Zeige Inhalt der Folge" +"Show Subscription info" "Zeige Bestellinformation" +"Show Downloads info" "Zeige Download Informationen" + +"Enclosure: " "Anlage: " + +"Lookup (Dictionary)" "Suche (Wörterbuch)" +"Lookup (Google)" "Suche (Google)" +"Lookup (Acronym Finder)" "Suche (Kurzwort Finder)" +"Copy" "Kopieren" +"Select All" "Alle auswählen" +"Copy URL" "Kopiere URL" +"Open URL" "Öffne URL" +"Subscription" "Bestellung" + + + +### PREFERENCES ----------------------------------- + +"Preferences" "Einstellungen" + +"Proxy" "Proxy" +"Enable Proxy" "Aktiviere Proxy" +"Address" "Addresse" +"Port" "Port" +"Username" "Benutzername" +"Password" "Passwort" + +"Max Downloads" "Maximale Downloads" + +"FileType" "Dateitypen" +"Browser" "Browser" +"Player" "Player" + +"Channels" "Kanäle" +"Check all channels on startup" "Überprüfe alle Kanäle beim Start" +"Check the channel every" "Überprüfe die Kanäle jedesmal" + +"never" "Niemals" +"5 minutes" "5 Minuten" +"15 minutes" "15 Minuten" +"30 minutes" "30 Minuten" +"1 hour" "1 Stunde" +"2 hour" "2 Stunden" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 neuer Eintrag" +"%d new items" "%d neue Einträge" +"new" "Neu" +"error" "Fehler" +"not down" "Nicht heruntergeladen" +"enquequed" "In Warteschlange" +"downloading" "Herunterladen" +"downloaded" "Heruntergeladen" +"connecting" "Verbinde" +"not found" "Nicht gefunden" +"stopped" "Angehalten" +"can't connect" "Keine Verbindung möglich" +"invalid format" "Ungültiges Format" + +"Icon" "Icon" +"Title" "Titel" +"Date" "Datum" +"Size" "Größe" +"Status" "Status" +"Download" "Download" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "Füge Kanal hinzu" +"Remove Channel" "Entferne Kanal" +"Check Channel" "Prüfe Kanal" +"Open Homepage" "Öffne Homepage" + +"Open Web Page" "Öffne Webseite" +"Open Enclosures folder" "Öffne Anlagenordner" +"Check All Channels" "Prüfe alle Kanäle" + +"Show Channel Image" "Zeige Kanal Abbild" + +"Play enclosure" "Spiele Anlage ab" +"(Re)start download" "Starte Download (neu)" +"Stop download" "Unterbreche Download" +"Remove Item" "Entferne Eintrag" + +"Find this Item" "Find this Item" +"Remove from this list" "Remove from this list" + + + + +### ALERT ----------------------------------- + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" + +"Can't open the selected file with:\n\n" "Can't open the selected file with:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nPlease check if the application is installed in the right way.\n" +"Download it!" "Download it!" + +"\nRemoving.." "\nLösche.." +"\nAn error occured while removing!" "\nEin Fehler trat während des Löschens auf!" +"Check all the podcasts for new items" "Prüfe alle Podcasts nach neuen Einträgen" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +Sie sind im Begriff, den ausgewählten Eintrag zu löschen. + +Sind Sie sicher? +(Sie werden evtl. eingebundene Dateien verlieren)" + + +_key="alert2a" + _value=" +Sie sind im Begriff, folgenden Kanal zu löschen: + +" + +_key="alert2b" + _value=" + +Wünschen Sie diesen Kanal zu archivieren +(alle Dateien und Anhänge werden behalten) +or möchten Sie den kompletten Kanal LÖSCHEN?" + +_key="alert3" + _value=" +Durchsuche Archiv" + +_key="alert_3gp" + _value=" +3GP is a multimedia container format defined by the Third Generation Partnership Project (3GPP) for use on 3G mobile phones. It stores video streams as MPEG-4 or H.263, and audio streams as AMR-NB or AAC-LC. + +VideoLAN still doesn't support the audio AMR (3GPP)" + +_key="alert_swf" + _value=" +SWF is a proprietary vector graphics file format produced by the Flash software from Adobe (formerly Macromedia). + +Currently Flash support in BeOS/Haiku/Zeta is limited to the old standalone Flash player version 4.1015, there isn't a modern Flash player" + + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Einführung" +"The User Interface" "Die Benutzeroberfläche" +"Menu Bar" "Menüleiste" +"Toolbar Buttons" "Werkzeugleiste" +"First time with BePodder" "Das erste Mal mit BePodder" +"Download Podcast's enclosure files" "Lade Podcast Anlagen herunter" +"Settings Overview" "Einstellungen überblicken" +"Directory lists" "Verzeichnis Listen" +"Loading Help..." "Ladehilfe..." +"Register your copy" "Registriere deine Kopie" +"Starting point" "Ausgangspunkt" +"First time with BePodder" "Das erste Mal mit BePodder" + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value="Willkommen zur BePodder Starthilfe." + +_key="help1-1" + _value="Sollten Sie schon Erfahrungen bzgl. Podcasts und RSS Feeds besitzen, können Sie +direkt zu BePodder durch Schließen dieses Fensters wechseln." + +_key="help1-2" +_value="Falls nicht, erhalten Sie hier eine kurze Einführung, die Ihnen alles zeigt, was sie wissen müssen, um mit BePodder arbeiten zu können. Benutzen Sie die unteren Tasten für diese Einführung." + + +_key="help2-0" + _value="Podcasting beschreibt eine Methode, Audio und Video Sendungen über das Internet zu verbreiten. Links zu freien Audio und Video Dateien werden in RSS und Atom Feeds eingefügt." + +_key="help2-1" +_value="Dadurch ist Podcasting einfach eine Art der Online Medien Übertragung. Benutzer tragen sich in einen Podcast durch Verwenden des Feeds (Einspeisung) ein. Solche wie RSS 'Really Simple Syndication' oder Atom." + +_key="help2-2" +_value=" +Ein Aggregrat (oder Podfänger) wie BePodder ist eine Software, die es Ihnen ermöglicht, sich in eine RSS Einspeisung einzutragen und regelmäßig nach neuen Inhalten zu suchen. Mit BePodder können die nach neuen Podcasts, Einträgen und Folgen Ihrer eingetragenen Kanäle suchen. Ein Eintrag kann eine Anlage beinhalten, so wie Emails einen solchen besitzen können." + + +_key="help3-0" +_value="BePodder hat eine einfache, dennoch mächtige Benutzeroberfläche. Das Hauptfenster ist in drei Felder aufgeteilt:" + +_key="help3-1" +_value="1) The Subscription list (the panel with the number 1 in the screenshot) with the list of the podcasts that you have subscribed to. When you click on a Channel you can see in the panel 2 the list of the channel's items." + +_key="help3-2" +_value="2) Die Folge Liste mit allen verfügbaren Einträgen." + +_key="help3-3" +_value="3) Das Informationsfeld zeigt: Inhalt der Folgen, Kanal Informationen oder Download Informationen; Sie können ein Informationsfeld wählen, indem Sie eine der drei unteren Tasten anklicken." + + + +_key="help4-0" +_value="At the very top of the BePodder main window is the menubar with seven menus available: File, Settings, Subscriptions, Episodes, Lists, View and Help. Some menu commands are followed by a right pointing arrow that indicates a submenu of related commands. As you explore each menu, be sure to take a look at the submenus as well. Click on a menus to show its commands:" + +_key="help4-1" +_value="Datei: Enthält Befehle, die Anwendung zu schließen und Informationen über BePodder zu zeigen." + +_key="help4-2" +_value="Einstellungen: Enthält Befehle, das Präferenzen Fenster zu öffnen, das Ihnen erlaubt, verschiedene BePodder Einstellungen bevozugt anzufertigen." + +_key="help4-3" +_value="Bestellungen: Enthält Befehle, die Tätigkeiten für die gewählten Kanäle Ihrer Bestellliste durchführen." + +_key="help4-4" +_value="Folgen: Enthält Befehle, die Tätigkeiten für dem gewählten Eintrag (Folge) aus der Kanal Liste durchführen." + +_key="help4-5" +_value="Listen: Enthält Befehle, um OPML Verzeichnisse von BePodder zu öffnen." + +_key="help4-6" +_value="Ansicht: Enthält Befehle und Kontrollen für das BePodder Fenster." + +_key="help4-7" +_value="Hilfe: Enthält Befehle, um die BePodder Starthilfe und die Tastaturkürzel Übersicht zu öffnen." + + + +_key="help5-0" + _value="Add Button: opens the Add Window to add a feed url (e.g. http://www.newpodcast.com/rss.xml) usually given on the podcast homepage; looks for text or graphic link that says something like 'XML', 'RSS' or 'Podcast Feed' on it." + +_key="help5-1" + _value="Channel Remove Button: opens a window in which you can select how remove the channel: just archive the select channel (keeping all the files and eclosure downloaded so far) or delete the whole channel from your computer." + +_key="help5-2" + _value="Überprüfen Taste: überprüft den vorgewählten Kanal und aktualisiert die Liste der vorhandenen Einträge für den Podcast, indem die neuen Einträge hinzugefügt werden." + +_key="help5-3" + _value="Web Button: shows the channel homepage in the browser. To select your favorite browser open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select your favorite browser." + +_key="help5-4" + _value="Play Button: with this button you can view or listen the file enclosure of the selected item(episode). To select your favorite player open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select you favorite player." + +_key="help5-5" + _value="Herunterladen Taste: Läd die Anlage des gewählten Eintrages (Folge); Sie können die Downloadinformation sehen, indem Sie auf die dritte Taste über der Informatiosfeld klicken." + +_key="help5-6" + _value="Unterbrechen Taste: Unterbricht das Herunterladen der Anlage des gewählten Eintrages (Folge). Die Wiederaufnahme funktioniert mit einem Doppelklick oder über Betätigung der 'Herunterladen' Taste." + +_key="help5-7" + _value="Item Remove Button: deletes the selected item (you will loose the enclosure file)." + + + +_key="help6-0" + _value="Starten mit BePodder ist einfach." + +_key="help6-1" + _value="Auf der linken Seite sehen Sie Ihre Feed Einträge. Wir haben bereits ein paar Einträge für Sie übernommen und sie können eigene auf zwei Arten hinzufügen:" + +_key="help6-2" + _value="1) Klicken Sie die 'Hinzufügen' Taste, geben Sie die URL der Einspeisung ( Beispiel: http://www.newpodcast.com/rss.xml) ein und klicken Sie auf 'Hinzufügen'." + +_key="help6-3" + _value="2) Wählen Sie 'Verzeichnis' im Menu und anschließend 'Podcast Liste' oder 'Videoblog Liste' aus, suchen sie einen Podcast und klicken sie 'Anmelden'." + +_key="help6-4" + _value="Wenn Sie einen Podcast in Ihrer Liste auswählen und die 'Überprüfen' Taste auswählen, wird BePodder neue Einträge zu der 'Folgen Liste' rechts hinzufügen; Sie können alle Ihre Podcasts überprüfen, indem Sie einen Rechtsklick tätigen und 'Prüfe Alle Kanäle' auswählen." + +_key="help6-5" + _value="Look at the screenshot above, there are 3 new items indicated by a black dot in the first column of the 'Episodes list'." + +_key="help6-6" + _value="In the second column there are icons that indicate the state of the item:" + +_key="help6-7" + _value="- the Episode 4 has an icon that indicates an error" + +_key="help6-8" + _value="- the Episode 3 has an icon that indicates that the item's enclosure download request is enquequed" + +_key="help6-9" + _value="- the Episode 2 has an icon that indicates that BePodder is downloading the item's enclosure file" + +_key="help6-10" + _value="- the Episode 1 has an icon that indicates that BePodder have just downloaded the item's enclosure file" + + + +_key="help7-0" + _value="Wählen Sie einen Eintrag aus der Liste der Folgen aus, klicken diesen doppelt oder wählen Sie die Download Taste. Sie können einen Download immer durch Betätigen der Stop Taste anhalten." + +_key="help7-1" + _value="Wenn Sie einen Podcast aus der Eintrag Liste auswählen, zeigt Ihnen die Software eine Liste an Folgen mit allen Einträgen, die bzgl. dieser Anmeldung zur Verfügung stehen. +Wählen Sie einen Eintrag aus und klicken Sie auf den Abspielbutton um die Datei zu sehen/hören." + +_key="help7-2" + _value="Sie können auf das Anlage Verzeichnis zugreifen, wenn Sie das Verzeichnis Icon im Info Feld auswählen, oder durch einen Rechtsclick mit Ihrer Maus und Auswahl von 'Öffne Inhaltsordner'." + + +_key="help8-0" + _value="Preferences can be accessed by clicking in the menu-bar Settings>Preferences. You can select a category from the left list of the preferences dialog: FileType, Channels, Download and Proxy." + +_key="help8-1" + _value="- FileType: to specify the default browser and player. " + +_key="help8-2" + _value="- Channels: to specify preferences that control the operation to check channels new items; you can choose to Check all channels on startup or check the channel every desired minutes." + +_key="help8-3" + _value="- Download: to specify the max number of item's files to download at the same time," + +_key="help8-4" + _value="- Proxy: to set up a proxy server to work with BePodder; a proxy server acts as a security barrier between your internal network and the Internet, keeping others on the Internet from accessing information on your internal network." + + + +_key="help9-0" + _value="BePodder has built-in podcast, videoblog, imagefeeds, newsfeeds, bittorrentfeeds and internationalfeeds OPML directories with thousands of feeds grouped by category." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) is an XML-based format that allows exchange of outline-structured information between applications." + +_key="help9-2" + _value="OPML directory can be accessed by clicking in the menu-bar 'Lists' and thenselecting a list. To browse the opml directory for a feed, expand the list by clicking the arrow of the category that you are interested in (see image); using this method, you can expand the opml directory until you find the desired feed. Once you have selected it, you can add it to the subscription list by clicking the button 'Subscribe', you can also collapse all categories in the directory list by clicking the button 'Collapse All'." + + +_key="help_shortcut1" +_value="Diese Seite beschreibt die Tastaturkürzel, die in BePodder benutzt werden können. Die Abkürzungen werden nach Funktion gruppiert." + +_key="help_shortcut2" +_value="Das bedeutet, daß Sie entweder Alt oder Steuerung verwenden. In Abhängigkeit zu Ihren Tastatur Einstellungen in den Deskbar Präferenzen. (Beispiel Alt+Q oder Ctrl+Q für Beenden der Anwendung)" + +_key="help_shortcut3" + _value="Allgemeine Kürzel" + +_key="help_shortcut4" + _value="Beendet das Programm" + +_key="help_shortcut5" + _value="Zeigt die bevorzugten Einstellungen" + +_key="help_shortcut6" + _value="Zeigt die Verzeichnisliste der Podcasts" + +_key="help_shortcut7" + _value="Zeigt die Verzeichnisliste der Videoblogs" + +_key="help_shortcut8" + _value="Zeigt die Verzeichnisliste der Bildeinspeisungen" + +_key="help_shortcut9" + _value="Zeigt die Verzeichnisliste der Nachrichteneinspeisungen" + +_key="help_shortcut9b" + _value="Zeigt die Verzeichnisliste der BitTorrentfeeds" + +_key="help_shortcut9c" + _value="Zeigt die Verzeichnisliste der Internationalfeeds" + +_key="help_shortcut10" + _value="Vollbild" + +_key="help_shortcut11" + _value="Zeigt/Versteckt die Werkzeugleiste" + +_key="help_shortcut12" + _value="Zeigt die Starthilfe" + +_key="help_shortcut13" + _value="Zeigt die Übersicht der Tastatur Kürzel" + +_key="help_shortcut14" + _value="Kanal Kürzel" + +_key="help_shortcut15" + _value="Fügt einen Podcast der Bestellliste hinzu" + +_key="help_shortcut16" + _value="Löscht den ausgewählten Podcast von der Bestellliste" + +_key="help_shortcut17" + _value="Überprüft den ausgewählten Podcast nach neuen Folgen (Einträgen)" + +_key="help_shortcut18" + _value="Überprüft alle ausgewählten Podcast nach neuen Folgen (Einträgen)" + +_key="help_shortcut19" + _value="Zeigt die Podcast Homepage" + +_key="help_shortcut20" + _value="Öffnet den Anlagenordner" + +_key="help_shortcut21" + _value="Folgen Kürzel" + +_key="help_shortcut22" + _value="Spielt Anlagen ab" + +_key="help_shortcut23" + _value="Startet Download der ausgewählten Folge (Eintrag) neu" + +_key="help_shortcut24" + _value="Unterbricht den Download der Folge (Eintrag)" + +_key="help_shortcut25" + _value="Löscht die ausgewählte Folge (Eintrag)" + +_key="help_shortcut26" + _value="Zeigt die Podcast Folge (Eintrag) Seite" + +_key="help_shortcut27" + _value="Öffnet den Anlagenordner" + +_key="help_buy1" + _value="BePodder Light is the basic version (free download and no time limited), the registered version adds some more nice features: unlimited number of channels, small Channel view, proxy support, automatic channels check, up to 5 enclosure downloads at the same time (multithreading)." + +_key="help_buy2" + _value="Bitte bezahlen Sie die Shareware Gebühr. Es sind nur 15 Euro (Kagi fügt in einigen Ländern Steuern hinzu), Die BePodder Lizenz kann online von Kagi gekauft werden." + +_key="help_buy3" + _value="Kaufe über www.funkyideasoft.com" + +_key="help_buy4" + _value="Nach dem Kauf wird Ihnen eine E-Mail mit der Schlüsseldatei und einer Anweisung zugesandt, wie die Schlüsseldatei zu installieren ist. Es ist nur ein kleiner Schritt, die Datei zu entpacken und sie in ein bestimmtes Verzeichnis zu bewegen." + +_key="help_buy5" + _value="Es gibt keine Schwierigkeiten, BePodder zu aktualisieren, wenn eine neue Version verfügbar ist. Die Schlüsseldatei wird alle heruntergeladenen Pakete aufschließen, wenn nichts anderes vereinbart wird." + + +### USELESS ######## + +"Opml Editor" "Opml Editor" +"name:" "Name:" +"Add a categorie" "Kategorie hinzufügen" +"Add a new Broadcast" "Ausstrahlung hinzufügen" +"feed:" "Einspeisung:" +"url:" "URL:" +"Test podcast" "Podcast testen" +"Del a categorie" "Eine Kategorie löschen" +"Add a categorie" "Eine Kategorie hinzufügen" +"Select the podcast categorie:" "Podcast Kategorie auswählen:" +"Check all" "Prüfe alle" +"Check" "Prüfe" +"Refresh the list" "Liste erneuern" +"Load" "Laden" +"Load the list" "Liste laden" +"Save" "Speichern" +"Save the list" "Liste speichern" +"Revert" "Zurückkehren" +"Apply" "Anwenden" + + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.enUK b/release/Language/Dictionaries/BePodder.enUK new file mode 100644 index 0000000..296dac8 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.enUK @@ -0,0 +1,604 @@ + +# Locale file for BePodder. +# Modified: 4/18/2006 +# Author: BePodderTeam +# E-mail: bepodder.team@gmail.com + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" + +"Web Site" "Web Site" + +"Can't connect!" "Can't connect!" +"Http port failed!" "Http port failed!" +"Can't resolve host!" "Can't resolve host!" +"Not found!" "Not found!" +"Bad resume!" "Bad resume!" +"Aborted by Callback!" "Aborted by Callback!" +"Can't resume! (range error)" "Can't resume! (range error)" +"Access Denied!" "Access Denied!" +"User or Password Incorrect!" "User or Password Incorrect!" +"Other error (cUrl code: " "Other error (cUrl code: " +"cUrl init error!" "cUrl init error!" +"Can't open file!" "Can't open file!" +"Other error (status code: " "Other error (status code: " +"Downloading" "Downloading" + + +### MENUBAR ----------------------------------- + +"File" "File" +"About..." "About..." +"Close!" "Close!" +"Quit" "Quit" + +"Settings" "Settings" +"Preferences..." "Preferences..." + +"Subscriptions" "Subscriptions" + +"Episodes" "Episodes" + +"Lists" "Lists" +"Podcast List" "Podcast List" +"Podcast directory list" "Podcast directory list" +"Videoblog List" "Videoblog List" +"Videoblog directory list" "Videoblog directory list" +"Imagefeeds List" "Imagefeeds List" +"Imagefeeds directory list" "Imagefeeds directory list" +"Newsfeeds List" "Newsfeeds List" +"Newsfeeds directory list" "Newsfeeds directory list" +"BitTorrentfeeds List" "BitTorrentfeeds List" +"BitTorrentfeeds directory list" "BitTorrentfeeds directory list" +"Internationalfeeds List" "Internationalfeeds List" +"Internationalfeeds directory list" "Internationalfeeds directory list" + +"View" "View" +"Full Screen" "Full Screen" +"Toolbar" "Toolbar" +"Subscriptions View" "Subscriptions View" +"Small Items" "Small Items" +"Big Items" "Big Items" +"Move BePodder on workspace:" "Move BePodder on workspace:" + +"Help" "Help" +"Getting Started" "Getting Started" +"Keyboard Shortcuts" "Keyboard Shortcuts" +"Tutorials" "Tutorials" +"Online Support" "Online Support" + + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "Insert the rss feed url!" +"Add" "Add" +"Paste" "Paste" + +# Buttons directory list window +"Collapse All" "Collapse All" +"Preview" "Preview" +"Subscribe" "Subscribe" + + +# Buttons help window +"Next" "Next" +"Prev" "Prev" +"Close" "Close" +"Index" "Index" + + +# Buttons remove windows +"Cancel" "Cancel" +"Delete" "Delete" +"Archive" "Archive" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Add the podcast to the Subscriptions list" +"Delete the podcast from the Subscriptions list" "Delete the podcast from the Subscriptions list" +"Check the selected podcast for new items" "Check the selected podcast for new items" +"Show the podcast homepage" "Show the podcast homepage" + +"Delete the item and the enclosure" "Delete the item and the enclosure" +"Stop the item download" "Stop the item download" +"Download the selected episode" "Download the selected episode" +"Play the selected episode" "Play the selected episode" + +"Submit bug and idea" "Submit bug and idea" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Collapse all categories in the directory list" +"Add the selected podcast to the Subscription list" "Add the selected podcast to the Subscription list" +"Checkout a podcast before downloading it" "Checkout a podcast before downloading it" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Show Channel Image" +"XML Feed Link" "XML Feed Link" + +"Show Episode info" "Show Episode info" +"Show Subscription info" "Show Subscription info" +"Show Downloads info" "Show Downloads info" + +"Enclosure: " "Enclosure: " + +"Lookup (Dictionary)" "Lookup (Dictionary)" +"Lookup (Google)" "Lookup (Google)" +"Lookup (Acronym Finder)" "Lookup (Acronym Finder)" +"Copy" "Copy" +"Select All" "Select All" +"Copy URL" "Copy URL" +"Open URL" "Open URL" +"Subscription" "Subscription" + + +### PREFERENCES ----------------------------------- + +"Preferences" "Preferences" + +"Proxy" "Proxy" +"Enable Proxy" "Enable Proxy" +"Address" "Address" +"Port" "Port" +"Username" "Username" +"Password" "Password" + +"Max Downloads" "Max Downloads" + +"FileType" "FileType" +"Browser" "Browser" +"Player" "Player" + +"Channels" "Channels" +"Check all channels on startup" "Check all channels on startup" +"Check the channel every" "Check the channel every" + +"never" "never" +"5 minutes" "5 minutes" +"15 minutes" "15 minutes" +"30 minutes" "30 minutes" +"1 hour" "1 hour" +"2 hour" "2 hour" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 new item" +"%d new items" "%d new items" +"new" "new" +"error" "error" +"not down" "not down" +"enquequed" "enquequed" +"downloading" "downloading" +"downloaded" "downloaded" +"connecting" "connecting" +"not found" "not found" +"stopped" "stopped" +"can't connect" "can't connect" +"invalid format" "invalid format" + +"Icon" "Icon" +"Title" "Title" +"Date" "Date" +"Size" "Size" +"Status" "Status" +"Download" "Download" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "Add Channel" +"Remove Channel" "Remove Channel" +"Check Channel" "Check Channel" +"Open Homepage" "Open Homepage" + +"Open Web Page" "Open Web Page" +"Open Enclosures folder" "Open Enclosures folder" +"Check All Channels" "Check All Channels" + +"Show Channel Image" "Show Channel Image" + +"Play enclosure" "Play enclosure" +"(Re)start download" "(Re)start download" +"Stop download" "Stop download" +"Remove Item" "Remove Item" + +"Find this Item" "Find this Item" +"Remove from this list" "Remove from this list" + + + +### ALERT ----------------------------------- + +"\nRemoving.." "\nRemoving.." +"\nAn error occured while removing!" "\nAn error occured while removing!" +"Check all the podcasts for new items" "Check all the podcasts for new items" + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" + + +"Can't open the selected file with:\n\n" "Can't open the selected file with:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nPlease check if the application is installed in the right way.\n" +"Download it!" "Download it!" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +You are going to remove the selected item. + +Are you sure? +(you will lost the enclosure file if any)" + + +_key="alert2a" + _value=" +You are going to remove the channel: + +" + +_key="alert2b" + _value=" + +Would you like just to archive this +channel (keeping all the files and +enclosures downloaded so far) or +do you want to DELETE the whole + channel from you computer?" + +_key="alert3" + _value=" +Parsing archive.." + +_key="alert_3gp" + _value=" +3GP is a multimedia container format defined by the Third Generation Partnership Project (3GPP) for use on 3G mobile phones. It stores video streams as MPEG-4 or H.263, and audio streams as AMR-NB or AAC-LC. + +VideoLAN still doesn't support the audio AMR (3GPP)" + +_key="alert_swf" + _value=" +SWF is a proprietary vector graphics file format produced by the Flash software from Adobe (formerly Macromedia). + +Currently Flash support in BeOS/Haiku/Zeta is limited to the old standalone Flash player version 4.1015, there isn't a modern Flash player" + + + + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Introduction" +"The User Interface" "The User Interface" +"Menu Bar" "Menu Bar" +"Toolbar Buttons" "Toolbar Buttons" +"First time with BePodder" "First time with BePodder" +"Download Podcast's enclosure files" "Download Podcast's enclosure files" +"Settings Overview" "Settings Overview" +"Directory lists" "Directory lists" +"Loading Help..." "Loading Help..." +"Register your copy" "Register your copy" +"Starting point" "Starting point" + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value="Welcome to the BePodder Getting Started Guide." + +_key="help1-1" + _value="If you are already familiar with podcasts and RSS/Atom feeds you can immediately go to BePodder by closing this window." + +_key="help1-2" +_value="If not, this is a short introduction providing you everything you'll need to know on how to get started with BePodder. Use the buttons below to navigate through this tutorial." + + +_key="help2-0" +_value="Podcasting is a method for publishing audio and video broadcasts via the Internet; links to free audio and video files are enclosed in RSS and Atom feeds." + +_key="help2-1" +_value="Therefore Podcasting is simply a type of online media delivery; users can subscribe to a podcast using a feed (such as RSS 'Really Simple Syndication' or Atom)." + +_key="help2-2" +_value="An aggregator (or podcatcher) like BePodder, is a piece of software that allows you to subscribe to a RSS feed and periodically check for and download new content; with BePodder you can check for new Podcast items (Episodes) of your subscribed Channels. Any item can contain an enclosure, just like an Email can contain an attachment." + + + +_key="help3-0" +_value="BePodder has an easy to use yet powerful Graphical User Interface. The main window is split into tree panels:" + +_key="help3-1" +_value="1) The Subscription list (the panel with the number 1 in the screenshot) with the list of the podcasts that you have subscribed to. When you click on a Channel you can see in the panel 2 the list of the channel's items." + +_key="help3-2" +_value="2) The Episodes list with all the items available." + +_key="help3-3" +_value="3) The Info panel show: episode info, channel info or Downloads info; you can select an info panel by clicking one of the below three buttons." + + + +_key="help4-0" +_value="At the very top of the BePodder main window is the menubar with seven menus available: File, Settings, Subscriptions, Episodes, Lists, View and Help. Some menu commands are followed by a right pointing arrow that indicates a submenu of related commands. As you explore each menu, be sure to take a look at the submenus as well. Click on a menus to show its commands:" + +_key="help4-1" +_value="File: contains commands to close the application and to show information about BePodder" + +_key="help4-2" +_value="Settings: contains command to open the Preferences window that allows you to customize various BePodder settings." + +_key="help4-3" +_value="Subscriptions: contains commands that perform actions on the selected channel of your subscriptions list." + +_key="help4-4" +_value="Episodes: contains commands that perform actions on the selected item (episode) of the channel's episode list." + +_key="help4-5" +_value="Lists: contains commands to open BePodder's OPML directories." + +_key="help4-6" +_value="View: contains commands and controls for the BePodder window." + +_key="help4-7" +_value="Help: contains commands to open BePodder's 'Getting Started Guide' and the 'Keyboard Shortcuts List'." + + + +_key="help5-0" + _value="Add Button: opens the Add Window to add a feed url (e.g. http://www.newpodcast.com/rss.xml) usually given on the podcast homepage; looks for text or graphic link that says something like 'XML', 'RSS' or 'Podcast Feed' on it." + +_key="help5-1" + _value="Channel Remove Button: opens a window in which you can select how remove the channel: just archive the select channel (keeping all the files and eclosure downloaded so far) or delete the whole channel from your computer." + +_key="help5-2" + _value="Check Button: checks the selected channel and updates the list of the available items for that podcast adding the new items." + +_key="help5-3" + _value="Web Button: shows the channel homepage in the browser. To select your favorite browser open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select your favorite browser." + +_key="help5-4" + _value="Play Button: with this button you can view or listen the file enclosure of the selected item(episode). To select your favorite player open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select you favorite player." + +_key="help5-5" + _value="Download Button: downloads the file enclosure of the selected item (episode); you can see the download info by clicking on the third button over the info panel." + +_key="help5-6" + _value="Stop Button: stops to download the file enclosure of the selected item (episode); to resume the download double-click the item (episode) or select the item and click the Download Button" + +_key="help5-7" + _value="Item Remove Button: deletes the selected item (you will loose the enclosure file)." + + + +_key="help6-0" + _value="Getting started with BePodder is easy." + +_key="help6-1" + _value="On the left of the main window you can see the 'Subscription List' with all your feed subscriptions. We have added some subscriptions for you, and you can always add your own in two ways:" + +_key="help6-2" + _value="1) click the Add Button, then insert the feed url (example: http://www.newpodcast.com/rss.xml) and click add." + +_key="help6-3" + _value="2) in the menubar select 'Directory' and then 'Podcast list' or another list, choose a podcast and click 'Subscribe'." + +_key="help6-4" + _value="If you select a Podcast in the subscriptions list and use the check button, BePodder adds the new items to the 'Episodes list' (below on the right); you can check all your podcasts by right-clicking and selecting 'Check All Channels' in the context menu." + +_key="help6-5" + _value="Look at the screenshot above, there are 3 new items indicated by a black dot in the first column of the 'Episodes list'." + +_key="help6-6" + _value="In the second column there are icons that indicate the state of the item:" + +_key="help6-7" + _value="- the Episode 4 has an icon that indicates an error" + +_key="help6-8" + _value="- the Episode 3 has an icon that indicates that the item's enclosure download request is enquequed" + +_key="help6-9" + _value="- the Episode 2 has an icon that indicates that BePodder is downloading the item's enclosure file" + +_key="help6-10" + _value="- the Episode 1 have an icon that indicates that BePodder have just downloaded the item's enclosure file" + + + +_key="help7-0" + _value="Select an item in the 'Episodes list' and then double-click on it (or click the Download Button) to start downloading the enclosed file; you can always stop the download by clicking on the Stop Button." + +_key="help7-1" + _value="When you click on the Subscribed Podcasts in the 'Subscriptions List' the software shows you, in the 'List of episodes', all the items available in that Subscription. Select an item and then click play (Play Button) to view or listen to the file." + +_key="help7-2" + _value="You can access the Enclosures Folder by clicking on the folder icon in the Info Pannel or by right-clicking your mouse on an item and select 'Open Enclosures Folder' in the context menu." + + + +_key="help8-0" + _value="Preferences can be accessed by clicking in the menu-bar Settings>Preferences. You can select a category from the left list of the preferences dialog: FileType, Channels, Download and Proxy." + +_key="help8-1" + _value="- FileType: to specify the default browser and player. " + +_key="help8-2" + _value="- Channels: to specify preferences that control the operation to check channels new items; you can choose to Check all channels on startup or check the channel every desired minutes." + +_key="help8-3" + _value="- Download: to specify the max number of item's files to download at the same time," + +_key="help8-4" + _value="- Proxy: to set up a proxy server to work with BePodder; a proxy server acts as a security barrier between your internal network and the Internet, keeping others on the Internet from accessing information on your internal network." + + + +_key="help9-0" + _value="BePodder has built-in podcast, videoblog, imagefeeds, newsfeeds, bittorrentfeeds and internationalfeeds OPML directories with thousands of feeds grouped by category." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) is an XML-based format that allows exchange of outline-structured information between applications." + +_key="help9-2" + _value="OPML directory can be accessed by clicking in the menu-bar 'Lists' and thenselecting a list. To browse the opml directory for a feed, expand the list by clicking the arrow of the category that you are interested in (see image); using this method, you can expand the opml directory until you find the desired feed. Once you have selected it, you can add it to the subscription list by clicking the button 'Subscribe', you can also collapse all categories in the directory list by clicking the button 'Collapse All'." + +_key="help_shortcut1" +_value="This page describes the keyboard shortcuts that can be used in BePodder. The shortcuts are grouped here by function." + +_key="help_shortcut2" +_value="means that you can use either alt or control (es. Alt+Q or Ctrl+Q Quit the application), which way you have set it in the Deskbar menu preferences under Keyboard (the default shortcut key is Alt)." + +_key="help_shortcut3" + _value="General shortcuts" + +_key="help_shortcut4" + _value="Quit the application" + +_key="help_shortcut5" + _value="Shows the Preferences window" + +_key="help_shortcut6" + _value="Shows the Podcast directory list" + +_key="help_shortcut7" + _value="Shows the Videoblog directory list" + +_key="help_shortcut8" + _value="Shows the Imagefeeds directory list" + +_key="help_shortcut9" + _value="Shows the Newsfeeds directory list" + +_key="help_shortcut9b" + _value="Shows the BitTorrentfeeds directory list" + +_key="help_shortcut9c" + _value="Shows the Internationalfeeds directory list" + +_key="help_shortcut10" + _value="Fullscreen" + +_key="help_shortcut11" + _value="Shows/Hides the toolbar" + +_key="help_shortcut12" + _value="Shows the Getting Started Help" + +_key="help_shortcut13" + _value="Shows this keyboard shortcuts page" + +_key="help_shortcut14" + _value="Channels shortcuts" + +_key="help_shortcut15" + _value="Add a podcast to the subscriptions list" + +_key="help_shortcut16" + _value="Delete the selected podcast from the subscriptions list" + +_key="help_shortcut17" + _value="Check the selected podcast for new episodes (items)" + +_key="help_shortcut18" + _value="Check all podcasts for new episodes (items)" + +_key="help_shortcut19" + _value="Shows the podcast homepage" + +_key="help_shortcut20" + _value="Open enclosures folder" + +_key="help_shortcut21" + _value="Episodes shortcuts" + +_key="help_shortcut22" + _value="Play enclosure" + +_key="help_shortcut23" + _value="(Re)start download the selected episodes (items)" + +_key="help_shortcut24" + _value="Stop the episode (item) download" + +_key="help_shortcut25" + _value="Delete the selected episode (item)" + +_key="help_shortcut26" + _value="Shows the podcast episode (item) page " + +_key="help_shortcut27" + _value="Open enclosures folder" + +_key="help_buy1" + _value="BePodder Light is the basic version (free download and no time limited), the registered version adds some more nice features: unlimited number of channels, small Channel view, proxy support, automatic channels check, up to 5 enclosure downloads at the same time (multithreading)." + +_key="help_buy2" + _value="Please pay the shareware fee, it's only 15 euro (Kagi add tax in some countries), BePodder licence can be purchased online from Kagi." + +_key="help_buy3" + _value="Buy at www.funkyideasoft.com" + +_key="help_buy4" + _value="After purchasing, an email will be sent to you with a keyfile and instruction on how to install it. It's just a matter of unzipping a file and moving it to a certain directory." + +_key="help_buy5" + _value="There is no problem updating BePodder when a new version becomes available. The keyfile will unlock all downloadable packages unless otherwise notified." + + +### USELESS ######## + +"Opml Editor" "Opml Editor" +"name:" "name:" +"Add a category" "Add a category" +"Add a new Broadcast" "Add a new Broadcast" +"feed:" "feed:" +"url:" "url:" +"Test podcast" "Test podcast" +"Del a category" "Del a category" +"Add a category" "Add a category" +"Select the podcast category:" "Select the podcast category:" +"Check all" "Check all" +"Check" "Check" +"Refresh the list" "Refresh the list" +"Load" "Load" +"Load the list" "Load the list" +"Save" "Save" +"Save the list" "Save the list" +"Revert" "Revert" +"Apply" "Apply" + + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.enUS b/release/Language/Dictionaries/BePodder.enUS new file mode 100644 index 0000000..5e3a268 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.enUS @@ -0,0 +1,605 @@ + +# Locale file for BePodder. +# Modified: 4/18/2006 +# Author: BePodderTeam +# E-mail: bepodder.team@gmail.com + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" + +"Web Site" "Web Site" + +"Can't connect!" "Can't connect!" +"Http port failed!" "Http port failed!" +"Can't resolve host!" "Can't resolve host!" +"Not found!" "Not found!" +"Bad resume!" "Bad resume!" +"Aborted by Callback!" "Aborted by Callback!" +"Can't resume! (range error)" "Can't resume! (range error)" +"Access Denied!" "Access Denied!" +"User or Password Incorrect!" "User or Password Incorrect!" +"Other error (cUrl code: " "Other error (cUrl code: " +"cUrl init error!" "cUrl init error!" +"Can't open file!" "Can't open file!" +"Other error (status code: " "Other error (status code: " +"Downloading" "Downloading" + + +### MENUBAR ----------------------------------- + +"File" "File" +"About..." "About..." +"Close!" "Close!" +"Quit" "Quit" + +"Settings" "Settings" +"Preferences..." "Preferences..." + +"Subscriptions" "Subscriptions" + +"Episodes" "Episodes" + +"Lists" "Lists" +"Podcast List" "Podcast List" +"Podcast directory list" "Podcast directory list" +"Videoblog List" "Videoblog List" +"Videoblog directory list" "Videoblog directory list" +"Imagefeeds List" "Imagefeeds List" +"Imagefeeds directory list" "Imagefeeds directory list" +"Newsfeeds List" "Newsfeeds List" +"Newsfeeds directory list" "Newsfeeds directory list" +"BitTorrentfeeds List" "BitTorrentfeeds List" +"BitTorrentfeeds directory list" "BitTorrentfeeds directory list" +"Internationalfeeds List" "Internationalfeeds List" +"Internationalfeeds directory list" "Internationalfeeds directory list" + +"View" "View" +"Full Screen" "Full Screen" +"Toolbar" "Toolbar" +"Subscriptions View" "Subscriptions View" +"Small Items" "Small Items" +"Big Items" "Big Items" +"Move BePodder on workspace:" "Move BePodder on workspace:" + +"Help" "Help" +"Getting Started" "Getting Started" +"Keyboard Shortcuts" "Keyboard Shortcuts" +"Tutorials" "Tutorials" +"Online Support" "Online Support" + + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "Insert the rss feed url!" +"Add" "Add" +"Paste" "Paste" + +# Buttons directory list window +"Collapse All" "Collapse All" +"Preview" "Preview" +"Subscribe" "Subscribe" + + +# Buttons help window +"Next" "Next" +"Prev" "Prev" +"Close" "Close" +"Index" "Index" + + +# Buttons remove windows +"Cancel" "Cancel" +"Delete" "Delete" +"Archive" "Archive" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Add the podcast to the Subscriptions list" +"Delete the podcast from the Subscriptions list" "Delete the podcast from the Subscriptions list" +"Check the selected podcast for new items" "Check the selected podcast for new items" +"Show the podcast homepage" "Show the podcast homepage" + +"Delete the item and the enclosure" "Delete the item and the enclosure" +"Stop the item download" "Stop the item download" +"Download the selected episode" "Download the selected episode" +"Play the selected episode" "Play the selected episode" + +"Submit bug and idea" "Submit bug and idea" +"Collapse all categories in the directory list" "Collapse all categories in the directory list" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Collapse all categories in the directory list" +"Add the selected podcast to the Subscription list" "Add the selected podcast to the Subscription list" +"Checkout a podcast before downloading it" "Checkout a podcast before downloading it" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Show Channel Image" +"XML Feed Link" "XML Feed Link" + +"Show Episode info" "Show Episode info" +"Show Subscription info" "Show Subscription info" +"Show Downloads info" "Show Downloads info" + +"Enclosure: " "Enclosure: " + +"Lookup (Dictionary)" "Lookup (Dictionary)" +"Lookup (Google)" "Lookup (Google)" +"Lookup (Acronym Finder)" "Lookup (Acronym Finder)" +"Copy" "Copy" +"Select All" "Select All" +"Copy URL" "Copy URL" +"Open URL" "Open URL" +"Subscription" "Subscription" + + +### PREFERENCES ----------------------------------- + +"Preferences" "Preferences" + +"Proxy" "Proxy" +"Enable Proxy" "Enable Proxy" +"Address" "Address" +"Port" "Port" +"Username" "Username" +"Password" "Password" + +"Max Downloads" "Max Downloads" + +"FileType" "FileType" +"Browser" "Browser" +"Player" "Player" + +"Channels" "Channels" +"Check all channels on startup" "Check all channels on startup" +"Check the channel every" "Check the channel every" + +"never" "never" +"5 minutes" "5 minutes" +"15 minutes" "15 minutes" +"30 minutes" "30 minutes" +"1 hour" "1 hour" +"2 hour" "2 hour" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 new item" +"%d new items" "%d new items" +"new" "new" +"error" "error" +"not down" "not down" +"enquequed" "enquequed" +"downloading" "downloading" +"downloaded" "downloaded" +"connecting" "connecting" +"not found" "not found" +"stopped" "stopped" +"can't connect" "can't connect" +"invalid format" "invalid format" + +"Icon" "Icon" +"Title" "Title" +"Date" "Date" +"Size" "Size" +"Status" "Status" +"Download" "Download" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "Add Channel" +"Remove Channel" "Remove Channel" +"Check Channel" "Check Channel" +"Open Homepage" "Open Homepage" + +"Open Web Page" "Open Web Page" +"Open Enclosures folder" "Open Enclosures folder" +"Check All Channels" "Check All Channels" + +"Show Channel Image" "Show Channel Image" + +"Play enclosure" "Play enclosure" +"(Re)start download" "(Re)start download" +"Stop download" "Stop download" +"Remove Item" "Remove Item" + +"Find this Item" "Find this Item" +"Remove from this list" "Remove from this list" + + + +### ALERT ----------------------------------- + +"\nRemoving.." "\nRemoving.." +"\nAn error occured while removing!" "\nAn error occured while removing!" +"Check all the podcasts for new items" "Check all the podcasts for new items" + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" + +"Can't open the selected file with:\n\n" "Can't open the selected file with:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nPlease check if the application is installed in the right way.\n" +"Download it!" "Download it!" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +You are going to remove the selected item. + +Are you sure? +(you will lost the enclosure file if any)" + + +_key="alert2a" + _value=" +You are going to remove the channel: + +" + +_key="alert2b" + _value=" + +Would you like just to archive this +channel (keeping all the files and +enclosures downloaded so far) or +do you want to DELETE the whole + channel from you computer?" + +_key="alert3" + _value=" +Parsing archive.." + +_key="alert_3gp" + _value=" +3GP is a multimedia container format defined by the Third Generation Partnership Project (3GPP) for use on 3G mobile phones. It stores video streams as MPEG-4 or H.263, and audio streams as AMR-NB or AAC-LC. + +VideoLAN still doesn't support the audio AMR (3GPP)" + +_key="alert_swf" + _value=" +SWF is a proprietary vector graphics file format produced by the Flash software from Adobe (formerly Macromedia). + +Currently Flash support in BeOS/Haiku/Zeta is limited to the old standalone Flash player version 4.1015, there isn't a modern Flash player" + + + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Introduction" +"The User Interface" "The User Interface" +"Menu Bar" "Menu Bar" +"Toolbar Buttons" "Toolbar Buttons" +"First time with BePodder" "First time with BePodder" +"Download Podcast's enclosure files" "Download Podcast's enclosure files" +"Settings Overview" "Settings Overview" +"Directory lists" "Directory lists" +"Loading Help..." "Loading Help..." +"Register your copy" "Register your copy" +"Starting point" "Starting point" + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value="Welcome to the BePodder Getting Started Guide." + +_key="help1-1" + _value="If you are already familiar with podcasts and RSS/Atom feeds you can immediately go to BePodder by closing this window." + +_key="help1-2" +_value="If not, this is a short introduction providing you everything you'll need to know on how to get started with BePodder. Use the buttons below to navigate through this tutorial." + + + +_key="help2-0" +_value="Podcasting is a method for publishing audio and video broadcasts via the Internet; links to free audio and video files are enclosed in RSS and Atom feeds." + +_key="help2-1" +_value="Therefore Podcasting is simply a type of online media delivery; users can subscribe to a podcast using a feed (such as RSS 'Really Simple Syndication' or Atom)." + +_key="help2-2" +_value="An aggregator (or podcatcher) like BePodder, is a piece of software that allows you to subscribe to a RSS feed and periodically check for and download new content; with BePodder you can check for new Podcast items (Episodes) of your subscribed Channels. Any item can contain an enclosure, just like an Email can contain an attachment." + + + +_key="help3-0" +_value="BePodder has an easy to use yet powerful Graphical User Interface. The main window is split into tree panels:" + +_key="help3-1" +_value="1) The Subscription list (the panel with the number 1 in the screenshot) with the list of the podcasts that you have subscribed to. When you click on a Channel you can see in the panel 2 the list of the channel's items." + +_key="help3-2" +_value="2) The Episodes list with all the items available." + +_key="help3-3" +_value="3) The Info panel show: episode info, channel info or Downloads info; you can select an info panel by clicking one of the below three buttons." + + + +_key="help4-0" +_value="At the very top of the BePodder main window is the menubar with seven menus available: File, Settings, Subscriptions, Episodes, Lists, View and Help. Some menu commands are followed by a right pointing arrow that indicates a submenu of related commands. As you explore each menu, be sure to take a look at the submenus as well. Click on a menus to show its commands:" + +_key="help4-1" +_value="File: contains commands to close the application and to show information about BePodder" + +_key="help4-2" +_value="Settings: contains command to open the Preferences window that allows you to customize various BePodder settings." + +_key="help4-3" +_value="Subscriptions: contains commands that perform actions on the selected channel of your subscriptions list." + +_key="help4-4" +_value="Episodes: contains commands that perform actions on the selected item (episode) of the channel's episode list." + +_key="help4-5" +_value="Lists: contains commands to open BePodder's OPML directories." + +_key="help4-6" +_value="View: contains commands and controls for the BePodder window." + +_key="help4-7" +_value="Help: contains commands to open BePodder's 'Getting Started Guide' and the 'Keyboard Shortcuts List'." + + + +_key="help5-0" + _value="Add Button: opens the Add Window to add a feed url (e.g. http://www.newpodcast.com/rss.xml) usually given on the podcast homepage; looks for text or graphic link that says something like 'XML', 'RSS' or 'Podcast Feed' on it." + +_key="help5-1" + _value="Channel Remove Button: opens a window in which you can select how remove the channel: just archive the select channel (keeping all the files and eclosure downloaded so far) or delete the whole channel from your computer." + +_key="help5-2" + _value="Check Button: checks the selected channel and updates the list of the available items for that podcast adding the new items." + +_key="help5-3" + _value="Web Button: shows the channel homepage in the browser. To select your favorite browser open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select your favorite browser." + +_key="help5-4" + _value="Play Button: with this button you can view or listen the file enclosure of the selected item(episode). To select your favorite player open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select you favorite player." + +_key="help5-5" + _value="Download Button: downloads the file enclosure of the selected item (episode); you can see the download info by clicking on the third button over the info panel." + +_key="help5-6" + _value="Stop Button: stops to download the file enclosure of the selected item (episode); to resume the download double-click the item (episode) or select the item and click the Download Button" + +_key="help5-7" + _value="Item Remove Button: deletes the selected item (you will loose the enclosure file)." + + + +_key="help6-0" + _value="Getting started with BePodder is easy." + +_key="help6-1" + _value="On the left of the main window you can see the 'Subscription List' with all your feed subscriptions. We have added some subscriptions for you, and you can always add your own in two ways:" + +_key="help6-2" + _value="1) click the Add Button, then insert the feed url (example: http://www.newpodcast.com/rss.xml) and click add." + +_key="help6-3" + _value="2) in the menubar select 'Directory' and then 'Podcast list' or another list, choose a podcast and click 'Subscribe'." + +_key="help6-4" + _value="If you select a Podcast in the subscriptions list and use the check button, BePodder adds the new items to the 'Episodes list' (below on the right); you can check all your podcasts by right-clicking and selecting 'Check All Channels' in the context menu." + +_key="help6-5" + _value="Look at the screenshot above, there are 3 new items indicated by a black dot in the first column of the 'Episodes list'." + +_key="help6-6" + _value="In the second column there are icons that indicate the state of the item:" + +_key="help6-7" + _value="- the Episode 4 has an icon that indicates an error" + +_key="help6-8" + _value="- the Episode 3 has an icon that indicates that the item's enclosure download request is enquequed" + +_key="help6-9" + _value="- the Episode 2 has an icon that indicates that BePodder is downloading the item's enclosure file" + +_key="help6-10" + _value="- the Episode 1 have an icon that indicates that BePodder have just downloaded the item's enclosure file" + + + +_key="help7-0" + _value="Select an item in the 'Episodes list' and then double-click on it (or click the Download Button) to start downloading the enclosed file; you can always stop the download by clicking on the Stop Button." + +_key="help7-1" + _value="When you click on the Subscribed Podcasts in the 'Subscriptions List' the software shows you, in the 'List of episodes', all the items available in that Subscription. Select an item and then click play (Play Button) to view or listen to the file." + +_key="help7-2" + _value="You can access the Enclosures Folder by clicking on the folder icon in the Info Pannel or by right-clicking your mouse on an item and select 'Open Enclosures Folder' in the context menu." + + + +_key="help8-0" + _value="Preferences can be accessed by clicking in the menu-bar Settings>Preferences. You can select a category from the left list of the preferences dialog: FileType, Channels, Download and Proxy." + +_key="help8-1" + _value="- FileType: to specify the default browser and player. " + +_key="help8-2" + _value="- Channels: to specify preferences that control the operation to check channels new items; you can choose to Check all channels on startup or check the channel every desired minutes." + +_key="help8-3" + _value="- Download: to specify the max number of item's files to download at the same time," + +_key="help8-4" + _value="- Proxy: to set up a proxy server to work with BePodder; a proxy server acts as a security barrier between your internal network and the Internet, keeping others on the Internet from accessing information on your internal network." + + + +_key="help9-0" + _value="BePodder has built-in podcast, videoblog, imagefeeds, newsfeeds, bittorrentfeeds and internationalfeeds OPML directories with thousands of feeds grouped by category." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) is an XML-based format that allows exchange of outline-structured information between applications." + +_key="help9-2" + _value="OPML directory can be accessed by clicking in the menu-bar 'Lists' and thenselecting a list. To browse the opml directory for a feed, expand the list by clicking the arrow of the category that you are interested in (see image); using this method, you can expand the opml directory until you find the desired feed. Once you have selected it, you can add it to the subscription list by clicking the button 'Subscribe', you can also collapse all categories in the directory list by clicking the button 'Collapse All'." + + +_key="help_shortcut1" +_value="This page describes the keyboard shortcuts that can be used in BePodder. The shortcuts are grouped here by function." + +_key="help_shortcut2" +_value="means that you can use either alt or control (es. Alt+Q or Ctrl+Q Quit the application), which way you have set it in the Deskbar menu preferences under Keyboard (the default shortcut key is Alt)." + +_key="help_shortcut3" + _value="General shortcuts" + +_key="help_shortcut4" + _value="Quit the application" + +_key="help_shortcut5" + _value="Shows the Preferences window" + +_key="help_shortcut6" + _value="Shows the Podcast directory list" + +_key="help_shortcut7" + _value="Shows the Videoblog directory list" + +_key="help_shortcut8" + _value="Shows the Imagefeeds directory list" + +_key="help_shortcut9" + _value="Shows the Newsfeeds directory list" + +_key="help_shortcut9b" + _value="Shows the BitTorrentfeeds directory list" + +_key="help_shortcut9c" + _value="Shows the Internationalfeeds directory list" + +_key="help_shortcut10" + _value="Fullscreen" + +_key="help_shortcut11" + _value="Shows/Hides the toolbar" + +_key="help_shortcut12" + _value="Shows the Getting Started Help" + +_key="help_shortcut13" + _value="Shows this keyboard shortcuts page" + +_key="help_shortcut14" + _value="Channels shortcuts" + +_key="help_shortcut15" + _value="Add a podcast to the subscriptions list" + +_key="help_shortcut16" + _value="Delete the selected podcast from the subscriptions list" + +_key="help_shortcut17" + _value="Check the selected podcast for new episodes (items)" + +_key="help_shortcut18" + _value="Check all podcasts for new episodes (items)" + +_key="help_shortcut19" + _value="Shows the podcast homepage" + +_key="help_shortcut20" + _value="Open enclosures folder" + +_key="help_shortcut21" + _value="Episodes shortcuts" + +_key="help_shortcut22" + _value="Play enclosure" + +_key="help_shortcut23" + _value="(Re)start download the selected episodes (items)" + +_key="help_shortcut24" + _value="Stop the episode (item) download" + +_key="help_shortcut25" + _value="Delete the selected episode (item)" + +_key="help_shortcut26" + _value="Shows the podcast episode (item) page " + +_key="help_shortcut27" + _value="Open enclosures folder" + +_key="help_buy1" + _value="BePodder Light is the basic version (free download and no time limited), the registered version adds some more nice features: unlimited number of channels, small Channel view, proxy support, automatic channels check, up to 5 enclosure downloads at the same time (multithreading)." + +_key="help_buy2" + _value="Please pay the shareware fee, it's only 15 euro (Kagi add tax in some countries), BePodder licence can be purchased online from Kagi." + +_key="help_buy3" + _value="Buy at www.funkyideasoft.com" + +_key="help_buy4" + _value="After purchasing, an email will be sent to you with a keyfile and instruction on how to install it. It's just a matter of unzipping a file and moving it to a certain directory." + +_key="help_buy5" + _value="There is no problem updating BePodder when a new version becomes available. The keyfile will unlock all downloadable packages unless otherwise notified." + + +### USELESS ######## + +"Opml Editor" "Opml Editor" +"name:" "name:" +"Add a category" "Add a category" +"Add a new Broadcast" "Add a new Broadcast" +"feed:" "feed:" +"url:" "url:" +"Test podcast" "Test podcast" +"Del a category" "Del a category" +"Add a category" "Add a category" +"Select the podcast category:" "Select the podcast category:" +"Check all" "Check all" +"Check" "Check" +"Refresh the list" "Refresh the list" +"Load" "Load" +"Load the list" "Load the list" +"Save" "Save" +"Save the list" "Save the list" +"Revert" "Revert" +"Apply" "Apply" + + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.esAR b/release/Language/Dictionaries/BePodder.esAR new file mode 100644 index 0000000..83874e9 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.esAR @@ -0,0 +1,603 @@ + +# Locale file for BePodder. +# Modified: 4/18/2006 +# Author: BePodderTeam +# E-mail: bepodder.team@gmail.com + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" + +"Web Site" "Web Site" + +"Can't connect!" "Can't connect!" +"Http port failed!" "Http port failed!" +"Can't resolve host!" "Can't resolve host!" +"Not found!" "Not found!" +"Bad resume!" "Bad resume!" +"Aborted by Callback!" "Aborted by Callback!" +"Can't resume! (range error)" "Can't resume! (range error)" +"Access Denied!" "Access Denied!" +"User or Password Incorrect!" "User or Password Incorrect!" +"Other error (cUrl code: " "Other error (cUrl code: " +"cUrl init error!" "cUrl init error!" +"Can't open file!" "Can't open file!" +"Other error (status code: " "Other error (status code: " +"Downloading" "Downloading" + + +### MENUBAR ----------------------------------- + +"File" "File" +"About..." "About..." +"Close!" "Close!" +"Quit" "Quit" + +"Settings" "Settings" +"Preferences..." "Preferences..." + +"Subscriptions" "Subscriptions" + +"Episodes" "Episodes" + +"Lists" "Lists" +"Podcast List" "Podcast List" +"Podcast directory list" "Podcast directory list" +"Videoblog List" "Videoblog List" +"Videoblog directory list" "Videoblog directory list" +"Imagefeeds List" "Imagefeeds List" +"Imagefeeds directory list" "Imagefeeds directory list" +"Newsfeeds List" "Newsfeeds List" +"Newsfeeds directory list" "Newsfeeds directory list" +"BitTorrentfeeds List" "BitTorrentfeeds List" +"BitTorrentfeeds directory list" "BitTorrentfeeds directory list" +"Internationalfeeds List" "Internationalfeeds List" +"Internationalfeeds directory list" "Internationalfeeds directory list" + +"View" "View" +"Full Screen" "Full Screen" +"Toolbar" "Toolbar" +"Subscriptions View" "Subscriptions View" +"Small Items" "Small Items" +"Big Items" "Big Items" +"Move BePodder on workspace:" "Move BePodder on workspace:" + +"Help" "Help" +"Getting Started" "Getting Started" +"Keyboard Shortcuts" "Keyboard Shortcuts" +"Tutorials" "Tutorials" +"Online Support" "Online Support" + + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "Insert the rss feed url!" +"Add" "Add" +"Paste" "Paste" + +# Buttons directory list window +"Collapse All" "Collapse All" +"Preview" "Preview" +"Subscribe" "Subscribe" + + +# Buttons help window +"Next" "Next" +"Prev" "Prev" +"Close" "Close" +"Index" "Index" + + +# Buttons remove windows +"Cancel" "Cancel" +"Delete" "Delete" +"Archive" "Archive" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Add the podcast to the Subscriptions list" +"Delete the podcast from the Subscriptions list" "Delete the podcast from the Subscriptions list" +"Check the selected podcast for new items" "Check the selected podcast for new items" +"Show the podcast homepage" "Show the podcast homepage" + +"Delete the item and the enclosure" "Delete the item and the enclosure" +"Stop the item download" "Stop the item download" +"Download the selected episode" "Download the selected episode" +"Play the selected episode" "Play the selected episode" + +"Submit bug and idea" "Submit bug and idea" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Collapse all categories in the directory list" +"Add the selected podcast to the Subscription list" "Add the selected podcast to the Subscription list" +"Checkout a podcast before downloading it" "Checkout a podcast before downloading it" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Show Channel Image" +"XML Feed Link" "XML Feed Link" + +"Show Episode info" "Show Episode info" +"Show Subscription info" "Show Subscription info" +"Show Downloads info" "Show Downloads info" + +"Enclosure: " "Enclosure: " + +"Lookup (Dictionary)" "Lookup (Dictionary)" +"Lookup (Google)" "Lookup (Google)" +"Lookup (Acronym Finder)" "Lookup (Acronym Finder)" +"Copy" "Copy" +"Select All" "Select All" +"Copy URL" "Copy URL" +"Open URL" "Open URL" +"Subscription" "Subscription" + + +### PREFERENCES ----------------------------------- + +"Preferences" "Preferences" + +"Proxy" "Proxy" +"Enable Proxy" "Enable Proxy" +"Address" "Address" +"Port" "Port" +"Username" "Username" +"Password" "Password" + +"Max Downloads" "Max Downloads" + +"FileType" "FileType" +"Browser" "Browser" +"Player" "Player" + +"Channels" "Channels" +"Check all channels on startup" "Check all channels on startup" +"Check the channel every" "Check the channel every" + +"never" "never" +"5 minutes" "5 minutes" +"15 minutes" "15 minutes" +"30 minutes" "30 minutes" +"1 hour" "1 hour" +"2 hour" "2 hour" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 new item" +"%d new items" "%d new items" +"new" "new" +"error" "error" +"not down" "not down" +"enquequed" "enquequed" +"downloading" "downloading" +"downloaded" "downloaded" +"connecting" "connecting" +"not found" "not found" +"stopped" "stopped" +"can't connect" "can't connect" +"invalid format" "invalid format" + +"Icon" "Icon" +"Title" "Title" +"Date" "Date" +"Size" "Size" +"Status" "Status" +"Download" "Download" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "Add Channel" +"Remove Channel" "Remove Channel" +"Check Channel" "Check Channel" +"Open Homepage" "Open Homepage" + +"Open Web Page" "Open Web Page" +"Open Enclosures folder" "Open Enclosures folder" +"Check All Channels" "Check All Channels" + +"Show Channel Image" "Show Channel Image" + +"Play enclosure" "Play enclosure" +"(Re)start download" "(Re)start download" +"Stop download" "Stop download" +"Remove Item" "Remove Item" + +"Find this Item" "Find this Item" +"Remove from this list" "Remove from this list" + + + +### ALERT ----------------------------------- + +"\nRemoving.." "\nRemoving.." +"\nAn error occured while removing!" "\nAn error occured while removing!" +"Check all the podcasts for new items" "Check all the podcasts for new items" + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" + +"Can't open the selected file with:\n\n" "Can't open the selected file with:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nPlease check if the application is installed in the right way.\n" +"Download it!" "Download it!" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +You are going to remove the selected item. + +Are you sure? +(you will lost the enclosure file if any)" + + +_key="alert2a" + _value=" +You are going to remove the channel: + +" + +_key="alert2b" + _value=" + +Would you like just to archive this +channel (keeping all the files and +enclosures downloaded so far) or +do you want to DELETE the whole + channel from you computer?" + +_key="alert3" + _value=" +Parsing archive.." + +_key="alert_3gp" + _value=" +3GP is a multimedia container format defined by the Third Generation Partnership Project (3GPP) for use on 3G mobile phones. It stores video streams as MPEG-4 or H.263, and audio streams as AMR-NB or AAC-LC. + +VideoLAN still doesn't support the audio AMR (3GPP)" + +_key="alert_swf" + _value=" +SWF is a proprietary vector graphics file format produced by the Flash software from Adobe (formerly Macromedia). + +Currently Flash support in BeOS/Haiku/Zeta is limited to the old standalone Flash player version 4.1015, there isn't a modern Flash player" + + + + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Introduction" +"The User Interface" "The User Interface" +"Menu Bar" "Menu Bar" +"Toolbar Buttons" "Toolbar Buttons" +"First time with BePodder" "First time with BePodder" +"Download Podcast's enclosure files" "Download Podcast's enclosure files" +"Settings Overview" "Settings Overview" +"Directory lists" "Directory lists" +"Loading Help..." "Loading Help..." +"Register your copy" "Register your copy" +"Starting point" "Starting point" + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value="Welcome to the BePodder Getting Started Guide." + +_key="help1-1" + _value="If you are already familiar with podcasts and RSS/Atom feeds you can immediately go to BePodder by closing this window." + +_key="help1-2" +_value="If not, this is a short introduction providing you everything you'll need to know on how to get started with BePodder. Use the buttons below to navigate through this tutorial." + + +_key="help2-0" +_value="Podcasting is a method for publishing audio and video broadcasts via the Internet; links to free audio and video files are enclosed in RSS and Atom feeds." + +_key="help2-1" +_value="Therefore Podcasting is simply a type of online media delivery; users can subscribe to a podcast using a feed (such as RSS 'Really Simple Syndication' or Atom)." + +_key="help2-2" +_value="An aggregator (or podcatcher) like BePodder, is a piece of software that allows you to subscribe to a RSS feed and periodically check for and download new content; with BePodder you can check for new Podcast items (Episodes) of your subscribed Channels. Any item can contain an enclosure, just like an Email can contain an attachment." + + + +_key="help3-0" +_value="BePodder has an easy to use yet powerful Graphical User Interface. The main window is split into tree panels:" + +_key="help3-1" +_value="1) The Subscription list (the panel with the number 1 in the screenshot) with the list of the podcasts that you have subscribed to. When you click on a Channel you can see in the panel 2 the list of the channel's items." + +_key="help3-2" +_value="2) The Episodes list with all the items available." + +_key="help3-3" +_value="3) The Info panel show: episode info, channel info or Downloads info; you can select an info panel by clicking one of the below three buttons." + + + +_key="help4-0" +_value="At the very top of the BePodder main window is the menubar with seven menus available: File, Settings, Subscriptions, Episodes, Lists, View and Help. Some menu commands are followed by a right pointing arrow that indicates a submenu of related commands. As you explore each menu, be sure to take a look at the submenus as well. Click on a menus to show its commands:" + +_key="help4-1" +_value="File: contains commands to close the application and to show information about BePodder" + +_key="help4-2" +_value="Settings: contains command to open the Preferences window that allows you to customize various BePodder settings." + +_key="help4-3" +_value="Subscriptions: contains commands that perform actions on the selected channel of your subscriptions list." + +_key="help4-4" +_value="Episodes: contains commands that perform actions on the selected item (episode) of the channel's episode list." + +_key="help4-5" +_value="Lists: contains commands to open BePodder's OPML directories." + +_key="help4-6" +_value="View: contains commands and controls for the BePodder window." + +_key="help4-7" +_value="Help: contains commands to open BePodder's 'Getting Started Guide' and the 'Keyboard Shortcuts List'." + + + +_key="help5-0" + _value="Add Button: opens the Add Window to add a feed url (e.g. http://www.newpodcast.com/rss.xml) usually given on the podcast homepage; looks for text or graphic link that says something like 'XML', 'RSS' or 'Podcast Feed' on it." + +_key="help5-1" + _value="Channel Remove Button: opens a window in which you can select how remove the channel: just archive the select channel (keeping all the files and eclosure downloaded so far) or delete the whole channel from your computer." + +_key="help5-2" + _value="Check Button: checks the selected channel and updates the list of the available items for that podcast adding the new items." + +_key="help5-3" + _value="Web Button: shows the channel homepage in the browser. To select your favorite browser open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select your favorite browser." + +_key="help5-4" + _value="Play Button: with this button you can view or listen the file enclosure of the selected item(episode). To select your favorite player open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select you favorite player." + +_key="help5-5" + _value="Download Button: downloads the file enclosure of the selected item (episode); you can see the download info by clicking on the third button over the info panel." + +_key="help5-6" + _value="Stop Button: stops to download the file enclosure of the selected item (episode); to resume the download double-click the item (episode) or select the item and click the Download Button" + +_key="help5-7" + _value="Item Remove Button: deletes the selected item (you will loose the enclosure file)." + + + +_key="help6-0" + _value="Getting started with BePodder is easy." + +_key="help6-1" + _value="On the left of the main window you can see the 'Subscription List' with all your feed subscriptions. We have added some subscriptions for you, and you can always add your own in two ways:" + +_key="help6-2" + _value="1) click the Add Button, then insert the feed url (example: http://www.newpodcast.com/rss.xml) and click add." + +_key="help6-3" + _value="2) in the menubar select 'Directory' and then 'Podcast list' or another list, choose a podcast and click 'Subscribe'." + +_key="help6-4" + _value="If you select a Podcast in the subscriptions list and use the check button, BePodder adds the new items to the 'Episodes list' (below on the right); you can check all your podcasts by right-clicking and selecting 'Check All Channels' in the context menu." + +_key="help6-5" + _value="Look at the screenshot above, there are 3 new items indicated by a black dot in the first column of the 'Episodes list'." + +_key="help6-6" + _value="In the second column there are icons that indicate the state of the item:" + +_key="help6-7" + _value="- the Episode 4 has an icon that indicates an error" + +_key="help6-8" + _value="- the Episode 3 has an icon that indicates that the item's enclosure download request is enquequed" + +_key="help6-9" + _value="- the Episode 2 has an icon that indicates that BePodder is downloading the item's enclosure file" + +_key="help6-10" + _value="- the Episode 1 have an icon that indicates that BePodder have just downloaded the item's enclosure file" + + + +_key="help7-0" + _value="Select an item in the 'Episodes list' and then double-click on it (or click the Download Button) to start downloading the enclosed file; you can always stop the download by clicking on the Stop Button." + +_key="help7-1" + _value="When you click on the Subscribed Podcasts in the 'Subscriptions List' the software shows you, in the 'List of episodes', all the items available in that Subscription. Select an item and then click play (Play Button) to view or listen to the file." + +_key="help7-2" + _value="You can access the Enclosures Folder by clicking on the folder icon in the Info Pannel or by right-clicking your mouse on an item and select 'Open Enclosures Folder' in the context menu." + + + +_key="help8-0" + _value="Preferences can be accessed by clicking in the menu-bar Settings>Preferences. You can select a category from the left list of the preferences dialog: FileType, Channels, Download and Proxy." + +_key="help8-1" + _value="- FileType: to specify the default browser and player. " + +_key="help8-2" + _value="- Channels: to specify preferences that control the operation to check channels new items; you can choose to Check all channels on startup or check the channel every desired minutes." + +_key="help8-3" + _value="- Download: to specify the max number of item's files to download at the same time," + +_key="help8-4" + _value="- Proxy: to set up a proxy server to work with BePodder; a proxy server acts as a security barrier between your internal network and the Internet, keeping others on the Internet from accessing information on your internal network." + + + +_key="help9-0" + _value="BePodder has built-in podcast, videoblog, imagefeeds, newsfeeds, bittorrentfeeds and internationalfeeds OPML directories with thousands of feeds grouped by category." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) is an XML-based format that allows exchange of outline-structured information between applications." + +_key="help9-2" + _value="OPML directory can be accessed by clicking in the menu-bar 'Lists' and thenselecting a list. To browse the opml directory for a feed, expand the list by clicking the arrow of the category that you are interested in (see image); using this method, you can expand the opml directory until you find the desired feed. Once you have selected it, you can add it to the subscription list by clicking the button 'Subscribe', you can also collapse all categories in the directory list by clicking the button 'Collapse All'." + +_key="help_shortcut1" +_value="This page describes the keyboard shortcuts that can be used in BePodder. The shortcuts are grouped here by function." + +_key="help_shortcut2" +_value="means that you can use either alt or control (es. Alt+Q or Ctrl+Q Quit the application), which way you have set it in the Deskbar menu preferences under Keyboard (the default shortcut key is Alt)." + +_key="help_shortcut3" + _value="General shortcuts" + +_key="help_shortcut4" + _value="Quit the application" + +_key="help_shortcut5" + _value="Shows the Preferences window" + +_key="help_shortcut6" + _value="Shows the Podcast directory list" + +_key="help_shortcut7" + _value="Shows the Videoblog directory list" + +_key="help_shortcut8" + _value="Shows the Imagefeeds directory list" + +_key="help_shortcut9" + _value="Shows the Newsfeeds directory list" + +_key="help_shortcut9b" + _value="Shows the BitTorrentfeeds directory list" + +_key="help_shortcut9c" + _value="Shows the Internationalfeeds directory list" + +_key="help_shortcut10" + _value="Fullscreen" + +_key="help_shortcut11" + _value="Shows/Hides the toolbar" + +_key="help_shortcut12" + _value="Shows the Getting Started Help" + +_key="help_shortcut13" + _value="Shows this keyboard shortcuts page" + +_key="help_shortcut14" + _value="Channels shortcuts" + +_key="help_shortcut15" + _value="Add a podcast to the subscriptions list" + +_key="help_shortcut16" + _value="Delete the selected podcast from the subscriptions list" + +_key="help_shortcut17" + _value="Check the selected podcast for new episodes (items)" + +_key="help_shortcut18" + _value="Check all podcasts for new episodes (items)" + +_key="help_shortcut19" + _value="Shows the podcast homepage" + +_key="help_shortcut20" + _value="Open enclosures folder" + +_key="help_shortcut21" + _value="Episodes shortcuts" + +_key="help_shortcut22" + _value="Play enclosure" + +_key="help_shortcut23" + _value="(Re)start download the selected episodes (items)" + +_key="help_shortcut24" + _value="Stop the episode (item) download" + +_key="help_shortcut25" + _value="Delete the selected episode (item)" + +_key="help_shortcut26" + _value="Shows the podcast episode (item) page " + +_key="help_shortcut27" + _value="Open enclosures folder" + +_key="help_buy1" + _value="BePodder Light is the basic version (free download and no time limited), the registered version adds some more nice features: unlimited number of channels, small Channel view, proxy support, automatic channels check, up to 5 enclosure downloads at the same time (multithreading)." + +_key="help_buy2" + _value="Please pay the shareware fee, it's only 15 euro (Kagi add tax in some countries), BePodder licence can be purchased online from Kagi." + +_key="help_buy3" + _value="Buy at www.funkyideasoft.com" + +_key="help_buy4" + _value="After purchasing, an email will be sent to you with a keyfile and instruction on how to install it. It's just a matter of unzipping a file and moving it to a certain directory." + +_key="help_buy5" + _value="There is no problem updating BePodder when a new version becomes available. The keyfile will unlock all downloadable packages unless otherwise notified." + + +### USELESS ######## + +"Opml Editor" "Opml Editor" +"name:" "name:" +"Add a category" "Add a category" +"Add a new Broadcast" "Add a new Broadcast" +"feed:" "feed:" +"url:" "url:" +"Test podcast" "Test podcast" +"Del a category" "Del a category" +"Add a category" "Add a category" +"Select the podcast category:" "Select the podcast category:" +"Check all" "Check all" +"Check" "Check" +"Refresh the list" "Refresh the list" +"Load" "Load" +"Load the list" "Load the list" +"Save" "Save" +"Save the list" "Save the list" +"Revert" "Revert" +"Apply" "Apply" + + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.esES b/release/Language/Dictionaries/BePodder.esES new file mode 100644 index 0000000..83874e9 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.esES @@ -0,0 +1,603 @@ + +# Locale file for BePodder. +# Modified: 4/18/2006 +# Author: BePodderTeam +# E-mail: bepodder.team@gmail.com + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" + +"Web Site" "Web Site" + +"Can't connect!" "Can't connect!" +"Http port failed!" "Http port failed!" +"Can't resolve host!" "Can't resolve host!" +"Not found!" "Not found!" +"Bad resume!" "Bad resume!" +"Aborted by Callback!" "Aborted by Callback!" +"Can't resume! (range error)" "Can't resume! (range error)" +"Access Denied!" "Access Denied!" +"User or Password Incorrect!" "User or Password Incorrect!" +"Other error (cUrl code: " "Other error (cUrl code: " +"cUrl init error!" "cUrl init error!" +"Can't open file!" "Can't open file!" +"Other error (status code: " "Other error (status code: " +"Downloading" "Downloading" + + +### MENUBAR ----------------------------------- + +"File" "File" +"About..." "About..." +"Close!" "Close!" +"Quit" "Quit" + +"Settings" "Settings" +"Preferences..." "Preferences..." + +"Subscriptions" "Subscriptions" + +"Episodes" "Episodes" + +"Lists" "Lists" +"Podcast List" "Podcast List" +"Podcast directory list" "Podcast directory list" +"Videoblog List" "Videoblog List" +"Videoblog directory list" "Videoblog directory list" +"Imagefeeds List" "Imagefeeds List" +"Imagefeeds directory list" "Imagefeeds directory list" +"Newsfeeds List" "Newsfeeds List" +"Newsfeeds directory list" "Newsfeeds directory list" +"BitTorrentfeeds List" "BitTorrentfeeds List" +"BitTorrentfeeds directory list" "BitTorrentfeeds directory list" +"Internationalfeeds List" "Internationalfeeds List" +"Internationalfeeds directory list" "Internationalfeeds directory list" + +"View" "View" +"Full Screen" "Full Screen" +"Toolbar" "Toolbar" +"Subscriptions View" "Subscriptions View" +"Small Items" "Small Items" +"Big Items" "Big Items" +"Move BePodder on workspace:" "Move BePodder on workspace:" + +"Help" "Help" +"Getting Started" "Getting Started" +"Keyboard Shortcuts" "Keyboard Shortcuts" +"Tutorials" "Tutorials" +"Online Support" "Online Support" + + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "Insert the rss feed url!" +"Add" "Add" +"Paste" "Paste" + +# Buttons directory list window +"Collapse All" "Collapse All" +"Preview" "Preview" +"Subscribe" "Subscribe" + + +# Buttons help window +"Next" "Next" +"Prev" "Prev" +"Close" "Close" +"Index" "Index" + + +# Buttons remove windows +"Cancel" "Cancel" +"Delete" "Delete" +"Archive" "Archive" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Add the podcast to the Subscriptions list" +"Delete the podcast from the Subscriptions list" "Delete the podcast from the Subscriptions list" +"Check the selected podcast for new items" "Check the selected podcast for new items" +"Show the podcast homepage" "Show the podcast homepage" + +"Delete the item and the enclosure" "Delete the item and the enclosure" +"Stop the item download" "Stop the item download" +"Download the selected episode" "Download the selected episode" +"Play the selected episode" "Play the selected episode" + +"Submit bug and idea" "Submit bug and idea" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Collapse all categories in the directory list" +"Add the selected podcast to the Subscription list" "Add the selected podcast to the Subscription list" +"Checkout a podcast before downloading it" "Checkout a podcast before downloading it" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Show Channel Image" +"XML Feed Link" "XML Feed Link" + +"Show Episode info" "Show Episode info" +"Show Subscription info" "Show Subscription info" +"Show Downloads info" "Show Downloads info" + +"Enclosure: " "Enclosure: " + +"Lookup (Dictionary)" "Lookup (Dictionary)" +"Lookup (Google)" "Lookup (Google)" +"Lookup (Acronym Finder)" "Lookup (Acronym Finder)" +"Copy" "Copy" +"Select All" "Select All" +"Copy URL" "Copy URL" +"Open URL" "Open URL" +"Subscription" "Subscription" + + +### PREFERENCES ----------------------------------- + +"Preferences" "Preferences" + +"Proxy" "Proxy" +"Enable Proxy" "Enable Proxy" +"Address" "Address" +"Port" "Port" +"Username" "Username" +"Password" "Password" + +"Max Downloads" "Max Downloads" + +"FileType" "FileType" +"Browser" "Browser" +"Player" "Player" + +"Channels" "Channels" +"Check all channels on startup" "Check all channels on startup" +"Check the channel every" "Check the channel every" + +"never" "never" +"5 minutes" "5 minutes" +"15 minutes" "15 minutes" +"30 minutes" "30 minutes" +"1 hour" "1 hour" +"2 hour" "2 hour" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 new item" +"%d new items" "%d new items" +"new" "new" +"error" "error" +"not down" "not down" +"enquequed" "enquequed" +"downloading" "downloading" +"downloaded" "downloaded" +"connecting" "connecting" +"not found" "not found" +"stopped" "stopped" +"can't connect" "can't connect" +"invalid format" "invalid format" + +"Icon" "Icon" +"Title" "Title" +"Date" "Date" +"Size" "Size" +"Status" "Status" +"Download" "Download" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "Add Channel" +"Remove Channel" "Remove Channel" +"Check Channel" "Check Channel" +"Open Homepage" "Open Homepage" + +"Open Web Page" "Open Web Page" +"Open Enclosures folder" "Open Enclosures folder" +"Check All Channels" "Check All Channels" + +"Show Channel Image" "Show Channel Image" + +"Play enclosure" "Play enclosure" +"(Re)start download" "(Re)start download" +"Stop download" "Stop download" +"Remove Item" "Remove Item" + +"Find this Item" "Find this Item" +"Remove from this list" "Remove from this list" + + + +### ALERT ----------------------------------- + +"\nRemoving.." "\nRemoving.." +"\nAn error occured while removing!" "\nAn error occured while removing!" +"Check all the podcasts for new items" "Check all the podcasts for new items" + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" + +"Can't open the selected file with:\n\n" "Can't open the selected file with:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nPlease check if the application is installed in the right way.\n" +"Download it!" "Download it!" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +You are going to remove the selected item. + +Are you sure? +(you will lost the enclosure file if any)" + + +_key="alert2a" + _value=" +You are going to remove the channel: + +" + +_key="alert2b" + _value=" + +Would you like just to archive this +channel (keeping all the files and +enclosures downloaded so far) or +do you want to DELETE the whole + channel from you computer?" + +_key="alert3" + _value=" +Parsing archive.." + +_key="alert_3gp" + _value=" +3GP is a multimedia container format defined by the Third Generation Partnership Project (3GPP) for use on 3G mobile phones. It stores video streams as MPEG-4 or H.263, and audio streams as AMR-NB or AAC-LC. + +VideoLAN still doesn't support the audio AMR (3GPP)" + +_key="alert_swf" + _value=" +SWF is a proprietary vector graphics file format produced by the Flash software from Adobe (formerly Macromedia). + +Currently Flash support in BeOS/Haiku/Zeta is limited to the old standalone Flash player version 4.1015, there isn't a modern Flash player" + + + + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Introduction" +"The User Interface" "The User Interface" +"Menu Bar" "Menu Bar" +"Toolbar Buttons" "Toolbar Buttons" +"First time with BePodder" "First time with BePodder" +"Download Podcast's enclosure files" "Download Podcast's enclosure files" +"Settings Overview" "Settings Overview" +"Directory lists" "Directory lists" +"Loading Help..." "Loading Help..." +"Register your copy" "Register your copy" +"Starting point" "Starting point" + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value="Welcome to the BePodder Getting Started Guide." + +_key="help1-1" + _value="If you are already familiar with podcasts and RSS/Atom feeds you can immediately go to BePodder by closing this window." + +_key="help1-2" +_value="If not, this is a short introduction providing you everything you'll need to know on how to get started with BePodder. Use the buttons below to navigate through this tutorial." + + +_key="help2-0" +_value="Podcasting is a method for publishing audio and video broadcasts via the Internet; links to free audio and video files are enclosed in RSS and Atom feeds." + +_key="help2-1" +_value="Therefore Podcasting is simply a type of online media delivery; users can subscribe to a podcast using a feed (such as RSS 'Really Simple Syndication' or Atom)." + +_key="help2-2" +_value="An aggregator (or podcatcher) like BePodder, is a piece of software that allows you to subscribe to a RSS feed and periodically check for and download new content; with BePodder you can check for new Podcast items (Episodes) of your subscribed Channels. Any item can contain an enclosure, just like an Email can contain an attachment." + + + +_key="help3-0" +_value="BePodder has an easy to use yet powerful Graphical User Interface. The main window is split into tree panels:" + +_key="help3-1" +_value="1) The Subscription list (the panel with the number 1 in the screenshot) with the list of the podcasts that you have subscribed to. When you click on a Channel you can see in the panel 2 the list of the channel's items." + +_key="help3-2" +_value="2) The Episodes list with all the items available." + +_key="help3-3" +_value="3) The Info panel show: episode info, channel info or Downloads info; you can select an info panel by clicking one of the below three buttons." + + + +_key="help4-0" +_value="At the very top of the BePodder main window is the menubar with seven menus available: File, Settings, Subscriptions, Episodes, Lists, View and Help. Some menu commands are followed by a right pointing arrow that indicates a submenu of related commands. As you explore each menu, be sure to take a look at the submenus as well. Click on a menus to show its commands:" + +_key="help4-1" +_value="File: contains commands to close the application and to show information about BePodder" + +_key="help4-2" +_value="Settings: contains command to open the Preferences window that allows you to customize various BePodder settings." + +_key="help4-3" +_value="Subscriptions: contains commands that perform actions on the selected channel of your subscriptions list." + +_key="help4-4" +_value="Episodes: contains commands that perform actions on the selected item (episode) of the channel's episode list." + +_key="help4-5" +_value="Lists: contains commands to open BePodder's OPML directories." + +_key="help4-6" +_value="View: contains commands and controls for the BePodder window." + +_key="help4-7" +_value="Help: contains commands to open BePodder's 'Getting Started Guide' and the 'Keyboard Shortcuts List'." + + + +_key="help5-0" + _value="Add Button: opens the Add Window to add a feed url (e.g. http://www.newpodcast.com/rss.xml) usually given on the podcast homepage; looks for text or graphic link that says something like 'XML', 'RSS' or 'Podcast Feed' on it." + +_key="help5-1" + _value="Channel Remove Button: opens a window in which you can select how remove the channel: just archive the select channel (keeping all the files and eclosure downloaded so far) or delete the whole channel from your computer." + +_key="help5-2" + _value="Check Button: checks the selected channel and updates the list of the available items for that podcast adding the new items." + +_key="help5-3" + _value="Web Button: shows the channel homepage in the browser. To select your favorite browser open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select your favorite browser." + +_key="help5-4" + _value="Play Button: with this button you can view or listen the file enclosure of the selected item(episode). To select your favorite player open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select you favorite player." + +_key="help5-5" + _value="Download Button: downloads the file enclosure of the selected item (episode); you can see the download info by clicking on the third button over the info panel." + +_key="help5-6" + _value="Stop Button: stops to download the file enclosure of the selected item (episode); to resume the download double-click the item (episode) or select the item and click the Download Button" + +_key="help5-7" + _value="Item Remove Button: deletes the selected item (you will loose the enclosure file)." + + + +_key="help6-0" + _value="Getting started with BePodder is easy." + +_key="help6-1" + _value="On the left of the main window you can see the 'Subscription List' with all your feed subscriptions. We have added some subscriptions for you, and you can always add your own in two ways:" + +_key="help6-2" + _value="1) click the Add Button, then insert the feed url (example: http://www.newpodcast.com/rss.xml) and click add." + +_key="help6-3" + _value="2) in the menubar select 'Directory' and then 'Podcast list' or another list, choose a podcast and click 'Subscribe'." + +_key="help6-4" + _value="If you select a Podcast in the subscriptions list and use the check button, BePodder adds the new items to the 'Episodes list' (below on the right); you can check all your podcasts by right-clicking and selecting 'Check All Channels' in the context menu." + +_key="help6-5" + _value="Look at the screenshot above, there are 3 new items indicated by a black dot in the first column of the 'Episodes list'." + +_key="help6-6" + _value="In the second column there are icons that indicate the state of the item:" + +_key="help6-7" + _value="- the Episode 4 has an icon that indicates an error" + +_key="help6-8" + _value="- the Episode 3 has an icon that indicates that the item's enclosure download request is enquequed" + +_key="help6-9" + _value="- the Episode 2 has an icon that indicates that BePodder is downloading the item's enclosure file" + +_key="help6-10" + _value="- the Episode 1 have an icon that indicates that BePodder have just downloaded the item's enclosure file" + + + +_key="help7-0" + _value="Select an item in the 'Episodes list' and then double-click on it (or click the Download Button) to start downloading the enclosed file; you can always stop the download by clicking on the Stop Button." + +_key="help7-1" + _value="When you click on the Subscribed Podcasts in the 'Subscriptions List' the software shows you, in the 'List of episodes', all the items available in that Subscription. Select an item and then click play (Play Button) to view or listen to the file." + +_key="help7-2" + _value="You can access the Enclosures Folder by clicking on the folder icon in the Info Pannel or by right-clicking your mouse on an item and select 'Open Enclosures Folder' in the context menu." + + + +_key="help8-0" + _value="Preferences can be accessed by clicking in the menu-bar Settings>Preferences. You can select a category from the left list of the preferences dialog: FileType, Channels, Download and Proxy." + +_key="help8-1" + _value="- FileType: to specify the default browser and player. " + +_key="help8-2" + _value="- Channels: to specify preferences that control the operation to check channels new items; you can choose to Check all channels on startup or check the channel every desired minutes." + +_key="help8-3" + _value="- Download: to specify the max number of item's files to download at the same time," + +_key="help8-4" + _value="- Proxy: to set up a proxy server to work with BePodder; a proxy server acts as a security barrier between your internal network and the Internet, keeping others on the Internet from accessing information on your internal network." + + + +_key="help9-0" + _value="BePodder has built-in podcast, videoblog, imagefeeds, newsfeeds, bittorrentfeeds and internationalfeeds OPML directories with thousands of feeds grouped by category." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) is an XML-based format that allows exchange of outline-structured information between applications." + +_key="help9-2" + _value="OPML directory can be accessed by clicking in the menu-bar 'Lists' and thenselecting a list. To browse the opml directory for a feed, expand the list by clicking the arrow of the category that you are interested in (see image); using this method, you can expand the opml directory until you find the desired feed. Once you have selected it, you can add it to the subscription list by clicking the button 'Subscribe', you can also collapse all categories in the directory list by clicking the button 'Collapse All'." + +_key="help_shortcut1" +_value="This page describes the keyboard shortcuts that can be used in BePodder. The shortcuts are grouped here by function." + +_key="help_shortcut2" +_value="means that you can use either alt or control (es. Alt+Q or Ctrl+Q Quit the application), which way you have set it in the Deskbar menu preferences under Keyboard (the default shortcut key is Alt)." + +_key="help_shortcut3" + _value="General shortcuts" + +_key="help_shortcut4" + _value="Quit the application" + +_key="help_shortcut5" + _value="Shows the Preferences window" + +_key="help_shortcut6" + _value="Shows the Podcast directory list" + +_key="help_shortcut7" + _value="Shows the Videoblog directory list" + +_key="help_shortcut8" + _value="Shows the Imagefeeds directory list" + +_key="help_shortcut9" + _value="Shows the Newsfeeds directory list" + +_key="help_shortcut9b" + _value="Shows the BitTorrentfeeds directory list" + +_key="help_shortcut9c" + _value="Shows the Internationalfeeds directory list" + +_key="help_shortcut10" + _value="Fullscreen" + +_key="help_shortcut11" + _value="Shows/Hides the toolbar" + +_key="help_shortcut12" + _value="Shows the Getting Started Help" + +_key="help_shortcut13" + _value="Shows this keyboard shortcuts page" + +_key="help_shortcut14" + _value="Channels shortcuts" + +_key="help_shortcut15" + _value="Add a podcast to the subscriptions list" + +_key="help_shortcut16" + _value="Delete the selected podcast from the subscriptions list" + +_key="help_shortcut17" + _value="Check the selected podcast for new episodes (items)" + +_key="help_shortcut18" + _value="Check all podcasts for new episodes (items)" + +_key="help_shortcut19" + _value="Shows the podcast homepage" + +_key="help_shortcut20" + _value="Open enclosures folder" + +_key="help_shortcut21" + _value="Episodes shortcuts" + +_key="help_shortcut22" + _value="Play enclosure" + +_key="help_shortcut23" + _value="(Re)start download the selected episodes (items)" + +_key="help_shortcut24" + _value="Stop the episode (item) download" + +_key="help_shortcut25" + _value="Delete the selected episode (item)" + +_key="help_shortcut26" + _value="Shows the podcast episode (item) page " + +_key="help_shortcut27" + _value="Open enclosures folder" + +_key="help_buy1" + _value="BePodder Light is the basic version (free download and no time limited), the registered version adds some more nice features: unlimited number of channels, small Channel view, proxy support, automatic channels check, up to 5 enclosure downloads at the same time (multithreading)." + +_key="help_buy2" + _value="Please pay the shareware fee, it's only 15 euro (Kagi add tax in some countries), BePodder licence can be purchased online from Kagi." + +_key="help_buy3" + _value="Buy at www.funkyideasoft.com" + +_key="help_buy4" + _value="After purchasing, an email will be sent to you with a keyfile and instruction on how to install it. It's just a matter of unzipping a file and moving it to a certain directory." + +_key="help_buy5" + _value="There is no problem updating BePodder when a new version becomes available. The keyfile will unlock all downloadable packages unless otherwise notified." + + +### USELESS ######## + +"Opml Editor" "Opml Editor" +"name:" "name:" +"Add a category" "Add a category" +"Add a new Broadcast" "Add a new Broadcast" +"feed:" "feed:" +"url:" "url:" +"Test podcast" "Test podcast" +"Del a category" "Del a category" +"Add a category" "Add a category" +"Select the podcast category:" "Select the podcast category:" +"Check all" "Check all" +"Check" "Check" +"Refresh the list" "Refresh the list" +"Load" "Load" +"Load the list" "Load the list" +"Save" "Save" +"Save the list" "Save the list" +"Revert" "Revert" +"Apply" "Apply" + + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.etEE b/release/Language/Dictionaries/BePodder.etEE new file mode 100644 index 0000000..83874e9 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.etEE @@ -0,0 +1,603 @@ + +# Locale file for BePodder. +# Modified: 4/18/2006 +# Author: BePodderTeam +# E-mail: bepodder.team@gmail.com + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" + +"Web Site" "Web Site" + +"Can't connect!" "Can't connect!" +"Http port failed!" "Http port failed!" +"Can't resolve host!" "Can't resolve host!" +"Not found!" "Not found!" +"Bad resume!" "Bad resume!" +"Aborted by Callback!" "Aborted by Callback!" +"Can't resume! (range error)" "Can't resume! (range error)" +"Access Denied!" "Access Denied!" +"User or Password Incorrect!" "User or Password Incorrect!" +"Other error (cUrl code: " "Other error (cUrl code: " +"cUrl init error!" "cUrl init error!" +"Can't open file!" "Can't open file!" +"Other error (status code: " "Other error (status code: " +"Downloading" "Downloading" + + +### MENUBAR ----------------------------------- + +"File" "File" +"About..." "About..." +"Close!" "Close!" +"Quit" "Quit" + +"Settings" "Settings" +"Preferences..." "Preferences..." + +"Subscriptions" "Subscriptions" + +"Episodes" "Episodes" + +"Lists" "Lists" +"Podcast List" "Podcast List" +"Podcast directory list" "Podcast directory list" +"Videoblog List" "Videoblog List" +"Videoblog directory list" "Videoblog directory list" +"Imagefeeds List" "Imagefeeds List" +"Imagefeeds directory list" "Imagefeeds directory list" +"Newsfeeds List" "Newsfeeds List" +"Newsfeeds directory list" "Newsfeeds directory list" +"BitTorrentfeeds List" "BitTorrentfeeds List" +"BitTorrentfeeds directory list" "BitTorrentfeeds directory list" +"Internationalfeeds List" "Internationalfeeds List" +"Internationalfeeds directory list" "Internationalfeeds directory list" + +"View" "View" +"Full Screen" "Full Screen" +"Toolbar" "Toolbar" +"Subscriptions View" "Subscriptions View" +"Small Items" "Small Items" +"Big Items" "Big Items" +"Move BePodder on workspace:" "Move BePodder on workspace:" + +"Help" "Help" +"Getting Started" "Getting Started" +"Keyboard Shortcuts" "Keyboard Shortcuts" +"Tutorials" "Tutorials" +"Online Support" "Online Support" + + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "Insert the rss feed url!" +"Add" "Add" +"Paste" "Paste" + +# Buttons directory list window +"Collapse All" "Collapse All" +"Preview" "Preview" +"Subscribe" "Subscribe" + + +# Buttons help window +"Next" "Next" +"Prev" "Prev" +"Close" "Close" +"Index" "Index" + + +# Buttons remove windows +"Cancel" "Cancel" +"Delete" "Delete" +"Archive" "Archive" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Add the podcast to the Subscriptions list" +"Delete the podcast from the Subscriptions list" "Delete the podcast from the Subscriptions list" +"Check the selected podcast for new items" "Check the selected podcast for new items" +"Show the podcast homepage" "Show the podcast homepage" + +"Delete the item and the enclosure" "Delete the item and the enclosure" +"Stop the item download" "Stop the item download" +"Download the selected episode" "Download the selected episode" +"Play the selected episode" "Play the selected episode" + +"Submit bug and idea" "Submit bug and idea" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Collapse all categories in the directory list" +"Add the selected podcast to the Subscription list" "Add the selected podcast to the Subscription list" +"Checkout a podcast before downloading it" "Checkout a podcast before downloading it" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Show Channel Image" +"XML Feed Link" "XML Feed Link" + +"Show Episode info" "Show Episode info" +"Show Subscription info" "Show Subscription info" +"Show Downloads info" "Show Downloads info" + +"Enclosure: " "Enclosure: " + +"Lookup (Dictionary)" "Lookup (Dictionary)" +"Lookup (Google)" "Lookup (Google)" +"Lookup (Acronym Finder)" "Lookup (Acronym Finder)" +"Copy" "Copy" +"Select All" "Select All" +"Copy URL" "Copy URL" +"Open URL" "Open URL" +"Subscription" "Subscription" + + +### PREFERENCES ----------------------------------- + +"Preferences" "Preferences" + +"Proxy" "Proxy" +"Enable Proxy" "Enable Proxy" +"Address" "Address" +"Port" "Port" +"Username" "Username" +"Password" "Password" + +"Max Downloads" "Max Downloads" + +"FileType" "FileType" +"Browser" "Browser" +"Player" "Player" + +"Channels" "Channels" +"Check all channels on startup" "Check all channels on startup" +"Check the channel every" "Check the channel every" + +"never" "never" +"5 minutes" "5 minutes" +"15 minutes" "15 minutes" +"30 minutes" "30 minutes" +"1 hour" "1 hour" +"2 hour" "2 hour" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 new item" +"%d new items" "%d new items" +"new" "new" +"error" "error" +"not down" "not down" +"enquequed" "enquequed" +"downloading" "downloading" +"downloaded" "downloaded" +"connecting" "connecting" +"not found" "not found" +"stopped" "stopped" +"can't connect" "can't connect" +"invalid format" "invalid format" + +"Icon" "Icon" +"Title" "Title" +"Date" "Date" +"Size" "Size" +"Status" "Status" +"Download" "Download" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "Add Channel" +"Remove Channel" "Remove Channel" +"Check Channel" "Check Channel" +"Open Homepage" "Open Homepage" + +"Open Web Page" "Open Web Page" +"Open Enclosures folder" "Open Enclosures folder" +"Check All Channels" "Check All Channels" + +"Show Channel Image" "Show Channel Image" + +"Play enclosure" "Play enclosure" +"(Re)start download" "(Re)start download" +"Stop download" "Stop download" +"Remove Item" "Remove Item" + +"Find this Item" "Find this Item" +"Remove from this list" "Remove from this list" + + + +### ALERT ----------------------------------- + +"\nRemoving.." "\nRemoving.." +"\nAn error occured while removing!" "\nAn error occured while removing!" +"Check all the podcasts for new items" "Check all the podcasts for new items" + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" + +"Can't open the selected file with:\n\n" "Can't open the selected file with:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nPlease check if the application is installed in the right way.\n" +"Download it!" "Download it!" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +You are going to remove the selected item. + +Are you sure? +(you will lost the enclosure file if any)" + + +_key="alert2a" + _value=" +You are going to remove the channel: + +" + +_key="alert2b" + _value=" + +Would you like just to archive this +channel (keeping all the files and +enclosures downloaded so far) or +do you want to DELETE the whole + channel from you computer?" + +_key="alert3" + _value=" +Parsing archive.." + +_key="alert_3gp" + _value=" +3GP is a multimedia container format defined by the Third Generation Partnership Project (3GPP) for use on 3G mobile phones. It stores video streams as MPEG-4 or H.263, and audio streams as AMR-NB or AAC-LC. + +VideoLAN still doesn't support the audio AMR (3GPP)" + +_key="alert_swf" + _value=" +SWF is a proprietary vector graphics file format produced by the Flash software from Adobe (formerly Macromedia). + +Currently Flash support in BeOS/Haiku/Zeta is limited to the old standalone Flash player version 4.1015, there isn't a modern Flash player" + + + + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Introduction" +"The User Interface" "The User Interface" +"Menu Bar" "Menu Bar" +"Toolbar Buttons" "Toolbar Buttons" +"First time with BePodder" "First time with BePodder" +"Download Podcast's enclosure files" "Download Podcast's enclosure files" +"Settings Overview" "Settings Overview" +"Directory lists" "Directory lists" +"Loading Help..." "Loading Help..." +"Register your copy" "Register your copy" +"Starting point" "Starting point" + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value="Welcome to the BePodder Getting Started Guide." + +_key="help1-1" + _value="If you are already familiar with podcasts and RSS/Atom feeds you can immediately go to BePodder by closing this window." + +_key="help1-2" +_value="If not, this is a short introduction providing you everything you'll need to know on how to get started with BePodder. Use the buttons below to navigate through this tutorial." + + +_key="help2-0" +_value="Podcasting is a method for publishing audio and video broadcasts via the Internet; links to free audio and video files are enclosed in RSS and Atom feeds." + +_key="help2-1" +_value="Therefore Podcasting is simply a type of online media delivery; users can subscribe to a podcast using a feed (such as RSS 'Really Simple Syndication' or Atom)." + +_key="help2-2" +_value="An aggregator (or podcatcher) like BePodder, is a piece of software that allows you to subscribe to a RSS feed and periodically check for and download new content; with BePodder you can check for new Podcast items (Episodes) of your subscribed Channels. Any item can contain an enclosure, just like an Email can contain an attachment." + + + +_key="help3-0" +_value="BePodder has an easy to use yet powerful Graphical User Interface. The main window is split into tree panels:" + +_key="help3-1" +_value="1) The Subscription list (the panel with the number 1 in the screenshot) with the list of the podcasts that you have subscribed to. When you click on a Channel you can see in the panel 2 the list of the channel's items." + +_key="help3-2" +_value="2) The Episodes list with all the items available." + +_key="help3-3" +_value="3) The Info panel show: episode info, channel info or Downloads info; you can select an info panel by clicking one of the below three buttons." + + + +_key="help4-0" +_value="At the very top of the BePodder main window is the menubar with seven menus available: File, Settings, Subscriptions, Episodes, Lists, View and Help. Some menu commands are followed by a right pointing arrow that indicates a submenu of related commands. As you explore each menu, be sure to take a look at the submenus as well. Click on a menus to show its commands:" + +_key="help4-1" +_value="File: contains commands to close the application and to show information about BePodder" + +_key="help4-2" +_value="Settings: contains command to open the Preferences window that allows you to customize various BePodder settings." + +_key="help4-3" +_value="Subscriptions: contains commands that perform actions on the selected channel of your subscriptions list." + +_key="help4-4" +_value="Episodes: contains commands that perform actions on the selected item (episode) of the channel's episode list." + +_key="help4-5" +_value="Lists: contains commands to open BePodder's OPML directories." + +_key="help4-6" +_value="View: contains commands and controls for the BePodder window." + +_key="help4-7" +_value="Help: contains commands to open BePodder's 'Getting Started Guide' and the 'Keyboard Shortcuts List'." + + + +_key="help5-0" + _value="Add Button: opens the Add Window to add a feed url (e.g. http://www.newpodcast.com/rss.xml) usually given on the podcast homepage; looks for text or graphic link that says something like 'XML', 'RSS' or 'Podcast Feed' on it." + +_key="help5-1" + _value="Channel Remove Button: opens a window in which you can select how remove the channel: just archive the select channel (keeping all the files and eclosure downloaded so far) or delete the whole channel from your computer." + +_key="help5-2" + _value="Check Button: checks the selected channel and updates the list of the available items for that podcast adding the new items." + +_key="help5-3" + _value="Web Button: shows the channel homepage in the browser. To select your favorite browser open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select your favorite browser." + +_key="help5-4" + _value="Play Button: with this button you can view or listen the file enclosure of the selected item(episode). To select your favorite player open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select you favorite player." + +_key="help5-5" + _value="Download Button: downloads the file enclosure of the selected item (episode); you can see the download info by clicking on the third button over the info panel." + +_key="help5-6" + _value="Stop Button: stops to download the file enclosure of the selected item (episode); to resume the download double-click the item (episode) or select the item and click the Download Button" + +_key="help5-7" + _value="Item Remove Button: deletes the selected item (you will loose the enclosure file)." + + + +_key="help6-0" + _value="Getting started with BePodder is easy." + +_key="help6-1" + _value="On the left of the main window you can see the 'Subscription List' with all your feed subscriptions. We have added some subscriptions for you, and you can always add your own in two ways:" + +_key="help6-2" + _value="1) click the Add Button, then insert the feed url (example: http://www.newpodcast.com/rss.xml) and click add." + +_key="help6-3" + _value="2) in the menubar select 'Directory' and then 'Podcast list' or another list, choose a podcast and click 'Subscribe'." + +_key="help6-4" + _value="If you select a Podcast in the subscriptions list and use the check button, BePodder adds the new items to the 'Episodes list' (below on the right); you can check all your podcasts by right-clicking and selecting 'Check All Channels' in the context menu." + +_key="help6-5" + _value="Look at the screenshot above, there are 3 new items indicated by a black dot in the first column of the 'Episodes list'." + +_key="help6-6" + _value="In the second column there are icons that indicate the state of the item:" + +_key="help6-7" + _value="- the Episode 4 has an icon that indicates an error" + +_key="help6-8" + _value="- the Episode 3 has an icon that indicates that the item's enclosure download request is enquequed" + +_key="help6-9" + _value="- the Episode 2 has an icon that indicates that BePodder is downloading the item's enclosure file" + +_key="help6-10" + _value="- the Episode 1 have an icon that indicates that BePodder have just downloaded the item's enclosure file" + + + +_key="help7-0" + _value="Select an item in the 'Episodes list' and then double-click on it (or click the Download Button) to start downloading the enclosed file; you can always stop the download by clicking on the Stop Button." + +_key="help7-1" + _value="When you click on the Subscribed Podcasts in the 'Subscriptions List' the software shows you, in the 'List of episodes', all the items available in that Subscription. Select an item and then click play (Play Button) to view or listen to the file." + +_key="help7-2" + _value="You can access the Enclosures Folder by clicking on the folder icon in the Info Pannel or by right-clicking your mouse on an item and select 'Open Enclosures Folder' in the context menu." + + + +_key="help8-0" + _value="Preferences can be accessed by clicking in the menu-bar Settings>Preferences. You can select a category from the left list of the preferences dialog: FileType, Channels, Download and Proxy." + +_key="help8-1" + _value="- FileType: to specify the default browser and player. " + +_key="help8-2" + _value="- Channels: to specify preferences that control the operation to check channels new items; you can choose to Check all channels on startup or check the channel every desired minutes." + +_key="help8-3" + _value="- Download: to specify the max number of item's files to download at the same time," + +_key="help8-4" + _value="- Proxy: to set up a proxy server to work with BePodder; a proxy server acts as a security barrier between your internal network and the Internet, keeping others on the Internet from accessing information on your internal network." + + + +_key="help9-0" + _value="BePodder has built-in podcast, videoblog, imagefeeds, newsfeeds, bittorrentfeeds and internationalfeeds OPML directories with thousands of feeds grouped by category." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) is an XML-based format that allows exchange of outline-structured information between applications." + +_key="help9-2" + _value="OPML directory can be accessed by clicking in the menu-bar 'Lists' and thenselecting a list. To browse the opml directory for a feed, expand the list by clicking the arrow of the category that you are interested in (see image); using this method, you can expand the opml directory until you find the desired feed. Once you have selected it, you can add it to the subscription list by clicking the button 'Subscribe', you can also collapse all categories in the directory list by clicking the button 'Collapse All'." + +_key="help_shortcut1" +_value="This page describes the keyboard shortcuts that can be used in BePodder. The shortcuts are grouped here by function." + +_key="help_shortcut2" +_value="means that you can use either alt or control (es. Alt+Q or Ctrl+Q Quit the application), which way you have set it in the Deskbar menu preferences under Keyboard (the default shortcut key is Alt)." + +_key="help_shortcut3" + _value="General shortcuts" + +_key="help_shortcut4" + _value="Quit the application" + +_key="help_shortcut5" + _value="Shows the Preferences window" + +_key="help_shortcut6" + _value="Shows the Podcast directory list" + +_key="help_shortcut7" + _value="Shows the Videoblog directory list" + +_key="help_shortcut8" + _value="Shows the Imagefeeds directory list" + +_key="help_shortcut9" + _value="Shows the Newsfeeds directory list" + +_key="help_shortcut9b" + _value="Shows the BitTorrentfeeds directory list" + +_key="help_shortcut9c" + _value="Shows the Internationalfeeds directory list" + +_key="help_shortcut10" + _value="Fullscreen" + +_key="help_shortcut11" + _value="Shows/Hides the toolbar" + +_key="help_shortcut12" + _value="Shows the Getting Started Help" + +_key="help_shortcut13" + _value="Shows this keyboard shortcuts page" + +_key="help_shortcut14" + _value="Channels shortcuts" + +_key="help_shortcut15" + _value="Add a podcast to the subscriptions list" + +_key="help_shortcut16" + _value="Delete the selected podcast from the subscriptions list" + +_key="help_shortcut17" + _value="Check the selected podcast for new episodes (items)" + +_key="help_shortcut18" + _value="Check all podcasts for new episodes (items)" + +_key="help_shortcut19" + _value="Shows the podcast homepage" + +_key="help_shortcut20" + _value="Open enclosures folder" + +_key="help_shortcut21" + _value="Episodes shortcuts" + +_key="help_shortcut22" + _value="Play enclosure" + +_key="help_shortcut23" + _value="(Re)start download the selected episodes (items)" + +_key="help_shortcut24" + _value="Stop the episode (item) download" + +_key="help_shortcut25" + _value="Delete the selected episode (item)" + +_key="help_shortcut26" + _value="Shows the podcast episode (item) page " + +_key="help_shortcut27" + _value="Open enclosures folder" + +_key="help_buy1" + _value="BePodder Light is the basic version (free download and no time limited), the registered version adds some more nice features: unlimited number of channels, small Channel view, proxy support, automatic channels check, up to 5 enclosure downloads at the same time (multithreading)." + +_key="help_buy2" + _value="Please pay the shareware fee, it's only 15 euro (Kagi add tax in some countries), BePodder licence can be purchased online from Kagi." + +_key="help_buy3" + _value="Buy at www.funkyideasoft.com" + +_key="help_buy4" + _value="After purchasing, an email will be sent to you with a keyfile and instruction on how to install it. It's just a matter of unzipping a file and moving it to a certain directory." + +_key="help_buy5" + _value="There is no problem updating BePodder when a new version becomes available. The keyfile will unlock all downloadable packages unless otherwise notified." + + +### USELESS ######## + +"Opml Editor" "Opml Editor" +"name:" "name:" +"Add a category" "Add a category" +"Add a new Broadcast" "Add a new Broadcast" +"feed:" "feed:" +"url:" "url:" +"Test podcast" "Test podcast" +"Del a category" "Del a category" +"Add a category" "Add a category" +"Select the podcast category:" "Select the podcast category:" +"Check all" "Check all" +"Check" "Check" +"Refresh the list" "Refresh the list" +"Load" "Load" +"Load the list" "Load the list" +"Save" "Save" +"Save the list" "Save the list" +"Revert" "Revert" +"Apply" "Apply" + + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.fiFI b/release/Language/Dictionaries/BePodder.fiFI new file mode 100644 index 0000000..83874e9 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.fiFI @@ -0,0 +1,603 @@ + +# Locale file for BePodder. +# Modified: 4/18/2006 +# Author: BePodderTeam +# E-mail: bepodder.team@gmail.com + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" + +"Web Site" "Web Site" + +"Can't connect!" "Can't connect!" +"Http port failed!" "Http port failed!" +"Can't resolve host!" "Can't resolve host!" +"Not found!" "Not found!" +"Bad resume!" "Bad resume!" +"Aborted by Callback!" "Aborted by Callback!" +"Can't resume! (range error)" "Can't resume! (range error)" +"Access Denied!" "Access Denied!" +"User or Password Incorrect!" "User or Password Incorrect!" +"Other error (cUrl code: " "Other error (cUrl code: " +"cUrl init error!" "cUrl init error!" +"Can't open file!" "Can't open file!" +"Other error (status code: " "Other error (status code: " +"Downloading" "Downloading" + + +### MENUBAR ----------------------------------- + +"File" "File" +"About..." "About..." +"Close!" "Close!" +"Quit" "Quit" + +"Settings" "Settings" +"Preferences..." "Preferences..." + +"Subscriptions" "Subscriptions" + +"Episodes" "Episodes" + +"Lists" "Lists" +"Podcast List" "Podcast List" +"Podcast directory list" "Podcast directory list" +"Videoblog List" "Videoblog List" +"Videoblog directory list" "Videoblog directory list" +"Imagefeeds List" "Imagefeeds List" +"Imagefeeds directory list" "Imagefeeds directory list" +"Newsfeeds List" "Newsfeeds List" +"Newsfeeds directory list" "Newsfeeds directory list" +"BitTorrentfeeds List" "BitTorrentfeeds List" +"BitTorrentfeeds directory list" "BitTorrentfeeds directory list" +"Internationalfeeds List" "Internationalfeeds List" +"Internationalfeeds directory list" "Internationalfeeds directory list" + +"View" "View" +"Full Screen" "Full Screen" +"Toolbar" "Toolbar" +"Subscriptions View" "Subscriptions View" +"Small Items" "Small Items" +"Big Items" "Big Items" +"Move BePodder on workspace:" "Move BePodder on workspace:" + +"Help" "Help" +"Getting Started" "Getting Started" +"Keyboard Shortcuts" "Keyboard Shortcuts" +"Tutorials" "Tutorials" +"Online Support" "Online Support" + + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "Insert the rss feed url!" +"Add" "Add" +"Paste" "Paste" + +# Buttons directory list window +"Collapse All" "Collapse All" +"Preview" "Preview" +"Subscribe" "Subscribe" + + +# Buttons help window +"Next" "Next" +"Prev" "Prev" +"Close" "Close" +"Index" "Index" + + +# Buttons remove windows +"Cancel" "Cancel" +"Delete" "Delete" +"Archive" "Archive" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Add the podcast to the Subscriptions list" +"Delete the podcast from the Subscriptions list" "Delete the podcast from the Subscriptions list" +"Check the selected podcast for new items" "Check the selected podcast for new items" +"Show the podcast homepage" "Show the podcast homepage" + +"Delete the item and the enclosure" "Delete the item and the enclosure" +"Stop the item download" "Stop the item download" +"Download the selected episode" "Download the selected episode" +"Play the selected episode" "Play the selected episode" + +"Submit bug and idea" "Submit bug and idea" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Collapse all categories in the directory list" +"Add the selected podcast to the Subscription list" "Add the selected podcast to the Subscription list" +"Checkout a podcast before downloading it" "Checkout a podcast before downloading it" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Show Channel Image" +"XML Feed Link" "XML Feed Link" + +"Show Episode info" "Show Episode info" +"Show Subscription info" "Show Subscription info" +"Show Downloads info" "Show Downloads info" + +"Enclosure: " "Enclosure: " + +"Lookup (Dictionary)" "Lookup (Dictionary)" +"Lookup (Google)" "Lookup (Google)" +"Lookup (Acronym Finder)" "Lookup (Acronym Finder)" +"Copy" "Copy" +"Select All" "Select All" +"Copy URL" "Copy URL" +"Open URL" "Open URL" +"Subscription" "Subscription" + + +### PREFERENCES ----------------------------------- + +"Preferences" "Preferences" + +"Proxy" "Proxy" +"Enable Proxy" "Enable Proxy" +"Address" "Address" +"Port" "Port" +"Username" "Username" +"Password" "Password" + +"Max Downloads" "Max Downloads" + +"FileType" "FileType" +"Browser" "Browser" +"Player" "Player" + +"Channels" "Channels" +"Check all channels on startup" "Check all channels on startup" +"Check the channel every" "Check the channel every" + +"never" "never" +"5 minutes" "5 minutes" +"15 minutes" "15 minutes" +"30 minutes" "30 minutes" +"1 hour" "1 hour" +"2 hour" "2 hour" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 new item" +"%d new items" "%d new items" +"new" "new" +"error" "error" +"not down" "not down" +"enquequed" "enquequed" +"downloading" "downloading" +"downloaded" "downloaded" +"connecting" "connecting" +"not found" "not found" +"stopped" "stopped" +"can't connect" "can't connect" +"invalid format" "invalid format" + +"Icon" "Icon" +"Title" "Title" +"Date" "Date" +"Size" "Size" +"Status" "Status" +"Download" "Download" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "Add Channel" +"Remove Channel" "Remove Channel" +"Check Channel" "Check Channel" +"Open Homepage" "Open Homepage" + +"Open Web Page" "Open Web Page" +"Open Enclosures folder" "Open Enclosures folder" +"Check All Channels" "Check All Channels" + +"Show Channel Image" "Show Channel Image" + +"Play enclosure" "Play enclosure" +"(Re)start download" "(Re)start download" +"Stop download" "Stop download" +"Remove Item" "Remove Item" + +"Find this Item" "Find this Item" +"Remove from this list" "Remove from this list" + + + +### ALERT ----------------------------------- + +"\nRemoving.." "\nRemoving.." +"\nAn error occured while removing!" "\nAn error occured while removing!" +"Check all the podcasts for new items" "Check all the podcasts for new items" + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" + +"Can't open the selected file with:\n\n" "Can't open the selected file with:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nPlease check if the application is installed in the right way.\n" +"Download it!" "Download it!" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +You are going to remove the selected item. + +Are you sure? +(you will lost the enclosure file if any)" + + +_key="alert2a" + _value=" +You are going to remove the channel: + +" + +_key="alert2b" + _value=" + +Would you like just to archive this +channel (keeping all the files and +enclosures downloaded so far) or +do you want to DELETE the whole + channel from you computer?" + +_key="alert3" + _value=" +Parsing archive.." + +_key="alert_3gp" + _value=" +3GP is a multimedia container format defined by the Third Generation Partnership Project (3GPP) for use on 3G mobile phones. It stores video streams as MPEG-4 or H.263, and audio streams as AMR-NB or AAC-LC. + +VideoLAN still doesn't support the audio AMR (3GPP)" + +_key="alert_swf" + _value=" +SWF is a proprietary vector graphics file format produced by the Flash software from Adobe (formerly Macromedia). + +Currently Flash support in BeOS/Haiku/Zeta is limited to the old standalone Flash player version 4.1015, there isn't a modern Flash player" + + + + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Introduction" +"The User Interface" "The User Interface" +"Menu Bar" "Menu Bar" +"Toolbar Buttons" "Toolbar Buttons" +"First time with BePodder" "First time with BePodder" +"Download Podcast's enclosure files" "Download Podcast's enclosure files" +"Settings Overview" "Settings Overview" +"Directory lists" "Directory lists" +"Loading Help..." "Loading Help..." +"Register your copy" "Register your copy" +"Starting point" "Starting point" + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value="Welcome to the BePodder Getting Started Guide." + +_key="help1-1" + _value="If you are already familiar with podcasts and RSS/Atom feeds you can immediately go to BePodder by closing this window." + +_key="help1-2" +_value="If not, this is a short introduction providing you everything you'll need to know on how to get started with BePodder. Use the buttons below to navigate through this tutorial." + + +_key="help2-0" +_value="Podcasting is a method for publishing audio and video broadcasts via the Internet; links to free audio and video files are enclosed in RSS and Atom feeds." + +_key="help2-1" +_value="Therefore Podcasting is simply a type of online media delivery; users can subscribe to a podcast using a feed (such as RSS 'Really Simple Syndication' or Atom)." + +_key="help2-2" +_value="An aggregator (or podcatcher) like BePodder, is a piece of software that allows you to subscribe to a RSS feed and periodically check for and download new content; with BePodder you can check for new Podcast items (Episodes) of your subscribed Channels. Any item can contain an enclosure, just like an Email can contain an attachment." + + + +_key="help3-0" +_value="BePodder has an easy to use yet powerful Graphical User Interface. The main window is split into tree panels:" + +_key="help3-1" +_value="1) The Subscription list (the panel with the number 1 in the screenshot) with the list of the podcasts that you have subscribed to. When you click on a Channel you can see in the panel 2 the list of the channel's items." + +_key="help3-2" +_value="2) The Episodes list with all the items available." + +_key="help3-3" +_value="3) The Info panel show: episode info, channel info or Downloads info; you can select an info panel by clicking one of the below three buttons." + + + +_key="help4-0" +_value="At the very top of the BePodder main window is the menubar with seven menus available: File, Settings, Subscriptions, Episodes, Lists, View and Help. Some menu commands are followed by a right pointing arrow that indicates a submenu of related commands. As you explore each menu, be sure to take a look at the submenus as well. Click on a menus to show its commands:" + +_key="help4-1" +_value="File: contains commands to close the application and to show information about BePodder" + +_key="help4-2" +_value="Settings: contains command to open the Preferences window that allows you to customize various BePodder settings." + +_key="help4-3" +_value="Subscriptions: contains commands that perform actions on the selected channel of your subscriptions list." + +_key="help4-4" +_value="Episodes: contains commands that perform actions on the selected item (episode) of the channel's episode list." + +_key="help4-5" +_value="Lists: contains commands to open BePodder's OPML directories." + +_key="help4-6" +_value="View: contains commands and controls for the BePodder window." + +_key="help4-7" +_value="Help: contains commands to open BePodder's 'Getting Started Guide' and the 'Keyboard Shortcuts List'." + + + +_key="help5-0" + _value="Add Button: opens the Add Window to add a feed url (e.g. http://www.newpodcast.com/rss.xml) usually given on the podcast homepage; looks for text or graphic link that says something like 'XML', 'RSS' or 'Podcast Feed' on it." + +_key="help5-1" + _value="Channel Remove Button: opens a window in which you can select how remove the channel: just archive the select channel (keeping all the files and eclosure downloaded so far) or delete the whole channel from your computer." + +_key="help5-2" + _value="Check Button: checks the selected channel and updates the list of the available items for that podcast adding the new items." + +_key="help5-3" + _value="Web Button: shows the channel homepage in the browser. To select your favorite browser open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select your favorite browser." + +_key="help5-4" + _value="Play Button: with this button you can view or listen the file enclosure of the selected item(episode). To select your favorite player open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select you favorite player." + +_key="help5-5" + _value="Download Button: downloads the file enclosure of the selected item (episode); you can see the download info by clicking on the third button over the info panel." + +_key="help5-6" + _value="Stop Button: stops to download the file enclosure of the selected item (episode); to resume the download double-click the item (episode) or select the item and click the Download Button" + +_key="help5-7" + _value="Item Remove Button: deletes the selected item (you will loose the enclosure file)." + + + +_key="help6-0" + _value="Getting started with BePodder is easy." + +_key="help6-1" + _value="On the left of the main window you can see the 'Subscription List' with all your feed subscriptions. We have added some subscriptions for you, and you can always add your own in two ways:" + +_key="help6-2" + _value="1) click the Add Button, then insert the feed url (example: http://www.newpodcast.com/rss.xml) and click add." + +_key="help6-3" + _value="2) in the menubar select 'Directory' and then 'Podcast list' or another list, choose a podcast and click 'Subscribe'." + +_key="help6-4" + _value="If you select a Podcast in the subscriptions list and use the check button, BePodder adds the new items to the 'Episodes list' (below on the right); you can check all your podcasts by right-clicking and selecting 'Check All Channels' in the context menu." + +_key="help6-5" + _value="Look at the screenshot above, there are 3 new items indicated by a black dot in the first column of the 'Episodes list'." + +_key="help6-6" + _value="In the second column there are icons that indicate the state of the item:" + +_key="help6-7" + _value="- the Episode 4 has an icon that indicates an error" + +_key="help6-8" + _value="- the Episode 3 has an icon that indicates that the item's enclosure download request is enquequed" + +_key="help6-9" + _value="- the Episode 2 has an icon that indicates that BePodder is downloading the item's enclosure file" + +_key="help6-10" + _value="- the Episode 1 have an icon that indicates that BePodder have just downloaded the item's enclosure file" + + + +_key="help7-0" + _value="Select an item in the 'Episodes list' and then double-click on it (or click the Download Button) to start downloading the enclosed file; you can always stop the download by clicking on the Stop Button." + +_key="help7-1" + _value="When you click on the Subscribed Podcasts in the 'Subscriptions List' the software shows you, in the 'List of episodes', all the items available in that Subscription. Select an item and then click play (Play Button) to view or listen to the file." + +_key="help7-2" + _value="You can access the Enclosures Folder by clicking on the folder icon in the Info Pannel or by right-clicking your mouse on an item and select 'Open Enclosures Folder' in the context menu." + + + +_key="help8-0" + _value="Preferences can be accessed by clicking in the menu-bar Settings>Preferences. You can select a category from the left list of the preferences dialog: FileType, Channels, Download and Proxy." + +_key="help8-1" + _value="- FileType: to specify the default browser and player. " + +_key="help8-2" + _value="- Channels: to specify preferences that control the operation to check channels new items; you can choose to Check all channels on startup or check the channel every desired minutes." + +_key="help8-3" + _value="- Download: to specify the max number of item's files to download at the same time," + +_key="help8-4" + _value="- Proxy: to set up a proxy server to work with BePodder; a proxy server acts as a security barrier between your internal network and the Internet, keeping others on the Internet from accessing information on your internal network." + + + +_key="help9-0" + _value="BePodder has built-in podcast, videoblog, imagefeeds, newsfeeds, bittorrentfeeds and internationalfeeds OPML directories with thousands of feeds grouped by category." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) is an XML-based format that allows exchange of outline-structured information between applications." + +_key="help9-2" + _value="OPML directory can be accessed by clicking in the menu-bar 'Lists' and thenselecting a list. To browse the opml directory for a feed, expand the list by clicking the arrow of the category that you are interested in (see image); using this method, you can expand the opml directory until you find the desired feed. Once you have selected it, you can add it to the subscription list by clicking the button 'Subscribe', you can also collapse all categories in the directory list by clicking the button 'Collapse All'." + +_key="help_shortcut1" +_value="This page describes the keyboard shortcuts that can be used in BePodder. The shortcuts are grouped here by function." + +_key="help_shortcut2" +_value="means that you can use either alt or control (es. Alt+Q or Ctrl+Q Quit the application), which way you have set it in the Deskbar menu preferences under Keyboard (the default shortcut key is Alt)." + +_key="help_shortcut3" + _value="General shortcuts" + +_key="help_shortcut4" + _value="Quit the application" + +_key="help_shortcut5" + _value="Shows the Preferences window" + +_key="help_shortcut6" + _value="Shows the Podcast directory list" + +_key="help_shortcut7" + _value="Shows the Videoblog directory list" + +_key="help_shortcut8" + _value="Shows the Imagefeeds directory list" + +_key="help_shortcut9" + _value="Shows the Newsfeeds directory list" + +_key="help_shortcut9b" + _value="Shows the BitTorrentfeeds directory list" + +_key="help_shortcut9c" + _value="Shows the Internationalfeeds directory list" + +_key="help_shortcut10" + _value="Fullscreen" + +_key="help_shortcut11" + _value="Shows/Hides the toolbar" + +_key="help_shortcut12" + _value="Shows the Getting Started Help" + +_key="help_shortcut13" + _value="Shows this keyboard shortcuts page" + +_key="help_shortcut14" + _value="Channels shortcuts" + +_key="help_shortcut15" + _value="Add a podcast to the subscriptions list" + +_key="help_shortcut16" + _value="Delete the selected podcast from the subscriptions list" + +_key="help_shortcut17" + _value="Check the selected podcast for new episodes (items)" + +_key="help_shortcut18" + _value="Check all podcasts for new episodes (items)" + +_key="help_shortcut19" + _value="Shows the podcast homepage" + +_key="help_shortcut20" + _value="Open enclosures folder" + +_key="help_shortcut21" + _value="Episodes shortcuts" + +_key="help_shortcut22" + _value="Play enclosure" + +_key="help_shortcut23" + _value="(Re)start download the selected episodes (items)" + +_key="help_shortcut24" + _value="Stop the episode (item) download" + +_key="help_shortcut25" + _value="Delete the selected episode (item)" + +_key="help_shortcut26" + _value="Shows the podcast episode (item) page " + +_key="help_shortcut27" + _value="Open enclosures folder" + +_key="help_buy1" + _value="BePodder Light is the basic version (free download and no time limited), the registered version adds some more nice features: unlimited number of channels, small Channel view, proxy support, automatic channels check, up to 5 enclosure downloads at the same time (multithreading)." + +_key="help_buy2" + _value="Please pay the shareware fee, it's only 15 euro (Kagi add tax in some countries), BePodder licence can be purchased online from Kagi." + +_key="help_buy3" + _value="Buy at www.funkyideasoft.com" + +_key="help_buy4" + _value="After purchasing, an email will be sent to you with a keyfile and instruction on how to install it. It's just a matter of unzipping a file and moving it to a certain directory." + +_key="help_buy5" + _value="There is no problem updating BePodder when a new version becomes available. The keyfile will unlock all downloadable packages unless otherwise notified." + + +### USELESS ######## + +"Opml Editor" "Opml Editor" +"name:" "name:" +"Add a category" "Add a category" +"Add a new Broadcast" "Add a new Broadcast" +"feed:" "feed:" +"url:" "url:" +"Test podcast" "Test podcast" +"Del a category" "Del a category" +"Add a category" "Add a category" +"Select the podcast category:" "Select the podcast category:" +"Check all" "Check all" +"Check" "Check" +"Refresh the list" "Refresh the list" +"Load" "Load" +"Load the list" "Load the list" +"Save" "Save" +"Save the list" "Save the list" +"Revert" "Revert" +"Apply" "Apply" + + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.frBE b/release/Language/Dictionaries/BePodder.frBE new file mode 100644 index 0000000..cdb5154 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.frBE @@ -0,0 +1,601 @@ +# Locale file for BePodder. +# Modified: 21/04/2006 +# Author: Rémi Grumeau +# E-mail: remi@beosfrance.com + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Application en version Shareware !\n\nMerci pour votre support!\n\nAcheter une license!\nPlus d'infos sur le site internet\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "Désolé, la periode d'éssai de BePodder est terminée !\nMerci d'acheter une license.\n" + +"Web Site" "Site Internet" + +"Can't connect!" "Connection impossible!" +"Http port failed!" "Port HTTP indisponible!" +"Can't resolve host!" "Hôte introuvable !" +"Not found!" "Introuvable !" +"Bad resume!" "Résume impossible !" +"Aborted by Callback!" "Annulé par l'utilisateur !" +"Can't resume! (range error)" "Résume impossible ! (erreur de classement)" +"Access Denied!" "Accès refusé !" +"User or Password Incorrect!" "Identifiant ou mot de passe incorrect !" +"Other error (cUrl code: " "Erreur inconnue (code cUr : " +"cUrl init error!" "erreur d'init cUrl !" +"Can't open file!" "Ouverture impossible!" +"Other error (status code: " "Erreur inconnue (statut code: " +"Downloading" "Téléchargement en cours" + +### MENUBAR ----------------------------------- + +"File" "Fichier" +"About..." "A propos...." +"Close!" "Fermer" +"Quit" "Quitter" + +"Settings" "Préférences" +"Preferences..." "Préférences..." + +"Subscriptions" "Abonnements" + +"Episodes" "Episodes" + +"Lists" "Listes" +"Podcast List" "Liste de Podcast" +"Podcast directory list" "Dossier de la liste Podcast" +"Videoblog List" "Liste de Videoblogs" +"Videoblog directory list" "Dossier de la liste de Videoblogs" +"Imagefeeds List" "Liste des Imagefeeds" +"Imagefeeds directory list" "Dossier de la liste de Imagefeeds" +"Newsfeeds List" "Liste des Newsfeeds" +"Newsfeeds directory list" "Dossier de la liste des Newsfeeds" +"BitTorrentfeeds List" "Liste des BitTorrentfeeds" +"BitTorrentfeeds directory list" "Dossier de la liste des BitTorrentfeeds" +"Internationalfeeds List" "Liste des Internationalfeeds" +"Internationalfeeds directory list" "Dossier de la liste des Internationalfeeds" + +"View" "Affichage" +"Full Screen" "Plein-écran" +"Toolbar" "Barre d'outils" +"Subscriptions View" "Liste des abonnements" +"Small Items" "Liste simple" +"Big Items" "Liste avec icones" +"Move BePodder on workspace:" "Déplacer BePodder sur le bureau:" + +"Help" "Aide" +"Getting Started" "Bien démarrer avec BePodder" +"Keyboard Shortcuts" "Raccourics clavier" +"Tutorials" "Didacticielles" +"Online Support" "Support en ligne" + + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "Entrer l'adresse du flux RSS!" +"Add" "Ajouter" +"Paste" "Coller" + +# Buttons directory list window +"Collapse All" "Tout minimiser" +"Preview" "Prévisualiser" +"Subscribe" "S'abonner" + + +# Buttons help window +"Next" "Suivant" +"Prev" "Précédent" +"Close" "Fermer" +"Index" "Index" + + +# Buttons remove windows +"Cancel" "Annuler" +"Delete" "Supprimer" +"Archive" "Archive" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Ajouter le PodCast a votre liste d'abonnements" +"Delete the podcast from the Subscriptions list" "Supprimer le PodCast de votre liste d'abonnements" +"Check the selected podcast for new items" "Mettre a jour le PodCast" +"Show the podcast homepage" "Afficher la page d'accueil du PodCast" + +"Delete the item and the enclosure" "Delete the item and the enclosure" +"Stop the item download" "Stopper le téléchargement" +"Download the selected episode" "Télécharger l'épisode sélectionné" +"Play the selected episode" "Lire l'épisode sélectionné" + +"Submit bug and idea" "Soumettre une idée ou signaler un bug" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Rassembler toutes les catégories dans la liste des dossiers" +"Add the selected podcast to the Subscription list" "Ajouter le PodCast sélectionné a votre liste d'abonnements" +"Checkout a podcast before downloading it" "Verifier le PodCast avant de le télécharger" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Afficher l'image" +"XML Feed Link" "Lien du Feed XML" + +"Show Episode info" "Afficher les infos de l'épisode" +"Show Subscription info" "Afficher les infos de l'abonnement" +"Show Downloads info" "Afficher les infos du télechargement" + +"Enclosure: " "Fichier inclus: " + +"Lookup (Dictionary)" "Rechercher dans 'Dictionary'" +"Lookup (Google)" "Rechercher dans 'Google'" +"Lookup (Acronym Finder)" "Rechercher dans 'Acronym Finder'" +"Copy" "Copier" +"Select All" "Tout sélectionner" +"Copy URL" "Copier l'adresse" +"Open URL" "Ouvrir l'adresse" +"Subscription" "Souscription" + +"Find this Item" "Trouver ce fichier" +"Remove from this list" "Supprimer ce fichier" + + +### PREFERENCES ----------------------------------- + +"Preferences" "Préférences" + +"Proxy" "Proxy" +"Enable Proxy" "Activer le proxy" +"Address" "Addresse" +"Port" "Port" +"Username" "Identifiant" +"Password" "Mot de passe" + +"Max Downloads" "Téléchargements Max" + +"FileType" "Ouvrir les fichiers" +"Browser" "Navigateur:" +"Player" "Lecteur Audio/Vidéo:" + +"Channels" "Abonnements" +"Check all channels on startup" "Verifier tous les abonnements au démarrage" +"Check the channel every" "Vérifier tout les " + +"never" "Ne jamais vérifier" +"5 minutes" "5 minutes" +"15 minutes" "15 minutes" +"30 minutes" "30 minutes" +"1 hour" "heures" +"2 hour" "2 heures" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 nouveau fichier" +"%d new items" "%d nouveaux fichiers" +"new" "nouveau" +"error" "erreur" +"not down" "non téléchargé" +"enquequed" "ajouté" +"downloading" "en cours de téléchargement" +"downloaded" "téléchargé" +"connecting" "connection en cours" +"not found" "introuvable" +"stopped" "arreté" +"can't connect" "connection impossible" +"invalid format" "format non valide" + +"Icon" "Icon" +"Title" "Titre" +"Date" "Date" +"Size" "Taille" +"Status" "Etat" +"Download" "Téléchargement" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "AJouter un abonnement" +"Remove Channel" "Supprimer un abonnement" +"Check Channel" "Vérifier les mises a jour" +"Open Homepage" "Ouvrir la page d'acceuil" + +"Open Web Page" "Aller sur le site internet" +"Open Enclosures folder" "Ouvrir le dossier" +"Check All Channels" "Vérifier tous les abonnements" + +"Show Channel Image" "Afficher la vignette de l'abonnement" + +"Play enclosure" "Afficher" +"(Re)start download" "(re)Télécharger" +"Stop download" "Arreter le téléchargement" +"Remove Item" "Supprimer" + +"Find this Item" "Trouver ce fichier" +"Remove from this list" "Supprimer ce fichier" + + + +### ALERT ----------------------------------- + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "Désolé mais vous ne pouvez vous inscrire qu'a 10 podcasts dans cette version d'essai.\n Veuillez vous enregistrer.\n" + +"Can't open the selected file with:\n\n" "Impossible d'ouvrir ce fichier avec:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nVeuillez vérifier que cette application est bien installée a cet endroit.\n" + +"Download it!" "Télécharger !" + +"\nRemoving.." "\nSuppression.." +"\nAn error occured while removing!" "\nUne erreur s'est produite lors de la suppression !" +"Check all the podcasts for new items" "Vérifier tous les PodCast et les mettre a jour" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +Vous etes sur le point de supprimer la ligne suivante. + +Etes-vous sur ? +(le fichier inclus sera perdu, si il y en a un)" + + +_key="alert2a" + _value=" +Vous etes sur le point de supprimer l'abonnement: + +" + +_key="alert2b" + _value=" + +Désirez-vous archiver cet abonnement +(et conserver les fichiers téléchargé) ou +voulez-vous supprimer tous les fichiers +en rapport avec cet abonnement ?" + +_key="alert3" + _value=" +Archivage en cours..." + +_key="alert_3gp" + _value=" +3GP est un format de contenance multimedia défini par le Third Generation Partnership Project (3GPP) pour une utilisation sur téléphone mobile 3G. Il enregistre la vidéo en MPEG-4 ou H.263, et l'audio en AMR-NB ou AAC-LC. + +VideoLAN ne supporte pas encore le AMR-NB (3GPP)" + +_key="alert_swf" + _value=" +SWF est un format d'animation vectorielle propriétaire appartenant a Adobe (créée par Macromedia). + +Pour l'instant, le support des animations flash sous BeOS, Zeta ou Haiku se limite à la version 4.1015, aucun lecteur plus récent n'est disponible." + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Introduction" +"The User Interface" "L'interface utilisateur" +"Menu Bar" "La barre du menu" +"Toolbar Buttons" "La barre d'outils" +"First time with BePodder" "Les premiers pas avec BePodder" +"Download Podcast's enclosure files" "Télécharger les fichiers relatifs aux Podcasts" +"Settings Overview" "Les parametres" +"Directory lists" "Listes des dossiers" +"Loading Help..." "Chargement de l'aide..." +"Register your copy" "Enregistrez-vous" +"Starting point" "Sommaire" + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value=Bienvenu dans l'aide à l'utilisation de BePodder." + +_key="help1-1" + _value="Si vous avez déjà utilisé BePodder ou familié aux logiciels de flux RSS/Atom, vous pouvez fermer cette fenêtre et commencer à utiliser BePodder." + +_key="help1-2" +_value="Le cas échéant, voici une petite introduction sur comment et pourquoi utiliser ce type de logiciel. Utilisez les boutons en bas de la fenetre pour naviguer dans ce didacticielle." + + + +_key="help2-0" +_value="Podcaster est une méthode pour publier du contenu audio ou vidéo sur Internet; les liens vers les fichiers sont définis dans les flux RSS/Atom." + +_key="help2-1" +_value="Le Podcasting est donc un simple moyen de mettre a disposition des fichiers; les utilisateurs peuvent alors souscrire à ce flux (comme un RSS 'Really Simple Syndication' ou Atom)." + +_key="help2-2" +_value="Un aggregator (ou podcatcher) comme BePodder, est un logiciel vous permettant de souscrire à ces flux et vérifier périodiquement si un flux à était mis à jour; avec BePodder vous pouvez vérifier si de nouveaux fichiers sont disponibles (Episodes) dans les flux souscrits. Chaque fichier peut alors contenir une pièce jointe, tout comme un email." + + + +_key="help3-0" +_value="BePodder a un interface simple et très complète. La fenêtre principale est divisée en trois parties:" + +_key="help3-1" +_value="1) La liste des abonnements (la partie avec le numéro 1) contenant la liste des flux ausquels vous avez souscrits. Lorsque vous sélectionnez un flux, vous pouvez voir la liste des épisodes qu'il contient dans la seconde partie (numéro 2)." + +_key="help3-2" +_value="2) La liste des épisodes avec les fichiers qu'ils contiennent." + +_key="help3-3" +_value="3) Informations. Cette troisième et dernière partie contient: informations générales, de l'épisodes ou du téléchargement; vous pouvez sélectionner l'info voulu en cliquant sur les boutons correspondants." + + + +_key="help4-0" +_value="Tout en haut de la fenêtre principale de BePodder se trouve le menu avec 7 sous menus: Fichier, Préférences, Abonnements, Episodes, Listes, Affichage et Aide. Les options des sous-menus précédés d'une flêche ont un autre menu déroulant associé. En explorant chaque menu, jeter un coup d'oeil à ces sous-menus également. Cliquez sur un menu pour en voir la commande:" + +_key="help4-1" +_value="Fichier: contient les commandes pour fermer l'application et afficher les informations au sujet de BePodder" + +_key="help4-2" +_value="Préférences: contient les commandes pour ouvrir le panneau des préférences, pour personnaliser les options de BePodder à votre goût." + +_key="help4-3" +_value="Abonnements: contient les commandes en relation avec l'abonnement sélectionné dans la liste des abonnements (partie 1)." + +_key="help4-4" +_value="Episodes: contient les commandes en relation avec l'épisode sélectionné dans la liste des épisode (partie 2)." + +_key="help4-5" +_value="Listes: contient la liste des flux (abonnements) prédéfinis dans BePodder ausquels vous pouvez souscrire." + +_key="help4-6" +_value="Affichage: contient les options d'affichage de la fenêtre principale de BePodder." + +_key="help4-7" +_value="Aide: contient les fiches d'aide à l'utilisation de BePodder et la liste des raccourcis clavier." + + + +_key="help5-0" + _value="Ajouter: Permet d'ajouter un flux en indiquant son adresse (ex. http://www.newpodcast.com/rss.xml), le plus souvent donné sur le site de l'auteur; Cherchez une icone ou un lien qui ressemble à 'XML', 'RSS' ou 'Podcast Feed' dessus." + +_key="help5-1" + _value="Supprimer: Permet de se déinscrire d'un flux: choississez juste d'archiver (conserve les fichiers téléchargés en relation) ou tout supprimer." + +_key="help5-2" + _value="Mise à jour: Vérifie si de nouveaux épisodes sont disponibles pour les abonnements sélectionnés." + +_key="help5-3" + _value="Site internet: Ouvre le site internet de l'abonnement dans le navigateur web. Pour sélectionner le navigateur à utiliser, ouvrez les préférences dans le menu Préférences > et sélectionnez votre navigateur dans la liste." + +_key="help5-4" + _value="Lecture: Ouvre la pièce jointe de l'épisode séléctionné. Pour sélectionner le lecteur média à utiliser, ouvrez les préférences dans le menu Préférences > et sélectionnez votre lecteur dans la liste." + +_key="help5-5" + _value="Télécharger: Télécharge la pièce jointe de l'épisode séléctionné; pour voir les informations de téléchargement, cliquez sur le troisième bouton dans la partie information (3)." + +_key="help5-6" + _value="Stop: Stoppe le téléchargement de la pièce jointe; pour relancer le téléchargement où il s'est arreté, double cliquez sur l'épisode dans la liste des épisodes (2)" + +_key="help5-7" + _value="Supprimer: supprime l'épisode (et les pièces jointes correspondante)." + + + +_key="help6-0" + _value="Démarrer avec BePodder est très simple." + +_key="help6-1" + _value="Sur la gauche, il y a la liste des abonnements, la liste de vos souscriptions. Nous en avons pré-souscrits pour vous, mais vous pouvez bien entendu en rajouter vous même:" + +_key="help6-2" + _value="1) cliquez sur le bouton Ajouter et entrer une adresse (example: http://www.newpodcast.com/rss.xml)." + +_key="help6-3" + _value="2) ou séléctionner un flux dans la liste prédéfinie dans BePodder (menu 'Listes' > 'Liste des Podcast' ou une autre liste, choississez un podcast et cliquez sur 'S'abonner'." + +_key="help6-4" + _value="Si vous séléctionnez un Podcast dans la liste des abonnements et cliquez sur le bouton 'Mise a jour', BePodder ajoute les nouveautées dans la liste des épisodes; Vous pouvez lancer une mise à jour de tous vos abonnements en même temps avec un clic droit sur ce même bouton et 'Mettre tous les abonnements à jour'." + +_key="help6-5" + _value="Sur la capture d'écran suivante, vous pouvez voir que 3 nouveaux épisodes ont été ajouté, mis en avant par un rond noir devant leur nom." + +_key="help6-6" + _value="Dans la seconde colonne il y a une icone qui indique son état:" + +_key="help6-7" + _value="- l'épisode 4 a une icone indiquant une erreur" + +_key="help6-8" + _value="- l'épisode 4 a une icone indiquant que sa pièce jointe n'a pas encore été téléchargé" + +_key="help6-9" + _value="- l'épisode 4 a une icone indiquant que BePodder télécharge la pièce jointe" + +_key="help6-10" + _value="- l'épisode 4 a une icone indiquant que BePodder a fini de télécharger la pièce jointe" + + + +_key="help7-0" + _value="Sélectionnez un épisode dans la liste des épisodes double cliquez dessus (ou cliquez surle bouton 'télécharger') pour lancer le téléchargement de la pièce jointe; Vous pouvez à tout moment le stopper en appuyant sur le bouton 'Stopper'." + +_key="help7-1" + _value="Lorsque vous cliquez sur un épisode (partie 2), BePodder affiche (partie 3) tous ce qui est disponible dans cet épisode. Sélectionnez un fichier et cliquez sur Lecture pour voir ou écouter la pièce jointe." + +_key="help7-2" + _value="Vous pouvez accéder au dossier contenant les pièces jointes téléchargées en cliquant sur le lien 'Fichiers inclus' dans le contenu de l'épisode (partie 3), ou par un clic droit sur un épisode (partie 2) et en sélectionnant 'Ouvrir le dossier'." + + + +_key="help8-0" + _value="Les préférences peuvent être personnalisées par le menu 'Préférences'. Vous pouvez alors choisir une catégorie dans la liste de gauche parmis 'Types de fichiers', 'Abonnements', 'Téléchargement' et 'Proxy'." + +_key="help8-1" + _value="- Type de fichiers: pour définir votre navigateur et lecteur audio/vidéo. " + +_key="help8-2" + _value="- Abonnements: pour définir la façon dont vous souhaitez vérifier les mises à jour de vos abonnements: au démarrage et/ou toutes les X minutes." + +_key="help8-3" + _value="- Téléchargement: pour définir le nombre de fichiers à télécharger en même temps," + +_key="help8-4" + _value="- Proxy: pour configurer les paramètres réseau si vous accéder à Internet à travers un proxy ou un routeur." + + +_key="help9-0" + _value="BePodder est livré avec une liste prédéfinie (OPML) d'une centaine de podcast, videoblog, imagefeeds, newsfeeds, bittorrentfeeds et internationalfeeds, tous classés par catégorie ." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) est un format basé sur de l'XML permettant l'échange de données entre plusieurs applications." + +_key="help9-2" + _value="Vous pouvez accéder à ces listes par le menu 'Listes' et en sélectionnant la liste voulue. Pour ouvrir une catégorie, cliquez sur la fleche noire à côté de son nom, jusqu'a trouver le flux de vos rêves ! Une fois sélectionné, ajoutez-le à votre liste d'abonnements en cliquant sur le bouton 'S'abonner', vous pouvez également replier toutes les catégories en cliquant sur le bouton 'minimiser'." + + +_key="help_shortcut1" +_value="Cette page liste les raccourcis clavier de BePodder. Les raccourcis sont ici regroupés par fonctions." + +_key="help_shortcut2" +_value="signifie que vous pouvez utiliser la touche alt ou ctrl (ex. Alt+Q ou Ctrl+Q pour quitter BePodder), selon la touche définie dans les préférences du clavier (par défaut, la touche utilisée est Alt)." + +_key="help_shortcut3" + _value="Principaux raccourcis" + +_key="help_shortcut4" + _value="Quitter" + +_key="help_shortcut5" + _value="Afficher le panneau de préférences" + +_key="help_shortcut6" + _value="Affiche la liste des Podcast" + +_key="help_shortcut7" + _value="Affiche la liste des Videoblog" + +_key="help_shortcut8" + _value="Affiche la liste des Imagefeeds" + +_key="help_shortcut9" + _value="Affiche la liste des Newsfeeds" + +_key="help_shortcut9b" + _value="Affiche la liste des BitTorrentfeeds" + +_key="help_shortcut9c" + _value="Affiche la liste des Internationalfeeds" + +_key="help_shortcut10" + _value="Plein écran" + +_key="help_shortcut11" + _value="Affiche/masque les boutons en haut" + +_key="help_shortcut12" + _value="Affiche le panneau d'aide" + +_key="help_shortcut13" + _value="Affiche le panneau des raccourcis clavier" + +_key="help_shortcut14" + _value="Raccourci des abonnements" + +_key="help_shortcut15" + _value="Ajouter un nouveau flux en tapant l'adresse" + +_key="help_shortcut16" + _value="Supprime l'abonnement sélectionné" + +_key="help_shortcut17" + _value="Vérifie les mises à jour disponible pour l'abonnement sélectionné" + +_key="help_shortcut18" + _value="Vérifie les mises à jour disponible pour tout les abonnements" + +_key="help_shortcut19" + _value="Accéder le site internet" + +_key="help_shortcut20" + _value="Ouvrir le dossier des pièces jointes" + +_key="help_shortcut21" + _value="Raccourcis des épisodes" + +_key="help_shortcut22" + _value="Ouvrir la pièce jointe" + +_key="help_shortcut23" + _value="Lancer/relancer le téléchargement" + +_key="help_shortcut24" + _value="Stopper le téléchargement" + +_key="help_shortcut25" + _value="Supprimer un épisode" + +_key="help_shortcut26" + _value="Afficher la page internet de l'épisode" + +_key="help_shortcut27" + _value="Ouvrir le dossier des pièces jointes" + +_key="help_buy1" + _value="BePodder Light est juste la version d'essai (pas de limite dans le temps). La version complète vient ajouter d'autres fonctionnalités sympa: nombre d'abonnements illimités, vue en icone plus petite de la liste des abonnements, support du proxy, vérification automatique, et jusqu'a 5 téléchargements simultannés (multithreadés)." + +_key="help_buy2" + _value="Merci d'enregistrer votre version de BePodder, c'est seulement 15 euros (Kagi ajoute une taxe pour certains pays), Une license BePodder peut être acheté sur Kagi." + +_key="help_buy3" + _value="Acheter sur www.funkyideasoft.com" + +_key="help_buy4" + _value="Après l'enregistrement, vous recevrez votre clé logiciel par email et comment l'installer (en gros, décompresser un zip et copier le fichier dans un dossier)." + +_key="help_buy5" + _value="Une clé BePodder est valable pour les prochaines versions et mise à jour du logiciel, vous serez de toute façon prévenu si ce n'est plus le cas." + + +### USELESS ######## + +"Opml Editor" "Editeur Opml" +"name:" "Nom:" +"Add a category" "Ajouter une catégorie" +"Add a new Broadcast" "Ajouter un nouvel abonnement" +"feed:" "feed:" +"url:" "adresse:" +"Test podcast" "Tester le podcast" +"Del a category" "Supprimer une categorie" +"Add a category" "Ajouter une categorie" +"Select the podcast category:" "Selectionnez la catégorie de podcast:" +"Check all" "Tout vérifier" +"Check" "Vérifier" +"Refresh the list" "Rafraichir" +"Load" "Charger" +"Load the list" "Charger la liste" +"Save" "Enregistrer" +"Save the list" "Enregistrer la liste" +"Revert" "Annuler" +"Apply" "Appliquer" + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.frFR b/release/Language/Dictionaries/BePodder.frFR new file mode 100644 index 0000000..cdb5154 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.frFR @@ -0,0 +1,601 @@ +# Locale file for BePodder. +# Modified: 21/04/2006 +# Author: Rémi Grumeau +# E-mail: remi@beosfrance.com + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Application en version Shareware !\n\nMerci pour votre support!\n\nAcheter une license!\nPlus d'infos sur le site internet\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "Désolé, la periode d'éssai de BePodder est terminée !\nMerci d'acheter une license.\n" + +"Web Site" "Site Internet" + +"Can't connect!" "Connection impossible!" +"Http port failed!" "Port HTTP indisponible!" +"Can't resolve host!" "Hôte introuvable !" +"Not found!" "Introuvable !" +"Bad resume!" "Résume impossible !" +"Aborted by Callback!" "Annulé par l'utilisateur !" +"Can't resume! (range error)" "Résume impossible ! (erreur de classement)" +"Access Denied!" "Accès refusé !" +"User or Password Incorrect!" "Identifiant ou mot de passe incorrect !" +"Other error (cUrl code: " "Erreur inconnue (code cUr : " +"cUrl init error!" "erreur d'init cUrl !" +"Can't open file!" "Ouverture impossible!" +"Other error (status code: " "Erreur inconnue (statut code: " +"Downloading" "Téléchargement en cours" + +### MENUBAR ----------------------------------- + +"File" "Fichier" +"About..." "A propos...." +"Close!" "Fermer" +"Quit" "Quitter" + +"Settings" "Préférences" +"Preferences..." "Préférences..." + +"Subscriptions" "Abonnements" + +"Episodes" "Episodes" + +"Lists" "Listes" +"Podcast List" "Liste de Podcast" +"Podcast directory list" "Dossier de la liste Podcast" +"Videoblog List" "Liste de Videoblogs" +"Videoblog directory list" "Dossier de la liste de Videoblogs" +"Imagefeeds List" "Liste des Imagefeeds" +"Imagefeeds directory list" "Dossier de la liste de Imagefeeds" +"Newsfeeds List" "Liste des Newsfeeds" +"Newsfeeds directory list" "Dossier de la liste des Newsfeeds" +"BitTorrentfeeds List" "Liste des BitTorrentfeeds" +"BitTorrentfeeds directory list" "Dossier de la liste des BitTorrentfeeds" +"Internationalfeeds List" "Liste des Internationalfeeds" +"Internationalfeeds directory list" "Dossier de la liste des Internationalfeeds" + +"View" "Affichage" +"Full Screen" "Plein-écran" +"Toolbar" "Barre d'outils" +"Subscriptions View" "Liste des abonnements" +"Small Items" "Liste simple" +"Big Items" "Liste avec icones" +"Move BePodder on workspace:" "Déplacer BePodder sur le bureau:" + +"Help" "Aide" +"Getting Started" "Bien démarrer avec BePodder" +"Keyboard Shortcuts" "Raccourics clavier" +"Tutorials" "Didacticielles" +"Online Support" "Support en ligne" + + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "Entrer l'adresse du flux RSS!" +"Add" "Ajouter" +"Paste" "Coller" + +# Buttons directory list window +"Collapse All" "Tout minimiser" +"Preview" "Prévisualiser" +"Subscribe" "S'abonner" + + +# Buttons help window +"Next" "Suivant" +"Prev" "Précédent" +"Close" "Fermer" +"Index" "Index" + + +# Buttons remove windows +"Cancel" "Annuler" +"Delete" "Supprimer" +"Archive" "Archive" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Ajouter le PodCast a votre liste d'abonnements" +"Delete the podcast from the Subscriptions list" "Supprimer le PodCast de votre liste d'abonnements" +"Check the selected podcast for new items" "Mettre a jour le PodCast" +"Show the podcast homepage" "Afficher la page d'accueil du PodCast" + +"Delete the item and the enclosure" "Delete the item and the enclosure" +"Stop the item download" "Stopper le téléchargement" +"Download the selected episode" "Télécharger l'épisode sélectionné" +"Play the selected episode" "Lire l'épisode sélectionné" + +"Submit bug and idea" "Soumettre une idée ou signaler un bug" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Rassembler toutes les catégories dans la liste des dossiers" +"Add the selected podcast to the Subscription list" "Ajouter le PodCast sélectionné a votre liste d'abonnements" +"Checkout a podcast before downloading it" "Verifier le PodCast avant de le télécharger" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Afficher l'image" +"XML Feed Link" "Lien du Feed XML" + +"Show Episode info" "Afficher les infos de l'épisode" +"Show Subscription info" "Afficher les infos de l'abonnement" +"Show Downloads info" "Afficher les infos du télechargement" + +"Enclosure: " "Fichier inclus: " + +"Lookup (Dictionary)" "Rechercher dans 'Dictionary'" +"Lookup (Google)" "Rechercher dans 'Google'" +"Lookup (Acronym Finder)" "Rechercher dans 'Acronym Finder'" +"Copy" "Copier" +"Select All" "Tout sélectionner" +"Copy URL" "Copier l'adresse" +"Open URL" "Ouvrir l'adresse" +"Subscription" "Souscription" + +"Find this Item" "Trouver ce fichier" +"Remove from this list" "Supprimer ce fichier" + + +### PREFERENCES ----------------------------------- + +"Preferences" "Préférences" + +"Proxy" "Proxy" +"Enable Proxy" "Activer le proxy" +"Address" "Addresse" +"Port" "Port" +"Username" "Identifiant" +"Password" "Mot de passe" + +"Max Downloads" "Téléchargements Max" + +"FileType" "Ouvrir les fichiers" +"Browser" "Navigateur:" +"Player" "Lecteur Audio/Vidéo:" + +"Channels" "Abonnements" +"Check all channels on startup" "Verifier tous les abonnements au démarrage" +"Check the channel every" "Vérifier tout les " + +"never" "Ne jamais vérifier" +"5 minutes" "5 minutes" +"15 minutes" "15 minutes" +"30 minutes" "30 minutes" +"1 hour" "heures" +"2 hour" "2 heures" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 nouveau fichier" +"%d new items" "%d nouveaux fichiers" +"new" "nouveau" +"error" "erreur" +"not down" "non téléchargé" +"enquequed" "ajouté" +"downloading" "en cours de téléchargement" +"downloaded" "téléchargé" +"connecting" "connection en cours" +"not found" "introuvable" +"stopped" "arreté" +"can't connect" "connection impossible" +"invalid format" "format non valide" + +"Icon" "Icon" +"Title" "Titre" +"Date" "Date" +"Size" "Taille" +"Status" "Etat" +"Download" "Téléchargement" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "AJouter un abonnement" +"Remove Channel" "Supprimer un abonnement" +"Check Channel" "Vérifier les mises a jour" +"Open Homepage" "Ouvrir la page d'acceuil" + +"Open Web Page" "Aller sur le site internet" +"Open Enclosures folder" "Ouvrir le dossier" +"Check All Channels" "Vérifier tous les abonnements" + +"Show Channel Image" "Afficher la vignette de l'abonnement" + +"Play enclosure" "Afficher" +"(Re)start download" "(re)Télécharger" +"Stop download" "Arreter le téléchargement" +"Remove Item" "Supprimer" + +"Find this Item" "Trouver ce fichier" +"Remove from this list" "Supprimer ce fichier" + + + +### ALERT ----------------------------------- + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "Désolé mais vous ne pouvez vous inscrire qu'a 10 podcasts dans cette version d'essai.\n Veuillez vous enregistrer.\n" + +"Can't open the selected file with:\n\n" "Impossible d'ouvrir ce fichier avec:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nVeuillez vérifier que cette application est bien installée a cet endroit.\n" + +"Download it!" "Télécharger !" + +"\nRemoving.." "\nSuppression.." +"\nAn error occured while removing!" "\nUne erreur s'est produite lors de la suppression !" +"Check all the podcasts for new items" "Vérifier tous les PodCast et les mettre a jour" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +Vous etes sur le point de supprimer la ligne suivante. + +Etes-vous sur ? +(le fichier inclus sera perdu, si il y en a un)" + + +_key="alert2a" + _value=" +Vous etes sur le point de supprimer l'abonnement: + +" + +_key="alert2b" + _value=" + +Désirez-vous archiver cet abonnement +(et conserver les fichiers téléchargé) ou +voulez-vous supprimer tous les fichiers +en rapport avec cet abonnement ?" + +_key="alert3" + _value=" +Archivage en cours..." + +_key="alert_3gp" + _value=" +3GP est un format de contenance multimedia défini par le Third Generation Partnership Project (3GPP) pour une utilisation sur téléphone mobile 3G. Il enregistre la vidéo en MPEG-4 ou H.263, et l'audio en AMR-NB ou AAC-LC. + +VideoLAN ne supporte pas encore le AMR-NB (3GPP)" + +_key="alert_swf" + _value=" +SWF est un format d'animation vectorielle propriétaire appartenant a Adobe (créée par Macromedia). + +Pour l'instant, le support des animations flash sous BeOS, Zeta ou Haiku se limite à la version 4.1015, aucun lecteur plus récent n'est disponible." + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Introduction" +"The User Interface" "L'interface utilisateur" +"Menu Bar" "La barre du menu" +"Toolbar Buttons" "La barre d'outils" +"First time with BePodder" "Les premiers pas avec BePodder" +"Download Podcast's enclosure files" "Télécharger les fichiers relatifs aux Podcasts" +"Settings Overview" "Les parametres" +"Directory lists" "Listes des dossiers" +"Loading Help..." "Chargement de l'aide..." +"Register your copy" "Enregistrez-vous" +"Starting point" "Sommaire" + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value=Bienvenu dans l'aide à l'utilisation de BePodder." + +_key="help1-1" + _value="Si vous avez déjà utilisé BePodder ou familié aux logiciels de flux RSS/Atom, vous pouvez fermer cette fenêtre et commencer à utiliser BePodder." + +_key="help1-2" +_value="Le cas échéant, voici une petite introduction sur comment et pourquoi utiliser ce type de logiciel. Utilisez les boutons en bas de la fenetre pour naviguer dans ce didacticielle." + + + +_key="help2-0" +_value="Podcaster est une méthode pour publier du contenu audio ou vidéo sur Internet; les liens vers les fichiers sont définis dans les flux RSS/Atom." + +_key="help2-1" +_value="Le Podcasting est donc un simple moyen de mettre a disposition des fichiers; les utilisateurs peuvent alors souscrire à ce flux (comme un RSS 'Really Simple Syndication' ou Atom)." + +_key="help2-2" +_value="Un aggregator (ou podcatcher) comme BePodder, est un logiciel vous permettant de souscrire à ces flux et vérifier périodiquement si un flux à était mis à jour; avec BePodder vous pouvez vérifier si de nouveaux fichiers sont disponibles (Episodes) dans les flux souscrits. Chaque fichier peut alors contenir une pièce jointe, tout comme un email." + + + +_key="help3-0" +_value="BePodder a un interface simple et très complète. La fenêtre principale est divisée en trois parties:" + +_key="help3-1" +_value="1) La liste des abonnements (la partie avec le numéro 1) contenant la liste des flux ausquels vous avez souscrits. Lorsque vous sélectionnez un flux, vous pouvez voir la liste des épisodes qu'il contient dans la seconde partie (numéro 2)." + +_key="help3-2" +_value="2) La liste des épisodes avec les fichiers qu'ils contiennent." + +_key="help3-3" +_value="3) Informations. Cette troisième et dernière partie contient: informations générales, de l'épisodes ou du téléchargement; vous pouvez sélectionner l'info voulu en cliquant sur les boutons correspondants." + + + +_key="help4-0" +_value="Tout en haut de la fenêtre principale de BePodder se trouve le menu avec 7 sous menus: Fichier, Préférences, Abonnements, Episodes, Listes, Affichage et Aide. Les options des sous-menus précédés d'une flêche ont un autre menu déroulant associé. En explorant chaque menu, jeter un coup d'oeil à ces sous-menus également. Cliquez sur un menu pour en voir la commande:" + +_key="help4-1" +_value="Fichier: contient les commandes pour fermer l'application et afficher les informations au sujet de BePodder" + +_key="help4-2" +_value="Préférences: contient les commandes pour ouvrir le panneau des préférences, pour personnaliser les options de BePodder à votre goût." + +_key="help4-3" +_value="Abonnements: contient les commandes en relation avec l'abonnement sélectionné dans la liste des abonnements (partie 1)." + +_key="help4-4" +_value="Episodes: contient les commandes en relation avec l'épisode sélectionné dans la liste des épisode (partie 2)." + +_key="help4-5" +_value="Listes: contient la liste des flux (abonnements) prédéfinis dans BePodder ausquels vous pouvez souscrire." + +_key="help4-6" +_value="Affichage: contient les options d'affichage de la fenêtre principale de BePodder." + +_key="help4-7" +_value="Aide: contient les fiches d'aide à l'utilisation de BePodder et la liste des raccourcis clavier." + + + +_key="help5-0" + _value="Ajouter: Permet d'ajouter un flux en indiquant son adresse (ex. http://www.newpodcast.com/rss.xml), le plus souvent donné sur le site de l'auteur; Cherchez une icone ou un lien qui ressemble à 'XML', 'RSS' ou 'Podcast Feed' dessus." + +_key="help5-1" + _value="Supprimer: Permet de se déinscrire d'un flux: choississez juste d'archiver (conserve les fichiers téléchargés en relation) ou tout supprimer." + +_key="help5-2" + _value="Mise à jour: Vérifie si de nouveaux épisodes sont disponibles pour les abonnements sélectionnés." + +_key="help5-3" + _value="Site internet: Ouvre le site internet de l'abonnement dans le navigateur web. Pour sélectionner le navigateur à utiliser, ouvrez les préférences dans le menu Préférences > et sélectionnez votre navigateur dans la liste." + +_key="help5-4" + _value="Lecture: Ouvre la pièce jointe de l'épisode séléctionné. Pour sélectionner le lecteur média à utiliser, ouvrez les préférences dans le menu Préférences > et sélectionnez votre lecteur dans la liste." + +_key="help5-5" + _value="Télécharger: Télécharge la pièce jointe de l'épisode séléctionné; pour voir les informations de téléchargement, cliquez sur le troisième bouton dans la partie information (3)." + +_key="help5-6" + _value="Stop: Stoppe le téléchargement de la pièce jointe; pour relancer le téléchargement où il s'est arreté, double cliquez sur l'épisode dans la liste des épisodes (2)" + +_key="help5-7" + _value="Supprimer: supprime l'épisode (et les pièces jointes correspondante)." + + + +_key="help6-0" + _value="Démarrer avec BePodder est très simple." + +_key="help6-1" + _value="Sur la gauche, il y a la liste des abonnements, la liste de vos souscriptions. Nous en avons pré-souscrits pour vous, mais vous pouvez bien entendu en rajouter vous même:" + +_key="help6-2" + _value="1) cliquez sur le bouton Ajouter et entrer une adresse (example: http://www.newpodcast.com/rss.xml)." + +_key="help6-3" + _value="2) ou séléctionner un flux dans la liste prédéfinie dans BePodder (menu 'Listes' > 'Liste des Podcast' ou une autre liste, choississez un podcast et cliquez sur 'S'abonner'." + +_key="help6-4" + _value="Si vous séléctionnez un Podcast dans la liste des abonnements et cliquez sur le bouton 'Mise a jour', BePodder ajoute les nouveautées dans la liste des épisodes; Vous pouvez lancer une mise à jour de tous vos abonnements en même temps avec un clic droit sur ce même bouton et 'Mettre tous les abonnements à jour'." + +_key="help6-5" + _value="Sur la capture d'écran suivante, vous pouvez voir que 3 nouveaux épisodes ont été ajouté, mis en avant par un rond noir devant leur nom." + +_key="help6-6" + _value="Dans la seconde colonne il y a une icone qui indique son état:" + +_key="help6-7" + _value="- l'épisode 4 a une icone indiquant une erreur" + +_key="help6-8" + _value="- l'épisode 4 a une icone indiquant que sa pièce jointe n'a pas encore été téléchargé" + +_key="help6-9" + _value="- l'épisode 4 a une icone indiquant que BePodder télécharge la pièce jointe" + +_key="help6-10" + _value="- l'épisode 4 a une icone indiquant que BePodder a fini de télécharger la pièce jointe" + + + +_key="help7-0" + _value="Sélectionnez un épisode dans la liste des épisodes double cliquez dessus (ou cliquez surle bouton 'télécharger') pour lancer le téléchargement de la pièce jointe; Vous pouvez à tout moment le stopper en appuyant sur le bouton 'Stopper'." + +_key="help7-1" + _value="Lorsque vous cliquez sur un épisode (partie 2), BePodder affiche (partie 3) tous ce qui est disponible dans cet épisode. Sélectionnez un fichier et cliquez sur Lecture pour voir ou écouter la pièce jointe." + +_key="help7-2" + _value="Vous pouvez accéder au dossier contenant les pièces jointes téléchargées en cliquant sur le lien 'Fichiers inclus' dans le contenu de l'épisode (partie 3), ou par un clic droit sur un épisode (partie 2) et en sélectionnant 'Ouvrir le dossier'." + + + +_key="help8-0" + _value="Les préférences peuvent être personnalisées par le menu 'Préférences'. Vous pouvez alors choisir une catégorie dans la liste de gauche parmis 'Types de fichiers', 'Abonnements', 'Téléchargement' et 'Proxy'." + +_key="help8-1" + _value="- Type de fichiers: pour définir votre navigateur et lecteur audio/vidéo. " + +_key="help8-2" + _value="- Abonnements: pour définir la façon dont vous souhaitez vérifier les mises à jour de vos abonnements: au démarrage et/ou toutes les X minutes." + +_key="help8-3" + _value="- Téléchargement: pour définir le nombre de fichiers à télécharger en même temps," + +_key="help8-4" + _value="- Proxy: pour configurer les paramètres réseau si vous accéder à Internet à travers un proxy ou un routeur." + + +_key="help9-0" + _value="BePodder est livré avec une liste prédéfinie (OPML) d'une centaine de podcast, videoblog, imagefeeds, newsfeeds, bittorrentfeeds et internationalfeeds, tous classés par catégorie ." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) est un format basé sur de l'XML permettant l'échange de données entre plusieurs applications." + +_key="help9-2" + _value="Vous pouvez accéder à ces listes par le menu 'Listes' et en sélectionnant la liste voulue. Pour ouvrir une catégorie, cliquez sur la fleche noire à côté de son nom, jusqu'a trouver le flux de vos rêves ! Une fois sélectionné, ajoutez-le à votre liste d'abonnements en cliquant sur le bouton 'S'abonner', vous pouvez également replier toutes les catégories en cliquant sur le bouton 'minimiser'." + + +_key="help_shortcut1" +_value="Cette page liste les raccourcis clavier de BePodder. Les raccourcis sont ici regroupés par fonctions." + +_key="help_shortcut2" +_value="signifie que vous pouvez utiliser la touche alt ou ctrl (ex. Alt+Q ou Ctrl+Q pour quitter BePodder), selon la touche définie dans les préférences du clavier (par défaut, la touche utilisée est Alt)." + +_key="help_shortcut3" + _value="Principaux raccourcis" + +_key="help_shortcut4" + _value="Quitter" + +_key="help_shortcut5" + _value="Afficher le panneau de préférences" + +_key="help_shortcut6" + _value="Affiche la liste des Podcast" + +_key="help_shortcut7" + _value="Affiche la liste des Videoblog" + +_key="help_shortcut8" + _value="Affiche la liste des Imagefeeds" + +_key="help_shortcut9" + _value="Affiche la liste des Newsfeeds" + +_key="help_shortcut9b" + _value="Affiche la liste des BitTorrentfeeds" + +_key="help_shortcut9c" + _value="Affiche la liste des Internationalfeeds" + +_key="help_shortcut10" + _value="Plein écran" + +_key="help_shortcut11" + _value="Affiche/masque les boutons en haut" + +_key="help_shortcut12" + _value="Affiche le panneau d'aide" + +_key="help_shortcut13" + _value="Affiche le panneau des raccourcis clavier" + +_key="help_shortcut14" + _value="Raccourci des abonnements" + +_key="help_shortcut15" + _value="Ajouter un nouveau flux en tapant l'adresse" + +_key="help_shortcut16" + _value="Supprime l'abonnement sélectionné" + +_key="help_shortcut17" + _value="Vérifie les mises à jour disponible pour l'abonnement sélectionné" + +_key="help_shortcut18" + _value="Vérifie les mises à jour disponible pour tout les abonnements" + +_key="help_shortcut19" + _value="Accéder le site internet" + +_key="help_shortcut20" + _value="Ouvrir le dossier des pièces jointes" + +_key="help_shortcut21" + _value="Raccourcis des épisodes" + +_key="help_shortcut22" + _value="Ouvrir la pièce jointe" + +_key="help_shortcut23" + _value="Lancer/relancer le téléchargement" + +_key="help_shortcut24" + _value="Stopper le téléchargement" + +_key="help_shortcut25" + _value="Supprimer un épisode" + +_key="help_shortcut26" + _value="Afficher la page internet de l'épisode" + +_key="help_shortcut27" + _value="Ouvrir le dossier des pièces jointes" + +_key="help_buy1" + _value="BePodder Light est juste la version d'essai (pas de limite dans le temps). La version complète vient ajouter d'autres fonctionnalités sympa: nombre d'abonnements illimités, vue en icone plus petite de la liste des abonnements, support du proxy, vérification automatique, et jusqu'a 5 téléchargements simultannés (multithreadés)." + +_key="help_buy2" + _value="Merci d'enregistrer votre version de BePodder, c'est seulement 15 euros (Kagi ajoute une taxe pour certains pays), Une license BePodder peut être acheté sur Kagi." + +_key="help_buy3" + _value="Acheter sur www.funkyideasoft.com" + +_key="help_buy4" + _value="Après l'enregistrement, vous recevrez votre clé logiciel par email et comment l'installer (en gros, décompresser un zip et copier le fichier dans un dossier)." + +_key="help_buy5" + _value="Une clé BePodder est valable pour les prochaines versions et mise à jour du logiciel, vous serez de toute façon prévenu si ce n'est plus le cas." + + +### USELESS ######## + +"Opml Editor" "Editeur Opml" +"name:" "Nom:" +"Add a category" "Ajouter une catégorie" +"Add a new Broadcast" "Ajouter un nouvel abonnement" +"feed:" "feed:" +"url:" "adresse:" +"Test podcast" "Tester le podcast" +"Del a category" "Supprimer une categorie" +"Add a category" "Ajouter une categorie" +"Select the podcast category:" "Selectionnez la catégorie de podcast:" +"Check all" "Tout vérifier" +"Check" "Vérifier" +"Refresh the list" "Rafraichir" +"Load" "Charger" +"Load the list" "Charger la liste" +"Save" "Enregistrer" +"Save the list" "Enregistrer la liste" +"Revert" "Annuler" +"Apply" "Appliquer" + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.hrHR b/release/Language/Dictionaries/BePodder.hrHR new file mode 100644 index 0000000..296dac8 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.hrHR @@ -0,0 +1,604 @@ + +# Locale file for BePodder. +# Modified: 4/18/2006 +# Author: BePodderTeam +# E-mail: bepodder.team@gmail.com + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" + +"Web Site" "Web Site" + +"Can't connect!" "Can't connect!" +"Http port failed!" "Http port failed!" +"Can't resolve host!" "Can't resolve host!" +"Not found!" "Not found!" +"Bad resume!" "Bad resume!" +"Aborted by Callback!" "Aborted by Callback!" +"Can't resume! (range error)" "Can't resume! (range error)" +"Access Denied!" "Access Denied!" +"User or Password Incorrect!" "User or Password Incorrect!" +"Other error (cUrl code: " "Other error (cUrl code: " +"cUrl init error!" "cUrl init error!" +"Can't open file!" "Can't open file!" +"Other error (status code: " "Other error (status code: " +"Downloading" "Downloading" + + +### MENUBAR ----------------------------------- + +"File" "File" +"About..." "About..." +"Close!" "Close!" +"Quit" "Quit" + +"Settings" "Settings" +"Preferences..." "Preferences..." + +"Subscriptions" "Subscriptions" + +"Episodes" "Episodes" + +"Lists" "Lists" +"Podcast List" "Podcast List" +"Podcast directory list" "Podcast directory list" +"Videoblog List" "Videoblog List" +"Videoblog directory list" "Videoblog directory list" +"Imagefeeds List" "Imagefeeds List" +"Imagefeeds directory list" "Imagefeeds directory list" +"Newsfeeds List" "Newsfeeds List" +"Newsfeeds directory list" "Newsfeeds directory list" +"BitTorrentfeeds List" "BitTorrentfeeds List" +"BitTorrentfeeds directory list" "BitTorrentfeeds directory list" +"Internationalfeeds List" "Internationalfeeds List" +"Internationalfeeds directory list" "Internationalfeeds directory list" + +"View" "View" +"Full Screen" "Full Screen" +"Toolbar" "Toolbar" +"Subscriptions View" "Subscriptions View" +"Small Items" "Small Items" +"Big Items" "Big Items" +"Move BePodder on workspace:" "Move BePodder on workspace:" + +"Help" "Help" +"Getting Started" "Getting Started" +"Keyboard Shortcuts" "Keyboard Shortcuts" +"Tutorials" "Tutorials" +"Online Support" "Online Support" + + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "Insert the rss feed url!" +"Add" "Add" +"Paste" "Paste" + +# Buttons directory list window +"Collapse All" "Collapse All" +"Preview" "Preview" +"Subscribe" "Subscribe" + + +# Buttons help window +"Next" "Next" +"Prev" "Prev" +"Close" "Close" +"Index" "Index" + + +# Buttons remove windows +"Cancel" "Cancel" +"Delete" "Delete" +"Archive" "Archive" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Add the podcast to the Subscriptions list" +"Delete the podcast from the Subscriptions list" "Delete the podcast from the Subscriptions list" +"Check the selected podcast for new items" "Check the selected podcast for new items" +"Show the podcast homepage" "Show the podcast homepage" + +"Delete the item and the enclosure" "Delete the item and the enclosure" +"Stop the item download" "Stop the item download" +"Download the selected episode" "Download the selected episode" +"Play the selected episode" "Play the selected episode" + +"Submit bug and idea" "Submit bug and idea" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Collapse all categories in the directory list" +"Add the selected podcast to the Subscription list" "Add the selected podcast to the Subscription list" +"Checkout a podcast before downloading it" "Checkout a podcast before downloading it" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Show Channel Image" +"XML Feed Link" "XML Feed Link" + +"Show Episode info" "Show Episode info" +"Show Subscription info" "Show Subscription info" +"Show Downloads info" "Show Downloads info" + +"Enclosure: " "Enclosure: " + +"Lookup (Dictionary)" "Lookup (Dictionary)" +"Lookup (Google)" "Lookup (Google)" +"Lookup (Acronym Finder)" "Lookup (Acronym Finder)" +"Copy" "Copy" +"Select All" "Select All" +"Copy URL" "Copy URL" +"Open URL" "Open URL" +"Subscription" "Subscription" + + +### PREFERENCES ----------------------------------- + +"Preferences" "Preferences" + +"Proxy" "Proxy" +"Enable Proxy" "Enable Proxy" +"Address" "Address" +"Port" "Port" +"Username" "Username" +"Password" "Password" + +"Max Downloads" "Max Downloads" + +"FileType" "FileType" +"Browser" "Browser" +"Player" "Player" + +"Channels" "Channels" +"Check all channels on startup" "Check all channels on startup" +"Check the channel every" "Check the channel every" + +"never" "never" +"5 minutes" "5 minutes" +"15 minutes" "15 minutes" +"30 minutes" "30 minutes" +"1 hour" "1 hour" +"2 hour" "2 hour" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 new item" +"%d new items" "%d new items" +"new" "new" +"error" "error" +"not down" "not down" +"enquequed" "enquequed" +"downloading" "downloading" +"downloaded" "downloaded" +"connecting" "connecting" +"not found" "not found" +"stopped" "stopped" +"can't connect" "can't connect" +"invalid format" "invalid format" + +"Icon" "Icon" +"Title" "Title" +"Date" "Date" +"Size" "Size" +"Status" "Status" +"Download" "Download" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "Add Channel" +"Remove Channel" "Remove Channel" +"Check Channel" "Check Channel" +"Open Homepage" "Open Homepage" + +"Open Web Page" "Open Web Page" +"Open Enclosures folder" "Open Enclosures folder" +"Check All Channels" "Check All Channels" + +"Show Channel Image" "Show Channel Image" + +"Play enclosure" "Play enclosure" +"(Re)start download" "(Re)start download" +"Stop download" "Stop download" +"Remove Item" "Remove Item" + +"Find this Item" "Find this Item" +"Remove from this list" "Remove from this list" + + + +### ALERT ----------------------------------- + +"\nRemoving.." "\nRemoving.." +"\nAn error occured while removing!" "\nAn error occured while removing!" +"Check all the podcasts for new items" "Check all the podcasts for new items" + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" + + +"Can't open the selected file with:\n\n" "Can't open the selected file with:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nPlease check if the application is installed in the right way.\n" +"Download it!" "Download it!" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +You are going to remove the selected item. + +Are you sure? +(you will lost the enclosure file if any)" + + +_key="alert2a" + _value=" +You are going to remove the channel: + +" + +_key="alert2b" + _value=" + +Would you like just to archive this +channel (keeping all the files and +enclosures downloaded so far) or +do you want to DELETE the whole + channel from you computer?" + +_key="alert3" + _value=" +Parsing archive.." + +_key="alert_3gp" + _value=" +3GP is a multimedia container format defined by the Third Generation Partnership Project (3GPP) for use on 3G mobile phones. It stores video streams as MPEG-4 or H.263, and audio streams as AMR-NB or AAC-LC. + +VideoLAN still doesn't support the audio AMR (3GPP)" + +_key="alert_swf" + _value=" +SWF is a proprietary vector graphics file format produced by the Flash software from Adobe (formerly Macromedia). + +Currently Flash support in BeOS/Haiku/Zeta is limited to the old standalone Flash player version 4.1015, there isn't a modern Flash player" + + + + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Introduction" +"The User Interface" "The User Interface" +"Menu Bar" "Menu Bar" +"Toolbar Buttons" "Toolbar Buttons" +"First time with BePodder" "First time with BePodder" +"Download Podcast's enclosure files" "Download Podcast's enclosure files" +"Settings Overview" "Settings Overview" +"Directory lists" "Directory lists" +"Loading Help..." "Loading Help..." +"Register your copy" "Register your copy" +"Starting point" "Starting point" + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value="Welcome to the BePodder Getting Started Guide." + +_key="help1-1" + _value="If you are already familiar with podcasts and RSS/Atom feeds you can immediately go to BePodder by closing this window." + +_key="help1-2" +_value="If not, this is a short introduction providing you everything you'll need to know on how to get started with BePodder. Use the buttons below to navigate through this tutorial." + + +_key="help2-0" +_value="Podcasting is a method for publishing audio and video broadcasts via the Internet; links to free audio and video files are enclosed in RSS and Atom feeds." + +_key="help2-1" +_value="Therefore Podcasting is simply a type of online media delivery; users can subscribe to a podcast using a feed (such as RSS 'Really Simple Syndication' or Atom)." + +_key="help2-2" +_value="An aggregator (or podcatcher) like BePodder, is a piece of software that allows you to subscribe to a RSS feed and periodically check for and download new content; with BePodder you can check for new Podcast items (Episodes) of your subscribed Channels. Any item can contain an enclosure, just like an Email can contain an attachment." + + + +_key="help3-0" +_value="BePodder has an easy to use yet powerful Graphical User Interface. The main window is split into tree panels:" + +_key="help3-1" +_value="1) The Subscription list (the panel with the number 1 in the screenshot) with the list of the podcasts that you have subscribed to. When you click on a Channel you can see in the panel 2 the list of the channel's items." + +_key="help3-2" +_value="2) The Episodes list with all the items available." + +_key="help3-3" +_value="3) The Info panel show: episode info, channel info or Downloads info; you can select an info panel by clicking one of the below three buttons." + + + +_key="help4-0" +_value="At the very top of the BePodder main window is the menubar with seven menus available: File, Settings, Subscriptions, Episodes, Lists, View and Help. Some menu commands are followed by a right pointing arrow that indicates a submenu of related commands. As you explore each menu, be sure to take a look at the submenus as well. Click on a menus to show its commands:" + +_key="help4-1" +_value="File: contains commands to close the application and to show information about BePodder" + +_key="help4-2" +_value="Settings: contains command to open the Preferences window that allows you to customize various BePodder settings." + +_key="help4-3" +_value="Subscriptions: contains commands that perform actions on the selected channel of your subscriptions list." + +_key="help4-4" +_value="Episodes: contains commands that perform actions on the selected item (episode) of the channel's episode list." + +_key="help4-5" +_value="Lists: contains commands to open BePodder's OPML directories." + +_key="help4-6" +_value="View: contains commands and controls for the BePodder window." + +_key="help4-7" +_value="Help: contains commands to open BePodder's 'Getting Started Guide' and the 'Keyboard Shortcuts List'." + + + +_key="help5-0" + _value="Add Button: opens the Add Window to add a feed url (e.g. http://www.newpodcast.com/rss.xml) usually given on the podcast homepage; looks for text or graphic link that says something like 'XML', 'RSS' or 'Podcast Feed' on it." + +_key="help5-1" + _value="Channel Remove Button: opens a window in which you can select how remove the channel: just archive the select channel (keeping all the files and eclosure downloaded so far) or delete the whole channel from your computer." + +_key="help5-2" + _value="Check Button: checks the selected channel and updates the list of the available items for that podcast adding the new items." + +_key="help5-3" + _value="Web Button: shows the channel homepage in the browser. To select your favorite browser open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select your favorite browser." + +_key="help5-4" + _value="Play Button: with this button you can view or listen the file enclosure of the selected item(episode). To select your favorite player open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select you favorite player." + +_key="help5-5" + _value="Download Button: downloads the file enclosure of the selected item (episode); you can see the download info by clicking on the third button over the info panel." + +_key="help5-6" + _value="Stop Button: stops to download the file enclosure of the selected item (episode); to resume the download double-click the item (episode) or select the item and click the Download Button" + +_key="help5-7" + _value="Item Remove Button: deletes the selected item (you will loose the enclosure file)." + + + +_key="help6-0" + _value="Getting started with BePodder is easy." + +_key="help6-1" + _value="On the left of the main window you can see the 'Subscription List' with all your feed subscriptions. We have added some subscriptions for you, and you can always add your own in two ways:" + +_key="help6-2" + _value="1) click the Add Button, then insert the feed url (example: http://www.newpodcast.com/rss.xml) and click add." + +_key="help6-3" + _value="2) in the menubar select 'Directory' and then 'Podcast list' or another list, choose a podcast and click 'Subscribe'." + +_key="help6-4" + _value="If you select a Podcast in the subscriptions list and use the check button, BePodder adds the new items to the 'Episodes list' (below on the right); you can check all your podcasts by right-clicking and selecting 'Check All Channels' in the context menu." + +_key="help6-5" + _value="Look at the screenshot above, there are 3 new items indicated by a black dot in the first column of the 'Episodes list'." + +_key="help6-6" + _value="In the second column there are icons that indicate the state of the item:" + +_key="help6-7" + _value="- the Episode 4 has an icon that indicates an error" + +_key="help6-8" + _value="- the Episode 3 has an icon that indicates that the item's enclosure download request is enquequed" + +_key="help6-9" + _value="- the Episode 2 has an icon that indicates that BePodder is downloading the item's enclosure file" + +_key="help6-10" + _value="- the Episode 1 have an icon that indicates that BePodder have just downloaded the item's enclosure file" + + + +_key="help7-0" + _value="Select an item in the 'Episodes list' and then double-click on it (or click the Download Button) to start downloading the enclosed file; you can always stop the download by clicking on the Stop Button." + +_key="help7-1" + _value="When you click on the Subscribed Podcasts in the 'Subscriptions List' the software shows you, in the 'List of episodes', all the items available in that Subscription. Select an item and then click play (Play Button) to view or listen to the file." + +_key="help7-2" + _value="You can access the Enclosures Folder by clicking on the folder icon in the Info Pannel or by right-clicking your mouse on an item and select 'Open Enclosures Folder' in the context menu." + + + +_key="help8-0" + _value="Preferences can be accessed by clicking in the menu-bar Settings>Preferences. You can select a category from the left list of the preferences dialog: FileType, Channels, Download and Proxy." + +_key="help8-1" + _value="- FileType: to specify the default browser and player. " + +_key="help8-2" + _value="- Channels: to specify preferences that control the operation to check channels new items; you can choose to Check all channels on startup or check the channel every desired minutes." + +_key="help8-3" + _value="- Download: to specify the max number of item's files to download at the same time," + +_key="help8-4" + _value="- Proxy: to set up a proxy server to work with BePodder; a proxy server acts as a security barrier between your internal network and the Internet, keeping others on the Internet from accessing information on your internal network." + + + +_key="help9-0" + _value="BePodder has built-in podcast, videoblog, imagefeeds, newsfeeds, bittorrentfeeds and internationalfeeds OPML directories with thousands of feeds grouped by category." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) is an XML-based format that allows exchange of outline-structured information between applications." + +_key="help9-2" + _value="OPML directory can be accessed by clicking in the menu-bar 'Lists' and thenselecting a list. To browse the opml directory for a feed, expand the list by clicking the arrow of the category that you are interested in (see image); using this method, you can expand the opml directory until you find the desired feed. Once you have selected it, you can add it to the subscription list by clicking the button 'Subscribe', you can also collapse all categories in the directory list by clicking the button 'Collapse All'." + +_key="help_shortcut1" +_value="This page describes the keyboard shortcuts that can be used in BePodder. The shortcuts are grouped here by function." + +_key="help_shortcut2" +_value="means that you can use either alt or control (es. Alt+Q or Ctrl+Q Quit the application), which way you have set it in the Deskbar menu preferences under Keyboard (the default shortcut key is Alt)." + +_key="help_shortcut3" + _value="General shortcuts" + +_key="help_shortcut4" + _value="Quit the application" + +_key="help_shortcut5" + _value="Shows the Preferences window" + +_key="help_shortcut6" + _value="Shows the Podcast directory list" + +_key="help_shortcut7" + _value="Shows the Videoblog directory list" + +_key="help_shortcut8" + _value="Shows the Imagefeeds directory list" + +_key="help_shortcut9" + _value="Shows the Newsfeeds directory list" + +_key="help_shortcut9b" + _value="Shows the BitTorrentfeeds directory list" + +_key="help_shortcut9c" + _value="Shows the Internationalfeeds directory list" + +_key="help_shortcut10" + _value="Fullscreen" + +_key="help_shortcut11" + _value="Shows/Hides the toolbar" + +_key="help_shortcut12" + _value="Shows the Getting Started Help" + +_key="help_shortcut13" + _value="Shows this keyboard shortcuts page" + +_key="help_shortcut14" + _value="Channels shortcuts" + +_key="help_shortcut15" + _value="Add a podcast to the subscriptions list" + +_key="help_shortcut16" + _value="Delete the selected podcast from the subscriptions list" + +_key="help_shortcut17" + _value="Check the selected podcast for new episodes (items)" + +_key="help_shortcut18" + _value="Check all podcasts for new episodes (items)" + +_key="help_shortcut19" + _value="Shows the podcast homepage" + +_key="help_shortcut20" + _value="Open enclosures folder" + +_key="help_shortcut21" + _value="Episodes shortcuts" + +_key="help_shortcut22" + _value="Play enclosure" + +_key="help_shortcut23" + _value="(Re)start download the selected episodes (items)" + +_key="help_shortcut24" + _value="Stop the episode (item) download" + +_key="help_shortcut25" + _value="Delete the selected episode (item)" + +_key="help_shortcut26" + _value="Shows the podcast episode (item) page " + +_key="help_shortcut27" + _value="Open enclosures folder" + +_key="help_buy1" + _value="BePodder Light is the basic version (free download and no time limited), the registered version adds some more nice features: unlimited number of channels, small Channel view, proxy support, automatic channels check, up to 5 enclosure downloads at the same time (multithreading)." + +_key="help_buy2" + _value="Please pay the shareware fee, it's only 15 euro (Kagi add tax in some countries), BePodder licence can be purchased online from Kagi." + +_key="help_buy3" + _value="Buy at www.funkyideasoft.com" + +_key="help_buy4" + _value="After purchasing, an email will be sent to you with a keyfile and instruction on how to install it. It's just a matter of unzipping a file and moving it to a certain directory." + +_key="help_buy5" + _value="There is no problem updating BePodder when a new version becomes available. The keyfile will unlock all downloadable packages unless otherwise notified." + + +### USELESS ######## + +"Opml Editor" "Opml Editor" +"name:" "name:" +"Add a category" "Add a category" +"Add a new Broadcast" "Add a new Broadcast" +"feed:" "feed:" +"url:" "url:" +"Test podcast" "Test podcast" +"Del a category" "Del a category" +"Add a category" "Add a category" +"Select the podcast category:" "Select the podcast category:" +"Check all" "Check all" +"Check" "Check" +"Refresh the list" "Refresh the list" +"Load" "Load" +"Load the list" "Load the list" +"Save" "Save" +"Save the list" "Save the list" +"Revert" "Revert" +"Apply" "Apply" + + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.huHU b/release/Language/Dictionaries/BePodder.huHU new file mode 100644 index 0000000..296dac8 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.huHU @@ -0,0 +1,604 @@ + +# Locale file for BePodder. +# Modified: 4/18/2006 +# Author: BePodderTeam +# E-mail: bepodder.team@gmail.com + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" + +"Web Site" "Web Site" + +"Can't connect!" "Can't connect!" +"Http port failed!" "Http port failed!" +"Can't resolve host!" "Can't resolve host!" +"Not found!" "Not found!" +"Bad resume!" "Bad resume!" +"Aborted by Callback!" "Aborted by Callback!" +"Can't resume! (range error)" "Can't resume! (range error)" +"Access Denied!" "Access Denied!" +"User or Password Incorrect!" "User or Password Incorrect!" +"Other error (cUrl code: " "Other error (cUrl code: " +"cUrl init error!" "cUrl init error!" +"Can't open file!" "Can't open file!" +"Other error (status code: " "Other error (status code: " +"Downloading" "Downloading" + + +### MENUBAR ----------------------------------- + +"File" "File" +"About..." "About..." +"Close!" "Close!" +"Quit" "Quit" + +"Settings" "Settings" +"Preferences..." "Preferences..." + +"Subscriptions" "Subscriptions" + +"Episodes" "Episodes" + +"Lists" "Lists" +"Podcast List" "Podcast List" +"Podcast directory list" "Podcast directory list" +"Videoblog List" "Videoblog List" +"Videoblog directory list" "Videoblog directory list" +"Imagefeeds List" "Imagefeeds List" +"Imagefeeds directory list" "Imagefeeds directory list" +"Newsfeeds List" "Newsfeeds List" +"Newsfeeds directory list" "Newsfeeds directory list" +"BitTorrentfeeds List" "BitTorrentfeeds List" +"BitTorrentfeeds directory list" "BitTorrentfeeds directory list" +"Internationalfeeds List" "Internationalfeeds List" +"Internationalfeeds directory list" "Internationalfeeds directory list" + +"View" "View" +"Full Screen" "Full Screen" +"Toolbar" "Toolbar" +"Subscriptions View" "Subscriptions View" +"Small Items" "Small Items" +"Big Items" "Big Items" +"Move BePodder on workspace:" "Move BePodder on workspace:" + +"Help" "Help" +"Getting Started" "Getting Started" +"Keyboard Shortcuts" "Keyboard Shortcuts" +"Tutorials" "Tutorials" +"Online Support" "Online Support" + + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "Insert the rss feed url!" +"Add" "Add" +"Paste" "Paste" + +# Buttons directory list window +"Collapse All" "Collapse All" +"Preview" "Preview" +"Subscribe" "Subscribe" + + +# Buttons help window +"Next" "Next" +"Prev" "Prev" +"Close" "Close" +"Index" "Index" + + +# Buttons remove windows +"Cancel" "Cancel" +"Delete" "Delete" +"Archive" "Archive" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Add the podcast to the Subscriptions list" +"Delete the podcast from the Subscriptions list" "Delete the podcast from the Subscriptions list" +"Check the selected podcast for new items" "Check the selected podcast for new items" +"Show the podcast homepage" "Show the podcast homepage" + +"Delete the item and the enclosure" "Delete the item and the enclosure" +"Stop the item download" "Stop the item download" +"Download the selected episode" "Download the selected episode" +"Play the selected episode" "Play the selected episode" + +"Submit bug and idea" "Submit bug and idea" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Collapse all categories in the directory list" +"Add the selected podcast to the Subscription list" "Add the selected podcast to the Subscription list" +"Checkout a podcast before downloading it" "Checkout a podcast before downloading it" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Show Channel Image" +"XML Feed Link" "XML Feed Link" + +"Show Episode info" "Show Episode info" +"Show Subscription info" "Show Subscription info" +"Show Downloads info" "Show Downloads info" + +"Enclosure: " "Enclosure: " + +"Lookup (Dictionary)" "Lookup (Dictionary)" +"Lookup (Google)" "Lookup (Google)" +"Lookup (Acronym Finder)" "Lookup (Acronym Finder)" +"Copy" "Copy" +"Select All" "Select All" +"Copy URL" "Copy URL" +"Open URL" "Open URL" +"Subscription" "Subscription" + + +### PREFERENCES ----------------------------------- + +"Preferences" "Preferences" + +"Proxy" "Proxy" +"Enable Proxy" "Enable Proxy" +"Address" "Address" +"Port" "Port" +"Username" "Username" +"Password" "Password" + +"Max Downloads" "Max Downloads" + +"FileType" "FileType" +"Browser" "Browser" +"Player" "Player" + +"Channels" "Channels" +"Check all channels on startup" "Check all channels on startup" +"Check the channel every" "Check the channel every" + +"never" "never" +"5 minutes" "5 minutes" +"15 minutes" "15 minutes" +"30 minutes" "30 minutes" +"1 hour" "1 hour" +"2 hour" "2 hour" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 new item" +"%d new items" "%d new items" +"new" "new" +"error" "error" +"not down" "not down" +"enquequed" "enquequed" +"downloading" "downloading" +"downloaded" "downloaded" +"connecting" "connecting" +"not found" "not found" +"stopped" "stopped" +"can't connect" "can't connect" +"invalid format" "invalid format" + +"Icon" "Icon" +"Title" "Title" +"Date" "Date" +"Size" "Size" +"Status" "Status" +"Download" "Download" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "Add Channel" +"Remove Channel" "Remove Channel" +"Check Channel" "Check Channel" +"Open Homepage" "Open Homepage" + +"Open Web Page" "Open Web Page" +"Open Enclosures folder" "Open Enclosures folder" +"Check All Channels" "Check All Channels" + +"Show Channel Image" "Show Channel Image" + +"Play enclosure" "Play enclosure" +"(Re)start download" "(Re)start download" +"Stop download" "Stop download" +"Remove Item" "Remove Item" + +"Find this Item" "Find this Item" +"Remove from this list" "Remove from this list" + + + +### ALERT ----------------------------------- + +"\nRemoving.." "\nRemoving.." +"\nAn error occured while removing!" "\nAn error occured while removing!" +"Check all the podcasts for new items" "Check all the podcasts for new items" + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" + + +"Can't open the selected file with:\n\n" "Can't open the selected file with:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nPlease check if the application is installed in the right way.\n" +"Download it!" "Download it!" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +You are going to remove the selected item. + +Are you sure? +(you will lost the enclosure file if any)" + + +_key="alert2a" + _value=" +You are going to remove the channel: + +" + +_key="alert2b" + _value=" + +Would you like just to archive this +channel (keeping all the files and +enclosures downloaded so far) or +do you want to DELETE the whole + channel from you computer?" + +_key="alert3" + _value=" +Parsing archive.." + +_key="alert_3gp" + _value=" +3GP is a multimedia container format defined by the Third Generation Partnership Project (3GPP) for use on 3G mobile phones. It stores video streams as MPEG-4 or H.263, and audio streams as AMR-NB or AAC-LC. + +VideoLAN still doesn't support the audio AMR (3GPP)" + +_key="alert_swf" + _value=" +SWF is a proprietary vector graphics file format produced by the Flash software from Adobe (formerly Macromedia). + +Currently Flash support in BeOS/Haiku/Zeta is limited to the old standalone Flash player version 4.1015, there isn't a modern Flash player" + + + + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Introduction" +"The User Interface" "The User Interface" +"Menu Bar" "Menu Bar" +"Toolbar Buttons" "Toolbar Buttons" +"First time with BePodder" "First time with BePodder" +"Download Podcast's enclosure files" "Download Podcast's enclosure files" +"Settings Overview" "Settings Overview" +"Directory lists" "Directory lists" +"Loading Help..." "Loading Help..." +"Register your copy" "Register your copy" +"Starting point" "Starting point" + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value="Welcome to the BePodder Getting Started Guide." + +_key="help1-1" + _value="If you are already familiar with podcasts and RSS/Atom feeds you can immediately go to BePodder by closing this window." + +_key="help1-2" +_value="If not, this is a short introduction providing you everything you'll need to know on how to get started with BePodder. Use the buttons below to navigate through this tutorial." + + +_key="help2-0" +_value="Podcasting is a method for publishing audio and video broadcasts via the Internet; links to free audio and video files are enclosed in RSS and Atom feeds." + +_key="help2-1" +_value="Therefore Podcasting is simply a type of online media delivery; users can subscribe to a podcast using a feed (such as RSS 'Really Simple Syndication' or Atom)." + +_key="help2-2" +_value="An aggregator (or podcatcher) like BePodder, is a piece of software that allows you to subscribe to a RSS feed and periodically check for and download new content; with BePodder you can check for new Podcast items (Episodes) of your subscribed Channels. Any item can contain an enclosure, just like an Email can contain an attachment." + + + +_key="help3-0" +_value="BePodder has an easy to use yet powerful Graphical User Interface. The main window is split into tree panels:" + +_key="help3-1" +_value="1) The Subscription list (the panel with the number 1 in the screenshot) with the list of the podcasts that you have subscribed to. When you click on a Channel you can see in the panel 2 the list of the channel's items." + +_key="help3-2" +_value="2) The Episodes list with all the items available." + +_key="help3-3" +_value="3) The Info panel show: episode info, channel info or Downloads info; you can select an info panel by clicking one of the below three buttons." + + + +_key="help4-0" +_value="At the very top of the BePodder main window is the menubar with seven menus available: File, Settings, Subscriptions, Episodes, Lists, View and Help. Some menu commands are followed by a right pointing arrow that indicates a submenu of related commands. As you explore each menu, be sure to take a look at the submenus as well. Click on a menus to show its commands:" + +_key="help4-1" +_value="File: contains commands to close the application and to show information about BePodder" + +_key="help4-2" +_value="Settings: contains command to open the Preferences window that allows you to customize various BePodder settings." + +_key="help4-3" +_value="Subscriptions: contains commands that perform actions on the selected channel of your subscriptions list." + +_key="help4-4" +_value="Episodes: contains commands that perform actions on the selected item (episode) of the channel's episode list." + +_key="help4-5" +_value="Lists: contains commands to open BePodder's OPML directories." + +_key="help4-6" +_value="View: contains commands and controls for the BePodder window." + +_key="help4-7" +_value="Help: contains commands to open BePodder's 'Getting Started Guide' and the 'Keyboard Shortcuts List'." + + + +_key="help5-0" + _value="Add Button: opens the Add Window to add a feed url (e.g. http://www.newpodcast.com/rss.xml) usually given on the podcast homepage; looks for text or graphic link that says something like 'XML', 'RSS' or 'Podcast Feed' on it." + +_key="help5-1" + _value="Channel Remove Button: opens a window in which you can select how remove the channel: just archive the select channel (keeping all the files and eclosure downloaded so far) or delete the whole channel from your computer." + +_key="help5-2" + _value="Check Button: checks the selected channel and updates the list of the available items for that podcast adding the new items." + +_key="help5-3" + _value="Web Button: shows the channel homepage in the browser. To select your favorite browser open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select your favorite browser." + +_key="help5-4" + _value="Play Button: with this button you can view or listen the file enclosure of the selected item(episode). To select your favorite player open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select you favorite player." + +_key="help5-5" + _value="Download Button: downloads the file enclosure of the selected item (episode); you can see the download info by clicking on the third button over the info panel." + +_key="help5-6" + _value="Stop Button: stops to download the file enclosure of the selected item (episode); to resume the download double-click the item (episode) or select the item and click the Download Button" + +_key="help5-7" + _value="Item Remove Button: deletes the selected item (you will loose the enclosure file)." + + + +_key="help6-0" + _value="Getting started with BePodder is easy." + +_key="help6-1" + _value="On the left of the main window you can see the 'Subscription List' with all your feed subscriptions. We have added some subscriptions for you, and you can always add your own in two ways:" + +_key="help6-2" + _value="1) click the Add Button, then insert the feed url (example: http://www.newpodcast.com/rss.xml) and click add." + +_key="help6-3" + _value="2) in the menubar select 'Directory' and then 'Podcast list' or another list, choose a podcast and click 'Subscribe'." + +_key="help6-4" + _value="If you select a Podcast in the subscriptions list and use the check button, BePodder adds the new items to the 'Episodes list' (below on the right); you can check all your podcasts by right-clicking and selecting 'Check All Channels' in the context menu." + +_key="help6-5" + _value="Look at the screenshot above, there are 3 new items indicated by a black dot in the first column of the 'Episodes list'." + +_key="help6-6" + _value="In the second column there are icons that indicate the state of the item:" + +_key="help6-7" + _value="- the Episode 4 has an icon that indicates an error" + +_key="help6-8" + _value="- the Episode 3 has an icon that indicates that the item's enclosure download request is enquequed" + +_key="help6-9" + _value="- the Episode 2 has an icon that indicates that BePodder is downloading the item's enclosure file" + +_key="help6-10" + _value="- the Episode 1 have an icon that indicates that BePodder have just downloaded the item's enclosure file" + + + +_key="help7-0" + _value="Select an item in the 'Episodes list' and then double-click on it (or click the Download Button) to start downloading the enclosed file; you can always stop the download by clicking on the Stop Button." + +_key="help7-1" + _value="When you click on the Subscribed Podcasts in the 'Subscriptions List' the software shows you, in the 'List of episodes', all the items available in that Subscription. Select an item and then click play (Play Button) to view or listen to the file." + +_key="help7-2" + _value="You can access the Enclosures Folder by clicking on the folder icon in the Info Pannel or by right-clicking your mouse on an item and select 'Open Enclosures Folder' in the context menu." + + + +_key="help8-0" + _value="Preferences can be accessed by clicking in the menu-bar Settings>Preferences. You can select a category from the left list of the preferences dialog: FileType, Channels, Download and Proxy." + +_key="help8-1" + _value="- FileType: to specify the default browser and player. " + +_key="help8-2" + _value="- Channels: to specify preferences that control the operation to check channels new items; you can choose to Check all channels on startup or check the channel every desired minutes." + +_key="help8-3" + _value="- Download: to specify the max number of item's files to download at the same time," + +_key="help8-4" + _value="- Proxy: to set up a proxy server to work with BePodder; a proxy server acts as a security barrier between your internal network and the Internet, keeping others on the Internet from accessing information on your internal network." + + + +_key="help9-0" + _value="BePodder has built-in podcast, videoblog, imagefeeds, newsfeeds, bittorrentfeeds and internationalfeeds OPML directories with thousands of feeds grouped by category." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) is an XML-based format that allows exchange of outline-structured information between applications." + +_key="help9-2" + _value="OPML directory can be accessed by clicking in the menu-bar 'Lists' and thenselecting a list. To browse the opml directory for a feed, expand the list by clicking the arrow of the category that you are interested in (see image); using this method, you can expand the opml directory until you find the desired feed. Once you have selected it, you can add it to the subscription list by clicking the button 'Subscribe', you can also collapse all categories in the directory list by clicking the button 'Collapse All'." + +_key="help_shortcut1" +_value="This page describes the keyboard shortcuts that can be used in BePodder. The shortcuts are grouped here by function." + +_key="help_shortcut2" +_value="means that you can use either alt or control (es. Alt+Q or Ctrl+Q Quit the application), which way you have set it in the Deskbar menu preferences under Keyboard (the default shortcut key is Alt)." + +_key="help_shortcut3" + _value="General shortcuts" + +_key="help_shortcut4" + _value="Quit the application" + +_key="help_shortcut5" + _value="Shows the Preferences window" + +_key="help_shortcut6" + _value="Shows the Podcast directory list" + +_key="help_shortcut7" + _value="Shows the Videoblog directory list" + +_key="help_shortcut8" + _value="Shows the Imagefeeds directory list" + +_key="help_shortcut9" + _value="Shows the Newsfeeds directory list" + +_key="help_shortcut9b" + _value="Shows the BitTorrentfeeds directory list" + +_key="help_shortcut9c" + _value="Shows the Internationalfeeds directory list" + +_key="help_shortcut10" + _value="Fullscreen" + +_key="help_shortcut11" + _value="Shows/Hides the toolbar" + +_key="help_shortcut12" + _value="Shows the Getting Started Help" + +_key="help_shortcut13" + _value="Shows this keyboard shortcuts page" + +_key="help_shortcut14" + _value="Channels shortcuts" + +_key="help_shortcut15" + _value="Add a podcast to the subscriptions list" + +_key="help_shortcut16" + _value="Delete the selected podcast from the subscriptions list" + +_key="help_shortcut17" + _value="Check the selected podcast for new episodes (items)" + +_key="help_shortcut18" + _value="Check all podcasts for new episodes (items)" + +_key="help_shortcut19" + _value="Shows the podcast homepage" + +_key="help_shortcut20" + _value="Open enclosures folder" + +_key="help_shortcut21" + _value="Episodes shortcuts" + +_key="help_shortcut22" + _value="Play enclosure" + +_key="help_shortcut23" + _value="(Re)start download the selected episodes (items)" + +_key="help_shortcut24" + _value="Stop the episode (item) download" + +_key="help_shortcut25" + _value="Delete the selected episode (item)" + +_key="help_shortcut26" + _value="Shows the podcast episode (item) page " + +_key="help_shortcut27" + _value="Open enclosures folder" + +_key="help_buy1" + _value="BePodder Light is the basic version (free download and no time limited), the registered version adds some more nice features: unlimited number of channels, small Channel view, proxy support, automatic channels check, up to 5 enclosure downloads at the same time (multithreading)." + +_key="help_buy2" + _value="Please pay the shareware fee, it's only 15 euro (Kagi add tax in some countries), BePodder licence can be purchased online from Kagi." + +_key="help_buy3" + _value="Buy at www.funkyideasoft.com" + +_key="help_buy4" + _value="After purchasing, an email will be sent to you with a keyfile and instruction on how to install it. It's just a matter of unzipping a file and moving it to a certain directory." + +_key="help_buy5" + _value="There is no problem updating BePodder when a new version becomes available. The keyfile will unlock all downloadable packages unless otherwise notified." + + +### USELESS ######## + +"Opml Editor" "Opml Editor" +"name:" "name:" +"Add a category" "Add a category" +"Add a new Broadcast" "Add a new Broadcast" +"feed:" "feed:" +"url:" "url:" +"Test podcast" "Test podcast" +"Del a category" "Del a category" +"Add a category" "Add a category" +"Select the podcast category:" "Select the podcast category:" +"Check all" "Check all" +"Check" "Check" +"Refresh the list" "Refresh the list" +"Load" "Load" +"Load the list" "Load the list" +"Save" "Save" +"Save the list" "Save the list" +"Revert" "Revert" +"Apply" "Apply" + + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.itIT b/release/Language/Dictionaries/BePodder.itIT new file mode 100644 index 0000000..ad95619 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.itIT @@ -0,0 +1,601 @@ +# Locale file for BePodder. +# Modified: 4/18/2006 +# Author: Giuseppe Gargaro +# E-mail: giuseppe.gargaro@tin.it + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Programma Shareware!\n\nPer favore supportateci!\n\nComprate una licenza del software!\nMaggiori informazioni sul nostro sito web\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "Questa copia di BePodder è scaduta!\nPer favore comprate una chiave e supportateci.\n" + +"Web Site" "Sito Web" + +"Can't connect!" "Connessione non riuscita!" +"Http port failed!" "Http port failed!" +"Can't resolve host!" "Host non trovato... controllare se siete connessi!" +"Not found!" "Non trovato!" +"Bad resume!" "Ripresa non riuscita!" +"Aborted by Callback!" "Abbandonato dalla richiamata!" +"Can't resume! (range error)" "Non posso riprendere! (range error)" +"Access Denied!" "Accesso negato!" +"User or Password Incorrect!" "User o Password errati!" +"Other error (cUrl code: " "Altro errore (cUrl code: " +"cUrl init error!" "cUrl init error!" +"Can't open file!" "Apertura file non riuscita!" +"Other error (status code: " "Altro errore (status code: " +"Downloading" "Scaricando" + + +### MENUBAR ----------------------------------- + +"File" "File" +"About..." "Informazioni..." +"Close!" "Chiudi!" +"Quit" "Esci" + +"Settings" "Impostazioni" +"Preferences..." "Preferenze..." + +"Subscriptions" "Sottoscrizioni" + +"Episodes" "Episodi" + +"Lists" "Liste" +"Podcast List" "Lista Podcast" +"Podcast directory list" "Lista Podcast per categorie" +"Videoblog List" "Lista Videoblog" +"Videoblog directory list" "Lista Videoblog per categorie" +"Imagefeeds List" "Lista Imagefeed" +"Imagefeeds directory list" "Lista Imagefeed per categorie" +"Newsfeeds List" "Lista Newsfeed" +"Newsfeeds directory list" "Lista Newsfeeds per categorie" +"BitTorrentfeeds List" "Lista BitTorrentfeed" +"BitTorrentfeeds directory list" "Lista BitTorrentfeed per categorie" +"Internationalfeeds List" "Lista Internationalfeed" +"Internationalfeed directory list" "Lista Internationalfeed per categorie" + +"View" "Visualizza" +"Full Screen" "A tutto schermo" +"Toolbar" "Barra pulsanti" +"Subscriptions View" "Vista sottoscrizioni" +"Small Items" "Voci piccole" +"Big Items" "Voci grandi" +"Move BePodder on workspace:" "Sposta BePodder sulla scrivania:" + +"Help" "Aiuto" +"Getting Started" "Per iniziare..." +"Keyboard Shortcuts" "Scorciatoie di tastiera" +"Tutorials" "Tutorials" +"Online Support" "Supporto online" + + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "Inserisci la url del feed rss!" +"Add" "Aggiungi" +"Paste" "Incolla" + +# Buttons directory list window +"Collapse All" "Chiudi tutte" +"Preview" "Preview" +"Subscribe" "Sottoscrivi" + + +# Buttons help window +"Next" "Avanti" +"Prev" "Indietro" +"Close" "Chiudi" +"Index" "Indice" + + +# Buttons remove windows +"Cancel" "Annulla" +"Delete" "Rimuovi" +"Archive" "Archivia" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Aggiunge il podcast alla lista Sottoscrizioni" +"Delete the podcast from the Subscriptions list" "Cancella il podcast dalla lista delle Sottoscrizioni" +"Check the selected podcast for new items" "Controlla la presenza di nuovi episodi per il podcast selezionato" +"Show the podcast homepage" "Mostra il sito del podcast" + +"Delete the item and the enclosure" "Elimina la voce selezionata e il file allegato" +"Stop the item download" "Interrompe il download della trasmissione" +"Download the selected episode" "Scarica la trasmissione selezionata" +"Play the selected episode" "Riproduce la trasmissione selezionata" + +"Submit bug and idea" "Segnala bug e idee" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Chiudi tutte le categorie nella lista" +"Add the selected podcast to the Subscription list" "Aggiungi il podcast selezionato alla lista Sottoscrizioni" +"Checkout a podcast before downloading it" "Checkout a podcast before downloading it" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Mostra immagine canale" +"XML Feed Link" "XML Feed Link" + +"Show Episode info" "Mostra informazioni sull'episodio" +"Show Subscription info" "Mostra informazioni sul canale" +"Show Downloads info" "Mostra informazioni sui download" + +"Enclosure: " "Allegato: " + +"Lookup (Dictionary)" "Ricerca (Dizionario)" +"Lookup (Google)" "Ricerca (Google)" +"Lookup (Acronym Finder)" "Ricerca (Acronym Finder)" +"Copy" "Copia" +"Select All" "Seleziona tutti" +"Copy URL" "Copia URL" +"Open URL" "Apri URL" +"Subscription" "Sottoscritto" + + +### PREFERENCES ----------------------------------- + +"Preferences" "Preferenze" + +"Proxy" "Proxy" +"Enable Proxy" "Abilita Proxy" +"Address" "Indirizzo" +"Port" "Porta" +"Username" "Nome utente" +"Password" "Password" + +"Max Downloads" "Massimo numero di Download contemporanei" + +"FileType" "Tipi di file" +"Browser" "Browser" +"Player" "Player" + +"Channels" "Canali" +"Check all channels on startup" "Controlla i canali sottoscritti all'avvio" +"Check the channel every" "Controlla il canale ogni" + +"never" "mai" +"5 minutes" "5 minuti" +"15 minutes" "15 minuti" +"30 minutes" "30 minuti" +"1 hour" "1 ora" +"2 hour" "2 ore" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 nuovo elemento" +"%d new items" "%d nuovi elementi" +"new" "nuovo" +"error" "errore" +"not down" "non scaricato" +"enquequed" "in coda" +"downloading" "scaricando" +"downloaded" "scaricato" +"connecting" "collegamento" +"not found" "non trovato" +"stopped" "incompleto" +"can't connect" "collegamento non riuscito" +"invalid format" "formato non valido" + +"Icon" "Icona" +"Title" "Titolo" +"Date" "Data" +"Size" "Dimensione" +"Status" "Stato" +"Download" "Download" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "Aggiungi canale" +"Remove Channel" "Rimuovi canale" +"Check Channel" "Controlla canale" +"Open Homepage" "Apri Homepage" + +"Open Web Page" "Apri pagina web" +"Open Enclosures folder" "Apri cartella file" +"Check All Channels" "Controlla tutti i canali" + +"Show Channel Image" "Mostra immagine canale" + +"Play enclosure" "Riproduci file" +"(Re)start download" "Riavvia download" +"Stop download" "Arresta download" +"Remove Item" "Rimuovi episodio" + +"Find this Item" "Trova la voce" +"Remove from this list" "Rimuovi dalla lista" + + + +### ALERT ----------------------------------- + +"\nRemoving.." "\nRimozione.." +"\nAn error occured while removing!" "\nSi è verificato un'errore durante la rimozione!" +"Check all the podcasts for new items" "Controlla la presenza di nuovi episodi per tutti i podcast" + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "Potete aggiungere solo 10 canali in questa versione non registrata di BePodder.\n Per favore registrate la vostra copia\n" +"Web Site" "Web Site" + +"Can't open the selected file with:\n\n" "Non è stato possibile aprire il file selezionato con l'appicazione:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nPer favore controllate che l'applicazione sia installata correttamente.\n" +"Download it!" "Scarica l'applicazione!" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +State per rimuovere la voce selezionata. + +Siete sicuri? +(perderete i file allegati se ce ne sono)" + + +_key="alert2a" + _value=" +State per rimuovere il canale: + +" + +_key="alert2b" + _value=" + +Volete soltanto archiviare questo +canale (mantenendo tutti i file +fino ad ora scaricati ) o volete +RIMUOVERE l'intero canale +dal vostro computer?" + +_key="alert3" + _value=" +Analisi archivio.." + +_key="alert_3gp" + _value=" +3GP è un formato per contenuti multimediali definito dal progetto Third Generation Partnership Project (3GPP) per l'uso su telefonini 3G. Questo formato contiene video stream in MPEG-4 o H.263, e audio stream in AMR-NB o AAC-LC. + +VideoLAN ancora non supporta l'audio AMR (3GPP)" + +_key="alert_swf" + _value=" +SWF è un formato proprietario per la grafica vettoriale realizzato con il software Flash della Adobe (precedentemente della Macromedia). + +Attualmente il supporto di Flash in BeOS/Haiku/Zeta è limitato alla vecchia versione del player Flash 4.1015, non c'è un moderno player Flash" + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Introduzione" +"The User Interface" "L'interfaccia utente" +"Menu Bar" "Barra dei menu" +"Toolbar Buttons" "Pulsanti toolbar" +"First time with BePodder" "La prima volta con BePodder" +"Download Podcast's enclosure files" "Scaricare i file allegati a un Podcast" +"Settings Overview" "Impostazione preferenze" +"Directory lists" "Liste" +"Loading Help..." "Avvio Help..." +"Register your copy" "Registra la tua copia" +"Starting point" "Pagina iniziale" + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value="Benvenuti nella guida rapida di BePodder." + +_key="help1-1" + _value="Se già avete familiarità con i Podcast e gli RSS feed potete immediatamente +iniziare ad utilizzare BePodder chiudendo questa finestra." + +_key="help1-2" +_value="Altrimenti eccovi una breve introduzione che vi spiegherà tutto quello che dovete sapere per iniziare ad usare l'applicazione. Utilizzate il pulsante qui sotto per proseguire attraverso questa guida." + +_key="help2-0" + _value="Il Podcasting è un metodo per pubblicare trasmissioni con contenuti audio e video in internet; i collegamenti ai file audio e video sono contenuti nei feed RSS e Atom." + +_key="help2-1" +_value="Quindi il Podcasting è semplicemente un nuovo sistema per distribuire media online; gli utenti possono sottoscrivere un podcast usando un feed (come RSS 'Really Simple Syndication' o Atom)." + +_key="help2-2" +_value=" Un aggregatore (o podcatcher) come BePoddder, è una applicazione che vi permette di sottoscrivere gli RSS feed e di cercare e scaricare nuovi contenuti periodicamente; con BePodder potete cercare nuove voci (episodi) di un podcast che avete precedentemente sottoscritto. Ogni voce può contenere un file allegato, proprio +come avviene per una Email" + + + +_key="help3-0" + _value="BePodder ha una interfaccia grafica potente e semplice. La finestra principale del programma è divisa in tre aree:" + +_key="help3-1" + _value="1) La 'lista sottoscrizioni' (nell'immagine l'area indicata dal numero 1) con tutti i Podcast che avete sottoscritto. Cliccando du un canale potete vedere nell 'area 2 la lista degli episodi disponibili per quel canale." + +_key="help3-2" + _value="2) La 'lista degli episodi' con tutti gli episodi disponibili." + +_key="help3-3" + _value="3) Il 'pannello informazioni' mostra: informazioni episodio, informazioni canale oppure informazioni sui download; potete selezionare un pannello informazioni cliccando uno dei tre pulsanti qui sotto." + + +_key="help4-0" +_value="Nella parte più alta della finestra principale di BePodder c'è la barra dei menù con sei menù disponibili: File, Impostazioni, Sottoscrizioni, Episodi, Liste, Visualizza ed Aiuto. Alcuni comandi dei menù sono seguiti da una freccia che indica la presenza di un sottomenù per il comando. Quando esplorate un menù accertatevi di dare anche un'occhiata ai sottomenù. Cliccate su un menù per visualizzarne i comandi:" + +_key="help4-1" +_value="File: contiene comandi per chiudere l'applicazione e per mostrare informazioni su BePodder" + +_key="help4-2" +_value="Impostazioni: contiene il comando che apre la finestra preferenze per consentirvi di impostare le preferenze di BePodder." + +_key="help4-3" +_value="Sottoscrizioni: contiene i comandi che eseguono alcune azioni sul canale selezionato nella vostra lista sottoscrizioni." + +_key="help4-4" +_value="Episodi: contiene i comandi che eseguono alcune azioni sulla voce(episodio) selezionata nella lista episodi del canale." + +_key="help4-5" +_value="Liste: contiene i comandi per aprire le liste OPML di BePodder." + +_key="help4-6" +_value="Visualizza: contiene i comandi per controllare la finestra di BePodder" + +_key="help4-7" +_value="Aiuto: contiene i comandi per aprire la guida rapida a BePodder e la lista delle scorciatoie di tastiera'." + + + +_key="help5-0" + _value="Add Button: apre la finestra per aggiungere un feed url (e.g. http://www.newpodcast.com/rss.xml) che normalmente potete trovare sulla homepage del podcast; cercate un link testuale o grafico che riporta la scritta 'XML', 'RSS' o 'Podcast Feed'." + +_key="help5-1" + _value="Channel Remove Button: apre una finestra in cui potete selezionare come rimuovere il canale: semplicemente archiviare (mantenendo tutti i file allegati che avete scaricato) o eliminare l'intero canale dal computer." + +_key="help5-2" + _value="Check Button: controlla il canale selezionato e aggiorna la lista degli episodi disponibili per quel podcast aggiungendo i nuovi episodi." + +_key="help5-3" + _value="Web Button: mostra la homepage del canale nel browser. Per selezionare il vostro browser preferito aprite le preferenze di BePodder, cliccate Impostazioni>Preferenze nella barra dei menu... e nella finestra delle preferenze sotto 'Tipi di file' selezionate il browser preferito." + +_key="help5-4" + _value="Play Button: con questo pulsante potete vedere o ascoltare il contenuto del file allegato all'episodio selezionato. Per selezionare il vostro player preferito aprite le preferenze di BePodder, cliccate Impostazioni>Preferenze nella barra dei menu... e nella finestra delle preferenze sotto 'Tipi di file' selezionate il player preferito." + +_key="help5-5" + _value="Download Button: scarica il file allegato all'episodio selezionato; potete visualizzare le informazioni sul download cliccando sul terzo bottone sopra il pannello delle informazioni." + +_key="help5-6" + _value="Stop Button: arresta lo scaricamento del file allegato all'episodio selezionato; per riavviare lo scaricamento cliccate due volte sull'episodio o selezionate l'episodio e cliccate Download Button" + +_key="help5-7" + _value="Item Remove Button: elimina l'episodio selezionato (perderete il file allegato)." + + +_key="help6-0" + _value="Iniziare ad utilizzare BePodder è semplice." + +_key="help6-1" + _value="Nella parte sinistra della finestra del programma c'è la lista dei feed che avete sottoscritto. Ne abbiamo aggiunti alcuni per voi, e naturalmente potete sempre +aggiungere i vostri in due modi:" + +_key="help6-2" + _value="1) cliccate sul pulsante Add (vedi toolbar overview), poi inserite l'url del feed (ad esempio: http://www.newpodcast.com/rss.xml) e premete su Aggiungi." + +_key="help6-3" + _value="2) nella barra dei menù selezionate 'Directory' e poi 'Lista Podcast' o 'Lista +Videoblog', scegliete un podcast e cliccate su 'Sottoscrivi'." + +_key="help6-4" + _value="Se dopo aver selezionato un Podcast nella lista dei sottoscritti utilizzate il pulsante Check, BePodder aggiungerà le nuove voci alla lista degli episodi sulla destra della finestra principale; potete effettuare la ricerca di nuove voci su tutti i podcast cliccando il tasto destro del mouse sulla lista dei sottoscritti e selezionando 'Controlla tutti i canali' nel menù contestuale." + +_key="help6-5" + _value="Guardate l'immagine qui sopra, ci sono 3 nuove voci contrassegnate da un quadratino nero nella prima colonna della lista degli Episodi." + +_key="help6-6" + _value="Nella seconda colonna ci sono le icone che indicano lo statoi dell'episodio:" + +_key="help6-7" + _value="- l'episodio 4 ha un icona che indica un errore" + +_key="help6-8" + _value="- l'episodio 3 ha un icona che indica che il downlod del file allegato all'episodio è in coda" + +_key="help6-9" + _value="- l'episodio 2 ha un icona che indica che BePodder sta scaricando il file allegato all'episodio" + +_key="help6-10" + _value="- l'episodio 1 ha un icona che indica che BePodder ha già scaricato il file allegato all'episodio" + + + +_key="help7-0" + _value="Selezionate una voce nella 'Lista degli episodi' ed effettuate un doppio click sulla stessa oppure cliccate sul pulsante Download; potete interrompere in ogni +momento il download cliccando sul pulsante Stop nella toolbar." + +_key="help7-1" + _value="Quando selezionate una voce nella 'Lista dei sottoscritti' l'applicazione vi mostra, nella 'Lista degli episodi', tutti gli episodi disponibili per quel canale. Selezionate una voce e poi cliccate sul pulsante Play per vederne o ascoltarne il contenuto." + +_key="help7-2" + _value="Potete accedere alla cartella degli Allegati cliccando sull'icona cartella nel pannello delle informazioni o cliccate il tasto destro del mouse su un episodio e selezionate 'Apri cartella file' nel menù contestuale." + + +_key="help8-0" + _value="Potete accedere alle preferenze cliccando Impostazioni>Preferenze nella barra dei menu. Potete selezionare una delle categorie dalla lista sulla sinistra nel pannello delle preferenze: Tipi di file, Canali, Download, Proxy." + +_key="help8-1" + _value="- Tipi di file: per impostare browser e player di default. " + +_key="help8-2" + _value="- Canali: per impostare le preferenze relative all'operazione di ricerca di nuovi episodi; potete impostare le preferenze affinchè all'avvio BePodder effettui la ricerca su tutti i canali oppure effetui la ricerca ogni tot minuti." + +_key="help8-3" + _value="- Download: per impostare il massimo numero di download contemporanei" + +_key="help8-4" + _value="- Proxy: per utilizzare un proxy server; un proxy server costituisce una sorta di barriera tra una rete locale e interneta, impedendo l'accesso di estranei alle informazioni presenti sulla rete locale." + + +_key="help9-0" + _value="BePodder contiene liste OPML integrate di podcast, videoblog, imagefeed, newsfeed, bittorrentfeed e internationalfeeds con migliaia di feed raggruppati per categorie." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) è un formato basato sullo XML che consente di scambiare informazioni strutturate tra le applicazioni." + +_key="help9-2" + _value="Potete accedere alle directory OPML cliccando nella barra dei menù 'Liste' e poi selezionando una lista. Per visualizzare i feed della lista OPML, dovete espandere la lista cliccando la freccia relativa alla categoria che vi interessa (vedi immagine); usando questo metodo, potete espandere la lista finchè non trovate il feed desiderato. Dopo averlo selezionato, potete aggiungerlo alla lista dei sottoscritti cliccando il tasto 'Sottoscrivi', potete chiudere tutte le categorie nella lista cliccando il tasto 'Chiudi tutte'." + + +_key="help_shortcut1" +_value="Questa pagina elenca le scorciatoie di tastiera che possono essere utilizzate in BePodder. Le scorciatoie di tastiera sono raggruppate per funzioni. " + +_key="help_shortcut2" +_value="indica che potete usare alternativamente i tasti alt o control (es. Alt+Q o Ctrl+Q chiudono l'applicazione), a seconda di quale avete impostato nella Deskbar sotto il menu Impostazioni Tastiera (il tasto di default per le scorciatoie di tastiera è Alt)." + +_key="help_shortcut3" + _value="Scorciatoie generali" + +_key="help_shortcut4" + _value="Chiude l'applicazione" + +_key="help_shortcut5" + _value="Mostra la finestra delle preferenze" + +_key="help_shortcut6" + _value="Mostra la lista dei Podcast" + +_key="help_shortcut7" + _value="Mostra la lista dei Videoblog" + +_key="help_shortcut8" + _value="Mostra la lista degli Imagefeeds" + +_key="help_shortcut9" + _value="Mostra la lista dei Newsfeeds" + +_key="help_shortcut9b" + _value="Mostra la lista dei BitTorrentfeeds" + +_key="help_shortcut9c" + _value="Mostra la lista degli Internationalfeeds" + +_key="help_shortcut10" + _value="A tutto schermo" + +_key="help_shortcut11" + _value="Mostra/Nasconde la barra dei pulsanti" + +_key="help_shortcut12" + _value="Mostra la guida rapida" + +_key="help_shortcut13" + _value="Mostra questa pagina con le scorciatoie di tastiere" + +_key="help_shortcut14" + _value="Scorciatoie Canali" + +_key="help_shortcut15" + _value=" Aggiunge un podcast alla lista dei sottoscritti" + +_key="help_shortcut16" + _value="Elimina il podcast selezionato nella lista dei sottoscritti" + +_key="help_shortcut17" + _value="Controlla la presenza di nuovi episodi per il podcast selezionato" + +_key="help_shortcut18" + _value="Controlla la presenza di nuovi episodi per tutti i podcast" + +_key="help_shortcut19" + _value="Mostra la homepage del podcast" + +_key="help_shortcut20" + _value="Apri cartella allegati" + +_key="help_shortcut21" + _value="Scorciatoie Episodi" + +_key="help_shortcut22" + _value="Riproduci file allegato" + +_key="help_shortcut23" + _value="(Ri)avvia download episodio selezionato" + +_key="help_shortcut24" + _value="Arresta download dell'episodio" + +_key="help_shortcut25" + _value="Elimina l'episodio selezionato" + +_key="help_shortcut26" + _value="Mostra la pagina web dell'episodio selezionato " + +_key="help_shortcut27" + _value="Apri cartella allegati" + +_key="help_buy1" + _value="BePodder Light è la versione base (download libero e durata illimitata), la versione registrata aggiunge alcune piacevoli caratteristiche: numero illimitato di canali, vista canali sottoscritti in piccolo, supporto proxy, controllo automatico dei canali, fino a 5 download contemporaneamente (multithreading)." + +_key="help_buy2" + _value="Per favore acquistate lo shareware, costa solo 15 euro (più IVA); la licenza può essere acquistata online tramite Kagi." + +_key="help_buy3" + _value="Compra su www.funkyideasoft.com" + +_key="help_buy4" + _value="Dopo l'acquisto, riceverete una mail con il keyfile e le istruzioni su come installarlo. Si tratta semplicemente di scompattare un file zip e muovere il file contenuto in una determinata cartella." + +_key="help_buy5" + _value="Non c'è nessun problema per aggiornare BePodder quando una nuova versione è disponibile. Il keyfile resta valido per tutti i package scaricabili a meno che non venga segnalato il contrario." + + +### USELESS ######## + +"Opml Editor" "Opml Editor" +"name:" "nome:" +"Add a categorie" "Aggiungi una categoria" +"Add a new Broadcast" "Aggiungi un nuovo Broadcast" +"feed:" "feed:" +"url:" "url:" +"Test podcast" "Controllo podcast" +"Del a categorie" "Elimina una categoria" +"Add a categorie" "Aggiungi una categoria" +"Select the podcast categorie:" "Seleziona la categoria del podcast:" +"Check all" "Controlla tutti" +"Check" "Controlla" +"Refresh the list" "Aggiorna la lista" +"Load" "Apri" +"Load the list" "Apre la lista" +"Save" "Salva" +"Save the list" "Salva la lista" +"Revert" "Ripristina" +"Apply" "Applica" + + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.jaJP b/release/Language/Dictionaries/BePodder.jaJP new file mode 100644 index 0000000..559a668 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.jaJP @@ -0,0 +1,789 @@ +# Locale file for BePodder. +# Modified: 05/21/2006 +# Author: Jorge G.Mare (koki) & Koichi Kimura (a.k.a. KiM) +# E-mail: koki@aequus.net & bem@jcom.home.ne.jp + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "これはシェアウェアです!\n\nソフトウェアライセンスを購入して\n私達を支援してください!\n\n詳細情報はウェブサイトを御覧ください。\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "この BePodder のコピーは期限切れです!\nkeyfile を購入し、私達を支援してください。\n" + +"Web Site" "ウェブサイト" + +"Can't connect!" "Can't connect!" +"Http port failed!" "Http port failed!" +"Can't resolve host!" "Can't resolve host!" +"Not found!" "Not found!" +"Bad resume!" "Bad resume!" +"Aborted by Callback!" "Aborted by Callback!" +"Can't resume! (range error)" "Can't resume! (range error)" +"Access Denied!" "Access Denied!" +"User or Password Incorrect!" "User or Password Incorrect!" +"Other error (cUrl code: " "Other error (cUrl code: " +"cUrl init error!" "cUrl init error!" +"Can't open file!" "Can't open file!" +"Other error (status code: " "Other error (status code: " +"Downloading" "Downloading" + + +### MENUBAR ----------------------------------- + +"File" "ファイル" +"About..." "BePodder について..." +"Close!" "閉じる!" +"Quit" "終了" + +"Settings" "設定" +"Preferences..." "BePodder の設定..." + +"Subscriptions" "購読" + +"Episodes" "エピソード" + +"Lists" "リスト" +"Podcast List" "ポッドキャスト リスト" +"Podcast directory list" "ポッドキャスト ディレクトリ リスト" +"Videoblog List" "ビデオブログ リスト" +"Videoblog directory list" "ビデオブログ ディレクトリ リスト" +"Imagefeeds List" "イメージフィード リスト" +"Imagefeeds directory list" "イメージフィード ディレクトリ リスト" +"Newsfeeds List" "ニュースフィード リスト" +"Newsfeeds directory list" "ニュースフィード ディレクトリ リスト" +"BitTorrentfeeds List" "BitTorrentfeeds List" +"BitTorrentfeeds directory list" "BitTorrentfeeds directory list" +"Internationalfeeds List" "Internationalfeeds List" +"Internationalfeeds directory list" "Internationalfeeds directory list" + +"View" "表示" +"Full Screen" "全画面表示" +"Toolbar" "ツールバー" +"Subscriptions View" "購読リスト表示" +"Small Items" "小" +"Big Items" "大" +"Move BePodder on workspace:" "ワークスペースを移動:" + +"Help" "ヘルプ" +"Getting Started" "ご使用の前に..." +"Keyboard Shortcuts" "キーボード ショートカット..." +"Tutorials" "チュートリアル" +"Online Support" "オンラインサポート" + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window + +"Insert the rss feed url!" "RSS フィード URL を入力" +"Add" "追加" +"Paste" "貼り付け" + + +# Buttons directory list window + +"Collapse All" "Collapse All" +"Preview" "プレビュー" +"Subscribe" "購読" + + +# Buttons help window + +"Next" "次へ" +"Prev" "前へ" +"Close" "閉じる" +"Index" "インデックス" + + +# Buttons remove windows + +"Cancel" "中止" +"Delete" "削除" +"Archive" "アーカイブ" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "ポッドキャストを購読リストに追加" +"Delete the podcast from the Subscriptions list" "ポッドキャストを購読リストから削除" +"Check the selected podcast for new items" "新着項目のチェック" +"Show the podcast homepage" "ポッドキャストのホームページを開く" + +"Delete the enclosure file associated with the selected item" "選択項目に関連する enclosure ファイルを削除" +"Delete the enclosed file associated with the selected item" "選択項目に関連する enclosure ファイルを削除" +"Stop the item download" "ダウンロードを停止" +"Download the selected episode" "ファイルをダウンロード" +"Play the selected episode" "ファイルを再生" + +"Submit bug and idea" "バグや要望を投稿" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Collapse all categories in the directory list" +"Add the selected podcast to the Subscription list" "選択したポッドキャストを購読リストに追加" +"Checkout a podcast before downloading it" "ポッドキャストのダウンロード前に検査を終了する" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "チャンネルの画像を表示" +"XML Feed Link" "XML フィードリンク" + +"Show Episode info" "エピソード情報を表示" +"Show Subscription info" "購読情報を表示" +"Show Downloads info" "ダウンロード情報を表示" + +"Enclosure: " "Enclosure: " + +"Lookup (Dictionary)" "Dictionary で検索" +"Lookup (Google)" "Google で検索" +"Lookup (Acronym Finder)" "Acronym Finder で検索" +"Copy" "コピー" +"Select All" "すべて選択" +"Copy URL" "URL をコピー" +"Open URL" "URL を開く" +"Subscription" "購読" + + +### PREFERENCES ----------------------------------- + +"Preferences" "BePodder の設定" + +"Proxy" "プロキシ" +"Enable Proxy" "プロキシを有効" +"Address" "アドレス" +"Port" "ポート" +"Username" "ユーザ名" +"Password" "パスワード" + +"Max Downloads" "ダウンロード最大数" + +"FileType" "ファイルタイプ" +"Browser" "ブラウザ" +"Player" "プレイヤー" + +"Channels" "チャンネル" +"Check all channels on startup" "起動時に全チャンネルをチェック" +"Check the channel every" "チャンネルのチェック" + +"never" "しない" +"5 minutes" "5 分毎" +"15 minutes" "15 分毎" +"30 minutes" "30 分毎" +"1 hour" "1 時間毎" +"2 hour" "2 時間毎" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 個の新着項目" +"%d new items" "%d 個の新着項目" +"new" "新着" +"error" "エラー" +"not down" "未ダウンロード" +"enquequed" "待機中" +"downloading" "ダウンロード中" +"downloaded" "ダウンロード済" +"connecting" "接続中" +"not found" "見付かりません" +"stopped" "停止中" +"can't connect" "接続できません" +"invalid format" "無効なフォーマット" + +"Icon" "Icon" +"Title" "タイトル" +"Date" "日付" +"Size" "サイズ" +"Status" "状態" +"Download" "ダウンロード" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "チャンネルを追加" +"Remove Channel" "チャンネルを削除" +"Check Channel" "チャンネルをチェック" +"Open Homepage" "ホームページを開く" + +"Open Web Page" "ホームページを開く" +"Open Enclosures folder" "Enclosures フォルダを開く" +"Check All Channels" "全チャンネルをチェック" + +"Show Channel Image" "チャンネルの画像を表示" + +"Play enclosure" "Enclosure を再生" +"(Re)start download" "ダウンロードを(再)開始" +"Stop download" "ダウンロードを停止" +"Remove Item" "項目を削除" + + + + +### ALERT ----------------------------------- + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" + + +"Can't open the selected file with:\n\n" "Can't open the selected file with:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nPlease check if the application is installed in the right way.\n" +"Download it!" "Download it!" + +"\nRemoving.." "\n削除中.." +"\nAn error occured while removing!" "\n削除中にエラーが発生しました。" +"Check all the podcasts for new items" "全ポッドキャストの新着項目をチェック" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +選択した項目を削除します。 + +本当によろしいですか? +(Enclosure ファイルも一緒に削除されます)" + + +_key="alert2a" + _value=" +次のチャンネルを削除しようとしています: + +" + +_key="alert2b" + _value=" + +今までダウンロードしたこのチャンネルの enclosure ファイルをアーカイブに保存しますか? +それとも完全に削除しますか?" + +_key="alert3" + _value=" +アーカイブを解析中.." + +_key="alert_3gp" + _value=" +3GP is a multimedia container format defined by the Third Generation Partnership Project (3GPP) for use on 3G mobile phones. It stores video streams as MPEG-4 or H.263, and audio streams as AMR-NB or AAC-LC. + +VideoLAN still doesn't support the audio AMR (3GPP)" + +_key="alert_swf" + _value=" +SWF is a proprietary vector graphics file format produced by the Flash software from Adobe (formerly Macromedia). + +Currently Flash support in BeOS/Haiku/Zeta is limited to the old standalone Flash player version 4.1015, there isn't a modern Flash player" + + + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "紹介" +"The User Interface" "ユーザ インタフェース" +"Menu Bar" "メニューバー" +"Toolbar Buttons" "ツールバー ボタン" +"First time with BePodder" "はじめて BePodder をご使用の方へ" +"Download Podcast's enclosure files" "ポッドキャスト enclosure ファイルのダウンロード" +"Settings Overview" "設定の概要" +"Directory lists" "ディレクトリ リスト" +"Loading Help..." "ヘルプの読込中..." +"Register your copy" "登録について" +"Starting point" "はじめに" + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value="BePodder 基本ガイドへようこそ!" + +_key="help1-1" + _value="あなたが既にポッドキャストおよびRSS/Atomフィード +について詳しいならば、このウィンドウを閉じて直ち +にBePodderを使い始めることができます。" + +_key="help1-2" +_value="このガイドはBePodderを開始するにあたり、あなたが必要とする +知識をすべて提供できるわけではありませんが、本ガイドを使用 +する場合には下のボタンをクリックしてください。" + + + +_key="help2-0" + _value=" ポッドキャスティングとはインターネットを通してオーディオおよび +ビデオ放送を発信する手段です。BePodderでは、無償のオーディオ +およびビデオファイルへのRSSまたはAtomフィードへのリンクを同封 +しています。" + +_key="help2-1" +_value="要するに、ポッドキャスティングとは単に一種のオンラインメディア +の配達手段です。ユーザがフィード (RSS 'Really Simple Syndication' +やAtomなど)を使用し、ポッドキャストを購読することができます。" + +_key="help2-2" +_value="BePodderはアグリゲータ(または、ポッドキャッチャー)に +好まれるでしょう。あなたが新しいコンテンツのRSSフィ +ードを購読して、定期的にチェックし、ダウンロードする +ための1つのソフトウェアです。あなたはBePodderと共に +購読したチャンネルに新しいポッドキャストの項目(エピ +ソード)をチェックすることができます。 +丁度、電子メールが添付ファイルを扱えるように、どんな +項目の enclosure を同梱することができます。" + + + +_key="help3-0" +_value="BePodderは簡単に使用でき、かつパワフルなグラフィカルユーザ +インタフェースを備えています。 +メインウィンドウは3つのパネルに分割されています。" + +_key="help3-1" +_value="1) 購読リスト(スクリーンショットの1番のパネル)はあなたが購読 +登録したポッドキャストのリストです。 +パネル2はチャンネルのリストです。 +クリックするとチャンネルを見ることができます。" + +_key="help3-2" +_value="2) エピソードリストは全項目が利用できる状態です。" + +_key="help3-3" +_value="3) 情報パネルの表示:エピソード情報、チャンネル情報、ダウンロード +情報は3つの内1つをクリックすることにより、情報パネルを選択す +ることができます。" + + + +_key="help4-0" +_value="BePodderのメインウィンドウ最上部にあるメニューバーでは以下の +7つのメニューを利用することができます: +[ファイル][設定][購読][エピソード][リスト][表示][ヘルプ] +一部のメニューコマンドには右側に矢印があり、関連するコマンドが +サブメニューにあります。各メニューを探る場合には、サブメニュー +にも必ず目を通してください。メニューをクリックして、コマンドを +確認してください:" + +_key="help4-1" +_value="[ファイル]:BePodderについての情報の表示およびアプリケーションを +閉じるコマンドを含んでいます。" + +_key="help4-2" +_value="[設定]:BePodderの様々な設定をカスタマイズする環境設定ウィンドウ +を開くコマンドを含んでいます。" + +_key="help4-3" +_value="[購読]:購読リストの選択されたチャンネルへの動作を実行するコマン +ドを含んでいます。" + +_key="help4-4" +_value="[エピソード]:チャンネルのエピソードリストの選択された項目(エピソ +ード)への動作を実行するコマンドを含んでいます。" + +_key="help4-5" +_value="[リスト]:BePodderのOPMLディレクトリを開くコマンドを含んでいま +す。" + +_key="help4-6" +_value="[表示]:BePodderのウィンドウ制御のコマンドを含んでいます。" + +_key="help4-7" +_value="[ヘルプ]:'基本ガイド''キーボードショートカットリスト'を開くコマンド +を含んでいます。" + +_key="help5-0" + _value="追加ボタン: 追加ウィンドウを開きます。 +追加するフィードのURLを入力します。 +(例: http://www.newpodcast.com/rss.xml) +通常、ポッドキャストのホームページ上で'XML'、'RSS'、 +'Podcast Feed'のテキストもしくはグラフィックのリンク +を得ることができます。" + +_key="help5-1" + _value="削除ボタン: チャンネルを除去するためにウィンドウを開 +き、どのようにするかを選択することができます。 +選んだチャンネルをアーカイブするか(今までダウンロー +ドした全てのファイルと eclosure を保持します)、また +はコンピュータからチャンネル全体を削除します。" + +_key="help5-2" + _value="チェックボタン: 選択されたチャンネルをチェックし、利 +用可能なリストの項目を更新し、ポッドキャストの新着 +項目を追加します。" + +_key="help5-3" + _value="ウェブボタン: ブラウザでチャンネルホームページを表示 +します。 +あなたのお気に入りのブラウザを開くにはBePodderの +環境設定で設定します。 +メニューバーの'設定'→'BePodder の設定'をクリックし、 +環境設定ウィンドウの'ファイルタイプ'でお気に入りの +ブラウザを選択してください。" + +_key="help5-4" + _value="再生ボタン: このボタンで、選択された項目(エピソード) +のenclosureファイルを視聴することができます。 +あなたのお気に入りのプレーヤーを開くにはBePodder +の環境設定で設定します。 +メニューバーの'設定'→'BePodder の設定'をクリックし、 +環境設定ウィンドウの'ファイルタイプ'でお気に入りの +プレーヤーを選択してください。" + +_key="help5-5" + _value="ダウンロードボタン: 選択項目(エピソード)のenclosure +ファイルのダウンロードを行います。情報パネルの上の +3番目のボタンをクリックすることにより、ダウンロー +ド情報を見ることができます。" + +_key="help5-6" + _value="停止ボタン: 選択項目(エピソード)のenclosureファイル +ダウンロードを停止します。ダウンロードを再開するた +めに、項目(エピソード)をダブルクリックするか、項目 +を選択してから、ダウンロードボタンをクリックしてく +ださい。" + +_key="help5-7" + _value="削除ボタン: 選択項目を削除します。 + (enclosureファイルを解放します)" + + + +_key="help6-0" + _value="BePodderの導入はとても簡単です。" + +_key="help6-1" + _value="次のようにすれば、あなたが購読した +フィードを参照することができます。 +私達はあなたのために、予めいくつか +のフィードを購読しており、あなたは +二通りの方法で追加することができま +す。" + +_key="help6-2" + _value="1) 「追加アイコン」ボタンをクリックすると、フィードのURL入力に +なります。 (入力例: http://www.newpodcast.com/rss.xml) +「追加」ボタンをクリックして購読します。" + +_key="help6-3" + _value="2) メニューバーにある「ディレクトリ」から「ポッドキャスト リスト +」または 「ビデオブログ リスト」を選択し、ポッドキャストを選んで +「購読」をクリックします。" + +_key="help6-4" + _value="購読リストでポッドキャストを選択して、チェックボタン使用してく +ださい。BePodder は正確に 'エピソードリスト' に新しい項目を追加 +します。右クリックして、コンテキストメニューから'全チャンネルを +チェック'を選択することにより、すべてのポッドキャストをチェック +することができます。" + +_key="help6-5" + _value="上のスクリーンショットを見てください。'エピソードリスト'の第1 +カラムには黒いドットによって示された3つの新着項目があります。" + +_key="help6-6" + _value="第2カラムには、項目の状態を示すアイコンがあります:" + +_key="help6-7" + _value="- Episode 4 のアイコンは、エラーを示します。" + +_key="help6-8" + _value="- Episode 3 のアイコンは、項目のenclosureファイルをダウンロード +要求中であることを示します。" + +_key="help6-9" + _value="- Episode 2 のアイコンは、項目のenclosureファイルをダウンロード +中であることを示します。" + +_key="help6-10" + _value="- Episode 1 のアイコンは、項目のenclosureファイルをダウンロード +したこと示します。" + + + +_key="help7-0" + _value=" 'エピソードリスト'で項目を選択して、項目をダブルクリックするか、 +またはダウンロードボタンをクリックしてください。ダウンロードは +停止ボタンをクリックすることでいつでも停止することができます。" + +_key="help7-1" + _value="予約購読で利用できるすべての項目を'エピソードリスト'で見るために +は、ソフトウェアの'購読リスト'で予約購読されたポッドキャストをク +リックしてください。項目を選択し、再生(再生ボタン)をクリックして +、ファイルを視聴してください。" + +_key="help7-2" + _value="情報パネルでフォルダアイコンをクリックするか、またはマウスを右 +クリックすることにより、コンテキストメニューから'Enclosures フォ +ルダを開く'を選択することで、Enclosuresフォルダにアクセスするこ +とができます。" + + + +_key="help8-0" + _value="メニューバーの'設定'→'BePodderの設定'をクリックすることで、環境 +設定へアクセスすることができます。環境設定ダイアログの左側のリ +スト'ファイルタイプ'、'チャンネル'、'ダウンロード'、'プロキシ'からカ +テゴリを選択してください。" + +_key="help8-1" + _value="- ファイルタイプ: デフォルトのブラウザとプレーヤーを指定します。 " + +_key="help8-2" + _value="- チャンネル: チャンネルの新着項目のチェックについての制御の設定 +です。アプリケーションの起動と同時に全チャンネルのチェックを行 +うかチャンネルのチェック間隔を指定します。" + +_key="help8-3" + _value="- ダウンロード: 同時にダウンロードすることができる、最大ファイル +数を指定します。" + +_key="help8-4" + _value="- プロキシ: BePodderで使用するプロキシサーバの設定を行います。 +プロキシサーバはあなたのローカルエリアネットワークとインターネ +ット間のセキュリティバリアとして機能します。インターネットから +あなたのローカルエリアネットワークへの不正アクセスを防止します。" + + + +_key="help9-0" + _value="BePodder has built-in podcast, videoblog, imagefeeds, newsfeeds, bittorrentfeeds and internationalfeeds OPML directories with thousands of feeds grouped by category." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) はアプリケーション間 +のアウトラインで構造化された情報の交換を許容するXMLベースの形 +式です。" + +_key="help9-2" + _value="OPML directory can be accessed by clicking in the menu-bar 'Lists' and thenselecting a list. To browse the opml directory for a feed, expand the list by clicking the arrow of the category that you are interested in (see image); using this method, you can expand the opml directory until you find the desired feed. Once you have selected it, you can add it to the subscription list by clicking the button 'Subscribe', you can also collapse all categories in the directory list by clicking the button 'Collapse All'." + + +_key="help_shortcut1" +_value="このページはBePodderで使用することができるキーボードショート +カットについて説明します。" + +_key="help_shortcut2" +_value="Alt/Ctrl キーはどちらでも使えます。 +(例:Alt+QまたはCtrl+Qでアプリケーションを終了) +どちらを使用するかはDeskbar-環境設定(Preferences) +→キーボード(Keyboard)で設定できます。 +(デフォルトはAlt)" + +_key="help_shortcut3" + _value="一般的なショートカット" + +_key="help_shortcut4" + _value="アプリケーションを終了" + +_key="help_shortcut5" + _value="「BePodder の設定」を開く" + +_key="help_shortcut6" + _value="ポッドキャスト ディレクトリ リスト +を開く" + +_key="help_shortcut7" + _value="ビデオブログ ディレクトリ リスト +を開く" + +_key="help_shortcut8" + _value="イメージフィード ディレクトリ リスト +を開く" + +_key="help_shortcut9" + _value="ニュースフィード ディレクトリ リスト +を開く" + + +_key="help_shortcut9b" + _value="Shows the BitTorrentfeeds directory list" + +_key="help_shortcut9c" + _value="Shows the Internationalfeeds directory list" + +_key="help_shortcut10" + _value="全画面表示" + +_key="help_shortcut11" + _value="ツールバーの表示/非表示" + +_key="help_shortcut12" + _value="「ご使用の前に」を表示" + +_key="help_shortcut13" + _value="「キーボード ショートカット」を表示" + +_key="help_shortcut14" + _value="チャンネルのショートカット" + +_key="help_shortcut15" + _value="ポッドキャストを購読リスト +に追加" + +_key="help_shortcut16" + _value="ポッドキャストを購読リスト +から削除" + +_key="help_shortcut17" + _value="選択中のポッドキャストの新着項目 +をチェック" + +_key="help_shortcut18" + _value="全ポッドキャストの新着項目 +をチェック" + +_key="help_shortcut19" + _value="ポッドキャストのホームページ +を開く" + +_key="help_shortcut20" + _value="Enclosures フォルダを開く" + +_key="help_shortcut21" + _value="エピソードのショートカット" + +_key="help_shortcut22" + _value="Enclosure を再生" + +_key="help_shortcut23" + _value="選択したエピソードのダウンロード +を(再)開始" + +_key="help_shortcut24" + _value="エピソードのダウンロードを停止" + +_key="help_shortcut25" + _value="選択したエピソードの削除" + +_key="help_shortcut26" + _value="ポッドキャストのホームページを開く" + +_key="help_shortcut27" + _value="Enclosures フォルダを開く" + +_key="help_buy1" + _value="BePodder Light is the basic version (free download and no time limited), the registered version adds some more nice features: unlimited number of channels, small Channel view, proxy support, automatic channels check, up to 5 enclosure downloads at the same time (multithreading)." + +_key="help_buy2" + _value="BePodderのライセンスはKagiからオンライン購入することができ +ます。シェアウェア料をお支払いください。 +15ユーロになります(いくつかの国はKagiに税を課金します)。" + +_key="help_buy3" + _value="購入先: www.funkyideasoft.com" + +_key="help_buy4" + _value="購入後、keyfileとそのインストール方法を記した電子メールがあな +たに送られます。添付ファイルを解凍して、あるディレクトリに +ファイルを移動するだけです。" + +_key="help_buy5" + _value="BePodderの新バージョンが出てもアップデートに支障はありませ +ん。別な方法で通知された場合を除き、keyfileはダウンロードでき +るパッケージを全て解除します。" + + +### + +"Opml Editor" "OPML エディタ" +"name:" "名前:" +"Add a categorie" "カテゴリの追加" +"Add a new Broadcast" "新しく放送を追加" +"feed:" "フィード:" +"url:" "URL:" +"Test podcast" "ポッドキャストのテスト" +"Del a categorie" "カテゴリの削除" +"Add a categorie" "カテゴリの追加" +"Select the podcast categorie:" "ポッドキャスト カテゴリの選択:" +"Check all" "すべてチェック" +"Check" "チェック" +"Refresh the list" "リストの更新" +"Load" "読込" +"Load the list" "リストを読込" +"Save" "保存" +"Save the list" "リストを保存" +"Revert" "元に戻す" +"Apply" "適用" + + + + +### LANGUAGE ----------------------------------- + +"Afrikaans" "アフリカーンス語" +"Albanian" "アルバニア語" +"Arabic" "アラビア語" +"Armenian" "アルメニア語" +"Belarusian" "ベラルーシ語" +"Bosnian" "ボスニア語" +"Breton" "ブルターニュ語" +"Bulgarian" "ブルガリア語" +"Catalan" "カタロニア語" +"Chechen" "チェチェン語" +"Chinese" "中国語" +"Czech" "チェコ語" +"Danish" "デンマーク語" +"Dutch" "オランダ語" +"English" "英語" +"Esperanto" "エス語" +"Estonian" "エストニア語" +"Finnish" "フィンランド語" +"French" "フランス語" +"Georgian" "グルジア語" +"German" "ドイツ語" +"Gaelic (Scots)" "ゲール語 (スコットランド)" +"Irish" "アイルランド語" +"Greek, Modern ()" "Greek, Modern ()" +"Hebrew" "ヘブライ語" +"Hungarian" "ハンガリー語" +"Icelandic" "アイスランド語" +"Indonesian" "インドネシア語" +"Italian" "イタリア語" +"Japanese" "日本語" +"Korean" "朝鮮語" +"Lithuanian" "リトアニア語" +"Moldavian" "モラビア語" +"Mongolian" "モンゴル語" +"Norwegian" "ノルウェー語" +"Norwegian Nynorsk" "Norwegian Nynorsk" +"Norwegian Bokmål" "Norwegian Bokmål" +"Polish" "ポーランド語" +"Portuguese" "ポルトガル語" +"Romanian" "ルーマニア語" +"Russian" "ロシア語" +"Serbian" "セルビア語" +"Croatian" "クロアチア語" +"Sinhalese" "シンハラ語" +"Slovak" "スロバキア語" +"Slovenian" "スロべニア語" +"Spanish" "スペイン語" +"Swedish" "スウェーデン語" +"Ukrainian" "ウクライナ語" + +"Downloads" "ダウンロード" +"BePodder Keyboard Shortcuts" "BePodder のキーボードショートカット" +"General" "全般" +"Archive" "アーカイブ保存" +"Toolbar Overview" "ツールバーの概要" +"Please feedback :)" "フィードバック送信" +"Unexpected error in window \"BePodder\".Should an attempt be made to continue running?" "BePodder のウィンドウで予期せぬエラーが発生しました。再試行してみますか?" +"Continue" "続行" +"Developers:" "開発者:" +"Graphic:" "グラフィック:" +"Version :" "バージョン :" +"Licensed to :" "登録者 :" +"License code:" "登録コード:" +"Only this person is allowed to use this copy of the software." "このソウトウェアは個人利用のみに使用することができます。" +"Getting Started With BePodder" "BePodder をご使用の前に" +"What are Podcasts?" "ポッドキャストとはなにか?" +"Find this Item" "この項目を検索" +"Remove from this list" "このリストから削除" + diff --git a/release/Language/Dictionaries/BePodder.nlBE b/release/Language/Dictionaries/BePodder.nlBE new file mode 100644 index 0000000..1031253 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.nlBE @@ -0,0 +1,1192 @@ + + +# Locale file for BePodder. + +# Modified: 4/18/2006 + +# Author: Begasus + +# E-mail: Begasus@skynet.be + + + + + +# Attention: don't remove empty space or \n + + + + + +### SHAREWARE POPUPS ----------------------------------- + + + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Shareware toepassing!\n\nSteun ons aub!\n\nKoop een licentie!\nMeer info op onze website\n" + + + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "Deze versie van BePodder is verlopen!\nGelieve een keyfile te kopen en ons te ondersteunen.\n" + + + +"Web Site" "Website" + +"Can't connect!" "Geen verbinding!" + +"Http port failed!" "Http poort mislukt!" + +"Can't resolve host!" "Kan host niet vinden!" + +"Not found!" "Niet gevonden!" + +"Bad resume!" "Slecht herstart!" + +"Aborted by Callback!" "Afgebroken door callback!" + +"Can't resume! (range error)" "Kan niet herstarten! (range fout)" + +"Access Denied!" "Toegang verboden!" + +"User or Password Incorrect!" "Gebruiker of paswoord foutief!" + +"Other error (cUrl code: " "Andere fout (cUrl code: " + +"cUrl init error!" "cUrl init fout!" + +"Can't open file!" "Kan bestand niet openen!" + +"Other error (status code: " "Andere fout (status code: " + +"Downloading" "Downloaden" + + + +### MENUBAR ----------------------------------- + + + +"File" "Bestand" + +"About..." "Over..." + +"Close!" "Sluiten!" + +"Quit" "Quit" + + + +"Settings" "Instellingen" + +"Preferences..." "Voorkeuren..." + + + +"Subscriptions" "Abonnementen" + + + +"Episodes" "Afleveringen" + + + +"Lists" "Lijsten" + +"Podcast List" "Podcast Lijst" + +"Podcast directory list" "Podcast maplijst" + +"Videoblog List" "Videoblog Lijst" + +"Videoblog directory list" "Videoblog maplijst" + +"Imagefeeds List" "Imagefeeds List" + +"Imagefeeds directory list" "Imagefeeds maplijst" + +"Newsfeeds List" "Newsfeeds lijst" + +"Newsfeeds directory list" "Newsfeeds maplijst" + +"BitTorrentfeeds List" "BitTorrentfeeds lijst" + +"BitTorrentfeeds directory list" "BitTorrentfeeds maplijst" + +"Internationalfeeds List" "Internationalfeeds lijst" + +"Internationalfeeds directory list" "Internationalfeeds maplijst" + + + +"View" "Venster" + +"Full Screen" "Schermvullend" + +"Toolbar" "Werkbalk" + +"Subscriptions View" "Abonnementen venster" + +"Small Items" "Kleine objecten" + +"Big Items" "Grote objecten" + +"Move BePodder on workspace:" "Verplaats BePodder naar bureaublad:" + + + +"Help" "Help" + +"Getting Started" "Handleiding" + +"Keyboard Shortcuts" "Toetscombinaties" + +"Online Support" "Online ondersteuning" + + + + + + + + + + + +### BUTTONS ----------------------------------- + + + +# Buttons add feed window + +"Insert the rss feed url!" "RSS feed url ingeven!" + +"Add" "Toevoegen" + +"Paste" "Plakken" + + + +# Buttons directory list window + +"Collapse All" "Alles inklappen" + +"Preview" "Voorbeeld" + +"Subscribe" "Abonneren" + + + + + +# Buttons help window + +"Next" "Verder" + +"Prev" "Terug" + +"Close" "Sluiten" + +"Index" "Index" + + + + + +# Buttons remove windows + +"Cancel" "Annuleren" + +"Delete" "Verwijder" + +"Archive" "Archive" + + + + + + + +### TOOLTIPS ----------------------------------- + + + +# Tooltips toolbar buttons + + + +"Add the podcast to the Subscriptions list" "Podcast toevoegen aan de abonementen" + +"Delete the podcast from the Subscriptions list" "Podcast verwijderen van de abonnementen" + +"Check the selected podcast for new items" "Podcast controleren op nieuwe objecten" + +"Show the podcast homepage" "Podcast homepage tonen" + + + +"Delete the item and the enclosure" "Delete the item and the enclosure" + +"Stop the item download" "Stop download van onderwerp" + +"Download the selected episode" "Download de geselecteerde aflevering" + +"Play the selected episode" "Geselecteerde aflevering afspelen" + + + +"Submit bug and idea" "Bug's en ideëen aanbrengen" + + + + + +# Tooltips directory window buttons + + + +"Collapse all categories in the directory list" "Alle categoriëen in de maplijst inklappen" + +"Add the selected podcast to the Subscription list" "Voeg de geselecteerde podcast toe aan de geaboneerde lijst" + +"Checkout a podcast before downloading it" "Controleer een podcast vooraleer toe te voegen" + + + +### INFO PANEL ----------------------------------- + + + +"Show channel Image" "Toon kanaal afbeelding" + +"XML Feed Link" "XML Feed Link" + + + +"Show Episode info" "Toon onderwerpsinfo" + +"Show Subscription info" "Toon abonnementsinfo" + +"Show Downloads info" "Toon downloadsinfo" + + + +"Enclosure: " "Bijlage: " + + + +"Lookup (Dictionary)" "Opzoeken (Dictionary)" + +"Lookup (Google)" "Opzoeken (Google)" + +"Lookup (Acronym Finder)" "Lookup (Acronym Finder)" + +"Copy" "Kopiëer" + +"Select All" "Selecteer alles" + +"Copy URL" "Copy URL" + +"Open URL" "Open URL" + +"Subscription" "Abonement" + + + + + +### PREFERENCES ----------------------------------- + + + +"Preferences" "Voorkeuren" + + + +"Proxy" "Proxy" + +"Enable Proxy" "Proxy inschakelen" + +"Address" "Address" + +"Port" "Poort" + +"Username" "Gebruikersnaam" + +"Password" "Paswoord" + + + +"Max Downloads" "Max Downloads" + + + +"FileType" "Bestandstype" + +"Browser" "Browser" + +"Player" "Speler" + + + +"Channels" "Kanalen" + +"Check all channels on startup" "Controleer alle kanalen bij het starten" + +"Check the channel every" "Controleer alle kanalen elke" + + + +"never" "nooit" + +"5 minutes" "5 minuten" + +"15 minutes" "15 minuten" + +"30 minutes" "30 minuten" + +"1 hour" "1 uur" + +"2 hour" "2 uur" + + + + + + + + + +### COLUMLISTVIEW ----------------------------------- + + + + + +"1 new item" "1 nieuw onderwerp" + +"%d new items" "%d nieuwe onderwerpen" + +"new" "nieuw" + +"error" "fout" + +"not down" "niet binnen" + +"enquequed" "wachtrij" + +"downloading" "downloaden" + +"downloaded" "gedownload" + +"connecting" "verbinden" + +"not found" "niet gevonden" + +"stopped" "gestopt" + +"can't connect" "geen verbinding" + +"invalid format" "ongeldig formaat" + + +"Icon" "Icon" + +"Title" "Titel" + +"Date" "Datum" + +"Size" "Grootte" + +"Status" "Status" + +"Download" "Download" + + + + + + + +### CONTEXT MENU ----------------------------------- + + + +"Add Channel" "Kanaal toevoegen" + +"Remove Channel" "Kanaal verwijderen" + +"Check Channel" "Kanaal controleren" + +"Open Homepage" "Open Homepage" + + + +"Open Web Page" "Open Web Page" + +"Open Enclosures folder" "Open bijlage map" + +"Check All Channels" "Controlleer alle kanalen" + + + +"Show Channel Image" "Toon kanaal afbeelding" + + + +"Play enclosure" "Bijlage afspelen" + +"(Re)start download" "(her)start download" + +"Stop download" "Stop download" + +"Remove Item" "Verwijder object" + + +"Find this Item" "Zoek dit object" + +"Remove from this list" "Verwijder uit de lijst" + + + + + + + + + +### ALERT ----------------------------------- + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "Je kan enkel tot 10 kanalen toevoegen in deze niet geregistreerde versie.\n Registreer je kopie\n" + + +"Can't open the selected file with:\n\n" "Kan het geselecteerd bestand niet openen met:\n\n" + +"\n\nPlease check if the application is installed in the right way.\n" "\n\nControlleer of de toepassing goed geïnstalleerd is.\n" + +"Download it!" "Download het!" + + + +"\nRemoving.." "\nVerwijren.." + +"\nAn error occured while removing!" "\nFout tijdens het verwijderen!" + +"Check all the podcasts for new items" "Controlleer alle podcasts voor nieuwe onderwerpen" + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + + +_key="alert1" + + _value=" + +Je gaat het geselecteerde onderwerp verwijderen. + + + +Ben je zeker? + +(alle bijlage in de map worden mee verwijderd)" + + + + + +_key="alert2a" + + _value=" + +Je verwijderd het kanaal: + + + +" + + + +_key="alert2b" + + _value=" + + + +Wil je dit kanaal liever archieveren + +(behoud van alle bijlagen en bestanden + +die al gedownload zijn) of wil je het + +volledig kanaal verwijderen van je pc?" + + + +_key="alert3" + + _value=" + +Archief ontleden.." + + +_key="alert_3gp" + _value=" +3GP is een multimedia container formaat gedefiniëerd door Third Generation Partnership Project (3GPP) voor het gebruik op 3G mobiele telefoons. Het slaat video streams op als MPEG-4 of H.263, en audio streams als AMR-NB of AAC-LC. + +VideoLAN ondersteund audio AMR (3GPP) nog niet" + +_key="alert_swf" + _value=" +SWF is een gebonden vector grafisch bestandsformaat geproduceerd door Flash software van Adobe (voormalig Macromedia). + +Huidige ondersteuning in BeOS/Haiku/ZETA is gelimiteerd tot de losstaande Flash speler versie 4.1015, er is tot op heden geen moderne Flash speler" + + + + +### HELP & SHORTCUTS ----------------------------------- + + + + + +"Introduction" "Introductie" + +"The User Interface" "Gebruikersinterface" + +"Menu Bar" "Menubalk" + +"Toolbar Buttons" "Werkbalk" + +"First time with BePodder" "Eerste gebruik van BePodder" + +"Download Podcast's enclosure files" "Download Podcast's bijlagen" + +"Settings Overview" "Instellingen overzicht" + +"Directory lists" "Directory lijsts" + +"Loading Help..." "Help laden..." + +"Register your copy" "Registeer je kopie" + +"Starting point" "Startpunt" + + + + + + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + + + + +_key="help1-0" + + _value="Welkom bij de BePodder startersgids." + + + +_key="help1-1" + + _value="Als je al bekend bent met podcast en RSS feeds kan je dadelijk naar BePodder gaan door dit venster te sluiten." + + + +_key="help1-2" + +_value="Indien niet, volgt hier een introductie dat je zal verder helpen met alles wat je moet weten om te kunnen starten met BePodder. + +Gebruik de knoppen hieronder om door de handleiding te wandelen." + + + + + +_key="help2-0" + + _value="Podcasting is een methode voor het publiceren van audio en video broadcasts + +via het Internet; links naar gratis audio en video bestanden zijn ingebonden in de + +RSS en Atom feeds." + + + +_key="help2-1" + +_value="Daardoor is Podcasting een type van online media verdeling; gebruikers kunnen + +abonneren op een podcast door een feed te gebruiken + +(zoals RSS 'Really Simple Syndication' of Atom)." + + + +_key="help2-2" + +_value="Een aggregator (of podcatcher) zoals BePodder, is een toepassing die je in staat stelt om op een RSS feed te abonneren en periodiek te controleren op en downloaden van nieuwe onderwerpen. Met BePodder kan je controleren op nieuwe Podcast onderwerpen (episodes) van je geabonneerd kanaal. Eender welk onderwerp kan een bijlage bevatten, net zoals + +email bijlages dan bevatten." + + + + + +_key="help3-0" + +_value="BePodder heeft een makkelijk doch krachtige gebruikersinterface. Het hoofdvenster is opgesplitst in drie panelen:" + + + +_key="help3-1" + +_value="1) Het abonementen venster (het paneel met nummer 1 in de schermafbeelding) met de lijst van podcasts waar je een abbonement op hebt. Als je klikt op een kanaal dan zie je in paneel 2 de ljist van de voorwerpen van het kanaal." + + + +_key="help3-2" + +_value="2) De lijst met voorwerpen die beschikbaar zijn." + + + +_key="help3-3" + +_value="3) Het info paneel toont: info over het object, kanaal info of download info; je kan een info paneel kiezen door het klikken van de drie knoppen vanonder." + + + + + + + +_key="help4-0" + +_value="Heel vanboven in het BePodder hoofdvenster vind je de menubalk met zeven beschikbare menu's: Bestand, Instellingen, Abonementen, Afleveringen, Lijst, Venster en Help. Sommige menu's commando's worden gevolgd door pijlen wat betekend dat er een submenu van gerelateerde commando's is. Als je hierdoor bladerd, kijk dan ook zeker eens in de submenu's. Klik op een menu om het commando te zien:" + + + +_key="help4-1" + +_value="Bestsand: bevat commando's zoals het sluiten van de toepassing of toont het info venster van BePodder" + + + +_key="help4-2" + +_value="Instellingen: bevat commando's voor het openen van het instellingen venster dat je toestaat verschillende instellingen van BePodder aan te passen." + + + +_key="help4-3" + +_value="Abonementen: bevat commando's die bepaalde akties uitvoeren op het geselecteerd kanaal in je abonementenlijst." + + + +_key="help4-4" + +_value="Afleveringen: bevat commando's die bepaalde akties uitvoeren op de geselecteerde objecten in de kanaallijst." + + + +_key="help4-5" + +_value="Lijsten: bevat commando's voor het openen van BePodder's OPML mappen." + + + +_key="help4-6" + +_value="Venster: bevat commando's en controle's voor het BePodder venster." + + + +_key="help4-7" + +_value="Help: bevat commando's zoals het openen van BePodder's 'Handleiding' en de 'Toetscombinaties'." + + + + + + + +_key="help5-0" + + _value="Knop 'Toevoegen': opent het 'toevoegen' venster om een feed url (bv. 'http://www.newpodcast.com/rss.xml' welke je kan vinden op de podcast homepage) toe te voegen; dit kan via een tekst of grafische link zijn zoals 'XML', 'RSS' of 'Podcast Feed' erop." + + + +_key="help5-1" + + _value="Knop 'Verwijder': opent een venster waarin je kan selecteren hoe je het kanaal wil verwijderen: enkel het archief van het kanaal (behouden van downloads) of verwijderen van het hele kanaal van je pc." + + + +_key="help5-2" + + _value="Knop 'Controleer': controleerd het geselecteerde kanaal en werkt de lijst van beschikbare objecten bij in lijst." + + + +_key="help5-3" + + _value="Knop 'Homepage': toont de homepage van het kanaal in je browser. Om je favoriete browser te selecteren open je BePodder's instellingen, via het menu 'Instellingen' > 'Voorkeuren...' en in het instellingsvenster onder 'Bestandstype' selecteer je je favoriete browser." + + + +_key="help5-4" + + _value="Knop 'Afspelen': met deze knop kan je de bijlagen of downloads bekijken of beluisteren. Om je favoriete MediaPlayer te kiezen ga je in het menu naar 'Instellingen' > 'Voorkeuren...' en in het instellingsvenster under 'Bestandstype kies je je favoriete speler." + + + +_key="help5-5" + + _value="Knop 'Download': deze zal het geselecteerd object in de lijst downloaden; je kan info opvragen door het klikken op de derde knop boven het info paneel." + + + +_key="help5-6" + + _value="Knop 'Stop':stopt de download van het bestand of bijlage van het geselecteerd object(aflevering); om verder te gaan met de download dubbelklik op het object (aflevering) of selecteer het object en klik op de 'Download' knop." + + + +_key="help5-7" + + _value="Knop 'Verwijder object': verwijderd het geselecteerd object (hierdoor ook de bijlage)." + + + + + + + +_key="help6-0" + + _value="Beginnen met BePodder is gemakkelijk." + + + +_key="help6-1" + + _value="Aan de linkerkant vind je een lijst van je abonnementen. We hebben al enkele abonnementen toegevoegd voor je, en je kan er altijd toevoegen op twee manieren:" + + + +_key="help6-2" + + _value="1) Handmatig via 'Voeg een podcast toe aan de abonnementen' knop, plak dan de feed url (bv: http://www.newpodcast.com/rss.xml) en klik dan op Toevoegen." + + + +_key="help6-3" + + _value="2) in de menu lijst selecteer 'Map' en dan 'Podcast lijst' of 'Videoblog lijst', kies een podcast en klik op 'Abonneren'." + + + +_key="help6-4" + + _value="Als je een Podcast in de abonnee lijst selecteerd, en dan de 'Controleer' knop klikt zal BePodder de nieuwe onderwerpen in de 'Episode lijst' rechts toevoegen; je kan al je podcast door rechtsklikken controleren door 'Controlleer alle kanalen' in het context menu." + + + +_key="help6-5" + + _value="Bekijk de schermafbeelding hierboven, 3 nieuwe objecten zijn aangegeven door een zwarte dot in de eerste kollom van de lijst van afleveringen." + + + +_key="help6-6" + + _value="In de tweede kollom staan de icoontjes die de status van het object aangeven:" + + + +_key="help6-7" + + _value="- aflevering 4 heeft een icoon wat aangeeft dat er een fout is" + + + +_key="help6-8" + + _value="- aflevering 3 heeft een icoon wat aangeeft dat het object download is aangevraagd (wachtrij)" + + + +_key="help6-9" + + _value="- aflevering 2 heeft een icoon wat aangeeft dat BePodder het bestand aan het downloaden is." + + + +_key="help6-10" + + _value="- aflevering 1 heeft een icoon wat aangeeft dat BePodder het bestand gedownload heeft." + + + + + + + +_key="help7-0" + + _value="Selecteer een onderwerp in de 'Episode lijst' en dubbelklik op het onderwerp of klik op de Download knop; je kan de download stoppen door te klikken op stop." + + + +_key="help7-1" + + _value="Als je klikt op de een van de abonnementen zal de software je alle onderwerpen tonen die beschikbaar zijn voor dat abonnement in de 'Episode lijst'. + +Selecteer een onderwerp en klik op afspelen (Afspelen knop) om het bestand te + +beluisteren of bekijken." + + + +_key="help7-2" + + _value="Je kan de bijlage map bereiken door het klikken op het map icoon in het info veld, + +of door rechtsklikken op het bestand en kiezen voor 'Open bijlage map' + +in het context menu. + +Tot hier de handleiding, met deze info ben je in staat om zelf podcast toe te voegen + +die je vind via het net, en te werken met BePodder. + + + + Veel plezier!!! ;)" + + + + + +_key="help8-0" + + _value="Voorkeuren kan je berijken via de menubalk Instellingen > Voorkeuren. Je kan een categorie selecteren vanuit de lijst van de voorkeuren: Bestandstype, kanalen, Download en Proxy." + + + +_key="help8-1" + + _value="- Bestandstype: voor het vastleggen van je standaard browser en speler." + + + +_key="help8-2" + + _value="- Kanalen: voor het instellen van de controle over de manier waarop kanalen gecontroleerd worden; je kan kiezen om alle kanalen bij het starten van BePodder te kontroleren of om op ingestelde intervallen te gaan controleren." + + + +_key="help8-3" + + _value="- Download: om het maximum aantal gelijktijdige downloads in te stellen." + + + +_key="help8-4" + + _value="- Proxy: voor het instellen van een proxy met BePodder; een proxy dient als veiligheidsbrug tussen jouw netwerk en het internet, zodat anderen op het internet niet aan informatie van je eigen netwerk kunnen benaderen." + + + + + + + +_key="help9-0" + _value=" BePodder heeft een ingebouwde podcast, videoblog, imagefeeds, newsfeeds, bittorrentfeeds en internationalfeeds OPML directories met duizenden feeds gegroepeerd op categorie." + +_key="help9-1" + + _value="OPML (Outline Processor Markup Language) is een XML-gebaseerd formaat dat uitwisseling toestaat van outline-gestructureerde informatie tussen twee toepassingen." + + + +_key="help9-2" + _value="OPML directory kan toegankelijk worden door het klikken in de menu-bar 'Lijsten' en dan door selecteren van een lijst. Om door de mappen van opml te bladeren voor een feed, klap je de lijst uit door het klikken op de pijl van de categorie waarin je interesse hebt (zie afbeelding); door dit te doen kan je elke opml map uitklappen totdat je gevonden hebt wat je zoekt. Eenmaal je deze geselecteerd hebt kan je deze toevoegen door het klikken van 'Abonneren', je kan ook alle categorien uitklappen door het klikken op 'Alles uitklappen'." + + + +_key="help_shortcut1" + +_value="Deze sectie beschrijft de toetscombinaties die kunnen gebruikt worden in BePodder. De toetscombinaties zijn gegroepeerd per functie. " + + + +_key="help_shortcut2" + +_value="betekend dat je ofwel van Alt of Control gebruik kan maken (bv. Alt+Q of Ctrl+Q sluit de toepassing), zoals deze ingesteld zijn in de instellingen voor toetsenbord (de standaard knop is 'Alt')." + + + +_key="help_shortcut3" + + _value="Algemene combinaties" + + + +_key="help_shortcut4" + + _value="Toepassing afsluiten" + + + +_key="help_shortcut5" + + _value="Toon het instellingen venster" + + + +_key="help_shortcut6" + + _value="Toon de Podcast maplijst" + + + +_key="help_shortcut7" + + _value="Toon de Videoblog maplijst" + + + +_key="help_shortcut8" + + _value="Toon de Imagefeeds maplijst" + + + +_key="help_shortcut9" + + _value="Toon de Newsfeeds maplijst" + + + +_key="help_shortcut9b" + + _value="Toon de BitTorrentfeeds maplijst" + + +_key="help_shortcut9c" + + _value="Toon de Internationalfeeds maplijst" + + +_key="help_shortcut10" + + _value="Schermvullend" + + + +_key="help_shortcut11" + + _value="Toon/verberd de werkbalk" + + + +_key="help_shortcut12" + + _value="Toon de handleiding" + + + +_key="help_shortcut13" + + _value="Toon de toetscombinaties" + + + +_key="help_shortcut14" + + _value="Channels shortcuts" + + + +_key="help_shortcut15" + + _value="Podcast toevoegen aan de abonementen" + + + +_key="help_shortcut16" + + _value="Podcast verwijderen van de abonementen" + + + +_key="help_shortcut17" + + _value="Controleer de geselecteerde podcast op nieuwe onderwerp(en)" + + + +_key="help_shortcut18" + + _value="Controleer alle podcast op nieuwe onderwerp(en)" + + + +_key="help_shortcut19" + + _value="Podcast homepage tonen" + + + +_key="help_shortcut20" + + _value="Open map van bijlage" + + + +_key="help_shortcut21" + + _value="Episodes shortcuts" + + + +_key="help_shortcut22" + + _value="Bijlage afspelen" + + + +_key="help_shortcut23" + + _value="(Her)start download het geselecteerde onderwerp" + + + +_key="help_shortcut24" + + _value="Stop de bijlage/onderwerp download" + + + +_key="help_shortcut25" + + _value="Verwijder geselecteerde bijlage(onderwerp)" + + + +_key="help_shortcut26" + + _value="Toon de podcast bijlage(onderwerp) pagina" + + + +_key="help_shortcut27" + + _value="Open map van bijlage" + + + +_key="help_buy1" + _value=" BePodder Light is de basis versie (gratis download en geen tijdslimiet), de geregistreerde versie voegt enkele mooie features toe: ongelimiteerd aantal kanalen, smal kanaal venster, proxy support, automatische kanaalcheck, tot 5 gelijktijdige downloads (multithreading)." + +_key="help_buy2" + + _value="Gelieve deze shareware te registeren, het is enkel 15 Euro (Kagi voegt tax toe in sommige landen), BePodder licentie kan online gekocht worden van Kagi." + + + +_key="help_buy3" + + _value="Koop op www.funkyideasoft.com" + + + +_key="help_buy4" + + _value="Na aankoop krijg je een email met een keyfile (sleutelbestand) en instructies over hoe deze te installeren. Het is enkel een kwestie van deze uit te pakken en te verplaatsen naar een bepaalde map." + + + +_key="help_buy5" + + _value="Er is geen probleem voor het updaten van BePodder als er een nieuwe versie beschikbaar is. Het sleutelbestand zal alle gedownloade pakketen ontsleutelen tenzij anders werd aangegeven." + + + + + +### USELESS ######## + + + +"Opml Editor" "Opml bewerken" + +"name:" "naam:" + +"Add a categorie" "Categorie toevoegen" + +"Add a new Broadcast" "Een nieuwe broadcast toevoegen" + +"feed:" "feed:" + +"url:" "url:" + +"Test podcast" "Test podcast" + +"Del a categorie" "Verwijder een categorie" + +"Add a categorie" "Een categorie toevoegen" + +"Select the podcast categorie:" "Selecteer de podcast categorie:" + +"Check all" "Controleer alles" + +"Check" "Controleer" + +"Refresh the list" "Ververs lijst" + +"Load" "Laad" + +"Load the list" "Laad de lijst" + +"Save" "Opslaan" + +"Save the list" "Opslaan van list" + +"Revert" "Terug" + +"Apply" "Toepassen" + + + + + + + + + + + + + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.nlNL b/release/Language/Dictionaries/BePodder.nlNL new file mode 100644 index 0000000..1031253 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.nlNL @@ -0,0 +1,1192 @@ + + +# Locale file for BePodder. + +# Modified: 4/18/2006 + +# Author: Begasus + +# E-mail: Begasus@skynet.be + + + + + +# Attention: don't remove empty space or \n + + + + + +### SHAREWARE POPUPS ----------------------------------- + + + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Shareware toepassing!\n\nSteun ons aub!\n\nKoop een licentie!\nMeer info op onze website\n" + + + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "Deze versie van BePodder is verlopen!\nGelieve een keyfile te kopen en ons te ondersteunen.\n" + + + +"Web Site" "Website" + +"Can't connect!" "Geen verbinding!" + +"Http port failed!" "Http poort mislukt!" + +"Can't resolve host!" "Kan host niet vinden!" + +"Not found!" "Niet gevonden!" + +"Bad resume!" "Slecht herstart!" + +"Aborted by Callback!" "Afgebroken door callback!" + +"Can't resume! (range error)" "Kan niet herstarten! (range fout)" + +"Access Denied!" "Toegang verboden!" + +"User or Password Incorrect!" "Gebruiker of paswoord foutief!" + +"Other error (cUrl code: " "Andere fout (cUrl code: " + +"cUrl init error!" "cUrl init fout!" + +"Can't open file!" "Kan bestand niet openen!" + +"Other error (status code: " "Andere fout (status code: " + +"Downloading" "Downloaden" + + + +### MENUBAR ----------------------------------- + + + +"File" "Bestand" + +"About..." "Over..." + +"Close!" "Sluiten!" + +"Quit" "Quit" + + + +"Settings" "Instellingen" + +"Preferences..." "Voorkeuren..." + + + +"Subscriptions" "Abonnementen" + + + +"Episodes" "Afleveringen" + + + +"Lists" "Lijsten" + +"Podcast List" "Podcast Lijst" + +"Podcast directory list" "Podcast maplijst" + +"Videoblog List" "Videoblog Lijst" + +"Videoblog directory list" "Videoblog maplijst" + +"Imagefeeds List" "Imagefeeds List" + +"Imagefeeds directory list" "Imagefeeds maplijst" + +"Newsfeeds List" "Newsfeeds lijst" + +"Newsfeeds directory list" "Newsfeeds maplijst" + +"BitTorrentfeeds List" "BitTorrentfeeds lijst" + +"BitTorrentfeeds directory list" "BitTorrentfeeds maplijst" + +"Internationalfeeds List" "Internationalfeeds lijst" + +"Internationalfeeds directory list" "Internationalfeeds maplijst" + + + +"View" "Venster" + +"Full Screen" "Schermvullend" + +"Toolbar" "Werkbalk" + +"Subscriptions View" "Abonnementen venster" + +"Small Items" "Kleine objecten" + +"Big Items" "Grote objecten" + +"Move BePodder on workspace:" "Verplaats BePodder naar bureaublad:" + + + +"Help" "Help" + +"Getting Started" "Handleiding" + +"Keyboard Shortcuts" "Toetscombinaties" + +"Online Support" "Online ondersteuning" + + + + + + + + + + + +### BUTTONS ----------------------------------- + + + +# Buttons add feed window + +"Insert the rss feed url!" "RSS feed url ingeven!" + +"Add" "Toevoegen" + +"Paste" "Plakken" + + + +# Buttons directory list window + +"Collapse All" "Alles inklappen" + +"Preview" "Voorbeeld" + +"Subscribe" "Abonneren" + + + + + +# Buttons help window + +"Next" "Verder" + +"Prev" "Terug" + +"Close" "Sluiten" + +"Index" "Index" + + + + + +# Buttons remove windows + +"Cancel" "Annuleren" + +"Delete" "Verwijder" + +"Archive" "Archive" + + + + + + + +### TOOLTIPS ----------------------------------- + + + +# Tooltips toolbar buttons + + + +"Add the podcast to the Subscriptions list" "Podcast toevoegen aan de abonementen" + +"Delete the podcast from the Subscriptions list" "Podcast verwijderen van de abonnementen" + +"Check the selected podcast for new items" "Podcast controleren op nieuwe objecten" + +"Show the podcast homepage" "Podcast homepage tonen" + + + +"Delete the item and the enclosure" "Delete the item and the enclosure" + +"Stop the item download" "Stop download van onderwerp" + +"Download the selected episode" "Download de geselecteerde aflevering" + +"Play the selected episode" "Geselecteerde aflevering afspelen" + + + +"Submit bug and idea" "Bug's en ideëen aanbrengen" + + + + + +# Tooltips directory window buttons + + + +"Collapse all categories in the directory list" "Alle categoriëen in de maplijst inklappen" + +"Add the selected podcast to the Subscription list" "Voeg de geselecteerde podcast toe aan de geaboneerde lijst" + +"Checkout a podcast before downloading it" "Controleer een podcast vooraleer toe te voegen" + + + +### INFO PANEL ----------------------------------- + + + +"Show channel Image" "Toon kanaal afbeelding" + +"XML Feed Link" "XML Feed Link" + + + +"Show Episode info" "Toon onderwerpsinfo" + +"Show Subscription info" "Toon abonnementsinfo" + +"Show Downloads info" "Toon downloadsinfo" + + + +"Enclosure: " "Bijlage: " + + + +"Lookup (Dictionary)" "Opzoeken (Dictionary)" + +"Lookup (Google)" "Opzoeken (Google)" + +"Lookup (Acronym Finder)" "Lookup (Acronym Finder)" + +"Copy" "Kopiëer" + +"Select All" "Selecteer alles" + +"Copy URL" "Copy URL" + +"Open URL" "Open URL" + +"Subscription" "Abonement" + + + + + +### PREFERENCES ----------------------------------- + + + +"Preferences" "Voorkeuren" + + + +"Proxy" "Proxy" + +"Enable Proxy" "Proxy inschakelen" + +"Address" "Address" + +"Port" "Poort" + +"Username" "Gebruikersnaam" + +"Password" "Paswoord" + + + +"Max Downloads" "Max Downloads" + + + +"FileType" "Bestandstype" + +"Browser" "Browser" + +"Player" "Speler" + + + +"Channels" "Kanalen" + +"Check all channels on startup" "Controleer alle kanalen bij het starten" + +"Check the channel every" "Controleer alle kanalen elke" + + + +"never" "nooit" + +"5 minutes" "5 minuten" + +"15 minutes" "15 minuten" + +"30 minutes" "30 minuten" + +"1 hour" "1 uur" + +"2 hour" "2 uur" + + + + + + + + + +### COLUMLISTVIEW ----------------------------------- + + + + + +"1 new item" "1 nieuw onderwerp" + +"%d new items" "%d nieuwe onderwerpen" + +"new" "nieuw" + +"error" "fout" + +"not down" "niet binnen" + +"enquequed" "wachtrij" + +"downloading" "downloaden" + +"downloaded" "gedownload" + +"connecting" "verbinden" + +"not found" "niet gevonden" + +"stopped" "gestopt" + +"can't connect" "geen verbinding" + +"invalid format" "ongeldig formaat" + + +"Icon" "Icon" + +"Title" "Titel" + +"Date" "Datum" + +"Size" "Grootte" + +"Status" "Status" + +"Download" "Download" + + + + + + + +### CONTEXT MENU ----------------------------------- + + + +"Add Channel" "Kanaal toevoegen" + +"Remove Channel" "Kanaal verwijderen" + +"Check Channel" "Kanaal controleren" + +"Open Homepage" "Open Homepage" + + + +"Open Web Page" "Open Web Page" + +"Open Enclosures folder" "Open bijlage map" + +"Check All Channels" "Controlleer alle kanalen" + + + +"Show Channel Image" "Toon kanaal afbeelding" + + + +"Play enclosure" "Bijlage afspelen" + +"(Re)start download" "(her)start download" + +"Stop download" "Stop download" + +"Remove Item" "Verwijder object" + + +"Find this Item" "Zoek dit object" + +"Remove from this list" "Verwijder uit de lijst" + + + + + + + + + +### ALERT ----------------------------------- + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "Je kan enkel tot 10 kanalen toevoegen in deze niet geregistreerde versie.\n Registreer je kopie\n" + + +"Can't open the selected file with:\n\n" "Kan het geselecteerd bestand niet openen met:\n\n" + +"\n\nPlease check if the application is installed in the right way.\n" "\n\nControlleer of de toepassing goed geïnstalleerd is.\n" + +"Download it!" "Download het!" + + + +"\nRemoving.." "\nVerwijren.." + +"\nAn error occured while removing!" "\nFout tijdens het verwijderen!" + +"Check all the podcasts for new items" "Controlleer alle podcasts voor nieuwe onderwerpen" + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + + +_key="alert1" + + _value=" + +Je gaat het geselecteerde onderwerp verwijderen. + + + +Ben je zeker? + +(alle bijlage in de map worden mee verwijderd)" + + + + + +_key="alert2a" + + _value=" + +Je verwijderd het kanaal: + + + +" + + + +_key="alert2b" + + _value=" + + + +Wil je dit kanaal liever archieveren + +(behoud van alle bijlagen en bestanden + +die al gedownload zijn) of wil je het + +volledig kanaal verwijderen van je pc?" + + + +_key="alert3" + + _value=" + +Archief ontleden.." + + +_key="alert_3gp" + _value=" +3GP is een multimedia container formaat gedefiniëerd door Third Generation Partnership Project (3GPP) voor het gebruik op 3G mobiele telefoons. Het slaat video streams op als MPEG-4 of H.263, en audio streams als AMR-NB of AAC-LC. + +VideoLAN ondersteund audio AMR (3GPP) nog niet" + +_key="alert_swf" + _value=" +SWF is een gebonden vector grafisch bestandsformaat geproduceerd door Flash software van Adobe (voormalig Macromedia). + +Huidige ondersteuning in BeOS/Haiku/ZETA is gelimiteerd tot de losstaande Flash speler versie 4.1015, er is tot op heden geen moderne Flash speler" + + + + +### HELP & SHORTCUTS ----------------------------------- + + + + + +"Introduction" "Introductie" + +"The User Interface" "Gebruikersinterface" + +"Menu Bar" "Menubalk" + +"Toolbar Buttons" "Werkbalk" + +"First time with BePodder" "Eerste gebruik van BePodder" + +"Download Podcast's enclosure files" "Download Podcast's bijlagen" + +"Settings Overview" "Instellingen overzicht" + +"Directory lists" "Directory lijsts" + +"Loading Help..." "Help laden..." + +"Register your copy" "Registeer je kopie" + +"Starting point" "Startpunt" + + + + + + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + + + + +_key="help1-0" + + _value="Welkom bij de BePodder startersgids." + + + +_key="help1-1" + + _value="Als je al bekend bent met podcast en RSS feeds kan je dadelijk naar BePodder gaan door dit venster te sluiten." + + + +_key="help1-2" + +_value="Indien niet, volgt hier een introductie dat je zal verder helpen met alles wat je moet weten om te kunnen starten met BePodder. + +Gebruik de knoppen hieronder om door de handleiding te wandelen." + + + + + +_key="help2-0" + + _value="Podcasting is een methode voor het publiceren van audio en video broadcasts + +via het Internet; links naar gratis audio en video bestanden zijn ingebonden in de + +RSS en Atom feeds." + + + +_key="help2-1" + +_value="Daardoor is Podcasting een type van online media verdeling; gebruikers kunnen + +abonneren op een podcast door een feed te gebruiken + +(zoals RSS 'Really Simple Syndication' of Atom)." + + + +_key="help2-2" + +_value="Een aggregator (of podcatcher) zoals BePodder, is een toepassing die je in staat stelt om op een RSS feed te abonneren en periodiek te controleren op en downloaden van nieuwe onderwerpen. Met BePodder kan je controleren op nieuwe Podcast onderwerpen (episodes) van je geabonneerd kanaal. Eender welk onderwerp kan een bijlage bevatten, net zoals + +email bijlages dan bevatten." + + + + + +_key="help3-0" + +_value="BePodder heeft een makkelijk doch krachtige gebruikersinterface. Het hoofdvenster is opgesplitst in drie panelen:" + + + +_key="help3-1" + +_value="1) Het abonementen venster (het paneel met nummer 1 in de schermafbeelding) met de lijst van podcasts waar je een abbonement op hebt. Als je klikt op een kanaal dan zie je in paneel 2 de ljist van de voorwerpen van het kanaal." + + + +_key="help3-2" + +_value="2) De lijst met voorwerpen die beschikbaar zijn." + + + +_key="help3-3" + +_value="3) Het info paneel toont: info over het object, kanaal info of download info; je kan een info paneel kiezen door het klikken van de drie knoppen vanonder." + + + + + + + +_key="help4-0" + +_value="Heel vanboven in het BePodder hoofdvenster vind je de menubalk met zeven beschikbare menu's: Bestand, Instellingen, Abonementen, Afleveringen, Lijst, Venster en Help. Sommige menu's commando's worden gevolgd door pijlen wat betekend dat er een submenu van gerelateerde commando's is. Als je hierdoor bladerd, kijk dan ook zeker eens in de submenu's. Klik op een menu om het commando te zien:" + + + +_key="help4-1" + +_value="Bestsand: bevat commando's zoals het sluiten van de toepassing of toont het info venster van BePodder" + + + +_key="help4-2" + +_value="Instellingen: bevat commando's voor het openen van het instellingen venster dat je toestaat verschillende instellingen van BePodder aan te passen." + + + +_key="help4-3" + +_value="Abonementen: bevat commando's die bepaalde akties uitvoeren op het geselecteerd kanaal in je abonementenlijst." + + + +_key="help4-4" + +_value="Afleveringen: bevat commando's die bepaalde akties uitvoeren op de geselecteerde objecten in de kanaallijst." + + + +_key="help4-5" + +_value="Lijsten: bevat commando's voor het openen van BePodder's OPML mappen." + + + +_key="help4-6" + +_value="Venster: bevat commando's en controle's voor het BePodder venster." + + + +_key="help4-7" + +_value="Help: bevat commando's zoals het openen van BePodder's 'Handleiding' en de 'Toetscombinaties'." + + + + + + + +_key="help5-0" + + _value="Knop 'Toevoegen': opent het 'toevoegen' venster om een feed url (bv. 'http://www.newpodcast.com/rss.xml' welke je kan vinden op de podcast homepage) toe te voegen; dit kan via een tekst of grafische link zijn zoals 'XML', 'RSS' of 'Podcast Feed' erop." + + + +_key="help5-1" + + _value="Knop 'Verwijder': opent een venster waarin je kan selecteren hoe je het kanaal wil verwijderen: enkel het archief van het kanaal (behouden van downloads) of verwijderen van het hele kanaal van je pc." + + + +_key="help5-2" + + _value="Knop 'Controleer': controleerd het geselecteerde kanaal en werkt de lijst van beschikbare objecten bij in lijst." + + + +_key="help5-3" + + _value="Knop 'Homepage': toont de homepage van het kanaal in je browser. Om je favoriete browser te selecteren open je BePodder's instellingen, via het menu 'Instellingen' > 'Voorkeuren...' en in het instellingsvenster onder 'Bestandstype' selecteer je je favoriete browser." + + + +_key="help5-4" + + _value="Knop 'Afspelen': met deze knop kan je de bijlagen of downloads bekijken of beluisteren. Om je favoriete MediaPlayer te kiezen ga je in het menu naar 'Instellingen' > 'Voorkeuren...' en in het instellingsvenster under 'Bestandstype kies je je favoriete speler." + + + +_key="help5-5" + + _value="Knop 'Download': deze zal het geselecteerd object in de lijst downloaden; je kan info opvragen door het klikken op de derde knop boven het info paneel." + + + +_key="help5-6" + + _value="Knop 'Stop':stopt de download van het bestand of bijlage van het geselecteerd object(aflevering); om verder te gaan met de download dubbelklik op het object (aflevering) of selecteer het object en klik op de 'Download' knop." + + + +_key="help5-7" + + _value="Knop 'Verwijder object': verwijderd het geselecteerd object (hierdoor ook de bijlage)." + + + + + + + +_key="help6-0" + + _value="Beginnen met BePodder is gemakkelijk." + + + +_key="help6-1" + + _value="Aan de linkerkant vind je een lijst van je abonnementen. We hebben al enkele abonnementen toegevoegd voor je, en je kan er altijd toevoegen op twee manieren:" + + + +_key="help6-2" + + _value="1) Handmatig via 'Voeg een podcast toe aan de abonnementen' knop, plak dan de feed url (bv: http://www.newpodcast.com/rss.xml) en klik dan op Toevoegen." + + + +_key="help6-3" + + _value="2) in de menu lijst selecteer 'Map' en dan 'Podcast lijst' of 'Videoblog lijst', kies een podcast en klik op 'Abonneren'." + + + +_key="help6-4" + + _value="Als je een Podcast in de abonnee lijst selecteerd, en dan de 'Controleer' knop klikt zal BePodder de nieuwe onderwerpen in de 'Episode lijst' rechts toevoegen; je kan al je podcast door rechtsklikken controleren door 'Controlleer alle kanalen' in het context menu." + + + +_key="help6-5" + + _value="Bekijk de schermafbeelding hierboven, 3 nieuwe objecten zijn aangegeven door een zwarte dot in de eerste kollom van de lijst van afleveringen." + + + +_key="help6-6" + + _value="In de tweede kollom staan de icoontjes die de status van het object aangeven:" + + + +_key="help6-7" + + _value="- aflevering 4 heeft een icoon wat aangeeft dat er een fout is" + + + +_key="help6-8" + + _value="- aflevering 3 heeft een icoon wat aangeeft dat het object download is aangevraagd (wachtrij)" + + + +_key="help6-9" + + _value="- aflevering 2 heeft een icoon wat aangeeft dat BePodder het bestand aan het downloaden is." + + + +_key="help6-10" + + _value="- aflevering 1 heeft een icoon wat aangeeft dat BePodder het bestand gedownload heeft." + + + + + + + +_key="help7-0" + + _value="Selecteer een onderwerp in de 'Episode lijst' en dubbelklik op het onderwerp of klik op de Download knop; je kan de download stoppen door te klikken op stop." + + + +_key="help7-1" + + _value="Als je klikt op de een van de abonnementen zal de software je alle onderwerpen tonen die beschikbaar zijn voor dat abonnement in de 'Episode lijst'. + +Selecteer een onderwerp en klik op afspelen (Afspelen knop) om het bestand te + +beluisteren of bekijken." + + + +_key="help7-2" + + _value="Je kan de bijlage map bereiken door het klikken op het map icoon in het info veld, + +of door rechtsklikken op het bestand en kiezen voor 'Open bijlage map' + +in het context menu. + +Tot hier de handleiding, met deze info ben je in staat om zelf podcast toe te voegen + +die je vind via het net, en te werken met BePodder. + + + + Veel plezier!!! ;)" + + + + + +_key="help8-0" + + _value="Voorkeuren kan je berijken via de menubalk Instellingen > Voorkeuren. Je kan een categorie selecteren vanuit de lijst van de voorkeuren: Bestandstype, kanalen, Download en Proxy." + + + +_key="help8-1" + + _value="- Bestandstype: voor het vastleggen van je standaard browser en speler." + + + +_key="help8-2" + + _value="- Kanalen: voor het instellen van de controle over de manier waarop kanalen gecontroleerd worden; je kan kiezen om alle kanalen bij het starten van BePodder te kontroleren of om op ingestelde intervallen te gaan controleren." + + + +_key="help8-3" + + _value="- Download: om het maximum aantal gelijktijdige downloads in te stellen." + + + +_key="help8-4" + + _value="- Proxy: voor het instellen van een proxy met BePodder; een proxy dient als veiligheidsbrug tussen jouw netwerk en het internet, zodat anderen op het internet niet aan informatie van je eigen netwerk kunnen benaderen." + + + + + + + +_key="help9-0" + _value=" BePodder heeft een ingebouwde podcast, videoblog, imagefeeds, newsfeeds, bittorrentfeeds en internationalfeeds OPML directories met duizenden feeds gegroepeerd op categorie." + +_key="help9-1" + + _value="OPML (Outline Processor Markup Language) is een XML-gebaseerd formaat dat uitwisseling toestaat van outline-gestructureerde informatie tussen twee toepassingen." + + + +_key="help9-2" + _value="OPML directory kan toegankelijk worden door het klikken in de menu-bar 'Lijsten' en dan door selecteren van een lijst. Om door de mappen van opml te bladeren voor een feed, klap je de lijst uit door het klikken op de pijl van de categorie waarin je interesse hebt (zie afbeelding); door dit te doen kan je elke opml map uitklappen totdat je gevonden hebt wat je zoekt. Eenmaal je deze geselecteerd hebt kan je deze toevoegen door het klikken van 'Abonneren', je kan ook alle categorien uitklappen door het klikken op 'Alles uitklappen'." + + + +_key="help_shortcut1" + +_value="Deze sectie beschrijft de toetscombinaties die kunnen gebruikt worden in BePodder. De toetscombinaties zijn gegroepeerd per functie. " + + + +_key="help_shortcut2" + +_value="betekend dat je ofwel van Alt of Control gebruik kan maken (bv. Alt+Q of Ctrl+Q sluit de toepassing), zoals deze ingesteld zijn in de instellingen voor toetsenbord (de standaard knop is 'Alt')." + + + +_key="help_shortcut3" + + _value="Algemene combinaties" + + + +_key="help_shortcut4" + + _value="Toepassing afsluiten" + + + +_key="help_shortcut5" + + _value="Toon het instellingen venster" + + + +_key="help_shortcut6" + + _value="Toon de Podcast maplijst" + + + +_key="help_shortcut7" + + _value="Toon de Videoblog maplijst" + + + +_key="help_shortcut8" + + _value="Toon de Imagefeeds maplijst" + + + +_key="help_shortcut9" + + _value="Toon de Newsfeeds maplijst" + + + +_key="help_shortcut9b" + + _value="Toon de BitTorrentfeeds maplijst" + + +_key="help_shortcut9c" + + _value="Toon de Internationalfeeds maplijst" + + +_key="help_shortcut10" + + _value="Schermvullend" + + + +_key="help_shortcut11" + + _value="Toon/verberd de werkbalk" + + + +_key="help_shortcut12" + + _value="Toon de handleiding" + + + +_key="help_shortcut13" + + _value="Toon de toetscombinaties" + + + +_key="help_shortcut14" + + _value="Channels shortcuts" + + + +_key="help_shortcut15" + + _value="Podcast toevoegen aan de abonementen" + + + +_key="help_shortcut16" + + _value="Podcast verwijderen van de abonementen" + + + +_key="help_shortcut17" + + _value="Controleer de geselecteerde podcast op nieuwe onderwerp(en)" + + + +_key="help_shortcut18" + + _value="Controleer alle podcast op nieuwe onderwerp(en)" + + + +_key="help_shortcut19" + + _value="Podcast homepage tonen" + + + +_key="help_shortcut20" + + _value="Open map van bijlage" + + + +_key="help_shortcut21" + + _value="Episodes shortcuts" + + + +_key="help_shortcut22" + + _value="Bijlage afspelen" + + + +_key="help_shortcut23" + + _value="(Her)start download het geselecteerde onderwerp" + + + +_key="help_shortcut24" + + _value="Stop de bijlage/onderwerp download" + + + +_key="help_shortcut25" + + _value="Verwijder geselecteerde bijlage(onderwerp)" + + + +_key="help_shortcut26" + + _value="Toon de podcast bijlage(onderwerp) pagina" + + + +_key="help_shortcut27" + + _value="Open map van bijlage" + + + +_key="help_buy1" + _value=" BePodder Light is de basis versie (gratis download en geen tijdslimiet), de geregistreerde versie voegt enkele mooie features toe: ongelimiteerd aantal kanalen, smal kanaal venster, proxy support, automatische kanaalcheck, tot 5 gelijktijdige downloads (multithreading)." + +_key="help_buy2" + + _value="Gelieve deze shareware te registeren, het is enkel 15 Euro (Kagi voegt tax toe in sommige landen), BePodder licentie kan online gekocht worden van Kagi." + + + +_key="help_buy3" + + _value="Koop op www.funkyideasoft.com" + + + +_key="help_buy4" + + _value="Na aankoop krijg je een email met een keyfile (sleutelbestand) en instructies over hoe deze te installeren. Het is enkel een kwestie van deze uit te pakken en te verplaatsen naar een bepaalde map." + + + +_key="help_buy5" + + _value="Er is geen probleem voor het updaten van BePodder als er een nieuwe versie beschikbaar is. Het sleutelbestand zal alle gedownloade pakketen ontsleutelen tenzij anders werd aangegeven." + + + + + +### USELESS ######## + + + +"Opml Editor" "Opml bewerken" + +"name:" "naam:" + +"Add a categorie" "Categorie toevoegen" + +"Add a new Broadcast" "Een nieuwe broadcast toevoegen" + +"feed:" "feed:" + +"url:" "url:" + +"Test podcast" "Test podcast" + +"Del a categorie" "Verwijder een categorie" + +"Add a categorie" "Een categorie toevoegen" + +"Select the podcast categorie:" "Selecteer de podcast categorie:" + +"Check all" "Controleer alles" + +"Check" "Controleer" + +"Refresh the list" "Ververs lijst" + +"Load" "Laad" + +"Load the list" "Laad de lijst" + +"Save" "Opslaan" + +"Save the list" "Opslaan van list" + +"Revert" "Terug" + +"Apply" "Toepassen" + + + + + + + + + + + + + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.noNO b/release/Language/Dictionaries/BePodder.noNO new file mode 100644 index 0000000..f2b3b96 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.noNO @@ -0,0 +1,598 @@ + +# Locale file for BePodder. +# Modified: 4/18/2006 +# Author: Frank Paul Silye +# E-mail: frankps@gmail.com + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" + +"Web Site" "Web Site" + +"Can't connect!" "Can't connect!" +"Http port failed!" "Http port failed!" +"Can't resolve host!" "Can't resolve host!" +"Not found!" "Not found!" +"Bad resume!" "Bad resume!" +"Aborted by Callback!" "Aborted by Callback!" +"Can't resume! (range error)" "Can't resume! (range error)" +"Access Denied!" "Access Denied!" +"User or Password Incorrect!" "User or Password Incorrect!" +"Other error (cUrl code: " "Other error (cUrl code: " +"cUrl init error!" "cUrl init error!" +"Can't open file!" "Can't open file!" +"Other error (status code: " "Other error (status code: " +"Downloading" "Downloading" + + +### MENUBAR ----------------------------------- + +"File" "Fil" +"About..." "Om..." +"Close!" "Lukk" +"Quit" "Quit" + +"Settings" "Instillinger" +"Preferences..." "Innstillinger..." + +"Subscriptions" "Abonneringer" + +"Episodes" "Episoder" + +"Lists" "Lists" +"Podcast List" "Podcast liste" +"Podcast directory list" "Podcast mappe liste" +"Videoblog List" "Videoblog liste" +"Videoblog directory list" "Videoblog mappe liste" +"Imagefeeds List" "Bildefeeds liste" +"Imagefeeds directory list" "Bildefeeds katalog liste" +"Newsfeeds List" "Nyhetfeeds liste" +"Newsfeeds directory list" "Nyhetfeeds katalog liste" +"BitTorrentfeeds List" "BitTorrentfeeds Liste" +"BitTorrentfeeds directory list" "BitTorrentfeeds katalog liste" +"Internationalfeeds List" "Internationalfeeds liste" +"Internationalfeeds directory list" "Internationalfeeds katalog liste" + +"View" "Vis" +"Full Screen" "Fullskjerm" +"Toolbar" "Verktøylinje" +"Subscriptions View" "Abonneringsvisning" +"Small Items" "Små objekter" +"Big Items" "Store objekter" +"Move BePodder on workspace:" "Flytt BePodder til skrivebord:" + +"Help" "Hjelp" +"Getting Started" "Komme i gang" +"Keyboard Shortcuts" "Tastatur snarveier" +"Tutorials" "Tutorials" +"Online Support" "Online Support" + + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "Sett inn RSS kildens url!" +"Add" "Legg til" +"Paste" "Lim inn" + +# Buttons directory list window +"Collapse All" "Collapse All" +"Preview" "Forhåndsvis" +"Subscribe" "Abonner" + + +# Buttons help window +"Next" "Neste" +"Prev" "Forrige" +"Close" "Lukk" +"Index" "Index" + + +# Buttons remove windows +"Cancel" "Avbryt" +"Delete" "Slett" +"Archive" "Arkiv" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Legg til podcasten til abonneringslisten" +"Delete the podcast from the Subscriptions list" "Slett podcasten fra abonneringslisten" +"Check the selected podcast for new items" "Sjekk valgte podcast for nye publikasjoner" +"Show the podcast homepage" "Vis hjemmeside for podcast" + +"Delete the item and the enclosure" "Delete the item and the enclosure" +"Stop the item download" "Stopp nedlasting av publikasjon" +"Download the selected episode" "Last ned valgte episode" +"Play the selected episode" "Spill valgte episode" + +"Submit bug and idea" "Fortell oss om ideer og feil" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Collapse all categories in the directory list" +"Add the selected podcast to the Subscription list" "Legg til valgte podcast til abonneringsliste" +"Checkout a podcast before downloading it" "Sjekk ut en podcast før du laster den ned" + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Vis kanal bilde" +"XML Feed Link" "XML feed lenke" + +"Show Episode info" "Vis episode info" +"Show Subscription info" "Vis abonnement info" +"Show Downloads info" "Vis nedlastinger info" + +"Enclosure: " "Vedlegg: " + +"Lookup (Dictionary)" "Oppslag (Dictionary)" +"Lookup (Google)" "Oppslag (Google)" +"Lookup (Acronym Finder)" "Oppslag (Acronym Finder)" +"Copy" "Kopier" +"Select All" "Velg alt" +"Copy URL" "Kopier URL" +"Open URL" "Åpne URL" +"Subscription" "Abonnement" + + +### PREFERENCES ----------------------------------- + +"Preferences" "Innstillinger" + +"Proxy" "Proxy" +"Enable Proxy" "Aktiver Proxy" +"Address" "Adresse" +"Port" "Port" +"Username" "Brukernavn" +"Password" "Passord" + +"Max Downloads" "Maks ant. nedlastinger" + +"FileType" "Filtype" +"Browser" "Nettleser:" +"Player" "Avspiller:" + +"Channels" "Kanaler" +"Check all channels on startup" "Sjekk alle kanaler ved oppstart" +"Check the channel every" "Sjekk kanalen hver" + +"never" "aldri" +"5 minutes" "5 minutter" +"15 minutes" "15 minutter" +"30 minutes" "30 minutter" +"1 hour" "1 time" +"2 hour" "2 timer" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 ny publisering " +"%d new items" "nye publiseringer " +"new" "ny" +"error" "feil" +"not down" "ikke lastet ned" +"enquequed" "lagt i kø" +"downloading" "laster ned" +"downloaded" "nedlastet" +"connecting" "kobler til" +"not found" "ikke funnet" +"stopped" "stoppet" +"can't connect" "kan ikke koble til" +"invalid format" "ugyldig format" + +"Icon" "Icon" +"Title" "Tittel" +"Date" "Dato" +"Size" "Størrelse" +"Status" "Status" +"Download" "Last ned" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "Legg til kanal" +"Remove Channel" "Fjern kanal" +"Check Channel" "Sjekk kanal" +"Open Homepage" "Åpne hjemmeside" + +"Open Web Page" "Åpne webside" +"Open Enclosures folder" "Åpne vedleggsmappe" +"Check All Channels" "Sjekk alle kanaler" + +"Show Channel Image" "Vis kanal bilde" + +"Play enclosure" "Avspill vedlegg" +"(Re)start download" "(Re)start nedlasting" +"Stop download" "Stopp nedlasting" +"Remove Item" "Fjern publisering" + +"Find this Item" "Find this Item" +"Remove from this list" "Remove from this list" + + + +### ALERT ----------------------------------- + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" + + +"Can't open the selected file with:\n\n" "Can't open the selected file with:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nPlease check if the application is installed in the right way.\n" +"Download it!" "Download it!" + + +"\nRemoving.." "\nFjerner.." +"\nAn error occured while removing!" "\nEn feil oppstod ved fjerning!" +"Check all the podcasts for new items" "Sjekk alle podcaster for nye publikasjoner" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +Du er i ferd med å fjerne valgte publisering. + +Er du sikker på at du ønsker dette? +(du vil miste vedlagt fil om noens)" + + +_key="alert2a" + _value=" +Du er i ferd med å fjerne kanalen: + +" + +_key="alert2b" + _value=" + +Ønsker du bare å arkivere denne kanalen (beholde alle publikasjoner og vedlegg lastet ned til nå) eller ønsker du å SLETTE hele kanalen fra din datamaskin?" + +_key="alert3" + _value=" +Parser arkiv.." + +_key="alert_3gp" + _value=" +3GP is a multimedia container format defined by the Third Generation Partnership Project (3GPP) for use on 3G mobile phones. It stores video streams as MPEG-4 or H.263, and audio streams as AMR-NB or AAC-LC. + +VideoLAN still doesn't support the audio AMR (3GPP)" + +_key="alert_swf" + _value=" +SWF is a proprietary vector graphics file format produced by the Flash software from Adobe (formerly Macromedia). + +Currently Flash support in BeOS/Haiku/Zeta is limited to the old standalone Flash player version 4.1015, there isn't a modern Flash player" + + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Introduction" +"The User Interface" "The User Interface" +"Menu Bar" "Menu Bar" +"Toolbar Buttons" "Toolbar Buttons" +"First time with BePodder" "Første gang med BePodder" +"Download Podcast's enclosure files" "Download Podcast's enclosure files" +"Settings Overview" "Settings Overview" +"Directory lists" "Directory lists" +"Loading Help..." "Loading Help..." +"Register your copy" "Register your copy" +"Starting point" "Starting point" + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value="Velkommen til BePodder komme i gang manual" + +_key="help1-1" + _value="Dersom du allerede er kjent med podcast og RSS kilder kan du gå til BePodder ved å lukke dette vinduet." + +_key="help1-2" +_value="Dersom ikke, er dette en kort introduksjon som vil gi deg alt du trenger å vite om hvordan du kan komme i gang med BePodder, bruk knappene på bunnen for å gå gjennom denne manualen." + + + +_key="help2-0" + _value="Podcasting er en metode for å publisere audio og video kringkastinger over Internet; lenker til gratis audio og video filer er vedlagt i RSS og Atom kilder." + +_key="help2-1" +_value="Podcasting er derfor simpelten en type nettbasert levering av media; brukere kan abonnere på en podcast ved å bruke en kilde (som RSS 'Really Simple Syndication' eller Atom)." + +_key="help2-2" +_value="En aggregator (eller podcatcher) som BePodder, er et program som lar deg abonnere på en RSS kilde og periodisk sjekke etter og laste ned nytt innhold. Med BePodder kan du sjekke etter nye Podcast publikasjoner (episoder) på de kanalene du abonnerer på. En hver publikasjon kan inneholde et vedlegg, akkurat som en e-post kan inneholde et vedlegg." + + +_key="help3-0" +_value="BePodder has an easy to use yet powerful Graphical User Interface. The main window is split into tree panels:" + +_key="help3-1" +_value="1) The Subscription list (the panel with the number 1 in the screenshot) with the list of the podcasts that you have subscribed to. When you click on a Channel you can see in the panel 2 the list of the channel's items." + +_key="help3-2" +_value="2) The Episodes list with all the items available." + +_key="help3-3" +_value="3) The Info panel show: episode info, channel info or Downloads info; you can select an info panel by clicking one of the below three buttons." + + + +_key="help4-0" +_value="At the very top of the BePodder main window is the menubar with seven menus available: File, Settings, Subscriptions, Episodes, Lists, View and Help. Some menu commands are followed by a right pointing arrow that indicates a submenu of related commands. As you explore each menu, be sure to take a look at the submenus as well. Click on a menus to show its commands:" + +_key="help4-1" +_value="File: contains commands to close the application and to show information about BePodder" + +_key="help4-2" +_value="Settings: contains command to open the Preferences window that allows you to customize various BePodder settings." + +_key="help4-3" +_value="Subscriptions: contains commands that perform actions on the selected channel of your subscriptions list." + +_key="help4-4" +_value="Episodes: contains commands that perform actions on the selected item (episode) of the channel's episode list." + +_key="help4-5" +_value="Lists: contains commands to open BePodder's OPML directories." + +_key="help4-6" +_value="View: contains commands and controls for the BePodder window." + +_key="help4-7" +_value="Help: contains commands to open BePodder's 'Getting Started Guide' and the 'Keyboard Shortcuts List'." + + + +_key="help5-0" + _value="Add Button: opens the Add Window to add a feed url (e.g. http://www.newpodcast.com/rss.xml) usually given on the podcast homepage; looks for text or graphic link that says something like 'XML', 'RSS' or 'Podcast Feed' on it." + +_key="help5-1" + _value="Channel Remove Button: opens a window in which you can select how remove the channel: just archive the select channel (keeping all the files and eclosure downloaded so far) or delete the whole channel from your computer." + +_key="help5-2" + _value="Check Button: checks the selected channel and updates the list of the available items for that podcast adding the new items." + +_key="help5-3" + _value="Web Button: shows the channel homepage in the browser. To select your favorite browser open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select your favorite browser." + +_key="help5-4" + _value="Play Button: with this button you can view or listen the file enclosure of the selected item(episode). To select your favorite player open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select you favorite player." + +_key="help5-5" + _value="Download Button: downloads the file enclosure of the selected item (episode); you can see the download info by clicking on the third button over the info panel." + +_key="help5-6" + _value="Stop Button: stops to download the file enclosure of the selected item (episode); to resume the download double-click the item (episode) or select the item and click the Download Button" + +_key="help5-7" + _value="Item Remove Button: deletes the selected item (you will loose the enclosure file)." + + + +_key="help6-0" + _value="Getting started with BePodder is easy." + +_key="help6-1" + _value="On the left of the main window you can see the 'Subscription List' with all your feed subscriptions. We have added some subscriptions for you, and you can always add your own in two ways:" + +_key="help6-2" + _value="1) click the Add Button, then insert the feed url (example: http://www.newpodcast.com/rss.xml) and click add." + +_key="help6-3" + _value="2) in the menubar select 'Directory' and then 'Podcast list' or another list, choose a podcast and click 'Subscribe'." + +_key="help6-4" + _value="If you select a Podcast in the subscriptions list and use the check button, BePodder adds the new items to the 'Episodes list' (below on the right); you can check all your podcasts by right-clicking and selecting 'Check All Channels' in the context menu." + +_key="help6-5" + _value="Look at the screenshot above, there are 3 new items indicated by a black dot in the first column of the 'Episodes list'." + +_key="help6-6" + _value="In the second column there are icons that indicate the state of the item:" + +_key="help6-7" + _value="- the Episode 4 has an icon that indicates an error" + +_key="help6-8" + _value="- the Episode 3 has an icon that indicates that the item's enclosure download request is enquequed" + +_key="help6-9" + _value="- the Episode 2 has an icon that indicates that BePodder is downloading the item's enclosure file" + +_key="help6-10" + _value="- the Episode 1 has an icon that indicates that BePodder have just downloaded the item's enclosure file" + + + +_key="help7-0" + _value="Select an item in the 'Episodes list' and then double-click on it (or click the Download Button) to start downloading the enclosed file; you can always stop the download by clicking on the Stop Button." + +_key="help7-1" + _value="When you click on the Subscribed Podcasts in the 'Subscriptions List' the software shows you, in the 'List of episodes', all the items available in that Subscription. Select an item and then click play (Play Button) to view or listen to the file." + +_key="help7-2" + _value="You can access the Enclosures Folder by clicking on the folder icon in the Info Pannel or by right-clicking your mouse on an item and select 'Open Enclosures Folder' in the context menu." + + + +_key="help8-0" + _value="Preferences can be accessed by clicking in the menu-bar Settings>Preferences. You can select a category from the left list of the preferences dialog: FileType, Channels, Download and Proxy." + +_key="help8-1" + _value="- FileType: to specify the default browser and player. " + +_key="help8-2" + _value="- Channels: to specify preferences that control the operation to check channels new items; you can choose to Check all channels on startup or check the channel every desired minutes." + +_key="help8-3" + _value="- Download: to specify the max number of item's files to download at the same time," + +_key="help8-4" + _value="- Proxy: to set up a proxy server to work with BePodder; a proxy server acts as a security barrier between your internal network and the Internet, keeping others on the Internet from accessing information on your internal network." + + + +_key="help9-0" + _value="BePodder has built-in podcast, videoblog, imagefeeds, newsfeeds, bittorrentfeeds and internationalfeeds OPML directories with thousands of feeds grouped by category." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) is an XML-based format that allows exchange of outline-structured information between applications." + +_key="help9-2" + _value="OPML directory can be accessed by clicking in the menu-bar 'Lists' and thenselecting a list. To browse the opml directory for a feed, expand the list by clicking the arrow of the category that you are interested in (see image); using this method, you can expand the opml directory until you find the desired feed. Once you have selected it, you can add it to the subscription list by clicking the button 'Subscribe', you can also collapse all categories in the directory list by clicking the button 'Collapse All'." + +_key="help_shortcut1" +_value="Denne siden beskriver tastatur hurtigtilganger som kan brukes i BePodder. Hurtigtilgangene er blitt gruppert etter funksjonalitet." + +_key="help_shortcut2" +_value="means that you can use either alt or control (es. Alt+Q or Ctrl+Q Quit the application), which way you have set it in the Deskbar menu preferences under Keyboard (the default shortcut key is Alt)." + +_key="help_shortcut3" + _value="Generelle hurtigtilganger" + +_key="help_shortcut4" + _value="Avslutt applikasjonen" + +_key="help_shortcut5" + _value="Viser Innstillinger vinduet" + +_key="help_shortcut6" + _value="Viser Podcast katalog liste" + +_key="help_shortcut7" + _value="Viser Videoblog katalog liste" + +_key="help_shortcut8" + _value="Viser Bildefeeds katalog liste" + +_key="help_shortcut9" + _value="Viser Nyhetfeeds katalog liste" + +_key="help_shortcut9b" + _value="Viser BitTorrentfeeds katalog liste" + +_key="help_shortcut9c" + _value="Viser Internationalfeeds katalog liste" + +_key="help_shortcut10" + _value="Fullskjerm" + +_key="help_shortcut11" + _value="Viser/Skjuler verktøylinje" + +_key="help_shortcut12" + _value="Viser Hjelp til å komme i gang" + +_key="help_shortcut13" + _value="Viser this tastatur hurtigtilganger side" + +_key="help_shortcut14" + _value="Kanaler hurtigtilganger" + +_key="help_shortcut15" + _value="Add a podcast to the subscriptions list" + +_key="help_shortcut16" + _value="Delete the selected podcast from the subscriptions list" + +_key="help_shortcut17" + _value="Check the selected podcast for new episodes (items)" + +_key="help_shortcut18" + _value="Check all podcasts for new episodes (items)" + +_key="help_shortcut19" + _value="Viser the podcast homepage" + +_key="help_shortcut20" + _value="Open enclosures folder" + +_key="help_shortcut21" + _value="Episoder hurtigtilganger" + +_key="help_shortcut22" + _value="Spill av vedlegg" + +_key="help_shortcut23" + _value="(Re)start nedlasting av valgte episoder (objekter) " + +_key="help_shortcut24" + _value="Stopp nedlastingen av episode (objekt)" + +_key="help_shortcut25" + _value="Slett valgte episode (objekt)" + +_key="help_shortcut26" + _value="Viser the podcast episode (objekt) side" + +_key="help_shortcut27" + _value=" Åpner vedleggsmappe" + +_key="help_buy1" + _value="BePodder Light is the basic version (free download and no time limited), the registered version adds some more nice features: unlimited number of channels, small Channel view, proxy support, automatic channels check, up to 5 enclosure downloads at the same time (multithreading)." + +_key="help_buy2" + _value="Please pay the shareware fee, it's only 15 euro (Kagi add tax in some countries), BePodder licence can be purchased online from Kagi." + +_key="help_buy3" + _value="Buy at www.funkyideasoft.com" + +_key="help_buy4" + _value="After purchasing, an email will be sent to you with a keyfile and instruction on how to install it. It's just a matter of unzipping a file and moving it to a certain directory." + +_key="help_buy5" + _value="There is no problem updating BePodder when a new version becomes available. The keyfile will unlock all downloadable packages unless otherwise notified." + + +### USELESS ######## + +"Opml Editor" "Rediger Opml" +"name:" "navn:" +"Add a categorie" "Legg til kategori" +"Add a new Broadcast" "Legg til ny kringkasting" +"feed:" "kilde:" +"url:" "url:" +"Test podcast" "Test podcast" +"Del a categorie" "Slett en kategori" +"Add a categorie" "Legg til en kategori" +"Select the podcast categorie:" "Velg podcast kategorien:" +"Check all" "Velg alle" +"Check" "Velg" +"Refresh the list" "Oppdater listen" +"Load" "Hent" +"Load the list" "Hent listen" +"Save" "Lagre" +"Save the list" "Lagre listen" +"Revert" "Revert" +"Apply" "Apply" + + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.plPL b/release/Language/Dictionaries/BePodder.plPL new file mode 100644 index 0000000..736445a --- /dev/null +++ b/release/Language/Dictionaries/BePodder.plPL @@ -0,0 +1,599 @@ + +# Locale file for BePodder. +# Modified: 4/18/2006 +# Author: BePodderTeam +# E-mail: bepodder.team@gmail.com + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Aplikacja shareware!\n\nWspieraj rozwój tego programu!\n\nKup licencję!\nWięcej informacji na naszej stronie\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "Okres darmowego użytkowania programu dobiegł końca!\nKup klucz licencyjny i wesprzyj rozwój aplikacji.\n" + +"Web Site" "Strona www" + +"Can't connect!" "Brak połączenia!" +"Http port failed!" "Błąd portu Http!" +"Can't resolve host!" "Host nieznaleziony!" +"Not found!" "Nie znaleziono!" +"Bad resume!" "Niepoprawne wznowienie!" +"Aborted by Callback!" "Przerwane!" +"Can't resume! (range error)" "Nie można ponowić! (błąd zasięgu)" +"Access Denied!" "Dostęp zabroniony!" +"User or Password Incorrect!" "Hasło użytkownika niepoprawne!" +"Other error (cUrl code: " "Inny błąd (cUrl code: " +"cUrl init error!" "cUrl init error!" +"Can't open file!" "Nie można otworzyć pliku!" +"Other error (status code: " "Inny błąd (status code: " +"Downloading" "Pobieranie" + + +### MENUBAR ----------------------------------- + +"File" "Plik" +"About..." "O programie..." +"Close!" "Zamknij!" +"Quit" "Wyjdź" + +"Settings" "Ustawienia" +"Preferences..." "Preferencje..." + +"Subscriptions" "Subscrypcje" + +"Episodes" "Epizody" + +"Lists" "Listy" +"Podcast List" "Listy podcastów" +"Podcast directory list" "Katalog list podcastów" +"Videoblog List" "Listy wideoblogów" +"Videoblog directory list" "Katalog list wideoblegów" +"Imagefeeds List" "Lista obrazków" +"Imagefeeds directory list" "Katalog list obrazków" +"Newsfeeds List" "Lista newsów" +"Newsfeeds directory list" "Katalog list newsów" +"BitTorrentfeeds List" "Lista BitTorrentów" +"BitTorrentfeeds directory list" "Katalog list BitTorrentów" +"Internationalfeeds List" "Lista międzynarodowa" +"Internationalfeeds directory list" "Katalog list międzynarodowych" + +"View" "Widok" +"Full Screen" "Pełny ekran" +"Toolbar" "Toolbar" +"Subscriptions View" "Widok subskrypcji" +"Small Items" "Małe ikonki" +"Big Items" "Duże ikonki" +"Move BePodder on workspace:" "Przesuń BePoddera do pulpitu:" + +"Help" "Pomoc" +"Getting Started" "Dla początkujących" +"Keyboard Shortcuts" "Skróty klawiaturowe" +"Tutorials" "Poradniki" +"Online Support" "Wsparcie online" + + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "Podaj adres url kanału rss!" +"Add" "Dodaj" +"Paste" "Wklej" + +# Buttons directory list window +"Collapse All" "Zwiń wszystko" +"Preview" "Podgląd" +"Subscribe" "Subskrybuj" + + +# Buttons help window +"Next" "Następny" +"Prev" "Poprzedni" +"Close" "Zamknij" +"Index" "Indeks" + + +# Buttons remove windows +"Cancel" "Zaniechaj" +"Delete" "Usuń" +"Archive" "Archiwum" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Dodaj podcast listy subskrypcji" +"Delete the podcast from the Subscriptions list" "Usuń podcast z listy subskrypcji" +"Check the selected podcast for new items" "Sprawdź czy są nowe elementy w wybranym podcaście" +"Show the podcast homepage" "Przejdź do strony domowej podcastu" + +"Delete the item and the enclosure" "Skasuj wraz z załącznikiem" +"Stop the item download" "Zatrzymaj pobieranie" +"Download the selected episode" "Pobierz wybrany epizod" +"Play the selected episode" "Odtwórz zaznaczony epizod" + +"Submit bug and idea" "Zgłoś pomysł lub błąd" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Zwiń wszystkie kategorie w katalogu" +"Add the selected podcast to the Subscription list" "Dodaj wybrany podcast do listy subskrypcji" +"Checkout a podcast before downloading it" "Sprawdź podcast przed pobieraniem go" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Pokazuj obrazek kanału" +"XML Feed Link" "Link kanału XML" + +"Show Episode info" "Pokaż informacje o epizodzie" +"Show Subscription info" "Pokaż informacje o subskrypcji" +"Show Downloads info" "Pokaż informacje o elementach pobranych" + +"Enclosure: " "Załącznik: " + +"Lookup (Dictionary)" "Zablokuj (Słownik)" +"Lookup (Google)" "Zablokuj (Google)" +"Lookup (Acronym Finder)" "Zablokuj (Poszukiwacz Akronimów)" +"Copy" "Kopiuj" +"Select All" "Zaznacz wszystko" +"Copy URL" "Kopiuj URL" +"Open URL" "Otwórz URL" +"Subscription" "Subscrypcja" + + +### PREFERENCES ----------------------------------- + +"Preferences" "Preferencje" + +"Proxy" "Proxy" +"Enable Proxy" "Włącz Proxy" +"Address" "Adres" +"Port" "Port" +"Username" "Użytkownik" +"Password" "Hasło" + +"Max Downloads" "Max ilość pobieranych" + +"FileType" "Ty pliku" +"Browser" "Przeglądarka" +"Player" "Odtwarzacz" + +"Channels" "Kanały" +"Check all channels on startup" "Sprawdzaj wszystkie kanały na starcie" +"Check the channel every" "Sprawdzaj kanały co" + +"never" "nigdy" +"5 minutes" "5 minut" +"15 minutes" "15 minut" +"30 minutes" "30 minut" +"1 hour" "1 godzina" +"2 hour" "2 godziny" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 nowy element" +"%d new items" "%d nowych elementów" +"new" "nowy" +"error" "błąd" +"not down" "nieściągalny" +"enquequed" "oczekujący" +"downloading" "pobieranie" +"downloaded" "pobrany" +"connecting" "łączenie" +"not found" "nie znaleziono" +"stopped" "zatrzymany" +"can't connect" "brak połączenia" +"invalid format" "błędny format" + +"Icon" "Icon" +"Title" "Tytuł" +"Date" "Data" +"Size" "Rozmiar" +"Status" "Status" +"Download" "Pobierz" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "Dodaj kanał" +"Remove Channel" "Usuń kanał" +"Check Channel" "Sprawdź kanał" +"Open Homepage" "Odwiedź stronę www" + +"Open Web Page" "Otwórz www" +"Open Enclosures folder" "Otwórz katalog załączników" +"Check All Channels" "Sprawdź wszystkie kanały" + +"Show Channel Image" "Pokazuj obrazek kanału" + +"Play enclosure" "Odtwórz załącznik" +"(Re)start download" "(Re)startuj pobieranie" +"Stop download" "Zatrzymaj pobieranie" +"Remove Item" "Usuń element" + +"Find this Item" "Znajdź element" +"Remove from this list" "Usuń z listy" + + + +### ALERT ----------------------------------- + +"\nRemoving.." "\nUsuwanie.." +"\nAn error occured while removing!" "\nNastąpił błąd przy usuwaniu!" +"Check all the podcasts for new items" "Sprawdź czy są nowe elementy na podcastach" + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "Możesz dodać jedynie do 10 kanałów używając niezarejestrowanej wersji BePoddera.\n Zarejestruj swoją kopię\n" + + +"Can't open the selected file with:\n\n" "Nie można odtworzyć wybranego pliku za pomocą:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nSprawdź czy aplikacja jest zainstalowana poprawnie.\n" +"Download it!" "Pobierz to!" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +Chcesz usunąć wybrany element. + +Jesteś pewien? +(zostaną również usunięte załączniki)" + + +_key="alert2a" + _value=" +Chcesz usunąć kanał: + +" + +_key="alert2b" + _value=" + +Czy chciałbyś zarchiwizować ten +kanał (zachowując wszystkie pliki i +załączniki pobrane dotychczas) czy też +chcesz USUNĄC cały + kanał ze swojego komputera?" + +_key="alert3" + _value=" +Analiza archiwum.." + +_key="alert_3gp" + _value=" +3GP to multimedialny kontener stworzony przez Third Generation Partnership Project (3GPP) do użytku w telefonach 3G. Służy on przechowywaniu strumieni wideo, takich jak MPEG-4 albo H.263 i strumieni audio AMR-NB lub AAC-LC. + +VideoLAN nie obsługuje AMR audio (3GPP)" + +_key="alert_swf" + _value=" +SWF to format wektorowych plików graficznych stworzony przez Flash software z Adobe (uprzednio Macromedia). + +Aktualnie obsługa flasha w BeOSie/Haiku/Zecie ogranicza się do starej wersji odtwarzacza Flash w wersji 4.1015." + + + + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Wstęp" +"The User Interface" "Interfejs użytkownika" +"Menu Bar" "Opcje menu" +"Toolbar Buttons" "Przyciski Toolbara" +"First time with BePodder" "Pierwsze uruchomienie BePoddera" +"Download Podcast's enclosure files" "Pobieranie załączników z podcastami" +"Settings Overview" "Ustawienia" +"Directory lists" "Katalogi list" +"Loading Help..." "Wgrywanie..." +"Register your copy" "Rejestruj swoją kopię" +"Starting point" "Strona główna" + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value="Witaj w przewodniku użytkownika BePoddera." + +_key="help1-1" + _value="Jeśli rozumiesz już na czym polega podcast oraz RSS/Atom, to możesz natychmiast zamknąć to okno i przejść do BePoddera." + +_key="help1-2" +_value="Jeśli nie, to ten przewodnik wprowadzi Cię w podstawy, które umożliwią Ci bezproblemową obsługę programu. Użyj przycisków znajdujących się poniżej do nawigacji w niniejszym przewodniku." + + +_key="help2-0" +_value="Podcasting to metoda publikacji przekazów audio i wideo przez Internet; linki do audio i wideo znajdują się w wiadomościach RSS lub Atom." + +_key="help2-1" +_value="Podcasting jest prostą formą dostarczania mediów online: użytkownicy mogą subskrybować podcast używając czytników (takich jak RSS 'Really Simple Syndication' czy Atom)." + +_key="help2-2" +_value="Czytnik kanałów (agregator) jak BePodder to program, który umożliwia subskrypcję kanałów RSS i w określonych odstępach czasu sprawdza dostępność nowych zawartości; przy pomocy BePoddera możesz sprawdzać czy udostepniono na subskrybowanych kanałach nowe epizody . Każdy ściągnięty element, podobnie jak np. e-mail, może zawierać załącznik." + +_key="help3-0" +_value="BePodder posiada przyjazny interfejs użytkownika (GUI). Główne okno programu jest podzielone na trzy części:" + +_key="help3-1" +_value="1) Lista subskrybowanych kanałów (panel oznaczony numerem 1 na obrazku) zawiara listę suksrybowanych podcastów. Kliknięcie na kanał powoduje wyświetlenie się w panelu 2 listy dostępnych elementów." + +_key="help3-2" +_value="2) Lista epizodów ze wszystkimi dostępnymi elementami." + +_key="help3-3" +_value="3) Panel informacyjny: informacje o epizodzie, informacje o kanałach i pobranych plikach; możesz wybrać pnel informacyjny klikając na jeden z trzech poniższych przycisków." + + + +_key="help4-0" +_value="Na szczycie głównego okna BePoddera znajduje się pasek udostępniający siedem menu: Plik, Ustawienia, Subskrypcje, Epizody, Listy, Widok i Pomoc. Obok części menu z prawej strony znajdują się strzałki, które wskazują na istnienie podmenu. Podczas przeglądania menu należy więc także zwrócić uwagę na dostępne podmenu. Kliknij na menu aby zobaczyć dostępne opcje:" + +_key="help4-1" +_value="Plik: zawiera komendy dotyczące zamykania aplikacji i panel informacji o BePodderze" + +_key="help4-2" +_value="Ustawienia: zawiera komendę uruchamiającą okno preferencji przy pomocy którego można ustawić interesujące nas ustawienia programu." + +_key="help4-3" +_value="Subscrypcje: zawiera komendy dotyczące subskrybowanych kanałów na Twoich subskrybowanych listach." + +_key="help4-4" +_value="Epizody: zawiera komendy dotyczące poszczególnych epizodów." + +_key="help4-5" +_value="Listy: zawiera komendy dotyczace katalogów OPML." + +_key="help4-6" +_value="Widok: zawiera komendy i kontrolki okien BePoddera." + +_key="help4-7" +_value="Pomoc: zawiera komendy 'Przewodnik dla początkujących' i 'Skróty klawiaturowe'." + + + +_key="help5-0" + _value="Przycisk dodaj: otwiera okno w którym możesz podać url kanału rss (np. http://www.newpodcast.com/rss.xml) zazwyczaj podawany jest on na stronie podcastu; na stronach www szukaj grafiki lub tekstu dotyczącego 'XML', 'RSS' albo 'Podcastu'." + +_key="help5-1" + _value="Przycisk usuwania kanału: otwiera okno w którym możesz wybrać sposób usunięcia kanału: archiwizacja wybranego kanału (zachowując jednocześnie wszystkie ściągnięte pliki i załączniki) albo usunięcie całego kanału z Twojego kompoutera." + +_key="help5-2" + _value="Przycisk sprawdź: sprawdza wybrany kanał i aktualizuje listę dostępnych elementów w danym podcaście dodając nowe elementy." + +_key="help5-3" + _value="Przycisk strona www: otwiera stronę domową podcastu w przeglądarce. By wybrać swoją preferowaną przeglądarkę przejdź do ustawień programu, klikając na Ustawienia>Preferencje... i w oknie preferencji w zakładce 'Typy plików' wybierz swoją preferowaną przeglądarkę." + +_key="help5-4" + _value="Przycisk odtwórz: przy pomocy tego przycisku możesz oglądać albo słuchać pliku załączonego do wybranego elementu (epizodu). By wybrać swój preferowany odtwarzacz przejdź do ustawiń programu, klikając na Ustawienia>Preferencje... i w oknie preferencji w zakładce 'Typy plików' wybierz swój preferowany odtwarzacz.." + +_key="help5-5" + _value="Przycisk pobierania: pobiera załącznik wybranego elementu (epizodu); możesz zobaczyć informacje o pobieranym pliku, klikając na trzecim przycisku panelu informacyjnego ." +_key="help5-6" + _value="Przycisk stop: zatrzymuje pobieranie pliku załączonego do wybranego elementu (epizodu); by ponowić pobieranie kliknij dwukrotnie na elemencie (epizodzie) albo wybierz element i kliknij na przycisk pobierania." + +_key="help5-7" + _value="Przycisk usuwania elementu: usuwa wybrany element (usuwa również załączone pliki)." + + + +_key="help6-0" + _value="Obsługa BePoddera jest prosta." + +_key="help6-1" + _value="Z lewej strony głównego okna znajduje się 'Lista subskrypcji' ze wszystkimi subskrybowanymi kanałami. Autorzy programu dodali dla Ciebie kilka subskrypcji. Możesz do dostępnej listy dodać swoje subskrypcje na dwa sposoby:" + +_key="help6-2" + _value="1) kliknij na przycisk dodawania kanału, później podaj url kanału rss (np.: http://www.newpodcast.com/rss.xml) i kliknij dodaj." + +_key="help6-3" + _value="2) w pasku menu kliknij na 'Listy' następnie na 'Listę podcastów' lub inną listę, wybierz podcast i kliknij 'Subskrybuj'." + +_key="help6-4" + _value="Jeśli wybierzesz podcast na liście subskrypcji i użyjesz przycisku 'sprawdź', BePodder doda nowe elementy do 'Listy epizodów' (poniżej z prawej strony); możesz sprawdzić wszystkie swoje podcasty klikając prawym przyciskiem myszy i wybierając opcję Sprawdź wszystkie kanały' z menu kontekstowego." + +_key="help6-5" + _value="Na poniższym obrazku można zauważyć w pierwszej kolumnie 'Listy epizodów' 3 nowe elementy, oznaczone czarną kropką." + +_key="help6-6" + _value="W drugiej kolumnie widzimy ikony wskazujące na stan danego elementu:" + +_key="help6-7" + _value="- Epizod 4 z ikoną wskazującą na błąd" + +_key="help6-8" + _value="- Epizod 3 z ikoną wskazującą na oczekiwanie na pobranie żądanego załącznika do elementu" + +_key="help6-9" + _value="- Epizod 2 z ikoną wskazującą na pobieranie przez BePoddera załącznika do elementu" + +_key="help6-10" + _value="- Epizod 1 z ikoną wskazującą na zakończenie pobierania załącznika do elementu" + + +_key="help7-0" + _value="Wybierz jakiś element z 'Listy epizodów' i kliknij na nim dwukrotnie (albo kliknij na przycisk pobierania), zapoczątkuje to pobieranie załącznika; możesz w każdej chwili zatrzymać pobieranie, klikając na przycisk stop." + +_key="help7-1" + _value="Jeśli klikniesz na subskrybowanym podcaście na 'Liście subskrypcji' program wyświetli Ci, w 'Liście epizodów', wszystkie elementy dostępne w ramach tej subskrypcji. Wybierz element i kliknij na przycisk odtwarzania by obejrzeć albo wysłuchać pliku." + +_key="help7-2" + _value="Możesz uzyskać dostęp do folderu z załączonymi plikami klikając na ikonę folderu w panelu informacyjnym albo klikając prawym przyciskiem myszy na elemencie i wybierając 'Otwórz folder załączników' z menu kontekstowego." + + + +_key="help8-0" + _value="Dostęp do menu Preferencji możesz uzyskać klikając na menu Ustawienia>Preferencje. W oknie dialogowym preferencji z lewej strony znajdują się cztery kategorie (zakładki): Typy plików, Kanały, Pobieranie oraz Proxy." + +_key="help8-1" + _value="- Typy plików: w menu tym możesz wybrać preferowaną przeglądarkę i odtwarzacz. " + +_key="help8-2" + _value="- Kanały: w menu tym możesz ustawić co jaki czas będzie wykonywana operacja sprawdzania kanałów w celu poszukiwania nowych zawartości; możesz w nim także wybrać opcję sprawdzania wszystkich kanałów przy starcie programu bądź sprawdzanie kanałów w określonych odstępach czasu." + +_key="help8-3" + _value="- Pobieranie: w menu tym możesz ustawić maksymalną ilość plików pobieranych jednocześnie przez program," + +_key="help8-4" + _value="- Proxy: w menu tym możesz ustawić do pracy z BePodderem serwer proxy; serwer proxy może służyć jako bariera ochronna pomiędzy Twoją siecią wewnętrzną i internetem, zapobiegając uzyskiwaniu informacji z Twojego komputera przez innych użytkowników internetu ." + + +_key="help9-0" + _value="BePodder posiada wbudowaną bazę podcastów, wideoblogów, katalogów obrazków, newsów, katalogów bittorrentów podcastów międzynarodowych z tysiącami kanałów pogrupowanych na kategorie." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) jest formatem opartym o XML, który pozwala wymieniać informacje pomiędzy aplikacjami." + +_key="help9-2" + _value="Dostęp do kanału OPML można uzyskać klikając na menu 'Katalogi' i wybierając odpowiednią listę. Poszukiwanie katalogu opml w celu odnalezienia pożądanego kanału rss polega na rozwinięciu listy poprzez kliknięcie na strzałce (patrz obrazek); używając tej metody, możesz rozwijać katalogi opml do czasu znalezienie interesującego Cię kanału. Kiedy znajdziesz już odpowiedni kanał, zaznacz go i dodaj do listy subskrypcji, klikając na przycisk 'Subskrybuj', możesz także zwinąć wszystkie kategorie w katalogu list, klikając na przycisk 'Zwiń wszystko'." + +_key="help_shortcut1" +_value="Ta strona opisuje skróty klawiaturowe, które mogą być używane w BePodderze. Skróty zostały pogrupowane według funkcji." + +_key="help_shortcut2" +_value="oznacza, że możesz użyć zarówno klawisza alt jak również control w celu wywołania różnych opcji (np. Alt+Q lub Ctrl+Q zamykają aplikację), ustawienia tego dokonałeś w menu preferences w ustawieniach klawiatury (domyślny klawisz skrótów to Alt)." + +_key="help_shortcut3" + _value="Główne skróty" + +_key="help_shortcut4" + _value="Wyjdź z programu" + +_key="help_shortcut5" + _value="Pokazuje okno preferencji" + +_key="help_shortcut6" + _value="Pokazuje listę podcastów" + +_key="help_shortcut7" + _value="Pokazuje listę wideoblogów" + +_key="help_shortcut8" + _value="Pokazuje listę obrazków" + +_key="help_shortcut9" + _value="Pokazuje listę newsów" + +_key="help_shortcut9b" + _value="Pokazuje listę BitTorrentów" + +_key="help_shortcut9c" + _value="Pokazuje listę kanałów międzynarodowych" + +_key="help_shortcut10" + _value="Pełny ekran" + +_key="help_shortcut11" + _value="Pokazuje/ukrywa toolbar" + +_key="help_shortcut12" + _value="Pokazuje poradnik dla początkujących" + +_key="help_shortcut13" + _value="Pokazuje stronę skrótów klawiaturowych" + +_key="help_shortcut14" + _value="Skróty do kanałów" + +_key="help_shortcut15" + _value="Dodaj podcast do listy subscrypcji" + +_key="help_shortcut16" + _value="Skasuj wybrany podcast z listy subskrypcji" + +_key="help_shortcut17" + _value="Sprawdź czy na wybranym podcaście są nowe epizody" + +_key="help_shortcut18" + _value="Sprawdź czy na wszystkich podcastach są nowe epizody" + +_key="help_shortcut19" + _value="Pokaż stronę domową podcastu" + +_key="help_shortcut20" + _value="Otwórz folder załączników" + +_key="help_shortcut21" + _value="Skróty do epizodów" + +_key="help_shortcut22" + _value="Odtwórz załącznik" + +_key="help_shortcut23" + _value="(Re)startuj pobieranie wybranych epizodów" + +_key="help_shortcut24" + _value="Zatrzymaj pobieranie epizodu" + +_key="help_shortcut25" + _value="Skasuj wybrany epizod" + +_key="help_shortcut26" + _value="Pokaż stronę epizodu podcastu" + +_key="help_shortcut27" + _value="Otwórz folder załączników" + +_key="help_buy1" + _value="BePodder Light jest podstawową wersją aplikacji (darmową i nielimitowaną czasowo), wersja zarejestrowana dodaje kilka interesujących nowych opcji: nielimitowaną liczbę kanałów, widok miniaturek, wsparcie dla proxy, automatyczne sprawdzanie kanałów, możliwość pobierania 5 załączników w tym samym czasie." + +_key="help_buy2" + _value="Prosimy o nabywanie pełnej wersji programu, która kosztuje jedynie 15 euro (Kagi dodaje podatek dla niektórych państw), licencję BePoddera można zakupić online od Kagi." + +_key="help_buy3" + _value="Licencję można kupić na www.funkyideasoft.com" + +_key="help_buy4" + _value="Po dokonaniu zakupu, otrzymasz email z kluczem do aplikacji wraz z instrukcją instalacji. Proces instalacji jest bardzo prosty - wypakowanie archiwum i skopiowanie pliku do określonego katalogu." + +_key="help_buy5" + _value="Żadnego problemu nie powinno też sprawić ewentualne uaktualnienie programu do nowej wersji. Klucz odblokuje też nowe wersje programu." + + +### USELESS ######## + +"Opml Editor" "Edytor Opml" +"name:" "nazwa:" +"Add a category" "Dodaj kategorię" +"Add a new Broadcast" "Dodaj nową audycję" +"feed:" "feed:" +"url:" "url:" +"Test podcast" "Testuj podcast" +"Del a category" "Usuń kategorię" +"Add a category" "Dodaj kategorię" +"Select the podcast category:" "Wybierz kategorię podcastów:" +"Check all" "Sprawdź wszystkie" +"Check" "Sprawdź" +"Refresh the list" "Odśwież listę" +"Load" "Wczytaj" +"Load the list" "Wczytaj listę" +"Save" "Zapisz" +"Save the list" "Zapisz listę" +"Revert" "Przywróć" +"Apply" "Akceptuj" + + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.ptBR b/release/Language/Dictionaries/BePodder.ptBR new file mode 100644 index 0000000..e1bd55a --- /dev/null +++ b/release/Language/Dictionaries/BePodder.ptBR @@ -0,0 +1,603 @@ + +# Locale file for BePodder. +# Modified: 4/18/2006 +# Author: Daniel "DaaT" Teixeira +# E-mail: daat@iscomputeron.com + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Aplicação Shareware!\n\nPor favor suporte o nosso trabalho!\n\nCompre uma licença!\nMais informação na nossa página na Internet\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "Esta cópia do BePodder expirou!\nPor favor compre uma licença, suportando o nosso trabalho.\n" + +"Web Site" "Página na Internet" + +"Can't connect!" "Não é possível conectar!" +"Http port failed!" "Erro na porta http!" +"Can't resolve host!" "Anfitrião não encontrado!" +"Not found!" "Não encontrado!" +"Bad resume!" "Erro ao resumir!" +"Aborted by Callback!" "Abortado por Callback!" +"Can't resume! (range error)" "Não é possível resumir! (erro de alcance)" +"Access Denied!" "Acesso Negado!" +"User or Password Incorrect!" "Utilizador ou Palavra-passe incorrectos!" +"Other error (cUrl code: " "Outro erro (código cUrl: " +"cUrl init error!" "cUrl erro init!" +"Can't open file!" "Não é possível abrir o ficheiro!" +"Other error (status code: " "Outro erro (código do status: " +"Downloading" "A transferir" + +### MENUBAR ----------------------------------- + +"File" "Ficheiro" +"About..." "Sobre..." +"Close!" "Fechar!" +"Quit" "Quit" + +"Settings" "Definições" +"Preferences..." "Preferências..." + +"Subscriptions" "Subscrições" + +"Episodes" "Episodes" + +"Lists" "Lists" +"Podcast List" "Lista de Podcasts" +"Podcast directory list" "Lista de directórios de Podcasts" +"Videoblog List" "Lista de Videoblogs" +"Videoblog directory list" "Lista de directórios de Videoblogs" +"Imagefeeds List" "Lista de Imagefeeds" +"Imagefeeds directory list" "Lista de directórios de Imagefeeds" +"Newsfeeds List" "Lista de Newsfeeds" +"Newsfeeds directory list" "Lista de directórios de Newsfeeds" +"BitTorrentfeeds List" "Lista de BitTorrentfeeds" +"BitTorrentfeeds directory list" "Lista de directórios de BitTorrentfeeds" +"Internationalfeeds List" "Lista de Internationalfeeds" +"Internationalfeeds directory list" "Lista de directórios de Internationalfeeds" + + +"View" "Ver" +"Full Screen" "Ecrã total" +"Toolbar" "Barra de Ferramentas" +"Subscriptions View" "Vista de subscrições" +"Small Items" "Items Pequenos" +"Big Items" "Items Grandes" +"Move BePodder on workspace:" "Mover o BePodder para o workspace:" + +"Help" "Ajuda" +"Getting Started" "Iniciar" +"Keyboard Shortcuts" "Atalhos do teclado" +"Tutorials" "Tutoriais" +"Online Support" "Suporte Online" + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "Insira o endereço do feed rss!" +"Add" "Adicionar" +"Paste" "Colar" + +# Buttons directory list window +"Collapse All" "Fechar Todos" +"Preview" "Previsão" +"Subscribe" "Subscrever" + + +# Buttons help window +"Next" "Seguinte" +"Prev" "Anterior" +"Close" "Fechar" +"Index" "Index" + + +# Buttons remove windows +"Cancel" "Cancelar" +"Delete" "Apagar" +"Archive" "Archive" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Adiciona o podcast à lista de Subscrições" +"Delete the podcast from the Subscriptions list" "Apaga o podcast da lista de Subscrições" +"Check the selected podcast for new items" "Verifica se existem items novos no podcast seleccionado" +"Show the podcast homepage" "Mostra a homepage do podcast" + +"Delete the item and the enclosure" "Delete the item and the enclosure" +"Stop the item download" "Pára a transferência" +"Download the selected episode" "Transfere o episódio seleccionado" +"Play the selected episode" "Ouvir/ver o episódio seleccionado" + +"Submit bug and idea" "Submete bugs e ideias" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Fechar todas as categorias na lista de directórios" +"Add the selected podcast to the Subscription list" "Adicionar o podcast seleccionado à lista de Subscrições" +"Checkout a podcast before downloading it" "Checkout a podcast before downloading it" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Show Channel Image" +"XML Feed Link" "XML Feed Link" + +"Show Episode info" "Show Episode info" +"Show Subscription info" "Show Subscription info" +"Show Downloads info" "Show Downloads info" + +"Enclosure: " "Anexo: " + +"Lookup (Dictionary)" "Procurar (Dicionário)" +"Lookup (Google)" "Procurar (Google)" +"Lookup (Acronym Finder)" "Procurar (Acrónimos)" +"Copy" "Copiar" +"Select All" "Seleccionar todos" +"Copy URL" "Copy URL" +"Open URL" "Open URL" +"Subscription" "Subscription" + + + +### PREFERENCES ----------------------------------- + +"Preferences" "Preferências" + +"Proxy" "Proxy" +"Enable Proxy" "Enable Proxy" +"Address" "Address" +"Port" "Port" +"Username" "Username" +"Password" "Password" + +"Max Downloads" "Max Downloads" + +"FileType" "FileType" +"Browser" "Navegador:" +"Player" "Leitor:" + +"Channels" "Channels" +"Check all channels on startup" "Check all channels on startup" +"Check the channel every" "Check the channel every" + +"never" "never" +"5 minutes" "5 minutes" +"15 minutes" "15 minutes" +"30 minutes" "30 minutes" +"1 hour" "1 hour" +"2 hour" "2 hour" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 novo item" +"%d new items" "%d novos items" +"new" "novo" +"error" "erro" +"not down" "não transferido" +"enquequed" "em fila de espera" +"downloading" "a transferir" +"downloaded" "transferido" +"connecting" "a conectar" +"not found" "não encontrado" +"stopped" "parado" +"can't connect" "can't connect" +"invalid format" "invalid format" + +"Icon" "Icon" +"Title" "Título" +"Date" "Data" +"Size" "Tamanho" +"Status" "Estado" +"Download" "Transferir" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "Adicionar Canal" +"Remove Channel" "Remover Canal" +"Check Channel" "Verificar Canal" +"Open Homepage" "Abrir Homepage" + +"Open Web Page" "Open Web Page" +"Open Enclosures folder" "Abrir pasta dos anexos" +"Check All Channels" "Verificar todos os Canais" + +"Show Channel Image" "Show Channel Image" + +"Play enclosure" "Ouvir/ver anexo" +"(Re)start download" "(Re)iniciar transferência" +"Stop download" "Parar transferência" +"Remove Item" "Remover Item" + +"Find this Item" "Procurar este item" +"Remove from this list" "Remover desta lista" + + + +### ALERT ----------------------------------- + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "Só pode adicionar até 10 canais nesta versão não registada do BePodder.\nPor favor registe a sua cópia\n" + + +"Can't open the selected file with:\n\n" "Não é possível abrir o ficheiro seleccionado com:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nPor favor verifique se a aplicação está instalada correctamente.\n" + +"Download it!" "Transfira!" + +"\nRemoving.." "\nA remover.." +"\nAn error occured while removing!" \nOcorreu um erro durante a remoção!" +"Check all the podcasts for new items" "Verificar se existem novos items em todos os podcasts" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +Vai remover o item seleccionado. + +Tem a certeza? +(perderá o anexo se presente)" + + +_key="alert2a" + _value=" +Vai remover o canal: + +" + +_key="alert2b" + _value=" + +Pretende apenas arquivar o canal (mantendo +todos os ficheiros e anexos transferidos) or +quer APAGAR do seu computador o canal na +sua totalidade?" + +_key="alert3" + _value=" +A optimizar o arquivo.." + +_key="alert_3gp" + _value=" +3GP é um formato multimédia, definido pelo projecto Third Generation Partnership Project (3GPP) para ser usado em telemóveis 3G. Armazena vídeos como MPEG-4 ou H.263, e áudio como AMR-NB ou AAC-LC. + +VideoLAN VLC ainda não suporta o formato de áudio AMR (3GPP)" + +_key="alert_swf" + _value=" +SWF é um formato proprietário de ficheiros de gráficos vectoriais produzido pelo software Flash da Adobe (anteriormente Macromedia). + +Actualmente o suporte Flash no BeOS/Haiku/Zeta está limitado a um leitor Flash versão 4.1015, não existe um leitor Flash recente." + + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Introducão" +"The User Interface" "O Interface do Utilizador" +"Menu Bar" "Barra de Menu" +"Toolbar Buttons" "Botões da Barra de Ferramentas" +"First time with BePodder" "Primeira vez com o BePodder" +"Download Podcast's enclosure files" "Transferir anexos dos Podcasts" +"Settings Overview" "Vista geral das definições" +"Directory lists" "Listas de Directórios" +"Loading Help..." "A carregar a Ajuda..." +"Register your copy" "Registe a sua cópia" +"Starting point" "Ponto de arranque" + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value="Welcome to the BePodder Getting Started Guide." + +_key="help1-1" + _value="Se já está familiarizado com podcasts e feeds RSS pode começar a usar o BePodder imediatamente fechando esta janela." + +_key="help1-2" +_value="Se não for o caso, esta é uma pequena introdução que lhe irá fornecer tudo o que precisa de saber para começar a usar o BePodder.Utilize os botões abaixo para ver este tutorial." + + +_key="help2-0" + _value="Podcasts são um método de publicação de áudio e vídeo na Internet; +links para ficheiros vídeo e áudio, gratuitos, são anexados aos feeds RSS e Atom." + +_key="help2-1" +_value="Portanto, Podcasts são apenas um método de distribuição multimédia online; os utilizadores podem subscrever um podcast usando para tal um feed (como o RSS 'Really Simple Syndication' ou o Atom)." + +_key="help2-2" +_value="Um agregador Existe software, como o BePodder, que agrega (podcatcher) todos os feeds que subscreveu e que periodicamente verifica se há novo conteúdo e o transfere. Com o BePodder pode procurar por novos episódios nos seus Canais. Qualquer um pode conter um anexo, como o e-mail o faz também." + + +_key="help3-0" +_value="O BePodder tem um interface fácil de utilizar mas poderoso ao mesmo tempo. A janela principal está dividida em três paineis:" + +_key="help3-1" +_value="1) A lista de Subscrições (o painel com o número 1 na imagem) contém a lista de Podcasts subscritos por si. Quando clica num Canal pode ver no painel 2 a lista de items do canal." + +_key="help3-2" +_value="2) A lista de Episódios com todos os items disponíveis." + +_key="help3-3" +_value="3) O painel de informações exibe: informação do episódio, informação do canal ou informação das transferências; pode seleccionar um painel de informações clicando num dos três botões." + + + +_key="help4-0" +_value="No cimo da janela principal do BePodder está a barra de menus com sete menus disponíveis: Ficheiro, Definições, Subscrições, Episódios, Listas, Ver e Ajuda. Alguns comandos nos menus têm uma seta à direita que indica a existência dum submenu com comandos relacionados. À medida que explora cada menu, não se esqueça de navegar pelos submenus também. Clique nos menus para ver os comandos de cada um:" + +_key="help4-1" +_value="Ficheiro: contém comandos para fechar esta aplicação e mostrar informação sobre o BePodder" + +_key="help4-2" +_value="Definiçõe: contém comandos para abrir as Preferências, que lhe permite customizar várias definições do BePodder." + +_key="help4-3" +_value="Subscrições: contém comandos que executam acções no canal escolhido, da sua lista de subscrições." + +_key="help4-4" +_value="Episódios: contém comandos que executam acções no item seleccionado (episódio) da lista dos episódios do canal." + +_key="help4-5" +_value="Listas: contém comandos para abrir os directórios OPML do BePodder." + +_key="help4-6" +_value="Ver: contém comandos e controlos para a janela do BePodder." + +_key="help4-7" +_value="Ajuda: contém comandos para abrir o 'Guia de Arranque' do BePodder e a 'Lista de Atalhos do Teclado'." + + + +_key="help5-0" + _value="Botão Adicionar: abre a janela Adicionar para que possa adicionar um URL (endereço) dum feed (p.e. http://www.newpodcast.com/rss.xml), normalmente fornecido na homepage do podcast; procure por um link de texto ou gráfico que diga algo como 'XML', 'RSS' ou 'Podcast Feed'." + +_key="help5-1" + _value="Botão Remover Canal: abre uma janela na qual pode seleccionar como remover o canal: arquivar apenas o canal (mantendo todos os ficheiros e anexos transferidos até à data) ou apagar totalmente o canal do seu computador." + +_key="help5-2" + _value="Botão de Verificação: verifica o canal seleccionado e actualiza a lista com novos items disponiveis para esse podcast, se os houver." + +_key="help5-3" + _value="Botão Web: mostra a homepage do canal no browser. Para escolher o seu browser preferido abra as Preferências do BePodder, clicando no menu Definiçoes->Preferências... e na janela das Preferências em 'Tipo de Ficheiro' seleccione o seu browser preferido." + +_key="help5-4" + _value="Botão de Leitura: com este botão pode ver ou ouvir os anexos do ite (episódio) seleccionado. Para escolher o seu leitor preferido abra as Preferências do BePodder, clicando no menu Definiçoes->Preferências... e na janela das Preferências em 'Tipo de Ficheiro' seleccione o seu leitor." + +_key="help5-5" + _value="Botão Transferir: transfere o(s) anexo(s) do item seleccionado (episódio); pode ver informação sobre a transferência clicando no terceiro botão no painel de informação." + +_key="help5-6" + _value="Botão Stop: pára a transferência do anexo do item (episódio) seleccionado; para resumir a transferência clique duas vezes o item ou seleccione-o e clique novamente no botão Transferir." + +_key="help5-7" + _value="Botão Remover Item: apaga o item seleccionado (perderá o anexo nele incluído)." + + + + +_key="help6-0" + _value="Começar a utilizar o BePodder é fácil." + +_key="help6-1" + _value="À esquerda pode ver uma lista das suas subscrições. Adicionámos algumas por si, mas pode sempre adicionar as suas de duas maneiras:" + +_key="help6-2" + _value="1) clique no botão 'Adicionar o podcast...', e de seguida na janela que aparece, escreva o endereço do feed (por exemplo: http://www.newpodcast.com/rss.xml) e clique em Adicionar." + +_key="help6-3" + _value="2) Seleccione o menu 'Directório' e depois 'Lista de Podcasts' ou 'Lista de Videoblogs', escolha um podcast e clique em 'Subscrever'." + +_key="help6-4" + _value="Se seleccionar um Podcast da lista e clicar no botão, o BePodder adiciona os novos items na 'Lista de Episódios' à direita; pode verificar todos os seus podcasts ao clicar com o botão direito e seleccionar 'Verificar todos os Canais' no menu." + +_key="help6-5" + _value="Veja as imagens acima, três items estão com um ponto negro na primeira coluna da 'Lista de Episódios'." + +_key="help6-6" + _value="Na segunda coluna existem ícones que indicam o estado do item:" + +_key="help6-7" + _value="- o Episódio 4 tem um ícone que indica um erro" + +_key="help6-8" + _value="- o Episódio 3 tem um ícone que indica que a transferência do anexo está em fila de espera" + +_key="help6-9" + _value="- o Episódio 2 tem um ícone que indica que o BePodder está a transferir o anexo" + +_key="help6-10" + _value="- o Episódio 1 tem um ícone que indica que o BePodder acabou de transferir o anexo" + + + +_key="help7-0" + _value="Seleccione um item na 'Lista de Episódios' e depois faça duplo-clique no item ou clique no botão (Transfere...); pode sempre interromper a transferência clicando no botão 'Parar transferência'." + +_key="help7-1" + _value="Quando clica num Podcast na 'Lista de Podcasts', o programa mostra-lhe na lista à direita todos os items disponíveis para esse Podcast. Seleccione um item e clique em 'Ouvir/Ver ...' para ver ou ouvir o ficheiro." + +_key="help7-2" + _value="Pode aceder à pasta dos anexos clicando no ícone da pasta no painel de Informação ou clicando com o botão direito e seleccionando 'Abrir pasta dos anexos' no menu." + + + +_key="help8-0" + _value="Pode aceder às Preferências clicando no menu Definições->Preferências. Pode escolher uma categoria da lista à esquerda: Tipo de Ficheiro, Canais, Transferências e Servidor Proxy."" + +_key="help8-1" + _value="- Tipo de Ficheiro: para especificar o browser e o leitor preferidos." + +_key="help8-2" + _value="- Canais: para especificar preferências que controlam a verificação de novos items nos canais; pode escolher entre verificar Todos no arranque do BePodder ou num intervalo especificado de minutos." + +_key="help8-3" + _value="- Transferências: para especificar o número máximo de anexos que podem ser transferidos ao mesmo tempo." + +_key="help8-4" + _value="- Servidor Proxy: para configurar um servidor proxy para trabalhar com o BePodder; um servidor de proxy actua como uma barreira de segurança entre a sua rede interna e a Internet, mantendo quem está na Internet afastados, impedindo-os de aceder à sua informação na rede interna." + + + +_key="help9-0" + _value="O BePodder tem incluídos directórios OPML de videoblogs, feeds de imagens, feeds de notícias, feeds bittorrent e feeds internacionais com milhares de feeds organizados por categorias." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) é um formato com base em XML que permite a troca de informação estruturada entre aplicações." + +_key="help9-2" + _value="Um directório OPML pode ser acedido clicando no menu 'Listas' e de seguida escolhendo a lista. Para navegar o directório à procura dum feed, expanda a lista clicando na seta da categoria desejada (ver imagem); ao usar este método, pode expandir o directório OPML até encontrar o feed desejado. Uma vez seleccionado, pode adicioná-lo à lista de subscrições clicando no botão 'Subscrever', pode também fechar todas as categorias na lista de directórios clicando no botão 'Fechar Todos'." + + +_key="help_shortcut1" +_value="Esta página descreve os atalhos de teclado que podem ser utilizados no BePodder. Os atalhos estão aqui agrupados por função." + +_key="help_shortcut2" +_value="signifca que pode utilizar ou Alt ou Control (p.e. Alt+Q ou Ctrl+Q Fecha a aplicação), dependendo da configuração por si definida nas Preferências da Deskbar na secção Teclado (a tecla de atalho pré-definida é Alt)." + +_key="help_shortcut3" + _value="atalhos gerais" + +_key="help_shortcut4" + _value="Fecha a aplicação" + +_key="help_shortcut5" + _value="Exibe a janela das Preferências" + +_key="help_shortcut6" + _value="Exibe a lista do directório de Podcasts" + +_key="help_shortcut7" + _value="Existe a lista do directório de Videoblogs" + +_key="help_shortcut8" + _value="Exibe a lista do directório de feeds de Imagens" + +_key="help_shortcut9" + _value="Exibe a lista do directório de feeds de Notícias" + +_key="help_shortcut9b" + _value="Exibe a lista do directório de feeds Bittorrent" + +_key="help_shortcut9c" + _value="Exibe a lista do directório de feeds Internacionais" + +_key="help_shortcut10" + _value="Ecrã Total" + +_key="help_shortcut11" + _value="Exibe/Esconde a barra de ferramentas" + +_key="help_shortcut12" + _value="Exibe o Guia de Arranque" + +_key="help_shortcut13" + _value="Exibe a página com os atalhos de Teclado" + +_key="help_shortcut14" + _value="Atalhos dos Canais" + +_key="help_shortcut15" + _value="Adiciona um podcast à lista de subscrições" + +_key="help_shortcut16" + _value="Apaga o podcast seleccionado à lista de subscrições" list" + +_key="help_shortcut17" + _value="Verifica se existem actualizações para o podcast seleccionado" + +_key="help_shortcut18" + _value="Verifica se existem actualizações para todos os podcasts" + +_key="help_shortcut19" + _value="Exibe a homepage do podcast" + +_key="help_shortcut20" + _value="Abre a pasta dos anexos" + +_key="help_shortcut21" + _value="Atalhos dos Episódios" + +_key="help_shortcut22" + _value="Lê anexo" + +_key="help_shortcut23" + _value="Resume a transferência dos episódios seleccionados" + +_key="help_shortcut24" + _value="Pára a transferência do episódio" + +_key="help_shortcut25" + _value="Apaga o episódio seleccionado" + +_key="help_shortcut26" + _value="Exibe a página do episódio do podcast" + +_key="help_shortcut27" + _value="Abre a pasta dos anexos" + +_key="help_buy1" + _value="O BePodder Light é uma versão básica (transferência grátis e sem limite de tempo), a versão registada adiciona as melhorias: número ilimitado de canais, vista de Canal, suporte para servidor de proxy, verificação automática de canais, transferência simultânea de 5 anexos." + +_key="help_buy2" + _value="Por favor compre a versão registada, são apenas 15 euros (a Kagi adiciona impostos de venda em alguns países). A licença do BePodder pode ser adquirida online através da Kagi." + +_key="help_buy3" + _value="Compre em www.funkyideasoft.com" + +_key="help_buy4" + _value="Após a compra, um e-mail ser-lhe-á enviado com um ficheiro chave e instruções sobre como instalá-lo. Basta descompactar o ficheiro e movê-lo para um directório." + +_key="help_buy5" + _value="Pode actualizar o BePodder sem problemas, quando uma nova versão fica disponível. O ficheiro chave desbloqueia todos os pacotes transferidos, a não ser que receba instruções em contrário." + + + +### USELESS ######## + +"Opml Editor" "Editor Opml" +"name:" "nome:" +"Add a categorie" "Adicionar uma categoria" +"Add a new Broadcast" "Adicionar um novo Broadcast" +"feed:" "feed:" +"url:" "endereço:" +"Test podcast" "Testar o podcast" +"Del a categorie" "Apagar uma a categoria" +"Add a categorie" "Adicionar uma categoria" +"Select the podcast categorie:" "Seleccione a categoria do podcast:" +"Check all" "Verificar todos" +"Check" "Verificar" +"Refresh the list" "Actualizar a lista" +"Load" "Carregar" +"Load the list" "Carregar a lista" +"Save" "Gravar" +"Save the list" "Gravar a lista" +"Revert" "Revert" +"Apply" "Apply" + + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.ptPT b/release/Language/Dictionaries/BePodder.ptPT new file mode 100644 index 0000000..e1bd55a --- /dev/null +++ b/release/Language/Dictionaries/BePodder.ptPT @@ -0,0 +1,603 @@ + +# Locale file for BePodder. +# Modified: 4/18/2006 +# Author: Daniel "DaaT" Teixeira +# E-mail: daat@iscomputeron.com + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Aplicação Shareware!\n\nPor favor suporte o nosso trabalho!\n\nCompre uma licença!\nMais informação na nossa página na Internet\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "Esta cópia do BePodder expirou!\nPor favor compre uma licença, suportando o nosso trabalho.\n" + +"Web Site" "Página na Internet" + +"Can't connect!" "Não é possível conectar!" +"Http port failed!" "Erro na porta http!" +"Can't resolve host!" "Anfitrião não encontrado!" +"Not found!" "Não encontrado!" +"Bad resume!" "Erro ao resumir!" +"Aborted by Callback!" "Abortado por Callback!" +"Can't resume! (range error)" "Não é possível resumir! (erro de alcance)" +"Access Denied!" "Acesso Negado!" +"User or Password Incorrect!" "Utilizador ou Palavra-passe incorrectos!" +"Other error (cUrl code: " "Outro erro (código cUrl: " +"cUrl init error!" "cUrl erro init!" +"Can't open file!" "Não é possível abrir o ficheiro!" +"Other error (status code: " "Outro erro (código do status: " +"Downloading" "A transferir" + +### MENUBAR ----------------------------------- + +"File" "Ficheiro" +"About..." "Sobre..." +"Close!" "Fechar!" +"Quit" "Quit" + +"Settings" "Definições" +"Preferences..." "Preferências..." + +"Subscriptions" "Subscrições" + +"Episodes" "Episodes" + +"Lists" "Lists" +"Podcast List" "Lista de Podcasts" +"Podcast directory list" "Lista de directórios de Podcasts" +"Videoblog List" "Lista de Videoblogs" +"Videoblog directory list" "Lista de directórios de Videoblogs" +"Imagefeeds List" "Lista de Imagefeeds" +"Imagefeeds directory list" "Lista de directórios de Imagefeeds" +"Newsfeeds List" "Lista de Newsfeeds" +"Newsfeeds directory list" "Lista de directórios de Newsfeeds" +"BitTorrentfeeds List" "Lista de BitTorrentfeeds" +"BitTorrentfeeds directory list" "Lista de directórios de BitTorrentfeeds" +"Internationalfeeds List" "Lista de Internationalfeeds" +"Internationalfeeds directory list" "Lista de directórios de Internationalfeeds" + + +"View" "Ver" +"Full Screen" "Ecrã total" +"Toolbar" "Barra de Ferramentas" +"Subscriptions View" "Vista de subscrições" +"Small Items" "Items Pequenos" +"Big Items" "Items Grandes" +"Move BePodder on workspace:" "Mover o BePodder para o workspace:" + +"Help" "Ajuda" +"Getting Started" "Iniciar" +"Keyboard Shortcuts" "Atalhos do teclado" +"Tutorials" "Tutoriais" +"Online Support" "Suporte Online" + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "Insira o endereço do feed rss!" +"Add" "Adicionar" +"Paste" "Colar" + +# Buttons directory list window +"Collapse All" "Fechar Todos" +"Preview" "Previsão" +"Subscribe" "Subscrever" + + +# Buttons help window +"Next" "Seguinte" +"Prev" "Anterior" +"Close" "Fechar" +"Index" "Index" + + +# Buttons remove windows +"Cancel" "Cancelar" +"Delete" "Apagar" +"Archive" "Archive" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Adiciona o podcast à lista de Subscrições" +"Delete the podcast from the Subscriptions list" "Apaga o podcast da lista de Subscrições" +"Check the selected podcast for new items" "Verifica se existem items novos no podcast seleccionado" +"Show the podcast homepage" "Mostra a homepage do podcast" + +"Delete the item and the enclosure" "Delete the item and the enclosure" +"Stop the item download" "Pára a transferência" +"Download the selected episode" "Transfere o episódio seleccionado" +"Play the selected episode" "Ouvir/ver o episódio seleccionado" + +"Submit bug and idea" "Submete bugs e ideias" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Fechar todas as categorias na lista de directórios" +"Add the selected podcast to the Subscription list" "Adicionar o podcast seleccionado à lista de Subscrições" +"Checkout a podcast before downloading it" "Checkout a podcast before downloading it" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Show Channel Image" +"XML Feed Link" "XML Feed Link" + +"Show Episode info" "Show Episode info" +"Show Subscription info" "Show Subscription info" +"Show Downloads info" "Show Downloads info" + +"Enclosure: " "Anexo: " + +"Lookup (Dictionary)" "Procurar (Dicionário)" +"Lookup (Google)" "Procurar (Google)" +"Lookup (Acronym Finder)" "Procurar (Acrónimos)" +"Copy" "Copiar" +"Select All" "Seleccionar todos" +"Copy URL" "Copy URL" +"Open URL" "Open URL" +"Subscription" "Subscription" + + + +### PREFERENCES ----------------------------------- + +"Preferences" "Preferências" + +"Proxy" "Proxy" +"Enable Proxy" "Enable Proxy" +"Address" "Address" +"Port" "Port" +"Username" "Username" +"Password" "Password" + +"Max Downloads" "Max Downloads" + +"FileType" "FileType" +"Browser" "Navegador:" +"Player" "Leitor:" + +"Channels" "Channels" +"Check all channels on startup" "Check all channels on startup" +"Check the channel every" "Check the channel every" + +"never" "never" +"5 minutes" "5 minutes" +"15 minutes" "15 minutes" +"30 minutes" "30 minutes" +"1 hour" "1 hour" +"2 hour" "2 hour" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 novo item" +"%d new items" "%d novos items" +"new" "novo" +"error" "erro" +"not down" "não transferido" +"enquequed" "em fila de espera" +"downloading" "a transferir" +"downloaded" "transferido" +"connecting" "a conectar" +"not found" "não encontrado" +"stopped" "parado" +"can't connect" "can't connect" +"invalid format" "invalid format" + +"Icon" "Icon" +"Title" "Título" +"Date" "Data" +"Size" "Tamanho" +"Status" "Estado" +"Download" "Transferir" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "Adicionar Canal" +"Remove Channel" "Remover Canal" +"Check Channel" "Verificar Canal" +"Open Homepage" "Abrir Homepage" + +"Open Web Page" "Open Web Page" +"Open Enclosures folder" "Abrir pasta dos anexos" +"Check All Channels" "Verificar todos os Canais" + +"Show Channel Image" "Show Channel Image" + +"Play enclosure" "Ouvir/ver anexo" +"(Re)start download" "(Re)iniciar transferência" +"Stop download" "Parar transferência" +"Remove Item" "Remover Item" + +"Find this Item" "Procurar este item" +"Remove from this list" "Remover desta lista" + + + +### ALERT ----------------------------------- + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "Só pode adicionar até 10 canais nesta versão não registada do BePodder.\nPor favor registe a sua cópia\n" + + +"Can't open the selected file with:\n\n" "Não é possível abrir o ficheiro seleccionado com:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nPor favor verifique se a aplicação está instalada correctamente.\n" + +"Download it!" "Transfira!" + +"\nRemoving.." "\nA remover.." +"\nAn error occured while removing!" \nOcorreu um erro durante a remoção!" +"Check all the podcasts for new items" "Verificar se existem novos items em todos os podcasts" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +Vai remover o item seleccionado. + +Tem a certeza? +(perderá o anexo se presente)" + + +_key="alert2a" + _value=" +Vai remover o canal: + +" + +_key="alert2b" + _value=" + +Pretende apenas arquivar o canal (mantendo +todos os ficheiros e anexos transferidos) or +quer APAGAR do seu computador o canal na +sua totalidade?" + +_key="alert3" + _value=" +A optimizar o arquivo.." + +_key="alert_3gp" + _value=" +3GP é um formato multimédia, definido pelo projecto Third Generation Partnership Project (3GPP) para ser usado em telemóveis 3G. Armazena vídeos como MPEG-4 ou H.263, e áudio como AMR-NB ou AAC-LC. + +VideoLAN VLC ainda não suporta o formato de áudio AMR (3GPP)" + +_key="alert_swf" + _value=" +SWF é um formato proprietário de ficheiros de gráficos vectoriais produzido pelo software Flash da Adobe (anteriormente Macromedia). + +Actualmente o suporte Flash no BeOS/Haiku/Zeta está limitado a um leitor Flash versão 4.1015, não existe um leitor Flash recente." + + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Introducão" +"The User Interface" "O Interface do Utilizador" +"Menu Bar" "Barra de Menu" +"Toolbar Buttons" "Botões da Barra de Ferramentas" +"First time with BePodder" "Primeira vez com o BePodder" +"Download Podcast's enclosure files" "Transferir anexos dos Podcasts" +"Settings Overview" "Vista geral das definições" +"Directory lists" "Listas de Directórios" +"Loading Help..." "A carregar a Ajuda..." +"Register your copy" "Registe a sua cópia" +"Starting point" "Ponto de arranque" + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value="Welcome to the BePodder Getting Started Guide." + +_key="help1-1" + _value="Se já está familiarizado com podcasts e feeds RSS pode começar a usar o BePodder imediatamente fechando esta janela." + +_key="help1-2" +_value="Se não for o caso, esta é uma pequena introdução que lhe irá fornecer tudo o que precisa de saber para começar a usar o BePodder.Utilize os botões abaixo para ver este tutorial." + + +_key="help2-0" + _value="Podcasts são um método de publicação de áudio e vídeo na Internet; +links para ficheiros vídeo e áudio, gratuitos, são anexados aos feeds RSS e Atom." + +_key="help2-1" +_value="Portanto, Podcasts são apenas um método de distribuição multimédia online; os utilizadores podem subscrever um podcast usando para tal um feed (como o RSS 'Really Simple Syndication' ou o Atom)." + +_key="help2-2" +_value="Um agregador Existe software, como o BePodder, que agrega (podcatcher) todos os feeds que subscreveu e que periodicamente verifica se há novo conteúdo e o transfere. Com o BePodder pode procurar por novos episódios nos seus Canais. Qualquer um pode conter um anexo, como o e-mail o faz também." + + +_key="help3-0" +_value="O BePodder tem um interface fácil de utilizar mas poderoso ao mesmo tempo. A janela principal está dividida em três paineis:" + +_key="help3-1" +_value="1) A lista de Subscrições (o painel com o número 1 na imagem) contém a lista de Podcasts subscritos por si. Quando clica num Canal pode ver no painel 2 a lista de items do canal." + +_key="help3-2" +_value="2) A lista de Episódios com todos os items disponíveis." + +_key="help3-3" +_value="3) O painel de informações exibe: informação do episódio, informação do canal ou informação das transferências; pode seleccionar um painel de informações clicando num dos três botões." + + + +_key="help4-0" +_value="No cimo da janela principal do BePodder está a barra de menus com sete menus disponíveis: Ficheiro, Definições, Subscrições, Episódios, Listas, Ver e Ajuda. Alguns comandos nos menus têm uma seta à direita que indica a existência dum submenu com comandos relacionados. À medida que explora cada menu, não se esqueça de navegar pelos submenus também. Clique nos menus para ver os comandos de cada um:" + +_key="help4-1" +_value="Ficheiro: contém comandos para fechar esta aplicação e mostrar informação sobre o BePodder" + +_key="help4-2" +_value="Definiçõe: contém comandos para abrir as Preferências, que lhe permite customizar várias definições do BePodder." + +_key="help4-3" +_value="Subscrições: contém comandos que executam acções no canal escolhido, da sua lista de subscrições." + +_key="help4-4" +_value="Episódios: contém comandos que executam acções no item seleccionado (episódio) da lista dos episódios do canal." + +_key="help4-5" +_value="Listas: contém comandos para abrir os directórios OPML do BePodder." + +_key="help4-6" +_value="Ver: contém comandos e controlos para a janela do BePodder." + +_key="help4-7" +_value="Ajuda: contém comandos para abrir o 'Guia de Arranque' do BePodder e a 'Lista de Atalhos do Teclado'." + + + +_key="help5-0" + _value="Botão Adicionar: abre a janela Adicionar para que possa adicionar um URL (endereço) dum feed (p.e. http://www.newpodcast.com/rss.xml), normalmente fornecido na homepage do podcast; procure por um link de texto ou gráfico que diga algo como 'XML', 'RSS' ou 'Podcast Feed'." + +_key="help5-1" + _value="Botão Remover Canal: abre uma janela na qual pode seleccionar como remover o canal: arquivar apenas o canal (mantendo todos os ficheiros e anexos transferidos até à data) ou apagar totalmente o canal do seu computador." + +_key="help5-2" + _value="Botão de Verificação: verifica o canal seleccionado e actualiza a lista com novos items disponiveis para esse podcast, se os houver." + +_key="help5-3" + _value="Botão Web: mostra a homepage do canal no browser. Para escolher o seu browser preferido abra as Preferências do BePodder, clicando no menu Definiçoes->Preferências... e na janela das Preferências em 'Tipo de Ficheiro' seleccione o seu browser preferido." + +_key="help5-4" + _value="Botão de Leitura: com este botão pode ver ou ouvir os anexos do ite (episódio) seleccionado. Para escolher o seu leitor preferido abra as Preferências do BePodder, clicando no menu Definiçoes->Preferências... e na janela das Preferências em 'Tipo de Ficheiro' seleccione o seu leitor." + +_key="help5-5" + _value="Botão Transferir: transfere o(s) anexo(s) do item seleccionado (episódio); pode ver informação sobre a transferência clicando no terceiro botão no painel de informação." + +_key="help5-6" + _value="Botão Stop: pára a transferência do anexo do item (episódio) seleccionado; para resumir a transferência clique duas vezes o item ou seleccione-o e clique novamente no botão Transferir." + +_key="help5-7" + _value="Botão Remover Item: apaga o item seleccionado (perderá o anexo nele incluído)." + + + + +_key="help6-0" + _value="Começar a utilizar o BePodder é fácil." + +_key="help6-1" + _value="À esquerda pode ver uma lista das suas subscrições. Adicionámos algumas por si, mas pode sempre adicionar as suas de duas maneiras:" + +_key="help6-2" + _value="1) clique no botão 'Adicionar o podcast...', e de seguida na janela que aparece, escreva o endereço do feed (por exemplo: http://www.newpodcast.com/rss.xml) e clique em Adicionar." + +_key="help6-3" + _value="2) Seleccione o menu 'Directório' e depois 'Lista de Podcasts' ou 'Lista de Videoblogs', escolha um podcast e clique em 'Subscrever'." + +_key="help6-4" + _value="Se seleccionar um Podcast da lista e clicar no botão, o BePodder adiciona os novos items na 'Lista de Episódios' à direita; pode verificar todos os seus podcasts ao clicar com o botão direito e seleccionar 'Verificar todos os Canais' no menu." + +_key="help6-5" + _value="Veja as imagens acima, três items estão com um ponto negro na primeira coluna da 'Lista de Episódios'." + +_key="help6-6" + _value="Na segunda coluna existem ícones que indicam o estado do item:" + +_key="help6-7" + _value="- o Episódio 4 tem um ícone que indica um erro" + +_key="help6-8" + _value="- o Episódio 3 tem um ícone que indica que a transferência do anexo está em fila de espera" + +_key="help6-9" + _value="- o Episódio 2 tem um ícone que indica que o BePodder está a transferir o anexo" + +_key="help6-10" + _value="- o Episódio 1 tem um ícone que indica que o BePodder acabou de transferir o anexo" + + + +_key="help7-0" + _value="Seleccione um item na 'Lista de Episódios' e depois faça duplo-clique no item ou clique no botão (Transfere...); pode sempre interromper a transferência clicando no botão 'Parar transferência'." + +_key="help7-1" + _value="Quando clica num Podcast na 'Lista de Podcasts', o programa mostra-lhe na lista à direita todos os items disponíveis para esse Podcast. Seleccione um item e clique em 'Ouvir/Ver ...' para ver ou ouvir o ficheiro." + +_key="help7-2" + _value="Pode aceder à pasta dos anexos clicando no ícone da pasta no painel de Informação ou clicando com o botão direito e seleccionando 'Abrir pasta dos anexos' no menu." + + + +_key="help8-0" + _value="Pode aceder às Preferências clicando no menu Definições->Preferências. Pode escolher uma categoria da lista à esquerda: Tipo de Ficheiro, Canais, Transferências e Servidor Proxy."" + +_key="help8-1" + _value="- Tipo de Ficheiro: para especificar o browser e o leitor preferidos." + +_key="help8-2" + _value="- Canais: para especificar preferências que controlam a verificação de novos items nos canais; pode escolher entre verificar Todos no arranque do BePodder ou num intervalo especificado de minutos." + +_key="help8-3" + _value="- Transferências: para especificar o número máximo de anexos que podem ser transferidos ao mesmo tempo." + +_key="help8-4" + _value="- Servidor Proxy: para configurar um servidor proxy para trabalhar com o BePodder; um servidor de proxy actua como uma barreira de segurança entre a sua rede interna e a Internet, mantendo quem está na Internet afastados, impedindo-os de aceder à sua informação na rede interna." + + + +_key="help9-0" + _value="O BePodder tem incluídos directórios OPML de videoblogs, feeds de imagens, feeds de notícias, feeds bittorrent e feeds internacionais com milhares de feeds organizados por categorias." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) é um formato com base em XML que permite a troca de informação estruturada entre aplicações." + +_key="help9-2" + _value="Um directório OPML pode ser acedido clicando no menu 'Listas' e de seguida escolhendo a lista. Para navegar o directório à procura dum feed, expanda a lista clicando na seta da categoria desejada (ver imagem); ao usar este método, pode expandir o directório OPML até encontrar o feed desejado. Uma vez seleccionado, pode adicioná-lo à lista de subscrições clicando no botão 'Subscrever', pode também fechar todas as categorias na lista de directórios clicando no botão 'Fechar Todos'." + + +_key="help_shortcut1" +_value="Esta página descreve os atalhos de teclado que podem ser utilizados no BePodder. Os atalhos estão aqui agrupados por função." + +_key="help_shortcut2" +_value="signifca que pode utilizar ou Alt ou Control (p.e. Alt+Q ou Ctrl+Q Fecha a aplicação), dependendo da configuração por si definida nas Preferências da Deskbar na secção Teclado (a tecla de atalho pré-definida é Alt)." + +_key="help_shortcut3" + _value="atalhos gerais" + +_key="help_shortcut4" + _value="Fecha a aplicação" + +_key="help_shortcut5" + _value="Exibe a janela das Preferências" + +_key="help_shortcut6" + _value="Exibe a lista do directório de Podcasts" + +_key="help_shortcut7" + _value="Existe a lista do directório de Videoblogs" + +_key="help_shortcut8" + _value="Exibe a lista do directório de feeds de Imagens" + +_key="help_shortcut9" + _value="Exibe a lista do directório de feeds de Notícias" + +_key="help_shortcut9b" + _value="Exibe a lista do directório de feeds Bittorrent" + +_key="help_shortcut9c" + _value="Exibe a lista do directório de feeds Internacionais" + +_key="help_shortcut10" + _value="Ecrã Total" + +_key="help_shortcut11" + _value="Exibe/Esconde a barra de ferramentas" + +_key="help_shortcut12" + _value="Exibe o Guia de Arranque" + +_key="help_shortcut13" + _value="Exibe a página com os atalhos de Teclado" + +_key="help_shortcut14" + _value="Atalhos dos Canais" + +_key="help_shortcut15" + _value="Adiciona um podcast à lista de subscrições" + +_key="help_shortcut16" + _value="Apaga o podcast seleccionado à lista de subscrições" list" + +_key="help_shortcut17" + _value="Verifica se existem actualizações para o podcast seleccionado" + +_key="help_shortcut18" + _value="Verifica se existem actualizações para todos os podcasts" + +_key="help_shortcut19" + _value="Exibe a homepage do podcast" + +_key="help_shortcut20" + _value="Abre a pasta dos anexos" + +_key="help_shortcut21" + _value="Atalhos dos Episódios" + +_key="help_shortcut22" + _value="Lê anexo" + +_key="help_shortcut23" + _value="Resume a transferência dos episódios seleccionados" + +_key="help_shortcut24" + _value="Pára a transferência do episódio" + +_key="help_shortcut25" + _value="Apaga o episódio seleccionado" + +_key="help_shortcut26" + _value="Exibe a página do episódio do podcast" + +_key="help_shortcut27" + _value="Abre a pasta dos anexos" + +_key="help_buy1" + _value="O BePodder Light é uma versão básica (transferência grátis e sem limite de tempo), a versão registada adiciona as melhorias: número ilimitado de canais, vista de Canal, suporte para servidor de proxy, verificação automática de canais, transferência simultânea de 5 anexos." + +_key="help_buy2" + _value="Por favor compre a versão registada, são apenas 15 euros (a Kagi adiciona impostos de venda em alguns países). A licença do BePodder pode ser adquirida online através da Kagi." + +_key="help_buy3" + _value="Compre em www.funkyideasoft.com" + +_key="help_buy4" + _value="Após a compra, um e-mail ser-lhe-á enviado com um ficheiro chave e instruções sobre como instalá-lo. Basta descompactar o ficheiro e movê-lo para um directório." + +_key="help_buy5" + _value="Pode actualizar o BePodder sem problemas, quando uma nova versão fica disponível. O ficheiro chave desbloqueia todos os pacotes transferidos, a não ser que receba instruções em contrário." + + + +### USELESS ######## + +"Opml Editor" "Editor Opml" +"name:" "nome:" +"Add a categorie" "Adicionar uma categoria" +"Add a new Broadcast" "Adicionar um novo Broadcast" +"feed:" "feed:" +"url:" "endereço:" +"Test podcast" "Testar o podcast" +"Del a categorie" "Apagar uma a categoria" +"Add a categorie" "Adicionar uma categoria" +"Select the podcast categorie:" "Seleccione a categoria do podcast:" +"Check all" "Verificar todos" +"Check" "Verificar" +"Refresh the list" "Actualizar a lista" +"Load" "Carregar" +"Load the list" "Carregar a lista" +"Save" "Gravar" +"Save the list" "Gravar a lista" +"Revert" "Revert" +"Apply" "Apply" + + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.ruRU b/release/Language/Dictionaries/BePodder.ruRU new file mode 100644 index 0000000..296dac8 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.ruRU @@ -0,0 +1,604 @@ + +# Locale file for BePodder. +# Modified: 4/18/2006 +# Author: BePodderTeam +# E-mail: bepodder.team@gmail.com + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" + +"Web Site" "Web Site" + +"Can't connect!" "Can't connect!" +"Http port failed!" "Http port failed!" +"Can't resolve host!" "Can't resolve host!" +"Not found!" "Not found!" +"Bad resume!" "Bad resume!" +"Aborted by Callback!" "Aborted by Callback!" +"Can't resume! (range error)" "Can't resume! (range error)" +"Access Denied!" "Access Denied!" +"User or Password Incorrect!" "User or Password Incorrect!" +"Other error (cUrl code: " "Other error (cUrl code: " +"cUrl init error!" "cUrl init error!" +"Can't open file!" "Can't open file!" +"Other error (status code: " "Other error (status code: " +"Downloading" "Downloading" + + +### MENUBAR ----------------------------------- + +"File" "File" +"About..." "About..." +"Close!" "Close!" +"Quit" "Quit" + +"Settings" "Settings" +"Preferences..." "Preferences..." + +"Subscriptions" "Subscriptions" + +"Episodes" "Episodes" + +"Lists" "Lists" +"Podcast List" "Podcast List" +"Podcast directory list" "Podcast directory list" +"Videoblog List" "Videoblog List" +"Videoblog directory list" "Videoblog directory list" +"Imagefeeds List" "Imagefeeds List" +"Imagefeeds directory list" "Imagefeeds directory list" +"Newsfeeds List" "Newsfeeds List" +"Newsfeeds directory list" "Newsfeeds directory list" +"BitTorrentfeeds List" "BitTorrentfeeds List" +"BitTorrentfeeds directory list" "BitTorrentfeeds directory list" +"Internationalfeeds List" "Internationalfeeds List" +"Internationalfeeds directory list" "Internationalfeeds directory list" + +"View" "View" +"Full Screen" "Full Screen" +"Toolbar" "Toolbar" +"Subscriptions View" "Subscriptions View" +"Small Items" "Small Items" +"Big Items" "Big Items" +"Move BePodder on workspace:" "Move BePodder on workspace:" + +"Help" "Help" +"Getting Started" "Getting Started" +"Keyboard Shortcuts" "Keyboard Shortcuts" +"Tutorials" "Tutorials" +"Online Support" "Online Support" + + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "Insert the rss feed url!" +"Add" "Add" +"Paste" "Paste" + +# Buttons directory list window +"Collapse All" "Collapse All" +"Preview" "Preview" +"Subscribe" "Subscribe" + + +# Buttons help window +"Next" "Next" +"Prev" "Prev" +"Close" "Close" +"Index" "Index" + + +# Buttons remove windows +"Cancel" "Cancel" +"Delete" "Delete" +"Archive" "Archive" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Add the podcast to the Subscriptions list" +"Delete the podcast from the Subscriptions list" "Delete the podcast from the Subscriptions list" +"Check the selected podcast for new items" "Check the selected podcast for new items" +"Show the podcast homepage" "Show the podcast homepage" + +"Delete the item and the enclosure" "Delete the item and the enclosure" +"Stop the item download" "Stop the item download" +"Download the selected episode" "Download the selected episode" +"Play the selected episode" "Play the selected episode" + +"Submit bug and idea" "Submit bug and idea" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Collapse all categories in the directory list" +"Add the selected podcast to the Subscription list" "Add the selected podcast to the Subscription list" +"Checkout a podcast before downloading it" "Checkout a podcast before downloading it" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Show Channel Image" +"XML Feed Link" "XML Feed Link" + +"Show Episode info" "Show Episode info" +"Show Subscription info" "Show Subscription info" +"Show Downloads info" "Show Downloads info" + +"Enclosure: " "Enclosure: " + +"Lookup (Dictionary)" "Lookup (Dictionary)" +"Lookup (Google)" "Lookup (Google)" +"Lookup (Acronym Finder)" "Lookup (Acronym Finder)" +"Copy" "Copy" +"Select All" "Select All" +"Copy URL" "Copy URL" +"Open URL" "Open URL" +"Subscription" "Subscription" + + +### PREFERENCES ----------------------------------- + +"Preferences" "Preferences" + +"Proxy" "Proxy" +"Enable Proxy" "Enable Proxy" +"Address" "Address" +"Port" "Port" +"Username" "Username" +"Password" "Password" + +"Max Downloads" "Max Downloads" + +"FileType" "FileType" +"Browser" "Browser" +"Player" "Player" + +"Channels" "Channels" +"Check all channels on startup" "Check all channels on startup" +"Check the channel every" "Check the channel every" + +"never" "never" +"5 minutes" "5 minutes" +"15 minutes" "15 minutes" +"30 minutes" "30 minutes" +"1 hour" "1 hour" +"2 hour" "2 hour" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 new item" +"%d new items" "%d new items" +"new" "new" +"error" "error" +"not down" "not down" +"enquequed" "enquequed" +"downloading" "downloading" +"downloaded" "downloaded" +"connecting" "connecting" +"not found" "not found" +"stopped" "stopped" +"can't connect" "can't connect" +"invalid format" "invalid format" + +"Icon" "Icon" +"Title" "Title" +"Date" "Date" +"Size" "Size" +"Status" "Status" +"Download" "Download" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "Add Channel" +"Remove Channel" "Remove Channel" +"Check Channel" "Check Channel" +"Open Homepage" "Open Homepage" + +"Open Web Page" "Open Web Page" +"Open Enclosures folder" "Open Enclosures folder" +"Check All Channels" "Check All Channels" + +"Show Channel Image" "Show Channel Image" + +"Play enclosure" "Play enclosure" +"(Re)start download" "(Re)start download" +"Stop download" "Stop download" +"Remove Item" "Remove Item" + +"Find this Item" "Find this Item" +"Remove from this list" "Remove from this list" + + + +### ALERT ----------------------------------- + +"\nRemoving.." "\nRemoving.." +"\nAn error occured while removing!" "\nAn error occured while removing!" +"Check all the podcasts for new items" "Check all the podcasts for new items" + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" + + +"Can't open the selected file with:\n\n" "Can't open the selected file with:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nPlease check if the application is installed in the right way.\n" +"Download it!" "Download it!" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +You are going to remove the selected item. + +Are you sure? +(you will lost the enclosure file if any)" + + +_key="alert2a" + _value=" +You are going to remove the channel: + +" + +_key="alert2b" + _value=" + +Would you like just to archive this +channel (keeping all the files and +enclosures downloaded so far) or +do you want to DELETE the whole + channel from you computer?" + +_key="alert3" + _value=" +Parsing archive.." + +_key="alert_3gp" + _value=" +3GP is a multimedia container format defined by the Third Generation Partnership Project (3GPP) for use on 3G mobile phones. It stores video streams as MPEG-4 or H.263, and audio streams as AMR-NB or AAC-LC. + +VideoLAN still doesn't support the audio AMR (3GPP)" + +_key="alert_swf" + _value=" +SWF is a proprietary vector graphics file format produced by the Flash software from Adobe (formerly Macromedia). + +Currently Flash support in BeOS/Haiku/Zeta is limited to the old standalone Flash player version 4.1015, there isn't a modern Flash player" + + + + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Introduction" +"The User Interface" "The User Interface" +"Menu Bar" "Menu Bar" +"Toolbar Buttons" "Toolbar Buttons" +"First time with BePodder" "First time with BePodder" +"Download Podcast's enclosure files" "Download Podcast's enclosure files" +"Settings Overview" "Settings Overview" +"Directory lists" "Directory lists" +"Loading Help..." "Loading Help..." +"Register your copy" "Register your copy" +"Starting point" "Starting point" + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value="Welcome to the BePodder Getting Started Guide." + +_key="help1-1" + _value="If you are already familiar with podcasts and RSS/Atom feeds you can immediately go to BePodder by closing this window." + +_key="help1-2" +_value="If not, this is a short introduction providing you everything you'll need to know on how to get started with BePodder. Use the buttons below to navigate through this tutorial." + + +_key="help2-0" +_value="Podcasting is a method for publishing audio and video broadcasts via the Internet; links to free audio and video files are enclosed in RSS and Atom feeds." + +_key="help2-1" +_value="Therefore Podcasting is simply a type of online media delivery; users can subscribe to a podcast using a feed (such as RSS 'Really Simple Syndication' or Atom)." + +_key="help2-2" +_value="An aggregator (or podcatcher) like BePodder, is a piece of software that allows you to subscribe to a RSS feed and periodically check for and download new content; with BePodder you can check for new Podcast items (Episodes) of your subscribed Channels. Any item can contain an enclosure, just like an Email can contain an attachment." + + + +_key="help3-0" +_value="BePodder has an easy to use yet powerful Graphical User Interface. The main window is split into tree panels:" + +_key="help3-1" +_value="1) The Subscription list (the panel with the number 1 in the screenshot) with the list of the podcasts that you have subscribed to. When you click on a Channel you can see in the panel 2 the list of the channel's items." + +_key="help3-2" +_value="2) The Episodes list with all the items available." + +_key="help3-3" +_value="3) The Info panel show: episode info, channel info or Downloads info; you can select an info panel by clicking one of the below three buttons." + + + +_key="help4-0" +_value="At the very top of the BePodder main window is the menubar with seven menus available: File, Settings, Subscriptions, Episodes, Lists, View and Help. Some menu commands are followed by a right pointing arrow that indicates a submenu of related commands. As you explore each menu, be sure to take a look at the submenus as well. Click on a menus to show its commands:" + +_key="help4-1" +_value="File: contains commands to close the application and to show information about BePodder" + +_key="help4-2" +_value="Settings: contains command to open the Preferences window that allows you to customize various BePodder settings." + +_key="help4-3" +_value="Subscriptions: contains commands that perform actions on the selected channel of your subscriptions list." + +_key="help4-4" +_value="Episodes: contains commands that perform actions on the selected item (episode) of the channel's episode list." + +_key="help4-5" +_value="Lists: contains commands to open BePodder's OPML directories." + +_key="help4-6" +_value="View: contains commands and controls for the BePodder window." + +_key="help4-7" +_value="Help: contains commands to open BePodder's 'Getting Started Guide' and the 'Keyboard Shortcuts List'." + + + +_key="help5-0" + _value="Add Button: opens the Add Window to add a feed url (e.g. http://www.newpodcast.com/rss.xml) usually given on the podcast homepage; looks for text or graphic link that says something like 'XML', 'RSS' or 'Podcast Feed' on it." + +_key="help5-1" + _value="Channel Remove Button: opens a window in which you can select how remove the channel: just archive the select channel (keeping all the files and eclosure downloaded so far) or delete the whole channel from your computer." + +_key="help5-2" + _value="Check Button: checks the selected channel and updates the list of the available items for that podcast adding the new items." + +_key="help5-3" + _value="Web Button: shows the channel homepage in the browser. To select your favorite browser open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select your favorite browser." + +_key="help5-4" + _value="Play Button: with this button you can view or listen the file enclosure of the selected item(episode). To select your favorite player open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select you favorite player." + +_key="help5-5" + _value="Download Button: downloads the file enclosure of the selected item (episode); you can see the download info by clicking on the third button over the info panel." + +_key="help5-6" + _value="Stop Button: stops to download the file enclosure of the selected item (episode); to resume the download double-click the item (episode) or select the item and click the Download Button" + +_key="help5-7" + _value="Item Remove Button: deletes the selected item (you will loose the enclosure file)." + + + +_key="help6-0" + _value="Getting started with BePodder is easy." + +_key="help6-1" + _value="On the left of the main window you can see the 'Subscription List' with all your feed subscriptions. We have added some subscriptions for you, and you can always add your own in two ways:" + +_key="help6-2" + _value="1) click the Add Button, then insert the feed url (example: http://www.newpodcast.com/rss.xml) and click add." + +_key="help6-3" + _value="2) in the menubar select 'Directory' and then 'Podcast list' or another list, choose a podcast and click 'Subscribe'." + +_key="help6-4" + _value="If you select a Podcast in the subscriptions list and use the check button, BePodder adds the new items to the 'Episodes list' (below on the right); you can check all your podcasts by right-clicking and selecting 'Check All Channels' in the context menu." + +_key="help6-5" + _value="Look at the screenshot above, there are 3 new items indicated by a black dot in the first column of the 'Episodes list'." + +_key="help6-6" + _value="In the second column there are icons that indicate the state of the item:" + +_key="help6-7" + _value="- the Episode 4 has an icon that indicates an error" + +_key="help6-8" + _value="- the Episode 3 has an icon that indicates that the item's enclosure download request is enquequed" + +_key="help6-9" + _value="- the Episode 2 has an icon that indicates that BePodder is downloading the item's enclosure file" + +_key="help6-10" + _value="- the Episode 1 have an icon that indicates that BePodder have just downloaded the item's enclosure file" + + + +_key="help7-0" + _value="Select an item in the 'Episodes list' and then double-click on it (or click the Download Button) to start downloading the enclosed file; you can always stop the download by clicking on the Stop Button." + +_key="help7-1" + _value="When you click on the Subscribed Podcasts in the 'Subscriptions List' the software shows you, in the 'List of episodes', all the items available in that Subscription. Select an item and then click play (Play Button) to view or listen to the file." + +_key="help7-2" + _value="You can access the Enclosures Folder by clicking on the folder icon in the Info Pannel or by right-clicking your mouse on an item and select 'Open Enclosures Folder' in the context menu." + + + +_key="help8-0" + _value="Preferences can be accessed by clicking in the menu-bar Settings>Preferences. You can select a category from the left list of the preferences dialog: FileType, Channels, Download and Proxy." + +_key="help8-1" + _value="- FileType: to specify the default browser and player. " + +_key="help8-2" + _value="- Channels: to specify preferences that control the operation to check channels new items; you can choose to Check all channels on startup or check the channel every desired minutes." + +_key="help8-3" + _value="- Download: to specify the max number of item's files to download at the same time," + +_key="help8-4" + _value="- Proxy: to set up a proxy server to work with BePodder; a proxy server acts as a security barrier between your internal network and the Internet, keeping others on the Internet from accessing information on your internal network." + + + +_key="help9-0" + _value="BePodder has built-in podcast, videoblog, imagefeeds, newsfeeds, bittorrentfeeds and internationalfeeds OPML directories with thousands of feeds grouped by category." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) is an XML-based format that allows exchange of outline-structured information between applications." + +_key="help9-2" + _value="OPML directory can be accessed by clicking in the menu-bar 'Lists' and thenselecting a list. To browse the opml directory for a feed, expand the list by clicking the arrow of the category that you are interested in (see image); using this method, you can expand the opml directory until you find the desired feed. Once you have selected it, you can add it to the subscription list by clicking the button 'Subscribe', you can also collapse all categories in the directory list by clicking the button 'Collapse All'." + +_key="help_shortcut1" +_value="This page describes the keyboard shortcuts that can be used in BePodder. The shortcuts are grouped here by function." + +_key="help_shortcut2" +_value="means that you can use either alt or control (es. Alt+Q or Ctrl+Q Quit the application), which way you have set it in the Deskbar menu preferences under Keyboard (the default shortcut key is Alt)." + +_key="help_shortcut3" + _value="General shortcuts" + +_key="help_shortcut4" + _value="Quit the application" + +_key="help_shortcut5" + _value="Shows the Preferences window" + +_key="help_shortcut6" + _value="Shows the Podcast directory list" + +_key="help_shortcut7" + _value="Shows the Videoblog directory list" + +_key="help_shortcut8" + _value="Shows the Imagefeeds directory list" + +_key="help_shortcut9" + _value="Shows the Newsfeeds directory list" + +_key="help_shortcut9b" + _value="Shows the BitTorrentfeeds directory list" + +_key="help_shortcut9c" + _value="Shows the Internationalfeeds directory list" + +_key="help_shortcut10" + _value="Fullscreen" + +_key="help_shortcut11" + _value="Shows/Hides the toolbar" + +_key="help_shortcut12" + _value="Shows the Getting Started Help" + +_key="help_shortcut13" + _value="Shows this keyboard shortcuts page" + +_key="help_shortcut14" + _value="Channels shortcuts" + +_key="help_shortcut15" + _value="Add a podcast to the subscriptions list" + +_key="help_shortcut16" + _value="Delete the selected podcast from the subscriptions list" + +_key="help_shortcut17" + _value="Check the selected podcast for new episodes (items)" + +_key="help_shortcut18" + _value="Check all podcasts for new episodes (items)" + +_key="help_shortcut19" + _value="Shows the podcast homepage" + +_key="help_shortcut20" + _value="Open enclosures folder" + +_key="help_shortcut21" + _value="Episodes shortcuts" + +_key="help_shortcut22" + _value="Play enclosure" + +_key="help_shortcut23" + _value="(Re)start download the selected episodes (items)" + +_key="help_shortcut24" + _value="Stop the episode (item) download" + +_key="help_shortcut25" + _value="Delete the selected episode (item)" + +_key="help_shortcut26" + _value="Shows the podcast episode (item) page " + +_key="help_shortcut27" + _value="Open enclosures folder" + +_key="help_buy1" + _value="BePodder Light is the basic version (free download and no time limited), the registered version adds some more nice features: unlimited number of channels, small Channel view, proxy support, automatic channels check, up to 5 enclosure downloads at the same time (multithreading)." + +_key="help_buy2" + _value="Please pay the shareware fee, it's only 15 euro (Kagi add tax in some countries), BePodder licence can be purchased online from Kagi." + +_key="help_buy3" + _value="Buy at www.funkyideasoft.com" + +_key="help_buy4" + _value="After purchasing, an email will be sent to you with a keyfile and instruction on how to install it. It's just a matter of unzipping a file and moving it to a certain directory." + +_key="help_buy5" + _value="There is no problem updating BePodder when a new version becomes available. The keyfile will unlock all downloadable packages unless otherwise notified." + + +### USELESS ######## + +"Opml Editor" "Opml Editor" +"name:" "name:" +"Add a category" "Add a category" +"Add a new Broadcast" "Add a new Broadcast" +"feed:" "feed:" +"url:" "url:" +"Test podcast" "Test podcast" +"Del a category" "Del a category" +"Add a category" "Add a category" +"Select the podcast category:" "Select the podcast category:" +"Check all" "Check all" +"Check" "Check" +"Refresh the list" "Refresh the list" +"Load" "Load" +"Load the list" "Load the list" +"Save" "Save" +"Save the list" "Save the list" +"Revert" "Revert" +"Apply" "Apply" + + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.svSE b/release/Language/Dictionaries/BePodder.svSE new file mode 100644 index 0000000..296dac8 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.svSE @@ -0,0 +1,604 @@ + +# Locale file for BePodder. +# Modified: 4/18/2006 +# Author: BePodderTeam +# E-mail: bepodder.team@gmail.com + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" + +"Web Site" "Web Site" + +"Can't connect!" "Can't connect!" +"Http port failed!" "Http port failed!" +"Can't resolve host!" "Can't resolve host!" +"Not found!" "Not found!" +"Bad resume!" "Bad resume!" +"Aborted by Callback!" "Aborted by Callback!" +"Can't resume! (range error)" "Can't resume! (range error)" +"Access Denied!" "Access Denied!" +"User or Password Incorrect!" "User or Password Incorrect!" +"Other error (cUrl code: " "Other error (cUrl code: " +"cUrl init error!" "cUrl init error!" +"Can't open file!" "Can't open file!" +"Other error (status code: " "Other error (status code: " +"Downloading" "Downloading" + + +### MENUBAR ----------------------------------- + +"File" "File" +"About..." "About..." +"Close!" "Close!" +"Quit" "Quit" + +"Settings" "Settings" +"Preferences..." "Preferences..." + +"Subscriptions" "Subscriptions" + +"Episodes" "Episodes" + +"Lists" "Lists" +"Podcast List" "Podcast List" +"Podcast directory list" "Podcast directory list" +"Videoblog List" "Videoblog List" +"Videoblog directory list" "Videoblog directory list" +"Imagefeeds List" "Imagefeeds List" +"Imagefeeds directory list" "Imagefeeds directory list" +"Newsfeeds List" "Newsfeeds List" +"Newsfeeds directory list" "Newsfeeds directory list" +"BitTorrentfeeds List" "BitTorrentfeeds List" +"BitTorrentfeeds directory list" "BitTorrentfeeds directory list" +"Internationalfeeds List" "Internationalfeeds List" +"Internationalfeeds directory list" "Internationalfeeds directory list" + +"View" "View" +"Full Screen" "Full Screen" +"Toolbar" "Toolbar" +"Subscriptions View" "Subscriptions View" +"Small Items" "Small Items" +"Big Items" "Big Items" +"Move BePodder on workspace:" "Move BePodder on workspace:" + +"Help" "Help" +"Getting Started" "Getting Started" +"Keyboard Shortcuts" "Keyboard Shortcuts" +"Tutorials" "Tutorials" +"Online Support" "Online Support" + + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "Insert the rss feed url!" +"Add" "Add" +"Paste" "Paste" + +# Buttons directory list window +"Collapse All" "Collapse All" +"Preview" "Preview" +"Subscribe" "Subscribe" + + +# Buttons help window +"Next" "Next" +"Prev" "Prev" +"Close" "Close" +"Index" "Index" + + +# Buttons remove windows +"Cancel" "Cancel" +"Delete" "Delete" +"Archive" "Archive" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Add the podcast to the Subscriptions list" +"Delete the podcast from the Subscriptions list" "Delete the podcast from the Subscriptions list" +"Check the selected podcast for new items" "Check the selected podcast for new items" +"Show the podcast homepage" "Show the podcast homepage" + +"Delete the item and the enclosure" "Delete the item and the enclosure" +"Stop the item download" "Stop the item download" +"Download the selected episode" "Download the selected episode" +"Play the selected episode" "Play the selected episode" + +"Submit bug and idea" "Submit bug and idea" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Collapse all categories in the directory list" +"Add the selected podcast to the Subscription list" "Add the selected podcast to the Subscription list" +"Checkout a podcast before downloading it" "Checkout a podcast before downloading it" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Show Channel Image" +"XML Feed Link" "XML Feed Link" + +"Show Episode info" "Show Episode info" +"Show Subscription info" "Show Subscription info" +"Show Downloads info" "Show Downloads info" + +"Enclosure: " "Enclosure: " + +"Lookup (Dictionary)" "Lookup (Dictionary)" +"Lookup (Google)" "Lookup (Google)" +"Lookup (Acronym Finder)" "Lookup (Acronym Finder)" +"Copy" "Copy" +"Select All" "Select All" +"Copy URL" "Copy URL" +"Open URL" "Open URL" +"Subscription" "Subscription" + + +### PREFERENCES ----------------------------------- + +"Preferences" "Preferences" + +"Proxy" "Proxy" +"Enable Proxy" "Enable Proxy" +"Address" "Address" +"Port" "Port" +"Username" "Username" +"Password" "Password" + +"Max Downloads" "Max Downloads" + +"FileType" "FileType" +"Browser" "Browser" +"Player" "Player" + +"Channels" "Channels" +"Check all channels on startup" "Check all channels on startup" +"Check the channel every" "Check the channel every" + +"never" "never" +"5 minutes" "5 minutes" +"15 minutes" "15 minutes" +"30 minutes" "30 minutes" +"1 hour" "1 hour" +"2 hour" "2 hour" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 new item" +"%d new items" "%d new items" +"new" "new" +"error" "error" +"not down" "not down" +"enquequed" "enquequed" +"downloading" "downloading" +"downloaded" "downloaded" +"connecting" "connecting" +"not found" "not found" +"stopped" "stopped" +"can't connect" "can't connect" +"invalid format" "invalid format" + +"Icon" "Icon" +"Title" "Title" +"Date" "Date" +"Size" "Size" +"Status" "Status" +"Download" "Download" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "Add Channel" +"Remove Channel" "Remove Channel" +"Check Channel" "Check Channel" +"Open Homepage" "Open Homepage" + +"Open Web Page" "Open Web Page" +"Open Enclosures folder" "Open Enclosures folder" +"Check All Channels" "Check All Channels" + +"Show Channel Image" "Show Channel Image" + +"Play enclosure" "Play enclosure" +"(Re)start download" "(Re)start download" +"Stop download" "Stop download" +"Remove Item" "Remove Item" + +"Find this Item" "Find this Item" +"Remove from this list" "Remove from this list" + + + +### ALERT ----------------------------------- + +"\nRemoving.." "\nRemoving.." +"\nAn error occured while removing!" "\nAn error occured while removing!" +"Check all the podcasts for new items" "Check all the podcasts for new items" + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" + + +"Can't open the selected file with:\n\n" "Can't open the selected file with:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nPlease check if the application is installed in the right way.\n" +"Download it!" "Download it!" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +You are going to remove the selected item. + +Are you sure? +(you will lost the enclosure file if any)" + + +_key="alert2a" + _value=" +You are going to remove the channel: + +" + +_key="alert2b" + _value=" + +Would you like just to archive this +channel (keeping all the files and +enclosures downloaded so far) or +do you want to DELETE the whole + channel from you computer?" + +_key="alert3" + _value=" +Parsing archive.." + +_key="alert_3gp" + _value=" +3GP is a multimedia container format defined by the Third Generation Partnership Project (3GPP) for use on 3G mobile phones. It stores video streams as MPEG-4 or H.263, and audio streams as AMR-NB or AAC-LC. + +VideoLAN still doesn't support the audio AMR (3GPP)" + +_key="alert_swf" + _value=" +SWF is a proprietary vector graphics file format produced by the Flash software from Adobe (formerly Macromedia). + +Currently Flash support in BeOS/Haiku/Zeta is limited to the old standalone Flash player version 4.1015, there isn't a modern Flash player" + + + + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Introduction" +"The User Interface" "The User Interface" +"Menu Bar" "Menu Bar" +"Toolbar Buttons" "Toolbar Buttons" +"First time with BePodder" "First time with BePodder" +"Download Podcast's enclosure files" "Download Podcast's enclosure files" +"Settings Overview" "Settings Overview" +"Directory lists" "Directory lists" +"Loading Help..." "Loading Help..." +"Register your copy" "Register your copy" +"Starting point" "Starting point" + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value="Welcome to the BePodder Getting Started Guide." + +_key="help1-1" + _value="If you are already familiar with podcasts and RSS/Atom feeds you can immediately go to BePodder by closing this window." + +_key="help1-2" +_value="If not, this is a short introduction providing you everything you'll need to know on how to get started with BePodder. Use the buttons below to navigate through this tutorial." + + +_key="help2-0" +_value="Podcasting is a method for publishing audio and video broadcasts via the Internet; links to free audio and video files are enclosed in RSS and Atom feeds." + +_key="help2-1" +_value="Therefore Podcasting is simply a type of online media delivery; users can subscribe to a podcast using a feed (such as RSS 'Really Simple Syndication' or Atom)." + +_key="help2-2" +_value="An aggregator (or podcatcher) like BePodder, is a piece of software that allows you to subscribe to a RSS feed and periodically check for and download new content; with BePodder you can check for new Podcast items (Episodes) of your subscribed Channels. Any item can contain an enclosure, just like an Email can contain an attachment." + + + +_key="help3-0" +_value="BePodder has an easy to use yet powerful Graphical User Interface. The main window is split into tree panels:" + +_key="help3-1" +_value="1) The Subscription list (the panel with the number 1 in the screenshot) with the list of the podcasts that you have subscribed to. When you click on a Channel you can see in the panel 2 the list of the channel's items." + +_key="help3-2" +_value="2) The Episodes list with all the items available." + +_key="help3-3" +_value="3) The Info panel show: episode info, channel info or Downloads info; you can select an info panel by clicking one of the below three buttons." + + + +_key="help4-0" +_value="At the very top of the BePodder main window is the menubar with seven menus available: File, Settings, Subscriptions, Episodes, Lists, View and Help. Some menu commands are followed by a right pointing arrow that indicates a submenu of related commands. As you explore each menu, be sure to take a look at the submenus as well. Click on a menus to show its commands:" + +_key="help4-1" +_value="File: contains commands to close the application and to show information about BePodder" + +_key="help4-2" +_value="Settings: contains command to open the Preferences window that allows you to customize various BePodder settings." + +_key="help4-3" +_value="Subscriptions: contains commands that perform actions on the selected channel of your subscriptions list." + +_key="help4-4" +_value="Episodes: contains commands that perform actions on the selected item (episode) of the channel's episode list." + +_key="help4-5" +_value="Lists: contains commands to open BePodder's OPML directories." + +_key="help4-6" +_value="View: contains commands and controls for the BePodder window." + +_key="help4-7" +_value="Help: contains commands to open BePodder's 'Getting Started Guide' and the 'Keyboard Shortcuts List'." + + + +_key="help5-0" + _value="Add Button: opens the Add Window to add a feed url (e.g. http://www.newpodcast.com/rss.xml) usually given on the podcast homepage; looks for text or graphic link that says something like 'XML', 'RSS' or 'Podcast Feed' on it." + +_key="help5-1" + _value="Channel Remove Button: opens a window in which you can select how remove the channel: just archive the select channel (keeping all the files and eclosure downloaded so far) or delete the whole channel from your computer." + +_key="help5-2" + _value="Check Button: checks the selected channel and updates the list of the available items for that podcast adding the new items." + +_key="help5-3" + _value="Web Button: shows the channel homepage in the browser. To select your favorite browser open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select your favorite browser." + +_key="help5-4" + _value="Play Button: with this button you can view or listen the file enclosure of the selected item(episode). To select your favorite player open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select you favorite player." + +_key="help5-5" + _value="Download Button: downloads the file enclosure of the selected item (episode); you can see the download info by clicking on the third button over the info panel." + +_key="help5-6" + _value="Stop Button: stops to download the file enclosure of the selected item (episode); to resume the download double-click the item (episode) or select the item and click the Download Button" + +_key="help5-7" + _value="Item Remove Button: deletes the selected item (you will loose the enclosure file)." + + + +_key="help6-0" + _value="Getting started with BePodder is easy." + +_key="help6-1" + _value="On the left of the main window you can see the 'Subscription List' with all your feed subscriptions. We have added some subscriptions for you, and you can always add your own in two ways:" + +_key="help6-2" + _value="1) click the Add Button, then insert the feed url (example: http://www.newpodcast.com/rss.xml) and click add." + +_key="help6-3" + _value="2) in the menubar select 'Directory' and then 'Podcast list' or another list, choose a podcast and click 'Subscribe'." + +_key="help6-4" + _value="If you select a Podcast in the subscriptions list and use the check button, BePodder adds the new items to the 'Episodes list' (below on the right); you can check all your podcasts by right-clicking and selecting 'Check All Channels' in the context menu." + +_key="help6-5" + _value="Look at the screenshot above, there are 3 new items indicated by a black dot in the first column of the 'Episodes list'." + +_key="help6-6" + _value="In the second column there are icons that indicate the state of the item:" + +_key="help6-7" + _value="- the Episode 4 has an icon that indicates an error" + +_key="help6-8" + _value="- the Episode 3 has an icon that indicates that the item's enclosure download request is enquequed" + +_key="help6-9" + _value="- the Episode 2 has an icon that indicates that BePodder is downloading the item's enclosure file" + +_key="help6-10" + _value="- the Episode 1 have an icon that indicates that BePodder have just downloaded the item's enclosure file" + + + +_key="help7-0" + _value="Select an item in the 'Episodes list' and then double-click on it (or click the Download Button) to start downloading the enclosed file; you can always stop the download by clicking on the Stop Button." + +_key="help7-1" + _value="When you click on the Subscribed Podcasts in the 'Subscriptions List' the software shows you, in the 'List of episodes', all the items available in that Subscription. Select an item and then click play (Play Button) to view or listen to the file." + +_key="help7-2" + _value="You can access the Enclosures Folder by clicking on the folder icon in the Info Pannel or by right-clicking your mouse on an item and select 'Open Enclosures Folder' in the context menu." + + + +_key="help8-0" + _value="Preferences can be accessed by clicking in the menu-bar Settings>Preferences. You can select a category from the left list of the preferences dialog: FileType, Channels, Download and Proxy." + +_key="help8-1" + _value="- FileType: to specify the default browser and player. " + +_key="help8-2" + _value="- Channels: to specify preferences that control the operation to check channels new items; you can choose to Check all channels on startup or check the channel every desired minutes." + +_key="help8-3" + _value="- Download: to specify the max number of item's files to download at the same time," + +_key="help8-4" + _value="- Proxy: to set up a proxy server to work with BePodder; a proxy server acts as a security barrier between your internal network and the Internet, keeping others on the Internet from accessing information on your internal network." + + + +_key="help9-0" + _value="BePodder has built-in podcast, videoblog, imagefeeds, newsfeeds, bittorrentfeeds and internationalfeeds OPML directories with thousands of feeds grouped by category." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) is an XML-based format that allows exchange of outline-structured information between applications." + +_key="help9-2" + _value="OPML directory can be accessed by clicking in the menu-bar 'Lists' and thenselecting a list. To browse the opml directory for a feed, expand the list by clicking the arrow of the category that you are interested in (see image); using this method, you can expand the opml directory until you find the desired feed. Once you have selected it, you can add it to the subscription list by clicking the button 'Subscribe', you can also collapse all categories in the directory list by clicking the button 'Collapse All'." + +_key="help_shortcut1" +_value="This page describes the keyboard shortcuts that can be used in BePodder. The shortcuts are grouped here by function." + +_key="help_shortcut2" +_value="means that you can use either alt or control (es. Alt+Q or Ctrl+Q Quit the application), which way you have set it in the Deskbar menu preferences under Keyboard (the default shortcut key is Alt)." + +_key="help_shortcut3" + _value="General shortcuts" + +_key="help_shortcut4" + _value="Quit the application" + +_key="help_shortcut5" + _value="Shows the Preferences window" + +_key="help_shortcut6" + _value="Shows the Podcast directory list" + +_key="help_shortcut7" + _value="Shows the Videoblog directory list" + +_key="help_shortcut8" + _value="Shows the Imagefeeds directory list" + +_key="help_shortcut9" + _value="Shows the Newsfeeds directory list" + +_key="help_shortcut9b" + _value="Shows the BitTorrentfeeds directory list" + +_key="help_shortcut9c" + _value="Shows the Internationalfeeds directory list" + +_key="help_shortcut10" + _value="Fullscreen" + +_key="help_shortcut11" + _value="Shows/Hides the toolbar" + +_key="help_shortcut12" + _value="Shows the Getting Started Help" + +_key="help_shortcut13" + _value="Shows this keyboard shortcuts page" + +_key="help_shortcut14" + _value="Channels shortcuts" + +_key="help_shortcut15" + _value="Add a podcast to the subscriptions list" + +_key="help_shortcut16" + _value="Delete the selected podcast from the subscriptions list" + +_key="help_shortcut17" + _value="Check the selected podcast for new episodes (items)" + +_key="help_shortcut18" + _value="Check all podcasts for new episodes (items)" + +_key="help_shortcut19" + _value="Shows the podcast homepage" + +_key="help_shortcut20" + _value="Open enclosures folder" + +_key="help_shortcut21" + _value="Episodes shortcuts" + +_key="help_shortcut22" + _value="Play enclosure" + +_key="help_shortcut23" + _value="(Re)start download the selected episodes (items)" + +_key="help_shortcut24" + _value="Stop the episode (item) download" + +_key="help_shortcut25" + _value="Delete the selected episode (item)" + +_key="help_shortcut26" + _value="Shows the podcast episode (item) page " + +_key="help_shortcut27" + _value="Open enclosures folder" + +_key="help_buy1" + _value="BePodder Light is the basic version (free download and no time limited), the registered version adds some more nice features: unlimited number of channels, small Channel view, proxy support, automatic channels check, up to 5 enclosure downloads at the same time (multithreading)." + +_key="help_buy2" + _value="Please pay the shareware fee, it's only 15 euro (Kagi add tax in some countries), BePodder licence can be purchased online from Kagi." + +_key="help_buy3" + _value="Buy at www.funkyideasoft.com" + +_key="help_buy4" + _value="After purchasing, an email will be sent to you with a keyfile and instruction on how to install it. It's just a matter of unzipping a file and moving it to a certain directory." + +_key="help_buy5" + _value="There is no problem updating BePodder when a new version becomes available. The keyfile will unlock all downloadable packages unless otherwise notified." + + +### USELESS ######## + +"Opml Editor" "Opml Editor" +"name:" "name:" +"Add a category" "Add a category" +"Add a new Broadcast" "Add a new Broadcast" +"feed:" "feed:" +"url:" "url:" +"Test podcast" "Test podcast" +"Del a category" "Del a category" +"Add a category" "Add a category" +"Select the podcast category:" "Select the podcast category:" +"Check all" "Check all" +"Check" "Check" +"Refresh the list" "Refresh the list" +"Load" "Load" +"Load the list" "Load the list" +"Save" "Save" +"Save the list" "Save the list" +"Revert" "Revert" +"Apply" "Apply" + + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.trTR b/release/Language/Dictionaries/BePodder.trTR new file mode 100644 index 0000000..296dac8 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.trTR @@ -0,0 +1,604 @@ + +# Locale file for BePodder. +# Modified: 4/18/2006 +# Author: BePodderTeam +# E-mail: bepodder.team@gmail.com + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" + +"Web Site" "Web Site" + +"Can't connect!" "Can't connect!" +"Http port failed!" "Http port failed!" +"Can't resolve host!" "Can't resolve host!" +"Not found!" "Not found!" +"Bad resume!" "Bad resume!" +"Aborted by Callback!" "Aborted by Callback!" +"Can't resume! (range error)" "Can't resume! (range error)" +"Access Denied!" "Access Denied!" +"User or Password Incorrect!" "User or Password Incorrect!" +"Other error (cUrl code: " "Other error (cUrl code: " +"cUrl init error!" "cUrl init error!" +"Can't open file!" "Can't open file!" +"Other error (status code: " "Other error (status code: " +"Downloading" "Downloading" + + +### MENUBAR ----------------------------------- + +"File" "File" +"About..." "About..." +"Close!" "Close!" +"Quit" "Quit" + +"Settings" "Settings" +"Preferences..." "Preferences..." + +"Subscriptions" "Subscriptions" + +"Episodes" "Episodes" + +"Lists" "Lists" +"Podcast List" "Podcast List" +"Podcast directory list" "Podcast directory list" +"Videoblog List" "Videoblog List" +"Videoblog directory list" "Videoblog directory list" +"Imagefeeds List" "Imagefeeds List" +"Imagefeeds directory list" "Imagefeeds directory list" +"Newsfeeds List" "Newsfeeds List" +"Newsfeeds directory list" "Newsfeeds directory list" +"BitTorrentfeeds List" "BitTorrentfeeds List" +"BitTorrentfeeds directory list" "BitTorrentfeeds directory list" +"Internationalfeeds List" "Internationalfeeds List" +"Internationalfeeds directory list" "Internationalfeeds directory list" + +"View" "View" +"Full Screen" "Full Screen" +"Toolbar" "Toolbar" +"Subscriptions View" "Subscriptions View" +"Small Items" "Small Items" +"Big Items" "Big Items" +"Move BePodder on workspace:" "Move BePodder on workspace:" + +"Help" "Help" +"Getting Started" "Getting Started" +"Keyboard Shortcuts" "Keyboard Shortcuts" +"Tutorials" "Tutorials" +"Online Support" "Online Support" + + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "Insert the rss feed url!" +"Add" "Add" +"Paste" "Paste" + +# Buttons directory list window +"Collapse All" "Collapse All" +"Preview" "Preview" +"Subscribe" "Subscribe" + + +# Buttons help window +"Next" "Next" +"Prev" "Prev" +"Close" "Close" +"Index" "Index" + + +# Buttons remove windows +"Cancel" "Cancel" +"Delete" "Delete" +"Archive" "Archive" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Add the podcast to the Subscriptions list" +"Delete the podcast from the Subscriptions list" "Delete the podcast from the Subscriptions list" +"Check the selected podcast for new items" "Check the selected podcast for new items" +"Show the podcast homepage" "Show the podcast homepage" + +"Delete the item and the enclosure" "Delete the item and the enclosure" +"Stop the item download" "Stop the item download" +"Download the selected episode" "Download the selected episode" +"Play the selected episode" "Play the selected episode" + +"Submit bug and idea" "Submit bug and idea" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Collapse all categories in the directory list" +"Add the selected podcast to the Subscription list" "Add the selected podcast to the Subscription list" +"Checkout a podcast before downloading it" "Checkout a podcast before downloading it" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Show Channel Image" +"XML Feed Link" "XML Feed Link" + +"Show Episode info" "Show Episode info" +"Show Subscription info" "Show Subscription info" +"Show Downloads info" "Show Downloads info" + +"Enclosure: " "Enclosure: " + +"Lookup (Dictionary)" "Lookup (Dictionary)" +"Lookup (Google)" "Lookup (Google)" +"Lookup (Acronym Finder)" "Lookup (Acronym Finder)" +"Copy" "Copy" +"Select All" "Select All" +"Copy URL" "Copy URL" +"Open URL" "Open URL" +"Subscription" "Subscription" + + +### PREFERENCES ----------------------------------- + +"Preferences" "Preferences" + +"Proxy" "Proxy" +"Enable Proxy" "Enable Proxy" +"Address" "Address" +"Port" "Port" +"Username" "Username" +"Password" "Password" + +"Max Downloads" "Max Downloads" + +"FileType" "FileType" +"Browser" "Browser" +"Player" "Player" + +"Channels" "Channels" +"Check all channels on startup" "Check all channels on startup" +"Check the channel every" "Check the channel every" + +"never" "never" +"5 minutes" "5 minutes" +"15 minutes" "15 minutes" +"30 minutes" "30 minutes" +"1 hour" "1 hour" +"2 hour" "2 hour" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 new item" +"%d new items" "%d new items" +"new" "new" +"error" "error" +"not down" "not down" +"enquequed" "enquequed" +"downloading" "downloading" +"downloaded" "downloaded" +"connecting" "connecting" +"not found" "not found" +"stopped" "stopped" +"can't connect" "can't connect" +"invalid format" "invalid format" + +"Icon" "Icon" +"Title" "Title" +"Date" "Date" +"Size" "Size" +"Status" "Status" +"Download" "Download" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "Add Channel" +"Remove Channel" "Remove Channel" +"Check Channel" "Check Channel" +"Open Homepage" "Open Homepage" + +"Open Web Page" "Open Web Page" +"Open Enclosures folder" "Open Enclosures folder" +"Check All Channels" "Check All Channels" + +"Show Channel Image" "Show Channel Image" + +"Play enclosure" "Play enclosure" +"(Re)start download" "(Re)start download" +"Stop download" "Stop download" +"Remove Item" "Remove Item" + +"Find this Item" "Find this Item" +"Remove from this list" "Remove from this list" + + + +### ALERT ----------------------------------- + +"\nRemoving.." "\nRemoving.." +"\nAn error occured while removing!" "\nAn error occured while removing!" +"Check all the podcasts for new items" "Check all the podcasts for new items" + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" + + +"Can't open the selected file with:\n\n" "Can't open the selected file with:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nPlease check if the application is installed in the right way.\n" +"Download it!" "Download it!" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +You are going to remove the selected item. + +Are you sure? +(you will lost the enclosure file if any)" + + +_key="alert2a" + _value=" +You are going to remove the channel: + +" + +_key="alert2b" + _value=" + +Would you like just to archive this +channel (keeping all the files and +enclosures downloaded so far) or +do you want to DELETE the whole + channel from you computer?" + +_key="alert3" + _value=" +Parsing archive.." + +_key="alert_3gp" + _value=" +3GP is a multimedia container format defined by the Third Generation Partnership Project (3GPP) for use on 3G mobile phones. It stores video streams as MPEG-4 or H.263, and audio streams as AMR-NB or AAC-LC. + +VideoLAN still doesn't support the audio AMR (3GPP)" + +_key="alert_swf" + _value=" +SWF is a proprietary vector graphics file format produced by the Flash software from Adobe (formerly Macromedia). + +Currently Flash support in BeOS/Haiku/Zeta is limited to the old standalone Flash player version 4.1015, there isn't a modern Flash player" + + + + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Introduction" +"The User Interface" "The User Interface" +"Menu Bar" "Menu Bar" +"Toolbar Buttons" "Toolbar Buttons" +"First time with BePodder" "First time with BePodder" +"Download Podcast's enclosure files" "Download Podcast's enclosure files" +"Settings Overview" "Settings Overview" +"Directory lists" "Directory lists" +"Loading Help..." "Loading Help..." +"Register your copy" "Register your copy" +"Starting point" "Starting point" + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value="Welcome to the BePodder Getting Started Guide." + +_key="help1-1" + _value="If you are already familiar with podcasts and RSS/Atom feeds you can immediately go to BePodder by closing this window." + +_key="help1-2" +_value="If not, this is a short introduction providing you everything you'll need to know on how to get started with BePodder. Use the buttons below to navigate through this tutorial." + + +_key="help2-0" +_value="Podcasting is a method for publishing audio and video broadcasts via the Internet; links to free audio and video files are enclosed in RSS and Atom feeds." + +_key="help2-1" +_value="Therefore Podcasting is simply a type of online media delivery; users can subscribe to a podcast using a feed (such as RSS 'Really Simple Syndication' or Atom)." + +_key="help2-2" +_value="An aggregator (or podcatcher) like BePodder, is a piece of software that allows you to subscribe to a RSS feed and periodically check for and download new content; with BePodder you can check for new Podcast items (Episodes) of your subscribed Channels. Any item can contain an enclosure, just like an Email can contain an attachment." + + + +_key="help3-0" +_value="BePodder has an easy to use yet powerful Graphical User Interface. The main window is split into tree panels:" + +_key="help3-1" +_value="1) The Subscription list (the panel with the number 1 in the screenshot) with the list of the podcasts that you have subscribed to. When you click on a Channel you can see in the panel 2 the list of the channel's items." + +_key="help3-2" +_value="2) The Episodes list with all the items available." + +_key="help3-3" +_value="3) The Info panel show: episode info, channel info or Downloads info; you can select an info panel by clicking one of the below three buttons." + + + +_key="help4-0" +_value="At the very top of the BePodder main window is the menubar with seven menus available: File, Settings, Subscriptions, Episodes, Lists, View and Help. Some menu commands are followed by a right pointing arrow that indicates a submenu of related commands. As you explore each menu, be sure to take a look at the submenus as well. Click on a menus to show its commands:" + +_key="help4-1" +_value="File: contains commands to close the application and to show information about BePodder" + +_key="help4-2" +_value="Settings: contains command to open the Preferences window that allows you to customize various BePodder settings." + +_key="help4-3" +_value="Subscriptions: contains commands that perform actions on the selected channel of your subscriptions list." + +_key="help4-4" +_value="Episodes: contains commands that perform actions on the selected item (episode) of the channel's episode list." + +_key="help4-5" +_value="Lists: contains commands to open BePodder's OPML directories." + +_key="help4-6" +_value="View: contains commands and controls for the BePodder window." + +_key="help4-7" +_value="Help: contains commands to open BePodder's 'Getting Started Guide' and the 'Keyboard Shortcuts List'." + + + +_key="help5-0" + _value="Add Button: opens the Add Window to add a feed url (e.g. http://www.newpodcast.com/rss.xml) usually given on the podcast homepage; looks for text or graphic link that says something like 'XML', 'RSS' or 'Podcast Feed' on it." + +_key="help5-1" + _value="Channel Remove Button: opens a window in which you can select how remove the channel: just archive the select channel (keeping all the files and eclosure downloaded so far) or delete the whole channel from your computer." + +_key="help5-2" + _value="Check Button: checks the selected channel and updates the list of the available items for that podcast adding the new items." + +_key="help5-3" + _value="Web Button: shows the channel homepage in the browser. To select your favorite browser open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select your favorite browser." + +_key="help5-4" + _value="Play Button: with this button you can view or listen the file enclosure of the selected item(episode). To select your favorite player open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select you favorite player." + +_key="help5-5" + _value="Download Button: downloads the file enclosure of the selected item (episode); you can see the download info by clicking on the third button over the info panel." + +_key="help5-6" + _value="Stop Button: stops to download the file enclosure of the selected item (episode); to resume the download double-click the item (episode) or select the item and click the Download Button" + +_key="help5-7" + _value="Item Remove Button: deletes the selected item (you will loose the enclosure file)." + + + +_key="help6-0" + _value="Getting started with BePodder is easy." + +_key="help6-1" + _value="On the left of the main window you can see the 'Subscription List' with all your feed subscriptions. We have added some subscriptions for you, and you can always add your own in two ways:" + +_key="help6-2" + _value="1) click the Add Button, then insert the feed url (example: http://www.newpodcast.com/rss.xml) and click add." + +_key="help6-3" + _value="2) in the menubar select 'Directory' and then 'Podcast list' or another list, choose a podcast and click 'Subscribe'." + +_key="help6-4" + _value="If you select a Podcast in the subscriptions list and use the check button, BePodder adds the new items to the 'Episodes list' (below on the right); you can check all your podcasts by right-clicking and selecting 'Check All Channels' in the context menu." + +_key="help6-5" + _value="Look at the screenshot above, there are 3 new items indicated by a black dot in the first column of the 'Episodes list'." + +_key="help6-6" + _value="In the second column there are icons that indicate the state of the item:" + +_key="help6-7" + _value="- the Episode 4 has an icon that indicates an error" + +_key="help6-8" + _value="- the Episode 3 has an icon that indicates that the item's enclosure download request is enquequed" + +_key="help6-9" + _value="- the Episode 2 has an icon that indicates that BePodder is downloading the item's enclosure file" + +_key="help6-10" + _value="- the Episode 1 have an icon that indicates that BePodder have just downloaded the item's enclosure file" + + + +_key="help7-0" + _value="Select an item in the 'Episodes list' and then double-click on it (or click the Download Button) to start downloading the enclosed file; you can always stop the download by clicking on the Stop Button." + +_key="help7-1" + _value="When you click on the Subscribed Podcasts in the 'Subscriptions List' the software shows you, in the 'List of episodes', all the items available in that Subscription. Select an item and then click play (Play Button) to view or listen to the file." + +_key="help7-2" + _value="You can access the Enclosures Folder by clicking on the folder icon in the Info Pannel or by right-clicking your mouse on an item and select 'Open Enclosures Folder' in the context menu." + + + +_key="help8-0" + _value="Preferences can be accessed by clicking in the menu-bar Settings>Preferences. You can select a category from the left list of the preferences dialog: FileType, Channels, Download and Proxy." + +_key="help8-1" + _value="- FileType: to specify the default browser and player. " + +_key="help8-2" + _value="- Channels: to specify preferences that control the operation to check channels new items; you can choose to Check all channels on startup or check the channel every desired minutes." + +_key="help8-3" + _value="- Download: to specify the max number of item's files to download at the same time," + +_key="help8-4" + _value="- Proxy: to set up a proxy server to work with BePodder; a proxy server acts as a security barrier between your internal network and the Internet, keeping others on the Internet from accessing information on your internal network." + + + +_key="help9-0" + _value="BePodder has built-in podcast, videoblog, imagefeeds, newsfeeds, bittorrentfeeds and internationalfeeds OPML directories with thousands of feeds grouped by category." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) is an XML-based format that allows exchange of outline-structured information between applications." + +_key="help9-2" + _value="OPML directory can be accessed by clicking in the menu-bar 'Lists' and thenselecting a list. To browse the opml directory for a feed, expand the list by clicking the arrow of the category that you are interested in (see image); using this method, you can expand the opml directory until you find the desired feed. Once you have selected it, you can add it to the subscription list by clicking the button 'Subscribe', you can also collapse all categories in the directory list by clicking the button 'Collapse All'." + +_key="help_shortcut1" +_value="This page describes the keyboard shortcuts that can be used in BePodder. The shortcuts are grouped here by function." + +_key="help_shortcut2" +_value="means that you can use either alt or control (es. Alt+Q or Ctrl+Q Quit the application), which way you have set it in the Deskbar menu preferences under Keyboard (the default shortcut key is Alt)." + +_key="help_shortcut3" + _value="General shortcuts" + +_key="help_shortcut4" + _value="Quit the application" + +_key="help_shortcut5" + _value="Shows the Preferences window" + +_key="help_shortcut6" + _value="Shows the Podcast directory list" + +_key="help_shortcut7" + _value="Shows the Videoblog directory list" + +_key="help_shortcut8" + _value="Shows the Imagefeeds directory list" + +_key="help_shortcut9" + _value="Shows the Newsfeeds directory list" + +_key="help_shortcut9b" + _value="Shows the BitTorrentfeeds directory list" + +_key="help_shortcut9c" + _value="Shows the Internationalfeeds directory list" + +_key="help_shortcut10" + _value="Fullscreen" + +_key="help_shortcut11" + _value="Shows/Hides the toolbar" + +_key="help_shortcut12" + _value="Shows the Getting Started Help" + +_key="help_shortcut13" + _value="Shows this keyboard shortcuts page" + +_key="help_shortcut14" + _value="Channels shortcuts" + +_key="help_shortcut15" + _value="Add a podcast to the subscriptions list" + +_key="help_shortcut16" + _value="Delete the selected podcast from the subscriptions list" + +_key="help_shortcut17" + _value="Check the selected podcast for new episodes (items)" + +_key="help_shortcut18" + _value="Check all podcasts for new episodes (items)" + +_key="help_shortcut19" + _value="Shows the podcast homepage" + +_key="help_shortcut20" + _value="Open enclosures folder" + +_key="help_shortcut21" + _value="Episodes shortcuts" + +_key="help_shortcut22" + _value="Play enclosure" + +_key="help_shortcut23" + _value="(Re)start download the selected episodes (items)" + +_key="help_shortcut24" + _value="Stop the episode (item) download" + +_key="help_shortcut25" + _value="Delete the selected episode (item)" + +_key="help_shortcut26" + _value="Shows the podcast episode (item) page " + +_key="help_shortcut27" + _value="Open enclosures folder" + +_key="help_buy1" + _value="BePodder Light is the basic version (free download and no time limited), the registered version adds some more nice features: unlimited number of channels, small Channel view, proxy support, automatic channels check, up to 5 enclosure downloads at the same time (multithreading)." + +_key="help_buy2" + _value="Please pay the shareware fee, it's only 15 euro (Kagi add tax in some countries), BePodder licence can be purchased online from Kagi." + +_key="help_buy3" + _value="Buy at www.funkyideasoft.com" + +_key="help_buy4" + _value="After purchasing, an email will be sent to you with a keyfile and instruction on how to install it. It's just a matter of unzipping a file and moving it to a certain directory." + +_key="help_buy5" + _value="There is no problem updating BePodder when a new version becomes available. The keyfile will unlock all downloadable packages unless otherwise notified." + + +### USELESS ######## + +"Opml Editor" "Opml Editor" +"name:" "name:" +"Add a category" "Add a category" +"Add a new Broadcast" "Add a new Broadcast" +"feed:" "feed:" +"url:" "url:" +"Test podcast" "Test podcast" +"Del a category" "Del a category" +"Add a category" "Add a category" +"Select the podcast category:" "Select the podcast category:" +"Check all" "Check all" +"Check" "Check" +"Refresh the list" "Refresh the list" +"Load" "Load" +"Load the list" "Load the list" +"Save" "Save" +"Save the list" "Save the list" +"Revert" "Revert" +"Apply" "Apply" + + + + + + + + + + + + diff --git a/release/Language/Dictionaries/BePodder.zhCN b/release/Language/Dictionaries/BePodder.zhCN new file mode 100644 index 0000000..296dac8 --- /dev/null +++ b/release/Language/Dictionaries/BePodder.zhCN @@ -0,0 +1,604 @@ + +# Locale file for BePodder. +# Modified: 4/18/2006 +# Author: BePodderTeam +# E-mail: bepodder.team@gmail.com + + +# Attention: don't remove empty space or \n + + +### SHAREWARE POPUPS ----------------------------------- + +"Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" "Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n" + +"This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" "This BePodder copy has expired!\nPlease buy a keyfile and support us.\n" + +"Web Site" "Web Site" + +"Can't connect!" "Can't connect!" +"Http port failed!" "Http port failed!" +"Can't resolve host!" "Can't resolve host!" +"Not found!" "Not found!" +"Bad resume!" "Bad resume!" +"Aborted by Callback!" "Aborted by Callback!" +"Can't resume! (range error)" "Can't resume! (range error)" +"Access Denied!" "Access Denied!" +"User or Password Incorrect!" "User or Password Incorrect!" +"Other error (cUrl code: " "Other error (cUrl code: " +"cUrl init error!" "cUrl init error!" +"Can't open file!" "Can't open file!" +"Other error (status code: " "Other error (status code: " +"Downloading" "Downloading" + + +### MENUBAR ----------------------------------- + +"File" "File" +"About..." "About..." +"Close!" "Close!" +"Quit" "Quit" + +"Settings" "Settings" +"Preferences..." "Preferences..." + +"Subscriptions" "Subscriptions" + +"Episodes" "Episodes" + +"Lists" "Lists" +"Podcast List" "Podcast List" +"Podcast directory list" "Podcast directory list" +"Videoblog List" "Videoblog List" +"Videoblog directory list" "Videoblog directory list" +"Imagefeeds List" "Imagefeeds List" +"Imagefeeds directory list" "Imagefeeds directory list" +"Newsfeeds List" "Newsfeeds List" +"Newsfeeds directory list" "Newsfeeds directory list" +"BitTorrentfeeds List" "BitTorrentfeeds List" +"BitTorrentfeeds directory list" "BitTorrentfeeds directory list" +"Internationalfeeds List" "Internationalfeeds List" +"Internationalfeeds directory list" "Internationalfeeds directory list" + +"View" "View" +"Full Screen" "Full Screen" +"Toolbar" "Toolbar" +"Subscriptions View" "Subscriptions View" +"Small Items" "Small Items" +"Big Items" "Big Items" +"Move BePodder on workspace:" "Move BePodder on workspace:" + +"Help" "Help" +"Getting Started" "Getting Started" +"Keyboard Shortcuts" "Keyboard Shortcuts" +"Tutorials" "Tutorials" +"Online Support" "Online Support" + + + + +### BUTTONS ----------------------------------- + +# Buttons add feed window +"Insert the rss feed url!" "Insert the rss feed url!" +"Add" "Add" +"Paste" "Paste" + +# Buttons directory list window +"Collapse All" "Collapse All" +"Preview" "Preview" +"Subscribe" "Subscribe" + + +# Buttons help window +"Next" "Next" +"Prev" "Prev" +"Close" "Close" +"Index" "Index" + + +# Buttons remove windows +"Cancel" "Cancel" +"Delete" "Delete" +"Archive" "Archive" + + + +### TOOLTIPS ----------------------------------- + +# Tooltips toolbar buttons + +"Add the podcast to the Subscriptions list" "Add the podcast to the Subscriptions list" +"Delete the podcast from the Subscriptions list" "Delete the podcast from the Subscriptions list" +"Check the selected podcast for new items" "Check the selected podcast for new items" +"Show the podcast homepage" "Show the podcast homepage" + +"Delete the item and the enclosure" "Delete the item and the enclosure" +"Stop the item download" "Stop the item download" +"Download the selected episode" "Download the selected episode" +"Play the selected episode" "Play the selected episode" + +"Submit bug and idea" "Submit bug and idea" + + +# Tooltips directory window buttons + +"Collapse all categories in the directory list" "Collapse all categories in the directory list" +"Add the selected podcast to the Subscription list" "Add the selected podcast to the Subscription list" +"Checkout a podcast before downloading it" "Checkout a podcast before downloading it" + + +### INFO PANEL ----------------------------------- + +"Show channel Image" "Show Channel Image" +"XML Feed Link" "XML Feed Link" + +"Show Episode info" "Show Episode info" +"Show Subscription info" "Show Subscription info" +"Show Downloads info" "Show Downloads info" + +"Enclosure: " "Enclosure: " + +"Lookup (Dictionary)" "Lookup (Dictionary)" +"Lookup (Google)" "Lookup (Google)" +"Lookup (Acronym Finder)" "Lookup (Acronym Finder)" +"Copy" "Copy" +"Select All" "Select All" +"Copy URL" "Copy URL" +"Open URL" "Open URL" +"Subscription" "Subscription" + + +### PREFERENCES ----------------------------------- + +"Preferences" "Preferences" + +"Proxy" "Proxy" +"Enable Proxy" "Enable Proxy" +"Address" "Address" +"Port" "Port" +"Username" "Username" +"Password" "Password" + +"Max Downloads" "Max Downloads" + +"FileType" "FileType" +"Browser" "Browser" +"Player" "Player" + +"Channels" "Channels" +"Check all channels on startup" "Check all channels on startup" +"Check the channel every" "Check the channel every" + +"never" "never" +"5 minutes" "5 minutes" +"15 minutes" "15 minutes" +"30 minutes" "30 minutes" +"1 hour" "1 hour" +"2 hour" "2 hour" + + + + +### COLUMLISTVIEW ----------------------------------- + + +"1 new item" "1 new item" +"%d new items" "%d new items" +"new" "new" +"error" "error" +"not down" "not down" +"enquequed" "enquequed" +"downloading" "downloading" +"downloaded" "downloaded" +"connecting" "connecting" +"not found" "not found" +"stopped" "stopped" +"can't connect" "can't connect" +"invalid format" "invalid format" + +"Icon" "Icon" +"Title" "Title" +"Date" "Date" +"Size" "Size" +"Status" "Status" +"Download" "Download" + + + +### CONTEXT MENU ----------------------------------- + +"Add Channel" "Add Channel" +"Remove Channel" "Remove Channel" +"Check Channel" "Check Channel" +"Open Homepage" "Open Homepage" + +"Open Web Page" "Open Web Page" +"Open Enclosures folder" "Open Enclosures folder" +"Check All Channels" "Check All Channels" + +"Show Channel Image" "Show Channel Image" + +"Play enclosure" "Play enclosure" +"(Re)start download" "(Re)start download" +"Stop download" "Stop download" +"Remove Item" "Remove Item" + +"Find this Item" "Find this Item" +"Remove from this list" "Remove from this list" + + + +### ALERT ----------------------------------- + +"\nRemoving.." "\nRemoving.." +"\nAn error occured while removing!" "\nAn error occured while removing!" +"Check all the podcasts for new items" "Check all the podcasts for new items" + +"You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" "You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n" + + +"Can't open the selected file with:\n\n" "Can't open the selected file with:\n\n" +"\n\nPlease check if the application is installed in the right way.\n" "\n\nPlease check if the application is installed in the right way.\n" +"Download it!" "Download it!" + +# multi line text... please translate only the text after _value= and don't remove empty space + +_key="alert1" + _value=" +You are going to remove the selected item. + +Are you sure? +(you will lost the enclosure file if any)" + + +_key="alert2a" + _value=" +You are going to remove the channel: + +" + +_key="alert2b" + _value=" + +Would you like just to archive this +channel (keeping all the files and +enclosures downloaded so far) or +do you want to DELETE the whole + channel from you computer?" + +_key="alert3" + _value=" +Parsing archive.." + +_key="alert_3gp" + _value=" +3GP is a multimedia container format defined by the Third Generation Partnership Project (3GPP) for use on 3G mobile phones. It stores video streams as MPEG-4 or H.263, and audio streams as AMR-NB or AAC-LC. + +VideoLAN still doesn't support the audio AMR (3GPP)" + +_key="alert_swf" + _value=" +SWF is a proprietary vector graphics file format produced by the Flash software from Adobe (formerly Macromedia). + +Currently Flash support in BeOS/Haiku/Zeta is limited to the old standalone Flash player version 4.1015, there isn't a modern Flash player" + + + + +### HELP & SHORTCUTS ----------------------------------- + + +"Introduction" "Introduction" +"The User Interface" "The User Interface" +"Menu Bar" "Menu Bar" +"Toolbar Buttons" "Toolbar Buttons" +"First time with BePodder" "First time with BePodder" +"Download Podcast's enclosure files" "Download Podcast's enclosure files" +"Settings Overview" "Settings Overview" +"Directory lists" "Directory lists" +"Loading Help..." "Loading Help..." +"Register your copy" "Register your copy" +"Starting point" "Starting point" + + + + +# multi line text... please translate only the text after _value= and don't remove empty space + + +_key="help1-0" + _value="Welcome to the BePodder Getting Started Guide." + +_key="help1-1" + _value="If you are already familiar with podcasts and RSS/Atom feeds you can immediately go to BePodder by closing this window." + +_key="help1-2" +_value="If not, this is a short introduction providing you everything you'll need to know on how to get started with BePodder. Use the buttons below to navigate through this tutorial." + + +_key="help2-0" +_value="Podcasting is a method for publishing audio and video broadcasts via the Internet; links to free audio and video files are enclosed in RSS and Atom feeds." + +_key="help2-1" +_value="Therefore Podcasting is simply a type of online media delivery; users can subscribe to a podcast using a feed (such as RSS 'Really Simple Syndication' or Atom)." + +_key="help2-2" +_value="An aggregator (or podcatcher) like BePodder, is a piece of software that allows you to subscribe to a RSS feed and periodically check for and download new content; with BePodder you can check for new Podcast items (Episodes) of your subscribed Channels. Any item can contain an enclosure, just like an Email can contain an attachment." + + + +_key="help3-0" +_value="BePodder has an easy to use yet powerful Graphical User Interface. The main window is split into tree panels:" + +_key="help3-1" +_value="1) The Subscription list (the panel with the number 1 in the screenshot) with the list of the podcasts that you have subscribed to. When you click on a Channel you can see in the panel 2 the list of the channel's items." + +_key="help3-2" +_value="2) The Episodes list with all the items available." + +_key="help3-3" +_value="3) The Info panel show: episode info, channel info or Downloads info; you can select an info panel by clicking one of the below three buttons." + + + +_key="help4-0" +_value="At the very top of the BePodder main window is the menubar with seven menus available: File, Settings, Subscriptions, Episodes, Lists, View and Help. Some menu commands are followed by a right pointing arrow that indicates a submenu of related commands. As you explore each menu, be sure to take a look at the submenus as well. Click on a menus to show its commands:" + +_key="help4-1" +_value="File: contains commands to close the application and to show information about BePodder" + +_key="help4-2" +_value="Settings: contains command to open the Preferences window that allows you to customize various BePodder settings." + +_key="help4-3" +_value="Subscriptions: contains commands that perform actions on the selected channel of your subscriptions list." + +_key="help4-4" +_value="Episodes: contains commands that perform actions on the selected item (episode) of the channel's episode list." + +_key="help4-5" +_value="Lists: contains commands to open BePodder's OPML directories." + +_key="help4-6" +_value="View: contains commands and controls for the BePodder window." + +_key="help4-7" +_value="Help: contains commands to open BePodder's 'Getting Started Guide' and the 'Keyboard Shortcuts List'." + + + +_key="help5-0" + _value="Add Button: opens the Add Window to add a feed url (e.g. http://www.newpodcast.com/rss.xml) usually given on the podcast homepage; looks for text or graphic link that says something like 'XML', 'RSS' or 'Podcast Feed' on it." + +_key="help5-1" + _value="Channel Remove Button: opens a window in which you can select how remove the channel: just archive the select channel (keeping all the files and eclosure downloaded so far) or delete the whole channel from your computer." + +_key="help5-2" + _value="Check Button: checks the selected channel and updates the list of the available items for that podcast adding the new items." + +_key="help5-3" + _value="Web Button: shows the channel homepage in the browser. To select your favorite browser open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select your favorite browser." + +_key="help5-4" + _value="Play Button: with this button you can view or listen the file enclosure of the selected item(episode). To select your favorite player open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select you favorite player." + +_key="help5-5" + _value="Download Button: downloads the file enclosure of the selected item (episode); you can see the download info by clicking on the third button over the info panel." + +_key="help5-6" + _value="Stop Button: stops to download the file enclosure of the selected item (episode); to resume the download double-click the item (episode) or select the item and click the Download Button" + +_key="help5-7" + _value="Item Remove Button: deletes the selected item (you will loose the enclosure file)." + + + +_key="help6-0" + _value="Getting started with BePodder is easy." + +_key="help6-1" + _value="On the left of the main window you can see the 'Subscription List' with all your feed subscriptions. We have added some subscriptions for you, and you can always add your own in two ways:" + +_key="help6-2" + _value="1) click the Add Button, then insert the feed url (example: http://www.newpodcast.com/rss.xml) and click add." + +_key="help6-3" + _value="2) in the menubar select 'Directory' and then 'Podcast list' or another list, choose a podcast and click 'Subscribe'." + +_key="help6-4" + _value="If you select a Podcast in the subscriptions list and use the check button, BePodder adds the new items to the 'Episodes list' (below on the right); you can check all your podcasts by right-clicking and selecting 'Check All Channels' in the context menu." + +_key="help6-5" + _value="Look at the screenshot above, there are 3 new items indicated by a black dot in the first column of the 'Episodes list'." + +_key="help6-6" + _value="In the second column there are icons that indicate the state of the item:" + +_key="help6-7" + _value="- the Episode 4 has an icon that indicates an error" + +_key="help6-8" + _value="- the Episode 3 has an icon that indicates that the item's enclosure download request is enquequed" + +_key="help6-9" + _value="- the Episode 2 has an icon that indicates that BePodder is downloading the item's enclosure file" + +_key="help6-10" + _value="- the Episode 1 have an icon that indicates that BePodder have just downloaded the item's enclosure file" + + + +_key="help7-0" + _value="Select an item in the 'Episodes list' and then double-click on it (or click the Download Button) to start downloading the enclosed file; you can always stop the download by clicking on the Stop Button." + +_key="help7-1" + _value="When you click on the Subscribed Podcasts in the 'Subscriptions List' the software shows you, in the 'List of episodes', all the items available in that Subscription. Select an item and then click play (Play Button) to view or listen to the file." + +_key="help7-2" + _value="You can access the Enclosures Folder by clicking on the folder icon in the Info Pannel or by right-clicking your mouse on an item and select 'Open Enclosures Folder' in the context menu." + + + +_key="help8-0" + _value="Preferences can be accessed by clicking in the menu-bar Settings>Preferences. You can select a category from the left list of the preferences dialog: FileType, Channels, Download and Proxy." + +_key="help8-1" + _value="- FileType: to specify the default browser and player. " + +_key="help8-2" + _value="- Channels: to specify preferences that control the operation to check channels new items; you can choose to Check all channels on startup or check the channel every desired minutes." + +_key="help8-3" + _value="- Download: to specify the max number of item's files to download at the same time," + +_key="help8-4" + _value="- Proxy: to set up a proxy server to work with BePodder; a proxy server acts as a security barrier between your internal network and the Internet, keeping others on the Internet from accessing information on your internal network." + + + +_key="help9-0" + _value="BePodder has built-in podcast, videoblog, imagefeeds, newsfeeds, bittorrentfeeds and internationalfeeds OPML directories with thousands of feeds grouped by category." + +_key="help9-1" + _value="OPML (Outline Processor Markup Language) is an XML-based format that allows exchange of outline-structured information between applications." + +_key="help9-2" + _value="OPML directory can be accessed by clicking in the menu-bar 'Lists' and thenselecting a list. To browse the opml directory for a feed, expand the list by clicking the arrow of the category that you are interested in (see image); using this method, you can expand the opml directory until you find the desired feed. Once you have selected it, you can add it to the subscription list by clicking the button 'Subscribe', you can also collapse all categories in the directory list by clicking the button 'Collapse All'." + +_key="help_shortcut1" +_value="This page describes the keyboard shortcuts that can be used in BePodder. The shortcuts are grouped here by function." + +_key="help_shortcut2" +_value="means that you can use either alt or control (es. Alt+Q or Ctrl+Q Quit the application), which way you have set it in the Deskbar menu preferences under Keyboard (the default shortcut key is Alt)." + +_key="help_shortcut3" + _value="General shortcuts" + +_key="help_shortcut4" + _value="Quit the application" + +_key="help_shortcut5" + _value="Shows the Preferences window" + +_key="help_shortcut6" + _value="Shows the Podcast directory list" + +_key="help_shortcut7" + _value="Shows the Videoblog directory list" + +_key="help_shortcut8" + _value="Shows the Imagefeeds directory list" + +_key="help_shortcut9" + _value="Shows the Newsfeeds directory list" + +_key="help_shortcut9b" + _value="Shows the BitTorrentfeeds directory list" + +_key="help_shortcut9c" + _value="Shows the Internationalfeeds directory list" + +_key="help_shortcut10" + _value="Fullscreen" + +_key="help_shortcut11" + _value="Shows/Hides the toolbar" + +_key="help_shortcut12" + _value="Shows the Getting Started Help" + +_key="help_shortcut13" + _value="Shows this keyboard shortcuts page" + +_key="help_shortcut14" + _value="Channels shortcuts" + +_key="help_shortcut15" + _value="Add a podcast to the subscriptions list" + +_key="help_shortcut16" + _value="Delete the selected podcast from the subscriptions list" + +_key="help_shortcut17" + _value="Check the selected podcast for new episodes (items)" + +_key="help_shortcut18" + _value="Check all podcasts for new episodes (items)" + +_key="help_shortcut19" + _value="Shows the podcast homepage" + +_key="help_shortcut20" + _value="Open enclosures folder" + +_key="help_shortcut21" + _value="Episodes shortcuts" + +_key="help_shortcut22" + _value="Play enclosure" + +_key="help_shortcut23" + _value="(Re)start download the selected episodes (items)" + +_key="help_shortcut24" + _value="Stop the episode (item) download" + +_key="help_shortcut25" + _value="Delete the selected episode (item)" + +_key="help_shortcut26" + _value="Shows the podcast episode (item) page " + +_key="help_shortcut27" + _value="Open enclosures folder" + +_key="help_buy1" + _value="BePodder Light is the basic version (free download and no time limited), the registered version adds some more nice features: unlimited number of channels, small Channel view, proxy support, automatic channels check, up to 5 enclosure downloads at the same time (multithreading)." + +_key="help_buy2" + _value="Please pay the shareware fee, it's only 15 euro (Kagi add tax in some countries), BePodder licence can be purchased online from Kagi." + +_key="help_buy3" + _value="Buy at www.funkyideasoft.com" + +_key="help_buy4" + _value="After purchasing, an email will be sent to you with a keyfile and instruction on how to install it. It's just a matter of unzipping a file and moving it to a certain directory." + +_key="help_buy5" + _value="There is no problem updating BePodder when a new version becomes available. The keyfile will unlock all downloadable packages unless otherwise notified." + + +### USELESS ######## + +"Opml Editor" "Opml Editor" +"name:" "name:" +"Add a category" "Add a category" +"Add a new Broadcast" "Add a new Broadcast" +"feed:" "feed:" +"url:" "url:" +"Test podcast" "Test podcast" +"Del a category" "Del a category" +"Add a category" "Add a category" +"Select the podcast category:" "Select the podcast category:" +"Check all" "Check all" +"Check" "Check" +"Refresh the list" "Refresh the list" +"Load" "Load" +"Load the list" "Load the list" +"Save" "Save" +"Save the list" "Save the list" +"Revert" "Revert" +"Apply" "Apply" + + + + + + + + + + + + diff --git a/release/helpR5.xml b/release/helpR5.xml new file mode 100644 index 0000000..e746aef --- /dev/null +++ b/release/helpR5.xml @@ -0,0 +1,433 @@ + + + + + help1.png + Welcome to the BePodder Getting Started Guide. + + dot.png + If you are already familiar with podcasts and RSS/Atom feeds you can immediately go to BePodder by closing this window. + + + If not, this is a short introduction providing you everything you'll need to know on how to get started with BePodder. Use the buttons below to navigate through this tutorial. + + + + + + Introduction + Podcasting is a method for publishing audio and video broadcasts via the Internet; links to free audio and video files are enclosed in RSS and Atom feeds. + diagram1.png + Therefore Podcasting is simply a type of online media delivery; users can subscribe to a podcast using a feed (such as RSS 'Really Simple Syndication' or Atom). + + dot2.png + An aggregator (or podcatcher) like BePodder, is a piece of software that allows you to subscribe to a RSS feed and periodically check for and download new content; with BePodder you can check for new Podcast items (Episodes) of your subscribed Channels. Any item can contain an enclosure, just like an Email can contain an attachment. + + + + + The User Interface + BePodder has an easy to use yet powerful Graphical User Interface. The main window is split into tree panels: + + gui1.png + + 1) The Subscription list (the panel with the number 1 in the screenshot) with the list of the podcasts that you have subscribed to. When you click on a Channel you can see in the panel 2 the list of the channel's items. + 2) The Episodes list with all the items available. + 3) The Info panel show: episode info, channel info or Downloads info; you can select an info panel by clicking one of the below three buttons. + info_button.png + + + + Menu Bar + At the very top of the BePodder main window is the menubar with seven menus available: File, Settings, Subscriptions, Episodes, Lists, View and Help. Some menu commands are followed by a right pointing arrow that indicates a submenu of related commands. As you explore each menu, be sure to take a look at the submenus as well. Click on a menus to show its commands: + File: contains commands to close the application and to show information about BePodder + Settings: contains command to open the Preferences window that allows you to customize various BePodder settings. + Subscriptions: contains commands that perform actions on the selected channel of your subscriptions list. + Episodes: contains commands that perform actions on the selected item (episode) of the channel's episode list. + Lists: contains commands to open BePodder's OPML directories. + View: contains commands and controls for the BePodder window. + Help: contains commands to open BePodder's 'Getting Started Guide' and the 'Keyboard Shortcuts List'. + + + + + Toolbar Buttons + + add-channel-file.png + Add Button: opens the Add Window to add a feed url (e.g. http://www.newpodcast.com/rss.xml) usually given on the podcast homepage; looks for text or graphic link that says something like 'XML', 'RSS' or 'Podcast Feed' on it. + + + delete-channel-file.png + Channel Remove Button: opens a window in which you can select how remove the channel: just archive the select channel (keeping all the files and eclosure downloaded so far) or delete the whole channel from your computer. + + + refresh-channel-file.png + Check Button: checks the selected channel and updates the list of the available items for that podcast adding the new items. + + + www-channel-file.png + Web Button: shows the channel homepage in the browser. To select your favorite browser open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select your favorite browser. + + + emblem-play.png + Play Button: with this button you can view or listen the file enclosure of the selected item(episode). To select your favorite player open BePodder's Preferences, click in the manu-bar Settings>Preferences... and in the Preferences Window under 'File Type' select you favorite player. + + + emblem-download.png + Download Button: downloads the file enclosure of the selected item (episode); you can see the download info by clicking on the third button over the info panel. + + + emblem-stop.png + Stop Button: stops to download the file enclosure of the selected item (episode); to resume the download double-click the item (episode) or select the item and click the Download Button + + + emblem-delete.png + Item Remove Button: deletes the selected item (you will loose the enclosure file). + + + + + + First time with BePodder + Getting started with BePodder is easy. + + gui2.png + On the left of the main window you can see the 'Subscription List' with all your feed subscriptions. We have added some subscriptions for you, and you can always add your own in two ways: + + 1) click the Add Button, then insert the feed url (example: http://www.newpodcast.com/rss.xml) and click add. + 2) in the menubar select 'Directory' and then 'Podcast list' or another list, choose a podcast and click 'Subscribe'. + If you select a Podcast in the subscriptions list and use the check button, BePodder adds the new items to the 'Episodes list' (below on the right); you can check all your podcasts by right-clicking and selecting 'Check All Channels' in the context menu. + gui3.png + Look at the screenshot above, there are 3 new items indicated by a black dot in the first column of the 'Episodes list'. + In the second column there are icons that indicate the state of the item: + - the Episode 4 has an icon that indicates an error + - the Episode 3 has an icon that indicates that the item's enclosure download request is enquequed + - the Episode 2 has an icon that indicates that BePodder is downloading the item's enclosure file + - the Episode 1 have an icon that indicates that BePodder have just downloaded the item's enclosure file + + + + Download Podcast's enclosure files + Select an item in the 'Episodes list' and then double-click on it (or click the Download Button) to start downloading the enclosed file; you can always stop the download by clicking on the Stop Button. + + gui4.png + + When you click on the Subscribed Podcasts in the 'Subscriptions List' the software shows you, in the 'List of episodes', all the items available in that Subscription. Select an item and then click play (Play Button) to view or listen to the file. + + gui5.png + + You can access the Enclosures Folder by clicking on the folder icon in the Info Pannel or by right-clicking your mouse on an item and select 'Open Enclosures Folder' in the context menu. + + + + Settings Overview + Preferences can be accessed by clicking in the menu-bar Settings>Preferences. You can select a category from the left list of the preferences dialog: FileType, Channels, Download and Proxy. + + gui6.png + + - FileType: to specify the default browser and player. + - Channels: to specify preferences that control the operation to check channels new items; you can choose to Check all channels on startup or check the channel every desired minutes. + - Download: to specify the max number of item's files to download at the same time, + - Proxy: to set up a proxy server to work with BePodder; a proxy server acts as a security barrier between your internal network and the Internet, keeping others on the Internet from accessing information on your internal network. + + + + Directory lists + BePodder has built-in podcast, videoblog, imagefeeds and newsfeeds OPML directories with thousands of feeds grouped by category. + OPML (Outline Processor Markup Language) is an XML-based format that allows exchange of outline-structured information between applications. + gui7.png + OPML directory can be accessed by clicking in the menu-bar 'Lists' and thenselecting a list. To browse the opml directory for a feed, expand the list by clicking the arrow of the category that you are interested in (see image); using this method, you can expand the opml directory until you find the desired feed. Once you have selected it, you can add it to the subscription list by clicking the button 'Subscribe', you can also refresh the list by clicking the button 'Refresh'. + + + + Keyboard Shortcuts + This page describes the keyboard shortcuts that can be used in BePodder. The shortcuts are grouped here by function. + + key_alt.png + / + key_ctrl.png + means that you can use either alt or control (es. Alt+Q or Ctrl+Q Quit the application), which way you have set it in the Deskbar menu preferences under Keyboard (the default shortcut key is Alt). + + + General shortcuts + + + key_alt.png + / + key_ctrl.png + + + key_q.png + arrow.png + Quit the application + + + key_alt.png + / + key_ctrl.png + + + key_p.png + arrow.png + Shows the Preferences window + + + key_alt.png + / + key_ctrl.png + + + key_l.png + arrow.png + Shows the Podcast directory list + + + key_alt.png + / + key_ctrl.png + + + key_m.png + arrow.png + Shows the Videoblog directory list + + + key_alt.png + / + key_ctrl.png + + + key_i.png + arrow.png + Shows the Imagefeeds directory list + + + key_alt.png + / + key_ctrl.png + + + key_n.png + arrow.png + Shows the Newsfeeds directory list + + + key_alt.png + / + key_ctrl.png + + + key_b.png + arrow.png + Shows the BitTorrentfeeds directory list + + + key_alt.png + / + key_ctrl.png + + + key_f.png + arrow.png + Fullscreen + + + key_alt.png + / + key_ctrl.png + + + key_t.png + arrow.png + Shows/Hides the toolbar + + + key_alt.png + / + key_ctrl.png + + + key_g.png + arrow.png + Shows the Getting Started Help + + + key_alt.png + / + key_ctrl.png + + + key_k.png + arrow.png + Shows this keyboard shortcuts page + + + Channels shortcuts + + + key_shift.png + key_alt.png + / + key_ctrl.png + + + key_a.png + arrow.png + Add a podcast to the subscriptions list + + + key_shift.png + key_alt.png + / + key_ctrl.png + + + key_r.png + arrow.png + Delete the selected podcast from the subscriptions list + + + key_shift.png + key_alt.png + / + key_ctrl.png + + + key_c.png + arrow.png + Check the selected podcast for new episodes (items) + + + key_shift.png + key_alt.png + / + key_ctrl.png + + + key_n.png + arrow.png + Check all podcasts for new episodes (items) + + + key_shift.png + key_alt.png + / + key_ctrl.png + + + key_h.png + arrow.png + Shows the podcast homepage + + + key_alt.png + / + key_ctrl.png + + + key_o.png + arrow.png + Open enclosures folder + + + Episodes shortcuts + + + key_alt.png + / + key_ctrl.png + + + key_e.png + arrow.png + Play enclosure + + + key_alt.png + / + key_ctrl.png + + + key_d.png + arrow.png + (Re)start download the selected episodes (items) + + + key_alt.png + / + key_ctrl.png + + + key_s.png + arrow.png + Stop the episode (item) download + + + key_alt.png + / + key_ctrl.png + + + key_r.png + arrow.png + Delete the selected episode (item) + + + key_alt.png + / + key_ctrl.png + + + key_h.png + arrow.png + Shows the podcast episode (item) page + + + key_alt.png + / + key_ctrl.png + + + key_o.png + arrow.png + Open enclosures folder + + + + + + + + Register your copy + The trial program is fully-functional but is will run only 30 days from the first time you open the application. + Please pay the shareware fee, it's only 15 euro (Kagi add tax in some countries), BePodder licence can be purchased online from Kagi. + Buy at www.funkyideasoft.com + After purchasing, an email will be sent to you with a keyfile and instruction on how to install it. It's just a matter of unzipping a file and moving it to a certain directory. + There is no problem updating BePodder when a new version becomes available. The keyfile will unlock all downloadable packages unless otherwise notified. + + + + + + Index + + dot_index.png + Starting point + + + + dot_index.png + Introduction + + + dot_index.png + The User Interface + + + dot_index.png + Menu Bar + + + dot_index.png + Toolbar Buttons + + + dot_index.png + First time with BePodder + + + dot_index.png + Download Podcast's enclosure files + + + dot_index.png + Settings Overview + + + dot_index.png + Register your copy + + + + + + + + diff --git a/release/tutorial/bittorrent.html b/release/tutorial/bittorrent.html new file mode 100644 index 0000000000000000000000000000000000000000..cd34faed98516b7dccd4a8d08a411a772e89eb67 GIT binary patch literal 3990 zcmbVPZExc?627k~(El)}LpKQ!Tj_4n?zOfLm)!(ipzQ{`E)M-vP}109Batde+x5S{ zXDG>1;@ivKIe{&aoVSP142QG7zJ32@`Rn~H{jmJ$N4o#z=Erw$D4C?`zh1pb)3?jF z?Znmel9o;xuY@2gzoI6``IGSl^%yvygwG}X0QvrorMf3vIAv@z?1 zR0SBvQ$s9^S*pb6lfg9TG}vxR8*Hw8Ky=U89xr`jdptGRrU+IS@}r2iy5P^WI$rw3 z>Ue6fdK~d%v@;!obq?fwCf;G;Z`hXs=wbZxjjn5@t7q)RHBUl}W1lu7L_QHlrl6#x zS0uGO<%o~t*dw05zW!>^_K4>#>mTvFqk3dd}Ws^e&u60cJM|cGBQ?klvN-m^PlBmr`ap51v@%CE0)}R1NZ|W=xHBl7F7;s#pAj z-SL*)1<6Wo-4a}#st5`(MQ6FHD)^?vv;2YGIqgaf?YTuU(MARKB2Fr1wLqXMXiEKsftylMmm1XH1?GMP=CAx7wK@!RQ8q9oTEDky^r8JLRy z54@+Q)RpzNDfc4rcsoO>LZ`%+c2gC!X)3Dl$@ReOK@kW_7`M0?5uk@xGB4bD6mr=;es$3`!Idt=7DNp zMJvq#StK&z(SS$8w!z_nk_%#ZfkPX>ma_{APXaqea>vSpq3t;Vj>~Z&KiT4@vg<;x z*X(9#CS#w-6*^9~ku3ehg^sBrrO?xdj~{8pT*Unsd<>v$)2!$8V5xVe_32l;={S)2 z95eyy77=+?4pc>un<_-zlmP3rWc4F zbOF4Dgbp-Py}&UHYKcPVsA&&pb}BmGdjPH9(a7ad(~}*roaVMpYr!OS-cNt`%|HH_ zADI+`FXF0s2hIx*+GqQDfpi_&=tdn^$EP~Bx6pZ;-Y6lGHsbzcyZ{x1d8>?s-fcd9 zM&|y1&Eo7qX`#1~S<*4YZUCFeY>;drdD23xH~QOnn#CSQ=$Q7>t%pl1nIa{v+eO>3 ziP5pik>VS$K{g(}(v*7Ms61!irpfKF>MpJl%H);KAA~2iRn^LqM#Ylc5$xWXm8E-y z8eI`ey?`ej+vFe$S~#k$I0q>dEEJ+TmNE~N^FXKX#nU7Er@e((9{&u4&UAB>m9Z)8 zk@!3uuUj1d1BRmPok1AV3?q}o=TS*)>$1??AYElaU)o|g+V~*H1S(3UrBR`?L$f$0 zK4&`kNP5*Y>8n?-zeyH1%gGJD|0vt47J}nvNM5~s`E{~b%Gp|L?_r<$B=7%Cls6MXHuh0nr>HTY1cz_ z`dY31ciRc24GNh24gK{|E7mS}eBJo_<^Rxz$#nx3@Q)svx@%1G?KSR0T_4suDz}E# zt^Q&$Zjig?bAX|7ynR|5WUTFU`@2xrO^+jd&W*l1jM;na)VLKMyfL^6KJ`Y%p7rJk b@58?JTP0-p^fP8sxs1w^c)i8LU*z*|j~x63 literal 0 HcmV?d00001 diff --git a/release/tutorial/gmail.html b/release/tutorial/gmail.html new file mode 100644 index 0000000000000000000000000000000000000000..91a36588eb125b86b6eae67900e56325baa6cdae GIT binary patch literal 2971 zcmb7GZExE)5Z+f8=zq9r*wzBES1g zY$t6xC9p*DcrVXAykq?1>AREbk5^~(=k?n+boJr*&E*LN<0$&)=}8owUY~Xghv9^- zt6vt9Aa7Kt`c^x^mIbb)SK__W2rJ%V5J)sQq2oDoxolGi=9YHNu5ma z>}Ue}#=>`ONM%{pBFmJXPmlblsYS{o-i=`GEIxjZ&+eC%WwT#&($p`%{R<>K=unZ( zV!&=?J`I$1)?{tUScQzRhjcWGRW+x^rqdvdR3+xJiMB;QnLH0`Jr78ffN^_ih-DT> zf_)whra`B{c3l`}Qqed>caQCD(LLMSOM`9lVD%yIM7&U${7$ReqI*`imj@Zkgc z$`codvkQiU9$gqS$02-+!DG~h!){}@s2UQKTZuC&6E7}wMpy5yNRIumk#?a{Nwqc1 zgp86EbqWvYMw_Lk+*nc$dXiRWLOW`Zd7L9+O(I(eonjjfj^cK?Nwl$pxgxR3xuuR{80T1thc8z~vR zl2)dLZ&huqW5+7lGX;H~IN>BvU48eKK2m89E{aq{Sr+BmUm402@) zLEC1RUaVzavHfuFPX#*=@i^j0BjMoB2H`!Rn>J}us}jk)@YXxHFLh$RkcWzJNWmAz z6Z{4!2!UQ_86CH%hv?B5-qCQ-1;=RjTFY{rc*(8mG;HS{#~SQsI?_|5WPbbz(f$<3N6mmg1O{<@(m6VN{|)}E7eYNVFGix0#B;R&o%`D5;w~b5pU=&9~1H1+GUEm|f PxRG*Z{2dn`Kk)M(p3s^^ literal 0 HcmV?d00001 diff --git a/release/tutorial/images/add-channel-button.png b/release/tutorial/images/add-channel-button.png new file mode 100644 index 0000000000000000000000000000000000000000..3c1acdc08997f61ec70cd0381b9848d453a98d6a GIT binary patch literal 2286 zcmV004R=004l4008;_004mK004C`008P>0026d000+nm#LZ5000Pi zNkl|P@c=*o zVR!(jSV&Av?2UwkgcdL+{?g5rcmOcunSoBZ@#4h`S#&vo0K)J9BO@adFk>_R{{8za zP}87DLco*&b`!{L=yCu7ge?XbffOT9({CUi6dr&&oDu3a6aWxFxIDlB^#IMwSSDbE zBLen6$X>?(45-$Ef*#pz$N(UKuq7czP;~tP0$O{3m4*G^&)?sezWw;Z0&yVoe|~PE zU;qC7WdvcEI*@yyNeIIO00D$820)$wY5GIUN)F`sYY$KJ^sdcOdGz`UCs2rym6_w8 zw`t0YWY4-s%uK96H~fQn0PH4^+t2|(0O8C7Kuv!Mc>wBBk{!KXk3^?)tKmcJ)LLl%D0>EOxQVe7t z$N(@6N@XB%U`fRU5`)P@Qr~~LJV*>PfSAE)9+)`)fB5>CT}N4w!AUQP0i;wx@*Kmy zv&R`efBV1!jDbJEFbAsp2XYJCUFhZk1YoO*aTo?+pcO-_Rut5o|G$U+phG4)Fjyr4 z;-n_Z&>>zt*}C)T&Zi0-NO(V%RE$wM=a`7l7{fW|JrzO-cljBM_r7SYw_5AayV$2M z0c$P)2bsd_Iu*jwChSCnJ1lE~F};9!gOuNJ5kzyNA<;+8?Te4wvvs4(xIRuZYU%(251)3&7j%K)c@gk?Hs_KuYPoJ^@J@os{ zn>VZ=#{=;nSS+vt9e@7rZozqb%G5r7f58cI)aUPCnB`a%8Qy-m&+r!*C0~EOVBq6r zU|4*xLUq-#8Wm99HB;QxP?UKOE8B#lj=8|_Wm&bi8{s}RB*W0Y-ZYi;5GL^ZS-{ltqY@BN%}ZdZK6=r;|0>u{7>WGZ)kJ~`}Y z4>K50Pu#F#Oc#vP6|eUVo$f#ban2wd9S;0bKGQ=>u@(PZXc0iTGBGnWy1?ZxFf@My z9mxLh;X_VybMvntv1`|^ae+Mg@#9A(VAA4LQ&am1$^&Q5p5+Fze{gVc{0D|4INHGw z2v}Jdfz8`r3}1e~V1QLI=%pBPGGY18%)kP4Au|)CHpZ5Q00OX8E-L_nKom6}Qy>K` z>M#8NuZkc-dXRNoL@g8!xEOTCxpypf0NhKy7kRi4!ij-37?N(FW@!;I6yVug;w)ZC z_#{h5{^y7j)A{k3<|Ru6%_sibiV5dP@`JZSUU!~8YK>9tn^Ju{T!c!g1CId0nu$S< z24Z$-G6L~I`G5hKRQ>@=7&c%`@UXD3fMV%CkY)guN{m2H{8Ld;`3XuoKrO5weXtA+ zbPfYME7!kptJr~V zD=@?vfSv*C;pF7}4=jPW$-=@1QU~_H&p%%o!Yn5|u~v_M`}5BiW^N84V12;A{Ok8mti>om z05ZyE1war8!kO-xR(2>l`2Mft-8b+a^fN04L5E>s53<8I60tjmog2e!c3k-R7US8h+nwpybUcP+EE+{C-49v*CKd0YPk_ zN11>X9vdh&^z`)p9X)!K16V>a0`mi?U5I2eC_(*YU;&oYf;^IcpMSW)AiysGPOTq5 zgYpLx10RP(P|0K)?S0fegxZ2F~EBJ_H8Bw z1%*Gr;`1LieZV3Xg#Z2c@q_KgjT@}ME-3@BR|m2Y6q6Vh1C9S5Xjc1S<%w6U_io*1 z1?4tIps{XR`Jc38oqqjg_{9d(2W_ITV9Ue+0fe;}g_azk)+i&eY-a$LKn(Zq-)93A zlb{gB)z1N02rO=yfohn5dEhrF2}0X37;66k^MsO^`M+YX1FwGk{sKxWzzUD$KR1UU zFhBoe1+_$B{REH)ph*$KAbjQZJfbbQgaK#{pfI^p;rZcGI zf$72Lcm()|(*J_ipSaxg6J0kz0O3nQ|M1n4ga9dOi7^YBgnpsR0R#}XB=jGei7`Ad zPypIO1|=a32LS{Sh6jKOAA?E~V9m<|%Ea_>B0=yU=%z0qx1mb_1Q3P?fN8i2Sey0$ zeG3{y8Wh7SK)?hnAf5o}8gvPO0Ad_0$%I@05I{qIbQ&PQ00_XPHq)$07*qo IM6N<$f))=NasU7T literal 0 HcmV?d00001 diff --git a/release/tutorial/images/bittorrent_off.png b/release/tutorial/images/bittorrent_off.png new file mode 100644 index 0000000000000000000000000000000000000000..d930510cc8d4ca0478e4c398073bbc8b6245dfed GIT binary patch literal 1936 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 RIbfm-BqO0HULk7e{~uUy2yFlW literal 0 HcmV?d00001 diff --git a/release/tutorial/images/enjoy.jpg b/release/tutorial/images/enjoy.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2ebd91eb29b1a560a3f078fcb17a14021bbc7253 GIT binary patch literal 84286 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 literal 0 HcmV?d00001 diff --git a/release/tutorial/images/gmail_off.png b/release/tutorial/images/gmail_off.png new file mode 100644 index 0000000000000000000000000000000000000000..bfe188ce71be735edbd475d590cc06a9cacc2492 GIT binary patch literal 2191 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 kLr}X?=(p!0 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 literal 0 HcmV?d00001 diff --git a/release/tutorial/images/gui6.png b/release/tutorial/images/gui6.png new file mode 100644 index 0000000000000000000000000000000000000000..e5f630a6a73045219770e954a15086a15f2079d8 GIT binary patch literal 11340 zcmdUVcT`i&yKd-Gr70lQAWcdD=^&s+0TK8B73m;?G(mbN6cLabL6MFW0qGzjHS{VV zy-2TO=rw_moZ(x)bJscl-hb}8E=jWYo;~x<%sbEX&ht*>KiX=vRM)5=5D2Y?I$RF| zAtHc3=1b(@4xg(ExZr_k!0$ZvPTQLGd-lYmNoDusu9#1su6lg0DDihP#JOZ=1Cib> zlGb)M(M)?i$-aU@Uj3L4oSPat`!5oX&G5G3T}phM~rh&-gJJ3GDmvK z=)?xz?Z!aF=D7XVSydQJ&Wn#dEmv;VRzSf_2!2gluxD-WHhY&}};Is6Qg0^8DkaMvjQz|I* zFW={L-iV6GT2;6d56$6xWM`vu70ltTl39QPts&D=fNyEa`Kup(W??uZ+?qz_+Ps0O zQvJ2ixBarHi0#e}t5uc8j}b|bJt~D*|DV$;47w4L6F6Qqqs>h@NA?2FNKSO1MKxXP z+waus-FSM%iIuZM@`Y`mE4E()S#y>s&O~%XU$bG#G9j%@=e`N*a5$c2`%lcI9pW`C z{1!{2GPVHIa#8l+okM(eXH7MNJP;;Ng$t73Wn$3nrgl4ZIw8tBgR~2qx4OGq*Q1$FVB{3tVtyuZfJIH^&T94r{A*Q9GVin zmU(*u0_oh=R2B{TycMFAKmZMVI!l#!RwdHM-#DsO?sm6n=2e#C5(~F)YGtJNzTnae}-Gd4(Vw)RY21+ zz{JeXsjP2p^LoV+8-lj$<7n#IX081EoV-F_gX^S?8Tt7EY3!$(ALNu%+{6&BbQktD zyiN3pj`k$_fS}x4-w+WYXe&>P*CRA}#LSQ845*5u@ms2#=&0qA1IcfuuYE}twz1

;3*j$;J!2icz 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 e!~Hlu6#N&7WiX+iEXDQ!0000=5 literal 0 HcmV?d00001 diff --git a/release/tutorial/images/next.png b/release/tutorial/images/next.png new file mode 100644 index 0000000000000000000000000000000000000000..afcd6c3de5b612e2d67a9dacf5b9a4f6a68e541e GIT binary patch literal 1409 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 Tvb3NpF@XQ>eY+m+U}XLQWUBzT literal 0 HcmV?d00001 diff --git a/release/tutorial/images/prev.png b/release/tutorial/images/prev.png new file mode 100644 index 0000000000000000000000000000000000000000..2814fbd7624b86dd79a4e08e52ad6b730684adcb GIT binary patch literal 1404 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 literal 0 HcmV?d00001 diff --git a/release/tutorial/images/rss.gif b/release/tutorial/images/rss.gif new file mode 100644 index 0000000000000000000000000000000000000000..70d8f8c3dd0762a2e241d515ca7524747aba2257 GIT binary patch literal 1105 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�HP2zjl> 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 z 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%0A_6V^gcLd;O>vSTzvcZTJZjbK7iQZ1n;S#KmS1 zMq{<=|Bo(^uAmtp7XH)q12npSu_05?1AyNo|5+lccRi{C_J6VfJMf=ZD1hfRb#HFa zTKlI&X?CPU#30+e}n6bX;a&QbwOwwvj;7V^W;#3Y#f?J|2)*!Ot{ zvar9@Y)C2m_O45$Zt5ZedJ=da>h6Z>dh&Z#2dv=;dDgBUtNlDZ)1HK%G|5(OGXqRha}LRU;&9G35%`I|aWgX?dyylt~UE!JD&WZy?GKs!9&vyr)PUU_fa z`T1$!IqpFS6%^$z!hrh0`~1$=UZLp9t}Z^HZP%%$TdYDYPpvG(%gEh5*zcz54UHm{ z%X;1cct`xpBJ9p0CU)HX>QZ$z(vjbCc3!r$q{(f&+!rQv{mYvi+!b=V{CVZY>G$s3 zc(Vb8yqHcpx zBm!#Z%1{{|&b?pXLoCt8KC}Ai5NIHZY5y`uE7wBP^>Kw*1&v~?PEKO-tUAD+du==c zYS!mH`&SyEWPj^M6uN-^R|Z0%lMA))J^+4?0mCxAEFFMa%3(&H$MI^62k<%!{^79Q zhrAAyAqcm&uCCne(eCu|jW0k$SAQ_A&;&^7r-7ytP|6aJlA8MZcEUMUIeljw%Xv5- zXeQD|Mw0y^De&RDAT!BvlfXq%ty#@2?uSmY^mh{=`zILpUN8brS)X%8tbt zLW)x6k>-kWwD;ecP&Amjue(KKRkq8zHFj2d2LvQ|r2 zF#A{fp9NX*sDvh+FWjE4q^6{7-ub=VRpgnY0@4T$0k^YfT3YNS01*j{VT6Yx@9pjN z+ya3Oh;@tStX6^7{8=lmPCzc`xH}X_{bhD&2nhhbT4=yFsjTcX2*K4QD7Dj>_700^ ziO4$plj>Z?cp@eL;Hpn}cM}m)9VU9IPX0R>z@UGR=uj`(x9Fn#>Ww%cXnatWZe9`(0U7mP zMIGc1r1$ZA4quKt|N1xq=h>k&h1`tX+I(evVMWwRODBEn-l!~)vv2$7cTjWiHQ7`v z-!Fhvb~}V$i#O9p@SASIE->kRgxr%jTc<*HZU1WCVXqGIJ|DOIsy5V0KW~@>YL?%a zY4ZDte1uU7vhEVK&CF0wNl6xH`$|$Q91YOaHkz?@I5}p0vgPGKQwrm%3OSY}YJVGh zx_>fndw8rQyZuO~y5(#fu`YuVw8X&B8u2|%V#cJBPppGaj0TONJNV3G&1`JbWyWR| zg`nR^H$^Cy_mb&JI+6;a6lc+LW1ThSWI$6*-Igk{?+eF(e@H0qM{)?mN+LH#5Chv<7x3v_Ir z&lE#gx_BTC+ScxsY5KDC`7qlMv>ggVbU$9$DrAA;7(8GIYq_Z z6;cqO7PfR7s3Tg3HD0W)f0pZVh_6t$EiiUq0%?VzCZ$@;N-$6w><@p!`3$7tIQ^#^ zfEsp`J>n)xuDA4eqywW9ysH%b?=D~rIc13w!Y!hD3M%wP;YTpM(E7z!l){IU2^;Zy z0R=?2XBGmzmQxyxKSh#+pc<^nj-W~l+X{x(H5Q?_Y8@5~4Km`L%P6utDxXgKsB0)m zoW;jvk{N;KgGVy$pK2U2J{tUs)Iab+c~Ykyb#*hUHb#{|$P1Kebv;g_s% zftB0qyZ;lmZqtuu)y>{|opGxW49E`+=SCHZ7#%Mx(gu_w_0+EalKV(DW*v;J~hq$$% z7{=$B+sAKN*!>zUp}{O9OboXQEt6f{>9}pF{xhyRk$}W*@ItCfSE>5YKO2#!U;Jas zt%d!$k$Vw5>o{{Kn%i38g1Y9n9m4X)Tg7WEWD>1Yq8|I-4%)-{W$yV0_c2>b@U z345L6aW1*6-M!4O7qxY*cmutG199L7Ax()uDoTvm=g5D+WFC+)>z zb2_Bnn$Qn>+h;Q57v4QY@*}|0!QRrg>q*`rRbaW}4RO#iP&UBY`W%v8yPIU~!A5pr z&hoD7F759m`t#VQ3-Zs5a!s4J67IWKJ%7GZ7LC(K`tSSPu^q+15{; z8Q~JU#P?>H1S|)9dfcCtW;mL?qwP0v$*uO*;m?6;YNHO)c=@6eO$WKJ5fJiGA?Q@&3>KV6L6~~d|`|Lb<4Tr?LR@?wKv%mT7As zalp+%+qo&f4ot0Z>w>* z`yqv^Ds0h=V8+~b#p@GW$N*}DX<7L|l{5C(Eap#>vfle<&zaovpr1>9ees?Ytr$%9JDfLY*{)%mJ3;m}s$yBiR9+QhgwQ+0?zy{pi|h=a3)`rvvykYC-$lJb zCHtE*u$!DUwgUPvmpyxyraR@V8!pekF>u#|-PbP9tS?3sgX=)<@Bh>gEYbe`)a{mW z(cI0WyD5vkG++e9|04gM8ii!*p;J=NA`w67Vu$k2xXWM{rh7>MEpvC3uY&sy+SVyY zPygWNC9Q$+*VHUEGwq&s!{i0F3He{UwcC41g|M!Hpy zOzL-CxQ#c$1IJ9Kqipy!_#KQsv@h8`A#DlLy@7gr%5MEuH~nT6)W-G2D8q9NgFRFg zrMD%rzTel>7r0mI9{rPUw@M^@a%H^@e{y6U4-(&3>A~x*Ctm5i=v%0?N@%5gtaBg7xULASA0FXX<-OD+txcY}(1`4r>_U4YZzK zTBNEz(FzZGhWm7H@*Yml-4Q^(5JFdwzJ5VGQbO7L>-L7yr1EGzEHbZ&sBi>&veum# zV!B1TMWbzis)YQ~61d_K#9?6C+x(j&Pci2OY zEi(TX62tqO%CMVhR~P&5?q4>rcEdz%w(j;ETz);nnKEB+j(CKK;hNcu>4@q7a{wNf$P%(3Ap+0`DfzX(Fu8$9)cRMAgU8 zOhP|ETP_X|LC9Jros7m%%Z-9-#YQL(q)c8Zt^yAji~P!_>i?Ftca`xoQpH-qEWSHp z7|9EY0e0BVL20kU>{kXT7}GQA(BbqbcUi0qdWHWYkzISwx=6a>(fUN2oCK|Ej?Ju` z#GEmo%|7RzVQYkexLjA;&PA|;?I%vEhU6F8wZ|phV^VD6`18mlYJ_I0{^qyG(;51agzcH8GL-vM15RxAGHyPt(>rtXQf*WXj@>Ke}T zssic3vcPUckC+Bm@!w-)I_PbEmJVsk#@iz4xi-dhIQen0pu=$Vf?xXlDTD`J=sY;G z^rY+}?7IgCiXWQcW9i?cyREX*<}1!+3%3R?|Iybo4uqEps}^I!wn-TNljg^(*0l!q zu92EEml_!G@spq1V4IzBWy0K|^Q&`7q56NR+rqiEFR2naM?^`m4%}kE0T)OC(?P663D&A4p!ivKENE zXKzkhTU=8;YIhlx=Br~8%aSXTMk`^1efH{ME3JI|vl#FCyo^|PJ?%zc(hkNrLp?j% zsK=@CvHfSnKe@$!f9i7Wc0no)y*gqqLy7<+onl*RyB2bw+nqXk*YEa-#bW0hT3gc= z?8e0D5K_4ykKLVgGy%kz%YS#(8;=zmyCaDcxP(_0cM~d!#|xF0VE_cE>sofh%y{QT zsU`Z>apj)G`|qu^Fk&_l6ygXtd2?2I|9((72&CjpY`VPNY=?z3-+Gtm=OxLg;!lHys!*JpQa~pz17>)ulvnFAo}qGfm;#JmU!u z5bgU>*C3Z|V59|TC`Fp?bywKiha~a^AQJ`Ffe9!hf0u4(58}BR*g%Ua5W)t5zG-pBvQp3~{kB z{mkR~;<7oCANGk|jiOY|?xPE5jcJRm7t?#b9sV3Y>=fcaS=mnIDnGQ5qbmswdZZ1X zdFZjn=PiVg(!vyc#}X-bp8B%}E20cnLe66k-9!9{$h3TLsT69)^6Kv1oHZaEd0~^? zxHw2Ar-g81(f$~yM9*2Xj|Z=pN1g37E!hl!6@^l*V_s=C9>(>_GZ&sLN=KrJdG3?n z{<<~0U&5G=XBe8B?}N|g&BuYW0oM zy$ox+Cy0@;`4I}+k@rxb7g@be2)wOhxaCPTIK}`F2G#s)7s&uvME+W%36;k@2HdW`R2b7r{(5Q|>T%Bu&i(A=Q;3t!i`kmrn zip%YEQ|%84dMM7F*V2$nCR;4TIoYqW&^9i1csBOtD?XDwY|n`E7}wT-V<$p3M-fEh zH%n0;onz(1dHr4myY3^qhR$El&Mz@u@7|*IpXZyJy&tf+xw+3eVlN0AFk!sByxQ-# zWAA%~pP7@%J0TOVCku2O*l#U8(S^966qto3Qup7O6}^!a{LFi@ zpYJ(?L+eg$U3b{br(Mrpj$;cS?es-jki6v$wG*!}kkva;i(B_1XQ=KZQ5MrqO_5J?=&;kbrWnAw7kN97q0v;F z)?IZ?>iucYcBVwBfAUY@euu|6=%_y~(QP(p6Ip0;2)!JHXNcL1nG|`FMSNm!z>-{ z2`OReJF6(&XvLB$g1*1aR$Hhhu+D$QE5katqKC5_e*+i^&1F4mb5G>LJH&nzH zBN(kLVRm{$HBo*U`=N+oovxnDnFT9}=>FkNZ?54T&o_>SC%pAZ`GR@kq_v%dii!JR zWG05HQChFy!k5wU}gU?auO8Qr;oC^8yr(vK(P5W7% zigCRT{e7m$w+2ZH_$U{UeAue0Md{yn-w%#{CKi-zk4gD6;3SiZ40Ov=4@M!+{&3!3 z`7Ld<#FjE{;KjwF!sgpZrzDayrVEtw7_!|3iWHw!I}I|z~e+pjL$97Ys9dwVo1 zD=Qhoep#}~%r$j&z0UjvmO@;D-T&3iuS-RzeD{l$1a@!GUs+ya$<;x5KyDi}86A9+ z-Nb=&SPI3ipR;jSQRpPiLr&mTUnF|6S=58pq=1+EsKu9pQUT5H2_^Y6o@m1~2^O0U ze3YiEFW~Tfz??}HDsSG_N{-Af9AmV$l>kjj2GN8vJaZIVnw^egqTOEx7OudrOeO?| zBvPg7xDEGoUQqvdJ3^f*_vWVUknV$YsnE4izX{h(7qlt(uD|q!!1ydrTXX+o&KW-p zTk!g2Z^{VF3B&E=faPAs`}t}A)*lHcsXpNck1a%J12Rj52ajwC(0Ob%z2kVTL2frM zr#eQ0VUCGGB{|>&D@}W>-vE3gkF7Q;PD)(NfIrh|f1GT=etrAbS8~JFhJKQ-l;HIa zfz?F~%AG=x(#le4MZSj#Hik;9g-9X9qpmXNT@@8pAqlcq6=m zS>CSq!^X^!S2kXoTR|HT(igU|-{;=bYXr9SIP&CY57F5v6|(L%dpTqp@xT4X4x3Vn zaU$(urz{=QxHvTSnt|*1@qlwEF~@mbaz^yA%9+T~(i98Sv9KUymoUdyuoU0h&pbv`qe=3`z^5 zU8UAR1_f4p8kW0D{_2#KcMn25G~cNb$JuU~(@Z$vG8CPr)b)Ksh@0%LP5=>MZK?w& zhUtv4I}X~y%j@nh9WE@woodM^$iFhE@kF`T2lzUv`u8`At;FQZg*4oRtC$rM+L5M&}J=BkldH}}YSFRedI<))LonuoYv`dYziH4PmI z9?)pYL~6VVX;@goY%f2?_jskQ3x~fi7}j6WL(38nIS^>sMee52_bBM%nlam4T`t`q zza^&{M6o(2I)w;C-90k|kGjmni7)OxQE#YAqj+9%z;C_hOcA(>6+7ifdiozw9;AvOBA1MZ}tS15x&Il@xRBozrMiC!{m|Sa5g$Cp1iDN zH%V~vF6dqhT#;XJ zD&VspK2z~Q9^_$lkU5u2aC>o$V}fup`nx}FUTL7dH$~JH@2)U6R$HG@$l@pI{ieX1 zV0imFj)oeb$YiZEXg7E6BGC*#44=caCx37T?&CZ{u@-2T#Q4@Ml;W}BQL@g$D(# zG%aqd>`&2VZ9+mK51iA^ROK06k)Ze0WsR@r#UGD_mM#9J-j168V!`5WZeIE{sz4@K z-4)vy(p@f~z@DBnwe8s*@!n$A$(Lf6A&gs}vb2yfIaS(0iTdxP%(^B4B7cdQ-GYe5 zTv^X_CY4y!uQF|Q^tu`6L_@GjL)%1SagqibET4?p0B)384IkI!haDa;x|VRkT^Cu- zNrgOyNe0AVZ7h`WJG7TlP%Vm7I;Wyy=YWiUMI270ZZ~2XkjOU#e@#$5 zC8S*2!(5USj4_ZK41w^`e$W+6Z7@8Yx6Ltlj-9JJmfku^3!$g)EzxMysQrdlZT@Xi zBw^NRNE{!pQAsChwgQ$Zm8JdDjtaG6$$&OhmXXZ_ku+uINeyiDi_xx2)M9mC?>Byp zru0{-tMBugZO1K;_AI1Y0)ONZ^&A1aA%Yf9!In(^&a$+jhK2T(+2>E_Ic5+e*gEgKQ}D@E)Ni4Dyx69E@#J1qQd5zLL#jumRVM#vXLeU|6P`% z8A&mr{At~W356|`>J(=IF=)@duJHN`H?6L|wUg{S4p!EsLkE;7 zrm=U`c*SU%={-)CJo;RZGSp_Q;dZC7r)hZsJbBqM!u(lMGt zcRmib3J)L&?3uPN)$*m7?fqn}vIgdYUF;twBsibE|G8H0%P0R=TD@57htwMUL87D~r2f(%Z2YpG1m`K?{WB!U5RY5Hxb&@YZ z4x~Kv>IZMVQQthfiW*U?6e@T|&*^Q>Nuoh$_V9#*mkW-TzNFIv!JCi@DZ)(}IgKv~ z&NUO$D8gRL>}OH_rM6A{-X*mp4c{HvFULT)zz9k@`j__j{V2{@|Kj(W>qju=A}KX_ zx^0kHY4vv(lciM7~YCS5!gDb8FOpx!8XDRIglAD zFjqrJw-3^laiU~cTZYOa@k?Ep5vf{RP)q8m6>W9iDVU&kt2841gv||Zi)Yd z%#_Vll>L>)-19uz_3gB`vbWjJy4-2oP}OdJ?lPD6d0;s;pINfsE1NJnV>LHPk*Jr3 zbQ9D}fg^q_I)F~w5~_0&!G;l#DhUc{dqbyoxbZ3xu0$L{O(4pn-oB`mlaeg;fDl;I z6w8c1+U-d5ZIEJ}2TOyu<46MWv%AYc^})fE>?xmoeUj`7;n+UH$}IGM?T7k~%qu#i zq-^}!XAV)h3gH|5$i*wWSu?~*t(ymRhmzxxgfDCC_;RIWR=s9=&WTsALM(gV?#EK{ z;X8X|S_*BXJ!A8t27jC12$Aba#m^LJwnDYx)bAe=m~7J73fH+vuTmG##=^f(K_+R$ z&7eA1`&@OU9a9mwj|2Z^=4*@+MbM3FVri-m9EvM#P#3<1B@rZx^kNTYs8|_NjF{!= z_}sXxyZ_-L^SwqHa~|mNz|7_*F!FSbLYpJOU$E8LtwB%e{%-}Q&MH1TK-m>{g{kJa z@X%VXUAnc+chv7)U&%2)qg-AL-d*$4>NYig^ncDjotggXx99OZkcjJ`d&flLo&D!# zLp+&hp3INuNe)WrRJf^ke=qy^p9t zy~h|`vh$j=8b?iuHEL`&a{-^ZEvSEon&8pqy{AQBL^UB2lF4CAQO>UOG1D6`;}{E4 zL;k{ErZf--Efy8Wt1dUilEXmpuwqD!N6@h-9{i57l_AeWb+4k zY9pVSpXz$h*8v6%q|LU}DH z{ChrZlcm@P*HbGQI-|_ev-#_OZ$&=}Q_baLl?yShZrT;6&ub{+D%cFPC8v zH$#R0(!w`YMMe^KzOv?==~X+{UJ|sr$L1x!u8)|Xp5hD5ThHxH2r7cMk}a!V>bzW| zV@ID4y8`9Ly-OdL(}j6}NRj=37U}jnr8qYq2JMYenhI+r&3uHGm8F>yqk&li zRfP{xV*ncahcVEJmD(u5c;#(QKzAhzI$I-?{zl3sQPjenykVBDC;MW>c_z_)YTvBY z1e%|H>l5#wHvi$`I01G#0}2u2YWyUF_*ZA;KoA_1~eocY^;r{YP)Rp_`W#mXU>#EqpM)xlLb^!?({x zMb~io9?Qy&zp=CP_3rjm<&0|IXIAB266orQB{!jP?6`G`g3jzWY4%axHB`#$uHSe2 zpfu@ez{l80g7!APu9ibZ0D&}gf_-}97qjABdpx+FJ*oG$f1jCs{78EHW6+*r+tS_- zAFAsL*TgByVLx`#;X2@HVcj?2_Vyj5@|oXvN2aQZHhOI@+(Bcn2C$M_uNutTDt2q% zc!oLn+xGxAOOBp+Y2s{q(}Q+k?-<&h_LHf*;_BIwt><}#cYIZ|RL}p_ant7i>8^WE z*{`bn^rHFp*3HXFJ3Si_?K<x-T6Mxz%L0s38LE zOF1~7sxUcl4p4kl2zX&Xu+^lq!K%>4n2brh1`Tn!cZ7(NHdMzyuhfVweW3xbh0610qysEo}UkGs>jF`cwPhholbOH7RINg zZ$VDRG3kYerX7rTiO%PQUgmdNXh#&tau0%T3bpU&Eh~))ELW(P`TNFxP{5h9g+uqm zGqJ3C>@z&Mon5rBc*h-%qrY?VCRK`-0NLnulCr-eHb(GlfsF^F|7(kY`sn;L0M>yV zPQ^#Vz%3q)v_H1|ylOGc{od)E63B!!_^&jhcdz=+9u=${m-ja??CVuy7`;#r920d9 zvm2lMnws=w590Upam$ReZ9^&t zbhlKwVTjRn^WN?jY3pLpg17tJy8)^>cCEA~tV5XTDt~%1;}xCXuZhQxwnIPmYx4O` zO!6V0^Xu90)xMb&DD-x|iy>ROZl%HNEV)}Ax#`Wto;1DA4>$VMstvceeg|rG07s7e zbt3$0l`mb+Yf1I6(fZj0nw}&gkkcTXRMNb^mFq-1zbkyKF*^uA2N*f)$KB>i77^fPQ+-3|%8K@YgeG zX>P$5i#q4IA**@RBh<*&#);mVM`&$JGp9V zgrWxp+DIx{9X%vl=nND%k_v{>fN(f&;w{K64No#CCMI@il~3YY{wVsc#Y`kCJ!Ky= z8C>w@oDc8keh`R1coo0S8B)~iDn{)2J-&ccU_tO7$oVuiq+72 zGnWwJS@8{Zf2IL)@5k2m-!@N#A8O?7t{h|ZU(X|Ue3jC<{L3^;F(C7Oe5a=y=B*wf zdqDb#ECW)(X!bM0SV^|=@6 zuD4%{O>Ilk#`sO&_mFLuQZl|gm#jadZRiVR?KA<$?gC%i!wO^7o7vs`_Gi5FSA7d! zgPjpSvAV0dT?5tAak8hXpTmbv7zDk%Ue^n1G1kn_>|68X?=SFTH`>n~!Q}m+j-p&5 z?8kZ-`N7wOcyTv5_H-?v@fiuafEpy~*P$5N0!S5gRs))K+FVt1NgYASY{7f6qzeT% zoro71Ee`q*GF~yB`bI=kNb7CrawZ}~Xd=aX%>uCbn#=ggc+%fXFV#`wh96X9_4_PH zPPv>sEp@4$l>LBkl?CyJCxg@z@byYoUQ zJxRMPtJ17Zx9X~rIgv4tGHc*8Vhe8(pf;PpPBggMCLv19`9;h!$Lo3b`*95Z zllliXik9*8WakRC#GIV%-?ZJh9bdV&U4~VXPZW4A9f!B3K7uPq1G6#f80R$9hEFXK zo-Oej4yXjU2_|(|6b1^Vc1K)i>2B+| z3Rq0UnA<~cR1-xG?oIx2l?{ZZhqDLiHkRR=7jRg(BKGrbjg#Zpy?wNMO4aMy*^=!W zD{>%?r5I!0=0Seicq(~p9v6zKsnYnIwM0pNkO1DpI2a2Xh(&B}Y|~uy62b( z+W64^D(uZ@yJ1btt|`{7#Bn5Mxz(z{c0j;rU$R`rjh!RosIzC{dMU`v!DU2dG2x+q z*Wobz)Zs{Ng@Tp66T{T=E+{Q(<$8izuuVnqzea>HW5XALr=#!r)XzUOZ#GHp=P+TP?Rvw+*5*@l^x$RN zMo!1&%E4brmX&SkD&ZfQoVT7?^&LSgk1+gxca`T=#1qnkek#P3d7%RJ3$KKBJIE$? z>C^~k`8&_I>M0pd#N;jH*}-VP7x?!ocn65oNp3pjrb*6CbeUMbq9H_Y)h<#}K_?Wm z6%`~iONLk4BP4{Tb8}I$CphC3POdJcC{KdBwew*eN;g%WUdjfnx;e49lF-)!WOHz- zp_OI%=@Q`Rt!6P`;*WZ$FQy7MzQ%KGU@LcUGni3NnNVq}WO6Cn{X>O? z?>i?4#ht4>#8wl76F$t($52Bz=%-^|hzQ5|l-Th5%FlY?lpOP)szRVgoNVQtRLg#I zA7~lU=_2$_A!O`N=f}C4{a~9=Bvf%D$Gw<`J|^n6oJ|1QnRzc%Llq-AmrZe43M@sL zS|hG=3iQ5T%-^=jRDW`_V*MF!uzr5%dQrZ`*w=a8rVsqH;aC|ZF)X6ZZ#JJ|3R{;` zvTl^6sHxldzZS+^6{0TWxd}x=)qQjK_PU|}ZqxU4!Pk~)Q)@6cmBZk4$+6+( zwCknm;kK#kB_O5MWq#ckdKJO<_?<;YUHiidCc1y$cHc0Dn%;t6*vmQW^>*&r{2pSB z!!i8w9%MNC+%LO-?v2>e71^y*dwqu2-04hUs2t3S{)8qiN;ebsb2ua(vRl+(_(U7s zkwqJaV0(_aLhR<_cj{icgB-@V@kD#@cUkwzxoKj)!kC3``1zDQYwPBCCv9fpZrR5E z)lYcN+ZVeKh2BqGHCc{nd?=&qBqe?a!hUQFNup?R)gJM;xHL>E&W{0=u`nX_rEm~v zZO8BC(iBpe+rC$X93H%r;-CTStJsL>q}mhbuGm|$@LV(@!?f``#}_Tahr(YdD;RPu z<+e!~s%>C%M`n3A*S9hXr-#`t&4DYOvM99D7@c1vWf_?$Qs&5dX5?49lO3F{BUsX? zIuKC4%!rMJ0k;Ko_+)>X=H)q@XnBfr@@XxswNkg@f&yaqag_@78b-LY^F1R+6y9Jm zxJTm@@D>zzBy=de8Sn2J{-A|QX6B!EPKe7-m@7?i z$3iz1^HSFDV|BltSl??gvbP?N=4d7@HmS1_NwNBUMA-Ax-^{VeG+eg6!86{m?^pl3 z*cmj3VK*ez@%jM0D$Sn$aj4Xo_-tOm*3B5%m#FT(+C`1SM69v=Rp7+0i}%)yw&CH+ z$;%?&cE;_1eO0H=J@!>^^4YR0a30WLyjaPcIPNq>BwXazbn3SRZ|%FKD_*w2?+)~m zPpv<%wRQSUyU&l^tvv#Zziv;u5N*EZc;04~?Zh#t`ctWDR7BG=lT;qph|}D&`8$U>}B4;)1 zP*Ee+q;N?fGn-xPg2IC799V_-?l1i7v{&RBc{J;7W6~q*N2%i@Vf%Cr$F@N2+Gd(R zQCTV1y;|Kx7HTM|Cw$W;q>Ri0U9m^(grb)K)2;=fVOWkfv+}3_dU>$s9{%BC2GOER zRE|b?>#Uj?O9u^&tXwGFE_C0t8B8Q{wFg^uE~c&Tk+pd>6M`BplR-6XHa&S~?{svI zr2;l3;rB5@`m3$)xWm(5tt-G-h0V>(lI+ysH5*`;znfI@XeGj$#|-(4^_aN$GcH7Q zC*?SU6!rDr9rf55lU0m!rRZT5v>R!9&gP^3Y$NTH;xp@q4!^fRxl)r=j?>}JZ6p4h zph+LbkXH4m0`((MiP7j$w^zf_qvPHqJWt>zE z{?<)Vhdty(+FX|ZbKC`L%xKA~kdd@;PauFHy6xC1EU|3A5nD1MlTiU&#~{>_#|BIM zp+Emu0Xd=Od+x#AG}6(0LPk@(A*<%_$qzqJf_D=Y#hV+N2DQ)iB*$&p-_9rNbByA#4JXO%Z-|N4!R>IN|sr@bes18(q7|u)YXN19j`XPIZ zTuC42-jqwGuVoc}Q1HC~$Uw7jQO?-WT9H;%)YAsOE1|&MWh*+)8Dty#%Vll*zd<}3 z+mI#M3_icOnPlcIZk}-Q*#I|x1gb`4i|qxN;#U-^No!-4E5&%9q^QKX!UcZ+)c~%t zD>GQKzOKaMO0CSLy8J$TrsKhvqJB}$MbL)5wW@D4Pgt;SizB+-<%QpJ?w z1#={28aEK^GPr49w*oTRoMIX-S!mm z4K~sUn)N;iL_>_)NtY5Ic2zFev}lBfYgw_u2~!c56dkSoL>%sAMt3Jf{lA-zK*JA` zpi;lFpI<231hj1?Xxg96{RWOl@jdRtKM7u)@GN;8upfQqXG@~0NoIzPcLC^H&zx#d z;-wQD$4T8_Q$ihiQ~e-R;+XywmlGqz5Gu;~gwJeaWzjeVP9h7tk6l@t%m-HI6kw)%1t||c|?2nj;QEl zqq9HT=iEzPz?t1?}`hzv+NzxM{?BwHM8SIv^FeXAjV=*TJ77#KPuJR5yQOL_+d{%T-3O@l)HbxJVJ42-aA>Q(J-A)(Jl*va$K&IJ-&NzpH9_&VfXlwPAcx zyNkK+AQaRJ8Q?qYb{eTtno#KUE$?t`ad1!p33}G}nlKfInnxlQ?VqXLP$wT`0l3v*lAzSTQ%L(C4XZnK`+~X3pZO73D z;h2)L+O2s!l>nN%?NXM4`_s5>yUQ=B=N(%_^B)#O+*B`e^TtawXY7;*YQvI(xOC0wFwR6gn>44$ zyRKuJIxD`l-vk4G=Tb`_YFcW~X-_-Xru8lPTZ6w_45mfA|9vUVkYDS1gAmf8UJ+^Q ze8U~6W^wr1Q8kc~eV{!jpm3~L^u!i18S%B=G?%HEa+|mP250;M)_2RCZ2y@NGkNgj z{M_+$*^3b$Bp&R#G~LLA_!M@swq(wh4KnwO&D#+Zje_idg;VwB_=Ps&RAXSwZMvNA zB5Xkl9-VM_81)Nb6_7n{6v0*Ot3tK*;UjvgEL-T(UbZ7WE~?~tcm9=o);98DtjP6& zSYKd6z@$cS+rn35ST8EUMCtJV1H?c(zqiHbXCi&4*;DhMi4jJXdm8G9WnTxb7Qhc z18W*2QzTuSS_=6QM1AKN5DP=nzs71TmN82u{d?%sbagGR5-&&gKx>ovu&G|FBUsz3G$6P8z3DJa|E@gq#Sh6fO0$bM*`h0Q;?ed zZcBDCY~IedxV-*%sdU$la*Ze4Znu2Ya08?36iEPx;}_1U`& z2sIUpPov1cP0p9ij2fh;#4s&BE?~K2ez?c>_9-5^{1|ifL}^my*J{~JCakL2nal6n z{ZRq91Ul0g6%qW^AsL^( zU!v88gi@H?09*}R?0&XKSyc=B>%`%448L<$KzZ$$4*>i+sdD|Ewb#{~%-?8vpeYs- zysy4jOW~4y9ddqAi$%@XiYj@tfU=nZRu?gYJ+UNBgE7?o6iNo!-hDAx$NIZ}UEJ(2 zsn2kphOZM)0(G9bIGnaLVF~I{@f_Y19%^p!*v-=%`9l_ma}Ew2M@QSJZW2RaxmTfo1Cs!PYI1&K-syH&`uWVtkl6>9{l>h59L1qImaW-7 z#p#O|IJmk&h)Y6PaJ+w=Yj3^GxwGfF_~;WL8;Q-#Sqf|CXsyGjO3C*QJtrvS#42QG z%+9U>M!hEHl!Ora@2@yxeYs%GP}F@hmd6>;QYD5Qa|l@0Q3QyZlZI$lG9fKxj&+Qf z9F@$Rie=tJK|^B3q>5?Ou74I&m#H6Ay0}3bm#WgXZHk=~spbo;<{o*SjXlylzfofU zejKh7mi>}E4$TGA74JOGJC^N|AP&T%uG?8J+;ACJF2fL7Bre#yvBz?L%%hJz&eo~Z zv^d01@Z!<7;=}A2(ugC0tsxV(bdr z*X-NS3RvkDBt82j0ny4CYx`QfYAA*7b8~m~4eI-RU5xJVxOHI8z^=U)^LdR!NDHO<&vH4Z8o;H*grTV)#J>iZp0_4a*SvUIdg1IT4cO#+I3u6 z->&}@g@99IjEybJDgygncKzf?-R38~_R0p@aF1@yI*j(<+XDyS>WpUVZ2b=2stp;n zyPY%M@S~0P)7!0^H~8TX|6TecJKVl$m^4iRMveFRW5s93*jTraf9%ayjOLuX4&1pc z^>8l9KD2`;Y)eB>XoE}O7D2?EwWI0-fD4A`FB+Pj3(&PAc&O5Ka#;xl&nKcs{iQK&Q zHj~XwHqTy!nMc$iq8-av0VU|Z=gjZ3ud>c*l2j+J`o*_3FltzEZBH491 zwjw!{xtMlFu4OI_Am_G-u`qGP@$l(9Zf}*rpz!agsrs?Z!tM=W*g$E>pRH z=*Ttux-~PGwv;X)Jxh%`wk8vA=4**` zyA}3)GU&I>ttuU_RlsqsK}greI)d{|JIVt($kzY$@SJ@ zg+i?6KjU9UUQ!}(4rQez5AXS0;}qpCxMrG4h)>HXXsabwR*iGN)U?!rF?fs zbp$U*<2jcuoCYGz#L+YxwCxh|_jJsFcG5IVCsPDrdvlYW-CZWrDF+9K z=@{{V5CF}xLXD|LCov!{kPF9@bz0Z|df~NybouQwp<-IEv?(|Qvn%ZuU@hg(?wQik z{%C(W?12Mt?+2znDA*cVwb4eqKNjMWFN#+aPm zF4vyhI@yT0NGYMD7Z3Z{a5sHE}?RQ_O!HLSs9>R)t;**HEr=4k(b#qlv- zY8hI})Y(iOP17*-o~ch80Fq^#&1{PIg7Yrbgd>526f2g1U5e#M{hT<5s?g@b@S2O3 zr?@^K1Hlq67gHGlC9#!WT#>?hm&&0h>7~y^;ecT>EN64tiOn#E*FYGmDLbj;nr|*i ztd?z?*aq=LT$W$ive!T;0WfjtUY5H%aB(ppR+n2}{OuzLd4^GriT#uoBBR z+z7G>^*N!D)$u%O9__owelz+T1L^#T#S&*`kNn-Oo~^BIF6>-n+ucM(nNAv)hS1}=f-{4A8OjXs#O_bS9+T|>)y*?0PAe>v=d18}2_Hrj(_(~TLY&YmWO zP^3HFC*YL;TFz`3vJ>XB!{8u zG#)Q$1dX2{O;fT4Hr~^SF!2uOVCukcY_rrrz;SSRz&qD&vax%b^S(iu(8wf#QJ*EM zl9R3oh)dF`t{5|k@`{#;F&9?PPI4>`T$Z!uH1@`Vkb$$sZe+BR>xlPv&65Lf05Gi) zd5+1>3F2}9Q!0|J`Td|F#el^?XcK^+AEnxG6X$T69HryqBV6No?1{(OJ+sS&vuD}e z+N5bbs*!mcxOH&E^_#cY+MIIw)E2I7*_~~&e{jq@xAst!JGZa1IBwZGbr#n&c;*mW z#7z-Nk}JhC+1O0;se-nFrt!?029dz=@q)H(QRhK?$81Q-ju}NOKtqmmk+NoO2n7gv zNY|Huh$pm>c~G>O5^~yq)j(ogGK&zC{LMgJBC?fcA}r!Dhl@jI+uJbRME#7VI@CcU zinN*K5o3WW=TD6RisfCCaMi4hff^^C2rP2Zbu@vuX@1TuUJXL7XPC}6@maZts_&3k zfsa_%Y{X*UBw^?bemW3HPV%BfCTwJt=4VixOA=}WJ^4ON3uVB`Aq8M)7Z0QzP@Cz6 z<^TX707*naRO`TH9kXVm=;~i~kBOS+UY;w^e%(v8pjs`jwQfjKze5N~@+y)y7TT0l z$Uu{7ALK*Xh$@?5syS&zj%O3loXsX;&u89hsOHyhYJ28O^K={Pg_+HuGGR`OX|+ux zo15HDjz9J$t?dy=QZAjgol;#yF|eDTiOJ>$k3IYZpFjIJjwJ^NdmJ3@vzQ-&q)ol; z7&+QMWVxKDjJT5SO{cK4xxu1sSW7v>~xES>_o~qR(uHLR^IGh~(WE2{og5{m_Nw!$zILXa$u8Yl)oJPL!o{2Yk zYI5YgxWqDa##G`!<8*`x_eHYQtK zI(v#!=T9d|>hcH)$+LX@&3Ae6rI%@%DVv)cI48`Hj%d8&u}2=}`1puxH*PU+m1bj$ z$3OQJli5ZGhDB*MHi_zpZQ3+wT*`-GD+_!zxKk`A;5EyE#yS8(sUZYk$FLP*jfng6-5MxMf4XW&*T9@(AEQhY*;jFG`Y#~2GX%i?t zx5tZPj*f)Iw#Q2(L_u-5X2x_DnN4RjzTx1`K3iLxh&cB495J-arV}Q)Xnea^;3sL* zu5l!mjRY>6*$h9O(TYhS4fG4n`IY$Vnj-5+vo3B<^ZE&rvmy&sh0%0ot{qyMQcK`d zv2poQ1xPF9yLq&~95w>D(MB8Xo|?nqwaLHonQKy^U8dM8X(c%#&f|Q8!=u@;Xxs$n zl-Ra3lL;mzQU#}u1`jR)B_zqS8t<7*Cb|4Tas-p}2Te06&Y;UNR6#@KNTwhE#ux_3 zUR{#MXo#6r^N15%}ceqCr%{CXlas80Na2uiaR+1^#!X2$K~1u-lL%Qp4TCopAFRp%1BAR@G}r44QBllqk6KRd@RGYR4y zembMtThANC>2HfOY#NXEO(p=OWVma*>-+`*RImW8E=L^Wpe5Q)1A|(EOE05vUQqRIh$>p*uWSg z-ua46$Z|<(s*HCzWl4U%qeciznkL^55gJX7ZGbF0_N5@ZZKiY^1yn#OF=CRx53F29 z!Zt349CmD2ac~W&6!tK&Ni9$k&4{J%Z#zI%*d2R4$dGBsL(7%A4Vc2j(E$v|fD?>e zHipog`96HpBH2yPTu#biZ5x`+(`_3?w%Mc^ph`WC?rH7;!(MJ1NO#qJ&Vq#XzF+_9iFpF{UmNuOncagwe(8PR6 z{y}P&xe%In1gE98n^>kw4~;;KNxGM0kQsc)3~@prl&pE89_M}8=?xn2k{n`$+~;NX z8ob)Vzo1tRe7)pvRE)mIRWOs5l?#fjEUR`ys#ruR8xMW3T>)(8K(xe)y1XeEjV-0Smxkn;f$Lrd z%Q|t;Xb-fF0PY^!AN>G+>yOgwZ$8rjroBUW;ord@|1kai^b_!{XW{Ir``^D2$c=U{ zZMit+;LZ(Vj4VS-iP;D#yIz-&Kv;;wPbRpg0TDuMX_rehBzcT;j;QHaOPx)uvM+j1 z(|DH0hbgFE5+HI}c6QW;k|sORcq#Lw1@ecO<(N7ByTyd~EDuy7F=-r0inUx%OoZ4f zp-u9$lEOQeCJ4*Oa?v6V{KO+ZJFwY_Ev%b@NRC<4B$-1TUM4sPu5mO*>i`-i;8pE23oK_;67JbU{`EJI*A zo3S%F!-a<~a>~J^@yw>vB(2?9aAta*^N&BnR^zyQai623V~*wvm`rF9CSJI7;T#X0 z+hk)Ryz!emEyAb~v@O!P&#e#;J=ucI69P zxcmsm^L^%RI4@4Uy$FTcv({(j2BnxB`0 zg9C2w?X!FCB4;i=fGTjdOUblL6#&jiTRy4)V@&B{;F2S;; zXL{E2{r|t#%FKN``&{bOsZy0xQVU52+ASg59oU4i!2uH(5a1Cr!+;6l8FOZgngKyD zg@6$RmkADn@SuIefn}>(YD+DtZYtI7T=v@t3HqmsSV#K5S20hem z+WmbWbi8Qi{-Qy|zIn+sHz+sFO!nObUvzH#w77{+lU(k{ER4^6@jb>uetP|)Kt^i3 zz=#6M-s|hMM{hdYzW90fS)~z--(Vs4kmUa7Dmu;+x*M-Og1b-qOw&HnQ8sEbdbK-* z$k-5s#e7B@dOm)9Nf+!p6f={H-;ep|0NzqsVX$4~IyvmGLR zO!l4Q3z`#IGpYlkN(zB~yQbf)(J-K`eV#g2eB+oiHZSVFx{*b=x5kFWO}Xt3z#*=l z-y@LyY=fNrb8kHU<9+{jeg4-ifcqt_@BHv4Q2Ndf;cxvvaB^T@CV%huZG7QB{42kl z?fLfC?f?I~{|(-Id<)=i*Dr46+_PCfC&p-<%NkmmbEf#P13PLV*UkrgW56SqLQaX2 z3XSt7qui4$jm3+WLN0}-X~=^xq*$eTf)Ac1G!-O3sP8!f0UyH7hJTbWRbb*Pi{+fR zxi=u@NKCN?aN9QcDlZi0k<#Gn97xW2%A})|DT<(v(YmN*X_W`_D0^t}4jSJ`Y&_~7gb(jHQ-&v^XoUCy69#-DzHJJOK+ z0!?|x6luY0K{WCH`vanp)+zUn4+sH1cy`SuDL;Md1AI3}!;DlQs}R}_0e+6BSFTwumn0REI+~+5d-*6BD1Yyw3p{zM_8&bYvHk)(r-d#Yrx@viPrYuemIJmPQ4~5g? zV_tr6k7gE-5RgU?uYCOYIY0ixcR4&d;n8cav*{zt)r!@6Z4zB4R*2_<_@)AOM=DBA znYNjci#dxrb)-DTS4+Ld0F^51GY8LN3Cp&BsMiHH_cgM2WAh@{Y&7_E@HWna3hpLx zGBQbfY+TA^uYj(TV>j5koosQGlip;`_Cb>DByeuLW~}-1B1w1?=hm4j-7!SEcmHB~ z-#s2|`rIw zPN8~pACJ_Y?i^izuG8et`O)qAe67zNfP1kk^Q*qT{dM~@0;O?%_zVu`@Sp#62p<0X z{}bN%@aA*B^M~;E2Qcs82k*igkKo_q>aqr2rU1r|8d6jR?{V8y;qQHK_gVH? z$J_NU>MB4)bud-{hj??~^1k34q?Cv;)^2)0N?@EV8JQSWZ*vsR8GBQTWs4P8e@DqF z)<&!q@LCit4$al9K%q1ZO$cnZTZR~E+pbD)ET3+QG_DxOSgpop^hD@~!5(*xlFMY` zAvl`Q;8K9W=7~}=^AhLG0>5M>rouK32E-~jYkWh~w4j#1HG1&->ZTZnNR+)`-`X3u zd6_bGeaC_ht&CeK&@`Y8AT=MR5+gvKq;E|y#maJ@~Ifps~c`8gg1O?XW-nsKWOHs{Zf z#e$F1oZ>o4zQX_E`_?#U0&Np$fZ!WDuFjYWQIj|yE*8vZ9gQmlm+Ne0!|e1WPVSs= z`rrW}1nvxx`SBZy3+^T{nD$<9-eZ&nR9+| zg`%w2OP)VJ{^DhRf0_ zY7JDV4!&YDV0-H(OSLm|nHWsQZ5SI?BM$f^yZ7S5Bk0_Je0;vt`_>JnY;V7@C+(Cv zqpPKm_U5uCm&TjOczXU67_aqS=e)hHn50su%``DKcRru9@C)K*#U`$4yyNuvi0yjA zX1k$l1AXK1LFl&|`hKA8X5^y8l>X3fC}eoNugq7!%L z-JY4(m@Qi4AEsmd0-NTAJ6^#5@ps_0hrfI|=@5ckj@LfX)Ip{@LnuKP3u>)Sm3a$vYV!90H(|xldM>FRw`Dccs~|0W@M6v z0^{5Q1dauJ<^qX`1t}Nnqvlj=#L$pa_+%Hqetrc8GO?tZ zb>=GY%xD^FhuLNxas?!#NdpMO*ohUY3#Uh_QAozjS-f*(iKG}!4%)OdO@}H(u`l^t za*dr*7z-X8jq}yz@C7ND6JtK9N~Js&QC4deQY8(`RGd*VDGd{gHs(0x7!7n%ja?kz z&5mE8cG3kwcSVf~l9f^trOqmi4wss%3={*u&O4k3t=(%>X`F+YnYqAm8~EVkD|GAV z7AGtYj``Ya$CPr-AAai*$OmKXwZenw@R)|an6~N z1~jR$dcbhKA-c%ocutx%YzhoH;&QccmyG62jvx|^#jMw(=0fAWnYXkpXhJp8G=ZjR zj1_*mqJ8fSC&CaTDGtm#1B7KTiCb2{gO^Om1Agd{AKD`2pKx z1?lC*IcLwGq0aH(!5voV5)a2l{QHX&g!-4n0obU@>QLa6rtd%E3E=w|mU>dIP?-Ba#!iyyui# zZtSxg$MF;UWOq+DrfrwSw=bdGKXzk7aoVfOjdOv$V?I6hX~*Igzx~>*&n8j!np0*~&0^0mMH4S4;bF@yibe{7HaPyg4a zzxL4rUbzqd(O=zd%iABofA$~T+_t~==j=7_9NF)G`ISHMU3a@aXR8z|c!F%9dw8v{_St7As0i(igCDW}Q74-Af^Vs4CyVz%+2#ko*r zmTGQ{r4FyFlGOlM2n}u9Om3PZ^XPrRyMU8G5lGoG(|pa*v)sKzj)5HJfTL(8<$;tF z;%fAOZ|w6FA*mH`<4oSTk3$HRQA{>7Q#;4wtV>DG_Cvi7dvAs&>&=={3bVGO3BlxQ zIg^q_Lx>abX2tEA#tkG31$hv08<(SN+)Oob^2CS>|r7?35LXwskplq)B@%P_h zIVj!9Dc#Wt-F(4jvthegb9i#X`LmCZGT=kYwvVjWJ-NX1vkSZqcKlZ7^w$wLU*P6* zQZ8(^Jwq;Z?VQjw93G#b&Lr64Evrv)q{@_v^Y;1G!0QMc42+HE;|`cn|MqEfZ@YV6 zA*0i^WS6$`X;t)2+PIrndvRV#*kji|<^9I@yfJ$8rqSZ{=* zZZyGCg15Qn*gM+RS5_@DpEuk)y~9a?A!p7nFW7EJf={i1ks~g&i1XyM+v-UgJI-Re zyvIR-_P^9W zt<&&}de1-U_xR2aO_KOu{-*|z{+s^=-u=!e<%UO#9g{V0KlwUc3xD>j@U5@G{S&(< zKD~gy_?z~;H-8439=`PGkH3xkulLz(8QOd5$vA8SD*w1_h)RE|}|C}vDSaVXAYPEzNfib*Razs{GV^glHOkPMKj#pnSdpS4WEE&?(5v%k zGO3JrmWNhqA?L?pPzuf&uq0qbPmL)kY6Y;Xf!<1?sF{X@THI5H8gQJ<#H190D>y0S zoQ!4EY%GB~(12)$GJvM~>CGWjr25d+?{=y4csUnhDdfh&({srav8YVe|3oko>ZoioJ= zLBUsKj7S8k2z9u_O+X zixO&XpXN+fMI_*YP{ffDT-#8Rs~L<6-qFnGh|Z7#K^&KA1nmLam>FUs7jU7&&*u2hnlVvf zYLWnxv*%by+j+Q8OWC>V>s+X-*SaYSyyaR3zhlhBeP%5&K7TS1DO9x;&VWxf5~j`g_RE*kxjMl*v441PJ4Q%{g{&zOm)9VgLXj07*naR8MX` z&#vVP!S=Rqyf=@5-OgEqs+3$`pl+i$L_ErFHf(aS+^70c>LjGKKl40lkyAocg(OEU(Wj6 z0XTr)`mNvMZ~o1{`Ad1PZ+`QeH!g%f?)t1*v#-4lADzMf@VD&os}=nAzw$?W&2N7L zVuH&RY=_K%6*ebj@$KFul+||KY9;-_q%`m=iRPf z-{r*QWI4rYUO~JKgO8CxBH-|l3q=QGD8!MAM_otPcBCPK6q>F@3-o=DNSR)*@h#p3 zbC$$g!6{}EAc{7bwYqmGd2;=JKg36my}J;s}^b)FK%&sYFyWIahYnL(UOW z!HKJ&*^x?SNCV!5>RuQz_sm*^v+TDFam7oW=j5Pcd3MEVxZu8j!oz!ycD zN_1^Q)0)9c%7r0jav4ZDvmJV4OoKOexj^e73j!oAyT@9Vf>E zy~=>S^Cq9Ij1Tmg_cx67SWYM3>s+qvX<*ohy~eEXIx3UTxrj89&u0 zVC1@=`j^l>1e3~6B9Z^>~W=0Zx!X1(F;e977QC0AG13~{jYIA`uZc)@}E0N3U-N3b^j897h=1n2@7=c7kNT8t-E7AE@bHtr@WR?`*1YxXCtR<#|IFXLUB9^X zxdd?E`qsDj*0;X(OMAb6UhuZRzWt3){(EGqwk`an->?{g7k}rguYL00Uwa+e#^jM7 zo$Y>pw197Z4Zi%U8Jz(9o8N+`=bw~Nj<5BNFTpnMOh-QJwLfcHKI`A(V}I#4|Czhy zcKw(+)k3R%@XVYs9wQ*kT9BkB zr*mS3q!ThbhNk2~2+qQ#T`joz{{Q_E(z=%P~=;po7DCE67wvc}o>EIgiKV2$qGHl@c@B7ZzPd8(R9* zlS(8ln7~>;9xVZ0?6A8_;*eI$t+to`D!M zRb{k@v0rJ3C=S;&;5~y=mi;x?n@e7Mc*6be6|TJfme?`ymG|B{X4w+<=2=W9CG#ig16%}&#%vTG@sE0hYP~VokN;FR%vaa-$aI#h$-{44?kqN-16YwJ({jF(}bMa4w0gslwcS@D5SI@%xZPTD=)u92!)e- zcllTU{9oY9Z~O*NFMHnm=sBTX@b=s9P=?4LnRxk(=Q;Dk@Baah&z=!xGn#_~ifb8C zVZBXUt|CVV1KTKk_~eq=tmSagBHMwVy!jRvXHOs}jutZ>zVv_(mhTbfbB-4$IKQZj zo-yM=K)OO`V~xGoNhrq}z+}la(@2~vz@uJ4meL7jm)R4Z@_RazZsq>#m24o=MHxU{Bg>~Vc!Z9R5D?o^~>;66Y8@sIfM$8Y|;um0Qh3tpc~0QbvUepRQ-7uRq9%l7Bz zJ@>Qz{l+8v^T&D4XFdMc|LV=3eb#ILQQzmY-t%_-i@5|-cLX1-8!h$)mr{XTaO2OM zNo>H?qSR!Q$BP3V-oHbR*EWM7t(iS+TdvnDN`aI;IYQ1>a5e(cSY}&6Z9c3NWT;?{ zQQ9Il1Yb;2lykuqz*WNvsa3&c54)lI{IN&B7|Knrq;RG^UsQc@zR(C3VVKn|{koVQ#oS8P_7 z7B|sf^7#2v-hJms^to7L-3JbiPdGd}X1+M!-GBTYybCm42eXdn!SU=5zKin>Y14D{ z_!-NmPw5vOZPy|q92_1npU;^s791TNadPL5{Y;G|KAz7(9Noi1()~I29^B{X_?XbN zq+Cc9s2c05q?8$kh;zQ0hhWD=gp{)}bbu=nEn9x?JCFJ4n?L1)w<5Z};=#e3`$vIt z)X^?ZIKBTeLx!vl=UY4XoH1_0FcABJQm>bhg>fRZA)q64F0!-m=F5#LYe9L+ozPkzP+Klw2iS3P|a6wmwbf52?k;-s)% zJ|}Ni4BHJEN76&O;}h;Z`~n*0Y_^5XCgE_bwmqxWHNiXDpafBZQx=`$!M(ebIPjxC z_yNx^1|-Z0O^av)*^Np_W80jf(j#FPgE4|1V@Pt9J=aovoB^!>%Q?Zd<7^WaVy

Dpu7{K#YGVN{dG-taXHBD3VC*6&PhL*9gw*o!Jor7;Kg;GQI#wN-*ySf9O zCM8ttUgCpgTzV0@wzbHWdX4+qn36g-sLp0W&Gpy7ldHk$xtc_I=MjXI5+!Hawl!ms zlIhw7^V!1W@HX4Kxm-+2)f1P3b zn4kRcyS($0KcsCs?j9Yp)-5?J+ihmG9XME=&~^v7PFb8B(x=Gf@|tB_G30{tW(Jaq z*5GH85+yD4F_Bb3Tks8{LemCBAVq=fkkXhDizE`!*a>V_F2{^|&;TKbeaUB=85(6+ zrW(>(EH+p$m38uqDvh@&$Z)ir*5VTL-XC*;h$oAKJ~kC-1G^7zS9q-lje72)RH|kZoev ztXXM91%_ncM^y<;!)!L^=;(-UHnU>UH_T?Ux^DxnG0Ez9ZTQfbq;@nrn83sC@3~|% zv1tNnWMr`8_wvL0%<>gK{@y?2{U3MC7l+Ij$1Fd72j?3OPwujPdXJQCcEPf2TFtF(}?QF)nf6V(IJ!Pvc(k=+|6K0DOobSkZsM5m_JUH+!?26xP zDgk4o%z1PKG1EL;m1U0--*IWS*+Sn0i)W~^xiYa+-W)_LfD26^r$VanB%{mhWQ?)L zPJ_wpLdwjls$m3%PS{0`)W(th{>~s}-#N2X^Po6HP>Xd*G45C(pomPY&-6M7UUwii zWxFoN=mgc;sIfPqX*y=zoGug=Ei|QPx$W^1@UEeoHO#uehMq_w5?E(gC!v=X^)rwF z6<`*Pl+q(wOg`^B)OmtaX3}%u240=Lg8R}dEZRfj&~x6-2;!KvE%R>9YPIHixvATm zflLU(!NI(;<%#V!ve^u%`YMlgIH^v?T5y`s60K=f<@s863>>PJ&6XX462b1II|Yc2 zYLSVR6UG>f@#(@&vdTWrtBq0E)vx=1*5W;rp7;@kF>?zcTA{4d8x}!0HyX z-LBj9C$nUHxO;*r?$#xoP=p2+`OXmiTjy%gd@Ns#9kB-;x z9U%8x`hMW)<10S8ddg|DCHMs~1-^LqYn+_E%w{{VTy1!MxguqyA2Qp1FvdnL0Jx9J z)v#q76TuZiW3xR?P)dOzSEog1^KCRr@mAbASKanvB*laz#Wj}gW`&(Y@C>=yw2KwB zuI5lF^~;@|^PIE5Cpt1d^+*{A-V7)D44WJoQjc?unXY7}`99RT!39NQCbafDDaEOv z3c-_erjHTl9Zd+7G>|odCY$4_U*6`(=W1axO6$~eQ0f{T-gFH7MnMxX+92&{Tw|n# z89dnBmq|NCO!8F_N-h3IOY=!7REtvsxEUC8;~bhT+M#tO(PEPSWGI0k0q`Uo+H`CS zTs?h8DVfGQ8t)LNI7zfpNZV`Z8e?#MqlN}d!u?#lNQDQ|>(a67z?zQ|6}({s47z z2nFAILTK=QL1?_O!d6#^|@&;zOv75St&%ML`ttHG{Fv z&xNkRCv$2YWp?AtoPy0AP85qnT*14>VoFp=gR!5Z1adzY?1n8pJHwW?X^c^?tevk$ zEMv7VRDe+3eN94W*FzAyXPHD?tqCSOCtONK)Upm$2l~y1`P^~uw3n?f%*s^Vf78CwES0T9cqIm!5tYNUIg|`2y!W+wInjw?;{- zsJZ{fp7r$=tK}71uE{Qdlev7WE(S2F0Q!V_QWjAX2-PMvBfS_8J8J_)K0wjgjyU{KRc5>)ww4(<~O#O(sjl~TH8{^ z1H|SK%>yABKpq?GHLP5aoxw&e4%N=42}E1?L3IjLdr(9{GL~ECZ6>mU`GT=fss;dt zzTZi>hR9gBW{q{8%;9RFy@rmX`(NPR7r(*b%U@;)he&sTHV4FFf!<9MXq-@jke#vI z$u(%0(Y6Qp!xKvGk&-w)IptU*DHTK-npuZ$8(Q%;2bj#+G+9zT!3Fl`%%*csgp?Eg z(4!;sg#jDy9ieS^b7$UF=8Vds>>^9dnKYA!>YUp6iCvo_O-iXubUpud=hA3BlbyMW zsx`=RPSZKJKT9>rxA$%7$8FL2xpGdFV&{QxJmVa)6ML)(H5<)j(l)m|N&pQoHnrJf zvg~AYv?NLzC^-_?^62D{M+cGR)rTzNWAf_Sr0{9M3dMQl@ZKG?*i6|~DJ*6WjM;N0 znHF`Z21*Vlt#^*%yn$LQ0;6DNSA86qIg@uD%ooJrh)Bt%Mc^EErM@bmg{TYdgndP9&cGbew*Q9$*gH8Q8>MOgqB1~JrC~Q z;ox9FH=7ee!>pUrwhb|5`k0x~vs|uOub*?&%~>4`F)=#U8?`JgwIXV@yyoKkjFaOdUjO2kP#o*chQ5Nhu~h12 zbGq3K6(MHFc2Jhf74N?H0q_0vJ+}Q|L9;6hj`n#&r)%gM(%~`d&6Z6n6hEhr;Iq=H zLsF0WSV2!hbH>ZgaV~^F@U9j!mIEh6Az3a`5Ql0;W5$W2YZq3qRcAe$UMmO*a5Q6Q zUTR^dT4NY8xLsJVU|`R8p@ImH561jxv7eP{q+;_n0U;24Q?1ksx!Bx}8-b>%O%|%s z1TzUS_5+GDsavu1c2qp#t+38RGD#qrMy$Z{vm@GjuW&sSa_UhcLM>($w6YIQ0-}l( zC_^C+Tl)+G>vD-xE0D5`pw*bBso$=9s-ry?WwHgYfPS3Wan)T9-LYF><`3iCVyQ6< zCatS-Duu?IymYheQ8o8cn^h`Pac(o8wiV;N%>L2>dHToh=cWFco~!kjM`>T(2CuG4 zVa?EEhcxPtCgU8C70IHbnME-NLf=qaOXvr`zVLOLyKk^=ju_NIZtJY(7AcWd zGEH!38%Rw{$&iy;1IRVTqGn^2n;DhnUa572ZzlTCYuy(Wt3u+i7k|OU;z51GmA4Dn+(qnv;Rzq{htddqcW9Qx?;( zH%6s(x7QerzMmc!=WGUTj6N78j>*8g_a3xVXGfF##boSx(=-%{#kOFKd#Ip6Dli+t z+UTCD#hMS^8;G}a+}wX%iF7Ve*phU^okih|`wi{p8Bc!pJ)~b!me;KNfpXd5RXI30 zqRiG@Ew5P(1!i}d9iEcgmg47j-KALB>K3x83yO1O9HO31p~I9N+kQ)13hS#&&YwPE zbG<~fG2g4z3hx~U2M2g3q$(k9+LmV9v*`!6LvOCJqx?K6DGmnYwrjQ*XRPI8^1%TE zW2Z!FaC?Eo8?Pd_Fu9}}-WV)?{z7*>S5K(Q`t z*R*)=$uV-ae2=FeyvuR-248ylUjhkSEeFIMaOdt_LTIdme7)lQ;)0wrn+U@;vVQiM z^Y`E4>}T&0V>Guy&1|zczB$l7xB(yQG6!dGeM$FxpxS;NtJs= zN88Ql+7>U0CSwArb2nwIp&6xFGG*6^A6+9|H7_uUSTnLP7~4})wNS?~Z@WoGW?kvT zY&N5v&8?V{oi%n!=Dz8IGqB|Z=NdxORgiCn2_7Xd0v0B=$3RWNhhWE6?fi1yY}eB! z*=KYaX{gSfil#!zJ-gjLfuzp zk0T(JL2?c1I*OYyKY5wMM_;AP9&pur;})kE z$vR3A4KPkpkuuB(UwjeTI?L! zcg##FP0~->_4XM`vgd~oOx{|uf&6g}H(OK3i$e>>K&h+qdCuHd_hf&2Lv;>R|zFu8ZWMF%}q~C5#YMV2|(9?De_hVkcyIG?Qs>HYvSQmis=TvI zrYDvg<;XEpYSCemtMTWM(_qD@w$>e&Q0M+C!xU#+{^0-sAOJ~3K~yZ4FP3D|yx?#y zfNRXXttcs3K>3tuB|GM}R8SP76;!_3rYmNPE?!3C%li53OHKp`Le@+l*CumRC3GFk zXQ=DVJyXW~E3+t9acG4as2E!*On^k|?4ci(c4HAGQdzT|91)Rv9bnf%t}z)SG!n~2 zq%v}LhzuxN_uNv+wMtwKU>a-VMVK{#?e&u97Z>C-OxuHuVT%=hjcnm~ZpaQGPnWEW z*7;M&A(PwPv~hbO!FzL66`_vstm4HNvc~HE9RF@1@`2DDvAFXJi+f){+EY?)Z6D=G zDGBeP3ASxsl-LB5BCoC~%L|$?$NL3d8dMz;69hp;i8Y-o_<%>yTu^b4)?{z_aznP` zJIRN`7|QLYqFF>JIYYLfbyX^Ws~L*H!q5wu;uTlfW=%F9i|S-E?}E4IdOuwwW47BE zQ=)ZF&0HN*r9yA!hM6gnxgUCLPRn`*I&Jq9Gf-LdR15o}c`^_3!B3LU(QVdCz~K#; zW(76YD5nY_#Mnz~Lez7jSh#y|;Jq>nF!w@H- znIx$8eV0+H$qY6VD-*j}_M$3ex@HTOa|t8sHr^Ah5tOqD-=_ozSk{)yIr^IcKt$^88wVj9T*35nlM9Ae6TO2k`mj^mLVnUm@lSvUn(tjdu!B`dwxmurV$)vbt*siP?Qk@(G z8JWQv)~i|Zp`mH#D4sY(V!uTwG{NzfzDJI~hm%lE28?BL-dUa;CTC13G4yN8x~qVS zI$PBDwTMShZE)><4o+WUaqo57(^qh_Q`V&;YOz_5P(e_soqFd{uT$aQZ#UE2j`s~X z&nV)X@_kTpEr^RciiA2#Vt`wzkpL*(3EG6p=9oRVnTePr%V7cPP784xiE%{{D;V3Z zF{^D9&55D6Q0KO3ketb-x282>?2}^qTnbVdEuD^CEm*|Sbsb$dBdMKZITp(*(giLYWvE015`x`b#^JHXn>-|IY=?q##gX2 zW+vsFrcOD4OwEfiUnxNxASY0JJ=LtU8d|PGm`jq+c zn{RQsyxM^RMv!RNkydk@9qU)+oVx4K@65`lC}O*4E9TlMD|KRtCJ=|kOBg=1f_}8z zmkGy?01wPy#ZQfj#p!DtJ@^vZp0McyxP+)(#||anXnl)sT5|CO6dEgTW51>h8I>*K z0wMv|bOddT?b1TZ1A`WVSO9lcDE$~nZr8brP<(?5qGpq2w}|p7@%%=xg?#{mddXocEI};rN<4^-zzeIaF4b&zaSJ@L`hU z8p~PF4`%=-YO;?S05-QNPZFSykX_}5w3Vn?!M0$2(68?|<-9R+}y23o%>Mzy(JUV@VfXi}!H3jjXpe z&pGZ7Fc)8O9`zR5;>?A`B3E)I=zt5#;o&j&PVcjD1O4?So6F2*yJ59na(#WpI z^GjA&Yx?b$zRtw0w;QfjD~1#)In#KLxCRu45^+Is!S;Kcxy?WM)82&Jb-RA0mmoG9Qxr`VJXA|= z73)yDuCZJx9gyNJe@Lr&g!ka*;Ae!zA)W{1JV1=Jb1RmONir+>Qf=qUFfjBRq9|?f z%nnY?Fe2qD9aMChJvDEMHtEQ z&!mjj(t2ZW7`0;su9M2FP~|R_wQ}7Z{Lvenyz(0y-G7zq2uWJRH#j1`5h#u{^k`w% zS$8|*0q?5}tIkzWrK^_L7RYH}y6oC|3@<{p2DkYu zGddB4#40VNH_dbA3CVjK-FYR5tgB}YW7Y&b{yeog9oa_Y%y@-K%cCzG1` z#)CKDNX_i4frEBc1&>HItpSXJblr#+B8VI2xt};?@Cb=6yTy?*L30l^3w1S3e zcHruHt4>j81^TXuKeB8U3|1!3&YcQAr+29TlIo;qdl7s`n4K`Y^Ag?h%am}ykcB=E zh(x>;g7;>{FJ?4i!SoI(f;b564DXa22Xh2mU*nu-K0jtYKceXtHiwxFsJhYGo(d?d z_k*iuI9{eiEen@dg_P?&8F)1}*O&&l#L`vIJz^`WxHRC#bU&8XlZow0VK4i09@&B>+ZoQVA=Y8kzc@I@_q4}0%b zRqtso{!gvl_9#A#>Bv<21qg`LUZ+}Bwch{pKg~Hax_aMo>hy79^h^o|`e9;>!A;#r zz0kLlLwT2qiF1qNTPn~+Zn!@h|VJ}}F>cs03xN9=xskL-045gtyUq2D+Bl{-*!*}3+ z`OQDiGknYcdA^>n=j)?fzxcP{mtXzyy?#oOd7iW(OpV?osS8nZwc0nzX{9VHwQky+ zv`Xon}7$Xqk1^e$&_pry12BS8n42R1>D=WRMoIKt>GH*3 zZXWFMOaXOsiC-O^(F>H5dx^riqmD7Cz4(vrARy+X)xsE+7#pK0vGP1Q9?-kFY_ws0 zWAsYvjoM&X86nZeU zQFAa-N)clc6{$bkpa&yGKUN&%!wi1DS|P-)1W62wN22Wv2=Yw@10vBhDNj=;c^YOo z`;`RpgUbue2Cc4a>xtf78pm)CPxEs~UaV;TI!z%b=CUk{f!5W>rsW>NDv-PDXU)Ig z?(#B)j?{A$dG}&>`PjUNZ>U^)oGT%m3~*1~{@Ag{U`ns&lFROOAYkK}a^bU_*Z=nr zfU}$l2lea?L(F*yq-b6PF(3rJrb+TwMu9!VW$bbCVlfZL8H-|w)oZxX7kRkM2FHsd z(=^lDEem-LuW<%0SQB`0`Qgqm?tN+spy+JNLhqfFv%2jH0!6xbwDHDh18PxHV)Q^B zhKKIZ1deU*R?}dll|pZ}&xur5()%+kl&%5wwG}Zo#S=wM_nEVZwF|(}kh-80x=UAY z2Q)gK=02*m7O!?uYV971l2Q_@xK|0psL-Eekc?!NmtOn~U-|5(;4ysg2XFJeH@`!< zexDaF16H2$-rIk`_0=QFs#M=r3)6HPyI*RfKE0yl#Lco%?Z6>KPxaMsW=gu@i+!*3 zHc&Q;?*Ad1UoU~ORkrIJw#~acL*U}#g5EmITA1ep!6G-OYt~XY#!E^c#OoWZcC1&w zzo;<1@4+Cw(@biPRtvSPG>($*X0JgRV%4gL2qg#EfdCy!uYS$kmcfhVb#|QH52<^s z?jHh(XGyi~|7{;T=yAK8d1sMhH1}mbUq1=!Bl{-f3t#2<#aBM6r+dDhujlI{TKVO_ z_G5khJ_hZ~aI6^J6W$`$8?AUT@FvMg&iS@t%x-&aB)yuj5Q)jz0<&{zZHS6lZ?$1@ zkU}H{V;v_3D-0Fyw$WL8$H=63Nyrm63>(c&;M&l4PuUAr$+7rGRi3RJGXte4_MsT~ zFkEBieuJ3AOtfCl8$|O>axI14Hd@yOacH`iB$d}QxZ3k>gF zGx=Wd4a|6kUGT!|TD|ak3}}^ZMk|A|Qz(|s{Zsm_cS(*H^6vkPVYDXZE(CqXS|sVy zhDNf-4(B-iXkzU4uBj0t0UVIHWUn`Q50{mYRxD*gnm8UWxV(Fpn2mK+>RQ{GQ)`lT z`UW-_bdzK)xomCsEw$FX9NO5+z++63UNNw)xbd|#Da~Rge=JA z`)_n+hjU`#p0?UrrGf{sNcI?A&KZM|W+NP(DaCv1Mx&1c*6CH}Nc0+m(e(ZUsw_~C znq+LdAF&ikJZsz2?ljq-lD;=X;Bl9GwkF1Kcu$-8wKjUAY};AdCAp|6jk8zDf`zEh zAl3Z!Itt_HO-ZM>vxI(@hY18q3TNqnO)i67PgqCidz?K9F)~d4#a^q2XB2q=EjlBp zUF_(C(TzhsK$f>^j7F;qwdz>hTx~4j3Wm89RsC);BnB#uZ{Afo#-Mniwf-h}5xu-j zDF*DBbFF)fdx+|!+gkO2p`HD`1&w-)Cq)Km==g-F#MZt8WFH>j;T#$OiE&DkWR}g- zOu@sT`cPiZ&VugGSv%doE8AJt(LF&k_`s&?b9S+7JMi8a+2$-`@O!d_NcD<=VU5e& zm_If1%6vh-)A{h~ZQgzBJIr@yKJm&c+}u3j-5H_BRA zwhD&067cL;fjTvV3Q>B zaB<0LtHd;sCZqO+u`4^qtrxY|CIClc)D3zgMSZttpQT@);hFjr*nN(WJ+Nksp?jnc zE1I+9!T~TML%lR#weTFiq=(lHdBZQ>u!^5RQ(0TcM{p75V48VQuYhUB<|NX!J z|NHUpUjJwQ;K{c?s<(5#sqadU+ZsilFP0d=lY@Z z&D>t@YLX(B)+kN?-r40oVzbhGAm>XM>W`AST)u`pO`6p9s*N-<`qw&`(v0OSU>YjD zyJW6)rj!*5;$asm?d^=(T*?@=>FbSB7PjpKqbV&fO^gvJ)q$62F@0vBZmZJOJmD?u zax~u{+qjLSR%*Mkryiyl$T4f9XM+$TTPbW?VT@fC1!HWS`={790sH&Tsuzd>+Qza9 z6#Gju7?fHt_vkQ8n_V;JDWAO{!#D3!oH$MgdJ`BVXp(O!^YTx<#OFW%c^*G`%-e7O z02+i*$>~6=<;*m~V8qV4o)D7|F(OkwFwK*^isdQmy7>E;&ptyH=;C0d(c2(RO2O== zO)72w1qrljtgC=+ipDf0EF}jQ4ya>NNl&OX60IyTH%ItXJhha@i-@*0j^Lf4Y} zTQ*A7@t$+`8U`;qkC9@7ZtXVcB@f~xwxE?wo7l3_dnKgl>}fi023x~=Cvz)v%sG?u zM5~2$SpWgj7!#C1XacW8G$^eoT7B=OG8q?0Yoh^z@3riP{= zovWu$>AjJsOm9h&{g@;b#YlOg)W_ucKuii#vXBT->9}l_+B&rlZ11`p8vL}O=E+WB zv`XmRlWrqnC~WE3RNojPwN=S!TW2eq-+R3sG)6+!ebdFbgwdovD5_Pt9T44K`)B`L z=nk|sgt6e~aV^x*DFy%B&(}}F`b)#5zI*+j`OUZg*N^P^c0;!Q_cPOqeUkqXt*?CY zm!AW;=j-|UW0p2583LqqaDPms6m2HvbRdr6X?pmEsL+b~%|@>Ra4~zCtkH+$aO=8a z!N@5SihjtH*r!BC!w4y#%Ti;E@}`8~fMGC20hL+@tv64c6cbf9$!-j1-sS^on%RFK zT|cP!@zKs<0v+}9j2Nh`(w%WEV^GV0Zmg?Os~DkL1KG4;Fa|jeNdZ%$kHA_Ra{4>| zGznz71I6g^|E+ZYk&lFs*oFW^8&% zT|jhr@6qo6YQ0G^WP#ClWB+jJks{E8xfHjHt;FSyy%cR|U7KVKf|r!X7>H9oZ04nSA1WoSu zLgmt{q?P*ynn;WjQ#`t4Z_`H3OyMmdDg4Ca-$Rt_@GKLwM2IsM1{TVB^BH4;Jm{Oi zLLZGhC2Z=9vYlDV&QK>FVi~)CKRFtaPH&YIS3;8SQUM(iim-0$%59l_uMJWFi?@EYF`y4R zowDt0sII-*8>JNi8-GB8?{yWTz!}nQ)bkR$ICJ;_*j9O_```0nX znc)XWQ&Mo2?ds|7(rXQJ45=e-gNdH6kNf&d1K>XTr5jw`Iya9uLNYF2oX`5<=j-`; zzW(d1WPvmcM&NS3(6n}l@v5~F2~6oI*-p-9IZ4^7Sgy9wTP4Oq@UEo}#00a&vt;nx zMdnfLI71VHn3;K+NYhLwP<%=mO<@KpX!6+{l+{uwWz#f&3^2tsV^tw=-B}1aV^qu< zP*~TKdqwnPoaX~6Cy0UCn>HJzL3N2tNH7Au8>0q+k>4b=^G8(!rbwh=L@9(6G@kYXlU~(MNN?)WG7(lqZhI19{T-6JsXl zNU4==E8e?={8?xdwv|ro4xp1kH=29WBApZx*%>+;fzagR*+F91dz(gQ3;{BlK#>KP z)cKibDPmn^-3p@gdWfj7m{taXOpXTu#4;FUEX-K%1RVHwZHOfgi}WC{WZk>NI`p9g zy-uTBr;R3dJO;+tXkFek3xN^jdmIc}m%phrNI~@!mK!lP$%{P%Bcx2snGh4{)>20) z8z}{H)_V$3f3u%ctq(#-lqNH}@L_3(yCpHc}SQ>K!k7?xX=RNX{GLyzi(nn@H)_M^~$Z`q7yW0t}L8 zx;(p9Y^YQmB%_TEV!=~D{XVyE+DC`#_qR?bI_K7E<6Qd?6ht)U={)q><(s-X_P#k) zbPUUkFj0r}0_c=@IKl%??Qdk-}X z@Ro~ODh&C0OV#jhSr@KuHl}co#zr02bo5iEWCr=*B&l~oLeh486aG6Ot5HmSN zMk_2gPk~DT%8{J?lD~CWphp3?*1J4$!P!wf^k)=Gl?OEh&Ys8MOzQbyx$laGeeBmyAb`8om=ECThYP>+@803!{=`@Q)@L~vi9TP? z*YovXW!dPAvO=v)7e_33k5{RjuCM8}aXcPKlQ!@IBHg7xoSC4MGK9d|HpUpFJaIf6 zkQd4*MLr-(mq#aR(pj4P5v4{2mV}HY$?WEEP%>sg;RT2>lizCMm?!!u46E+-8T7ib zr!dHa)RZO}RrEbP?s<$LHZ5gFfU=yNiBTXyPMX}Ge^1At79}j21qe`a5=x`k zm@x(xoF$CA*QlPW26om%n_KxS6+Td?b>~WlZ*(C+>YVSkGEhkC?O!B!j zWe2*!!(ys$X~i5hp!OmbY($19?S$z5lxAn|mMdamtP1Msg<1t{_k_LOqg1oM%#+s6#^#OA|(=)j}I$BU4rk|7Z<{K+0%=5Hc3Cdib1Gh;i}_X<(QD+vdge zAtr5XLsA6)XzUq(HWVDvTyAZ{1eSx*yGOg5I?sCD9NcKb98+eDdSZJh<}?%1m5yiRbw&%_gH`hRnqUlKo=9=_YL3bX!;9nH%NG*Z@Ywo;*uz>SB@E7Z4|%&% zp2YmLjW&#}K^aCJx*G1^e}R`@y3f5kmn@HNIGwJ~#oIe5X|3vhy)G=vN}gxdZQ=U* znv$-VE;PK@uQ9?2F?jOy38&?T zo9mNgwzcr|$z!gbUeQ};O3D3x@}HJsw6e0UtEcED)r_nsES`3wuVbn1K3JXeWz+pu zzBS2x#W3&nE($x*KunVMJz@CPKPRAO4ALH4(sy>;Yf5Y{_4e8Uo#4;N!k@2?`}&Ck zaAS|@8GylZQ+WHgA9MFp2bY8VxZmOP^?d!ewYKG&>ql=>duLk@fpg z+7Q&zeDkUV$KJY(=R=!A8SKSIlueP^F(%3VERoajA1{wm9-USibuEM*h#4rI)6yuR zsw>CM`jVn)BA;T=Mzgq=Z77!6d_&nJ|B+S*yNeR;gU4XSPZ1;$hNI) z*VnXlWtd^!vz?r_EaNE5G+Bgs2)Z0*6UOQE4-3Z_@`C@nSbReVzA<_N&2`Pg` z2*IndjI9>xx_W7`Hn}qbm93fT9LgfLpm&y4&)?cDaE&oBP4Xauq?Gb?X;U0M{#={b zfRV929Pl~N8@C;3f!m;gT2&;Ud;lKPM4l!lm($)ps#BV$Yu3VOjcD5NhCL~>4MMEs zJnL8vFn|9xI=wb52tbCM#TW*KW#pKlG}=}OF%i8wL%u$-q+-MH_q{Qie5Iu}fl0bc z6dk;E6%n_x(TdUPCZ-`KYA?j)+ynpsAOJ~3K~&n*4|Pekx(OHrNs436-a{5>>_H6> z8Rrn7zOzFXT#Dv@7rlz2I@mU2>q>wH$XUaIQY%|2gqX#8w86lbr${oFs-f>?t7256 zOO|6WKOTe90*r(bK;=5@J5ad^M6Yw?^N&dGGXy7 zvo*X3yzP=%-0Nn3{YA!TTwh;{adE~j#XZ@!vP-}jw+WDYDf`aE?dJjR%e3w+XzUKy zy+*{0UOQ#+p$tg686tB`bT5B5@X8Qf>p7YR3B6%MLkh;At|vl-Il8Po8W(r&a)(z~ zuHWO{i;4g4ue{35vT=3wlx0~V1Pus0L6o5yh_VHi<;2Z;V%;|RDr+INPM8D9lFmOW z%~Ytau&V|HMyu2z#@a^Z^5V$F<%Nb5F|eIhDI{W|R0ZDd^l&_(M$m^&(}}J`j`T^Tb9ko5SmVHgYCL-x?b6q zPOI?2_is2|HKseAC+}{|$HsJ#iIaDvcu&qgp_P~7$M(UVujlJ0Zq@C?a`TWj24zdw zBCpq!B~KIZ(kA(|h%F0ocpcf!Y!s~crZG)~AW6`=F0|U2<^zX$){onO<2;GB7=w{A zJx}V=@?@^o3toSEiG7)DE(kY$u7YWrVSRVY|e)OawlXAJpU_Efy;CBgGyhTc6b5W0j< zq&U&si8sY`4z2)6(gfO2?RE(6OVX4U0=QfbyG<=qMS&*ub3QO1FKD%~Z41lIO4-(P zs6#NZZ6Qq@F7J|3W)BY8kAH0{o)+WS+%DqMThRs@ynCzDdvM^F1RU_VZ=y@YOkpH-Fou!{N0DDB`zF>5 zh3{D4daX(t?JjNYjb&4k9j3lFQX>U{xb7v>^sYGiTI3ncI;T?hke&e}7%?Y5u0c#< zM_q_HIg?muaieZ0YTdMfv`+D!F@l{LyqJtQj4=YGHMY74Py|W&2CDUFbrrZ9!_Un` z+yvlM2dHz2(d6qY8ajj|rYr>gZrA>dN6gf@h<9vt8pD*NT6(2)ZG3BO5X6Fpn6Qw1 z2#~}=gn(J5S4jx0I!^I1W;idwlD* z5yD_T3}Wo0V4Rj4uHJo{X$pMt6QALw%gn>~e#qkwKcu7L@EA8@5d6M#ap1)l?lD|; zyEffdQ<|wm>{2uxdyC0gWQbYg7BH*_Xm~9L>i?W)E-o*aCur-2)ym=ii{z|i&L>YE zky7CL$rYnjrkn@?%Ic~ABZHkA)Y+P1MSCt5Kt&W*(5 z-E$%CF!L15!nW%1Aw@6rm8^80C4ZD;(9S7vwKezgRIyRL)ABx{Hl|sAtKA+IMxZqX zHrN0#Y<_<1=TeA~n2pio*PEsT$BPSXxLnB5yLO6co&b~(IwUcywG)-CuNZijV_I;@ zk|~9?o8k#$RGok}q4IZ%MKQ`&fFTB{^xCPwtR7#5}aZymKulEQ-}j`dZx|)?7jz$usmJiD;fCoqvNfqqV1C zhNN`A)*7Q!EUK3<8tS+hLC2vCwzA!_oBrGu6Vr$e2mu7H_GKYbN^|+6QU%QcK4#}| zA#^oTZP^oIyb`|2s1nV{+Lhl9HqQ6l2gGz*$HPueOLb zXf6XCy^~#HT*}5)_OKOQKMG;VXBl*NKGVMn@QMqaXGmQT0x4$3kSrPkV>Iek8A)>F z4?lR9AH4ZpzWC}(+`W6j_0ww}eej5z(?SeMU3_DuwZ@%02Y&kVpXH?&?()vtZlx9vU< zi&5U>)(53_C6bD;^z%jxe5-|CH?eRjl2g)vX$xpD94}|4$shs~y#Ln33!ggj z!YecD)53bw*`8M3ef*gBfBzA8U%ue8Uw)aN`svGa#P0L;d_7+u&6ejY9~(zVxBZ3{p~_)Z5m&cj6i%i8MVoXYHc@_iepm+ZGs-{aKh4On!ofjk5t=E&-2qsNMx(hrGcsZqV-+XKXVT1Icnq|0I9zDkQ;PeT#2T*K z4eN44-4@Aoaw1Q6NYlkxHl)oO9P*^@px*tn758KrPp_`ni()J; zb5qDj2yEpf7Q~V|ysG|wTa`+dr=%$KW^84pH+l9_R^0WnEZWSZK+M`KY|Fy7NP3xb z;^KH@PLZ4wW>Crm7#64V#`EU1vX|6~DG=DoaW4}NB%3sS9%2`^*5%8Ik#x9_f715N ztfY^@H~u)V7~MEt9M5c(%4>C;EC|q!(It;mQ5FDJqWdP3QW1RvKY%dA1RoAZf<9F5ffUqtXDKmFiEaY$l0vCh zFIe}EHBI?Q zqBgA|l5#w=Tscd^S;|VOE3H;?nwjQwa5S0ga~DSl6mRqv-&{m~tXz$w5oqR4vfOM!TC5a}X7M3w;v?PHju%Ic zmopC^eaNGyS1*9s>DXDIHaEMPz^9FVmdTFLoK@@O9H~_b3-$pO?w2EAmVg8!p3j$Ig%HvGz=HcV zhcnq_rPu4i<9Ba(@2zW|{BYq1|LH^00bcy%!e8qz@-==Oum2|W4kce@n1r>}6v`AVt<%uxOqz*Ae@-(CLxgx1g zcYlk^jcTpXH}{it<~);Q!mQC4%+svyqTZ=>fdNyDSPb-9*y^Gm&KQX)k*5Pwp4}TT zyx`U&>U*b@jk>Lb;eiohXwr%{T&---jcN`w!fqy4baO2m!@W?YD|wHwXanZ)<)F`Q zV-P}T(0ww$cRn??Z97YF419y@vDEQGz8(jw3c9H7pL0p7mqFtjSBvt8m0sCo`H>8< znMaR{vXDQ_i@jH|3TFB~Lx^WqG5V%5<-}oD;K5cp+w~10n7Y5}%Hc3GPqVhB-I#(g zLZCKDD0?4X9k5$l_HuHW_@kTm`zVrB1%V>5f+nw&8GXp(qwcjxni6@IN3GYw9)mtS zv?3o5>~ZL=YjbR74w{tS)@lpv3=dv@-Tgalq?k2W@)SyOuDWhV@3eJMRYWNQXEr>IQiGr1 zvgX#C{JE{@JT%E4gP8(e`cT?x%w9Z?`$h{`W7|$_t2|VfcQW&IVA*tEvSjC>LyVD9 zi)5&#e!Li?y3+Kjv5Xbqz? zA2Khza1Tb|=Jby49VxS{Ct9r>=7~>!;wA3hz2t)rKH%|(k6BlNsq32))AWQiU(mQC z7BMBdMLH@PAFWGLoU(>gL6TR@Q*xaNJ)KUh>r=+Iasxbh`a~5RUPW+eGW#=)0Y7saLV(h%TU*F45o^j(av((bD8+_^%Jo^egMw(_ zNZ;;*2M_q>H@^wMy?gig*`NJc{`z14>wNaJpZ!xm{*5=@_)8Bm9z1x!n{U3!*T4RC zUV7;z0N#7=J$~aieuK-)%a82+KYKj)_0_L_^+!Jce(e6<-}`&#e}4|x{_C$=E6Zu4 z*Dha~_Xnkvi9yrsQ5#zrG}rKNn*%9Yi071;Nd^?hxx$80x?p$mW~Wy-G=h=hat)JA7nPn23Q-_-RDMpN2d2<}M>+GLcns#`2-il0(s-8R-` zA*W2Mk+NxmKQOjU8?2NPt!|Xy+RvX*8Ft!adNfJZO zbYNRH|IQP~i;Ht_SFI82h`F59_tm;K%Tt~lltnB}j9RI+vaTz=@6&co>RZ>wb&P;z z$#rW{B3`Klh6VsrOw4muDS1q+bzn*1Fp?@JN!wbbTOiL9^E`7pU9)V?Y9@V8yG$;d zda4Y32m-Yfk{Ro|P{VB?PK?f4GT64&&$U5}V)t^I8K{t3Y(eyJn5gg4J%gIh^fRbB zZ;U;3MAxF7WsgcNbvawx^ZpIfA73V3;fV+aBn+g9aw^8o}=?;`}2 zqu2J#XPGA~CR*<-+sf(YhS3|NDkvvdq_&M5648u`fPh)jF-VcH1-7EWSE)_k%|2)t zd)hBJz0aI8BN{j5g!P7n&dv1`XIKx6UVNZs3cu-{(N$(XqGa8@ccv`HZCkHcOX0&u zPk8jyC^rIV+(;c5`E*2-&e-gu}uJveK--`8uclp@e5*7vpm6+!C04-Ukj z_R$$0EVU4Ml^XC8k zKKDL(NjhY%A1?Y~;Wj1c&$}Kxc)-8>m;aJ)eB&Fe>&kEa)^G9s?|+}a{kQ-29}D8X z_O-78@SX2`=g<8f{-m|P)}LoRc<_LK_Rszq_wL<01Eg<%``i4JfAUZGgCTfho$QACO>r&-h?#=IHPsSvM9YW&rH+o9hHBB?qGM5Wabs#t0NPJk$uZr#HqXwiMFwIzw{(hQvyHGuXEVjg>|nch6_Hz45QP4F z^kXZgv(^=QAXugMjW(Rw8H)KgQ$WwCm1SMoZm!Am0gG9{C?yP|m(A1X#E{tVuBhJ0 zDG@^ky5zKFqn8R^6_InMled zIp*c|wF#i4$=QfN43$y~WvkRs-5c7erFoZ|JZr5q2m3nD4~HYublV}ht_!7Z@Bkg|^g3)_pSv+0U6zXFpK&7-z^KQxNsiyrF@Weq#i5v}!gWi*XRV&W&X76)r zm_-K%>)C@edKL3-=4`*@*9weLXJhM~Iv`E6|INa3x~A5R!<0E*UU(wm;B<2ZL_*9C z_7?f-qCCZB0v!9j!5kzo+d~bfFvkXUtMt0SA#$8&mqHJfj7RnVSuMo+ zgn61d9s_I#(wuqxWTp1b9^`@<^E}apadSFRyI3#Xm)-x!kUumGPZbUBYt4+Vkf{`c zS4cdQzS&h}5JGBv##s8hGFkL9CV7U@<)dZ)&$@~_A`D@Gu^u=Im;Q%z0a+7_kOz+)mhEf1lY6> zHJA5_E!K1F!8sz`j3D-V@0qmVDqtxIK)$)~5$tQ9ufH7Y;|JiJ?9WGC(96|I%*N9X z7k>D^Kfy3w`O;m!^WZ(c_aENl#aAwQ^(#L`Svqh1KM#55dyn|}|FLuNLgu%=`6lnb zamCMl{d44l>xJ13$XXu-i2K^tzQ#ZNhyRduUHQ%5{7ruS*MFVYUVDwd^LPFZ@P}EY zzxr4IDqsKl*ZG~_`5hiTdIWHOTx*SA`lVk21dcxV-~(QH#y@OKl3yE@-P1~Z@u-_nVH%j z_weDv|01*XUs_L|JmH;p-r;mQQA*+Mx8LS;I{l%)`Qtw8{rmTS?PHd0Y~te(o^xg3~T` zt+$P>HAx~ZFwU{mGK4GD%slyUBIkqTDy^ZuAMfm`h3xV#3qgkSkg&b1c~Ae2fq6PI zy?Bt9%ZyqCC}N0bS=rf3We)O03%L9bx()CB8SXI)0zFCnaJOun%8*+rtjprky+EF3 za!PbVlDBAt$s9CQLV&U@N)%)$TqY+hNuCJ`aVb^h%rVJ}b)05G65Ehsp!JQ@>4vRr zl-@n2d(ay43Uz_5cvSKA02OhY&Jhg&`Z;xNnldrMx~R7)m{{0WE46#+?r;$AH4LS0 zN@nvSd3_JJ1>m5~RZ1q`Bpn;_^e_?@qkK;us?(aMg08pej9P=@a#jHvF+l-?j!R$T z*&j2|X0Y{2FOAs6ybL6v!x_3@>Uis0q1BC6i#C2yGP^WiaJ;-jCs2oXxS3K2PuDk; zvZ`Y$N+N8d6P+b!O%mN+H@4*l$N2&^DG`&p8JBf+S((Cha-O_XO){}s3)?2Z*2XQ^ z5nDOA?$Y%nx?(GZ z6f>8XcQFDvM?w-4#t?I|Ei21%QUa^XC<(zOwUUL7J{ZjtInN*js+4L9T8fDgO#PNX zo-$)7P({aX_xV-Ys_K(q&@GWHkxZ=79$-<5>KaBjG1HqWRiH7?S(4TmF~6@>uQ1s? zfl9B`;AfD@(}e~et%;57%>zz!U(*L_ux*T9o!ygs+<=G=TS%0}YcYby>!h6xD@;K} z*cX>aKJ}@Wu$Kof|I{bAx_ZKkFTF$?na9_S$4@ti6H95_EZ3aY8`fo&#RaI{ZUIg! z#IBCGRtuGl+Ev&d2Dfg=p?VBLAWbtl2;Rl2cp$%#) zEXzU+kvo@n00p!JGm7_N>K@&FFs6W_z#s*aES^rZK{rTQAa{76&p?1&wI3RG$R6N{ zpTkp3LnNh4DH~(-vxm19PfiVx^B(vWqzu7pV`6k*KF-q0*2Yfq+ zc!%%&ySKTxn^;eUul!G+;b;E)7kTUT4|)1<_dg0+A3l6Yt(AulAM(jhe)7!P-M@eT|MNUQ>T~}|$Lo*2pXck3Uls!Ca6zD9 zql)<`8~ZLXBpJX*Q>R!Q5t1g2U~JwCryppej7ncuV$94FB=_Q^6ln~`wo0yKfoaOj z^Q<4w9X-L>L$`YcM$|TCpAL7sEdd@3+K^Z$^Z=nT$|lKV+NY_BUd0S3g)m^jOJ}

Pi%~;xAlB<7e*EA^u+yU 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 literal 0 HcmV?d00001 diff --git a/release/tutorial/images/screen3.png b/release/tutorial/images/screen3.png new file mode 100644 index 0000000000000000000000000000000000000000..a7b1024d26d44ddc4debc6d83fe261f7f4c9c862 GIT binary patch literal 19131 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 literal 0 HcmV?d00001 diff --git a/release/tutorial/images/screen5.png b/release/tutorial/images/screen5.png new file mode 100644 index 0000000000000000000000000000000000000000..4f183843c447c6e656249ad4d47bdfcd59105e0f GIT binary patch literal 106721 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ⅆ$Ucv&ijuhm>Q5lsnW`-YAVgyM-qR% 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 literal 0 HcmV?d00001 diff --git a/release/tutorial/images/videocasting_on.png b/release/tutorial/images/videocasting_on.png new file mode 100644 index 0000000000000000000000000000000000000000..c2962d727608e24be91272807b7fb4e55167aeeb GIT binary patch literal 2600 zcmV+@3fJ|CP)R15TW2WR6A3rcE*9Ctrk&{Q4tXx#}~EM zcC$}0gv0t6C~Jjio*Z|*(k^pD-WyBm@aUe;E=J9qD%^E7hCe42+P^ zP^6MdA){zH(t`Lxke8Q7PEHPnVQ@T{2M!!yKl^xrKjWt@+=<&GfJ;i`eo{CE)gKZf zPS?U8;FxEVNVc&BfEf*Qm=>6h*XzaS^BtEIQz^x}>TN6n7#QI$V`oAv4T=y;|0mu( zZHRa*G@*4E_P_VxzvdL z7`aRUbn*BOaJEkl`7_NxtPM&Wl0mtu-dG(m*XbLvr^ZLk5 z&tqrZ4whCdcE>y`V=nUxZoqOZb~o;3WS>Ir-Fi0%oXWW8@0^|W1U*7X?6P~kdJRGf zCJvYg5+)6tgd-eYt6l?2fr1ek1r!f1!KeE`!M#J5Gk5e{nuE>c`Ep6~rbP)+@ZgA5 zTvIrUFKfOaJ2{8t7p)+PR8VkT=FeF&@h+rN?5^L%tdZC9#MozC-TMnxa_z|3d~^6~ z3bRLY_qe65?3Qs0$VklK)$&&;9#q1TQTMpAWf$B>qM5{})f<>FU;;Ph+yn~h{q;Cf zAf=?Py`G>9f`W1V$1x^ntgBy?Q^YlevoJLe9>c@zqB%@Wn*j<2=!02$;W7rK_NUHY z$GoC>6b~*TQA>*7#sE#z+*Q%j>NtiFO#u?N`ZrVAP)UCF2!@&kjO}+W74;SD41Rs= zHWV(O-)}tr4nGUG{F+-f|B9d!jFXQaFrI)NAlH|NBOUsr^kI_ka!_zp?$sE&!JV6L zXX)<6R5eslJgC^!J+J?HH2NEPuyPrzN>}lA#apiI-p}u*ysn&SdD8&sla%GkgmlR7 zlh62m6L`J+bzb`JFQLg%xr|n;h4zj%eqXkTgZ92IpGhgGYp-MBwww8&@&f>dr3?oJ zQ!=k4H8GX<_rA~KvPFDT`%Ro~8rqfVQw0*~Rr5e}9LVyPe~8anDhL0^3!PhPf~(K$twep`wyY(R7ST)1%o>ncBHpl=`x zFZc})7e0Q>>^-JTd|620k_+MOCuSRxQi1}hWS4{(%Iq~6E+LxIkxIs8OD`S#D?vNR zC3%<7Zng8`q36SGLRVzKN-3lg>_55>Uy_fT`!8U@px=^_oB?5(RD$ZJYCMLAH}|~( zN~5UnXufLu9H|65j%>#;4DK4XjH`Sz8J0DS{f+yvm4#G-eMk3`k(9xltm}Dj;zKMN zcNP>wH^AWh3))rF5@ITlMkTZ}DiGQ8>Tc!ZLqB&2Xd z&M!&RGNKtGAf-S`;W|l5fs)~%EEQ4;Hq@`9-D>CR{AsKxc#QK0o*$OWuzonJI>A$@ zE@KD^zH<)ob!3$Tt$ibrr zd8YgiuFdU-w~^#Y=8lUNGuSu>B=~JVfsTONCSdys*rBp5ZQ6ou*wO|C)piw+fAJVi zfhLA$4x_R@6v(ZxJi0=Te_Rp^ZSC5%YOQ#K&Fb?|1(A&F%;c+HlCTJLD^J$a@T=An zlAU7?quQzJ)@GWPL91#yrry9r#Jv2T2-5XFy!ey9QGTS1M|Q8|waIUilbTKOJ7bAG zYVwiE?P3W91qBoq7LuHt92ev}!+j6Ylt%0kfacN?GT-~et!MN^2GA`TJ;|!=?#Te6 zWOSNiCrbuEvuxno=31^Pn#HxFXA`gkyt?&OkkKSpLvs&YdwLm+g(-xVFgwv~=;*+wVuxS&EOO5qq`7zQ4Xhs4B0va+(s&CMk%D+{mJi)otZy58+- z(Uelk@AuQ%+Dcnn8NJvP)rfFapCZ=g(7zT!6xMcL?JC~4HmSZylw_z_&D}Su$oZ7l^H%vg}emwuVghY(> zCTBiNN<4bwtKRM^afI}ygR?ksoX7+=Pu0L#oL+Pv?$6@Cg8u-J1X2tjQ03JC0000< KMNUMnLSTX%A@$J! literal 0 HcmV?d00001 diff --git a/release/tutorial/images/xml.png b/release/tutorial/images/xml.png new file mode 100644 index 0000000000000000000000000000000000000000..78a8c101097492f33284bf8140e61717a3d7b511 GIT binary patch literal 373 zcmV-*0gC>KP)<;p4Vqlp0AA(`PBpkv|T7s#@BpjhGX$h)cbbVww zXj2^n!^x!x3m6y}7*bb2=u4X!4!>eSRj=oZV4Fw7nds^;^bzeK1_lO(c`*nJV2+v{ z!EkunS_WIOKd5TWqal|0H4(Isd1Jy)#6hVmuo}d`z<`;)(1CX?g1xmFs}e?hB{j^) z$QGfC9e%}v)gjo_VFSo|>&`Oai82Q4K1LVA6)ME4LkEnt#!UYYJ^xQwC7l2O_}zy9 Tn=l@000000NkvXXu0mjf6kMLs literal 0 HcmV?d00001 diff --git a/release/tutorial/introduction.html b/release/tutorial/introduction.html new file mode 100644 index 0000000000000000000000000000000000000000..c19d4132867086821088674c2a601d3f57057a20 GIT binary patch literal 4743 zcmb7IYj51R70p)%$bY!2qGp63@g7wN%^ z$uZq{WrK;vS=HwG>wjmIH8J)-=lR{;-Q@21#Q8eExyr9zpC2``YhN7at#d(7s#s;G zj~-5WQU2Ge!v6=;PDe#7<4AuV%wm?6&PHwHQC#*qqw#K*Mg1k_eENjSM){!Q?BmUw zqn}vn!8DrK>eDlQ>8eV5x^U&tL5N~Yr+In`?Rk^bP77BpiABz`KOM^_qoOWd>pWKG z^2w+*_IBLx=1oS6@&488AD=yYfya6tJLPL*XU7y>zrIcvcczLBo}{}*o4Sd!W0=c7 z)2ND8Q`(dL_2n`2I}h7&pww;KtEw`#p1qX2(5sT~_%xjLr_-}5T=L&(tWF=>BJ?NU z|BEO{zz?R#=V-*i!NJsYH3eVJvPo__RqK!&8@;QBl4JLqvyma|mEKdE zOug^(_SQY!+mE(%vtE|A*1e;;FflssQG%nt-%`BUxTkjW;Co7U9j-fN+W(_a_U!4B zwePB7^YII3J=a|>)yr2UT-36*Q_w%X{PRZMPC=*g-YIAnEOHS|DN=&q9wldLJIg)| zsGIo`P|&InW|?)qQ?1TUvFp)8`o?G4yg0oup>zwt!PWIO&9$!3Zn2>iN&pRBu#j&^ zpqs`7iUaa!REwi+OO0-OTDk$T?r(^RYnbm9y^}_ zaTeqCkH?7S_~BSRxzeg_mvn8q9w2qSw3R6ZOP>;Aq69gQ3KbC2Ij18YV)53%V>hS& zV2H#@7!H(Z{QIhg7ME zJ*C$QDS7O}=fRx>vZ}+Xj^$*6jA`l|G?lLFoTVXXwlC%1v`7l9=LKXdCCJ4F^-(t7 zSzvz+FWGMaVlEe5VA$bUYi>0a*bpZ4Yojep8lNQx?7GAb;TCHN3bBXng{H@CC8my1 z)Yas%mld|xYf|`KC~w>lDA^M>0UzTVASeLNf+%_t2E-4Mdlg;x^pJ`n$~yEGOPVW> z_>YmmfYI;>kw8Qd)iCtE^AUH^Rcbj|8!kt2tP8qbKu_iD7~_a*>R2P|;eaKZ?a&nn z9PUT3 zinin?fjZLAbJ%)~(&7H($}JmR-mXeKbsHHg<-hL3VUh^CLq8dQwnQirqEo7ry}GH2oRlXM=Zb|2pUQ)#zX_m z6oj0kA0x-dMzLEw08iLtmKzq#17#-!0&X)BpcB`?$@uw-2;`4R#$N)xVXy~i(34jc z><>Y3YY2k`sWuC=FdX47K>_ukJ;_S24o;`ESI~Z8N&ZUqlkqhxG8Ac@>Yg!e+naJPGW`*gY%91dy; zpD?9j!+{kr%Yf3^A!R7~j6KN4;E9V^u_&GdsOt{nxu;q#k7X*7j+prfJ%zEW?C_YX>H&*8txL0eNe-QS;p*grubvP{ejHftf zUiTjGa$gkL&?=PQk$I0;o?35kms*D4JD`xh!vq;00aoBkUc=Cw@oimE!c0!k`?dZcb zRhmHw+Am#siy3fvF8Eu~HJDSxdlE~RQ8i9_R!?kFp~_nX4e2bwPy%`;1>Pjz9Atlc3C2Eh`Gjg~^!L1jzX=iGSib;ozcz2bcMFSV}doRy9m(1krvp1)gAK#wSFPFc)qPHJjzWVi)qEV9k{^&GG&MwbF z$8kKSODlAvoHAOJNpk)=qNs4LK1q_*Y89^@#l|j@%Xi7U^V3n`s`7Z8l*TkN&RrhO z?%$hmqyLm5$LGPMl1>oY7|B0dwVXzo(N1bNa_d?~)ICijCqKD_XFsQ`5VnzS`r-0o z^pve0Oq_D1oV}E9O`c0jXC`Ya7!mC0BniD(Jt@MnlhovEVw2P8o3VdIlrAz;8jF^> ze??R(eccVXxQJ-kJ-;}Acyx4(ZaH_AunVQ9V{)e6eh*((Dt85X!c!sDqHxnO+~uE% z6KN?ajESB+9%FrD;X5W|vMg(n=SnZ8kNs0qi;SOmHiEUY$;)^68s6DhKKo9mP5u1K z@5qEtI!xrV3DR!md>Se3tjXJqa}{%jeM%1wCaPLcW3y=#C#n()*(AfES7ttsYrTj_ zlt|;StB++iNd)_R&@T-*`Ig)4*M)H=6OBW#SMa7cKkVtvdrKSBJ3%c~E;p9$2x>TV zFQ{Qxzv?YP4fB~Q=Zv+0-yIA01NWBgJHE8&?k+AWp~^cJ^keqc@@-#SCII$;k(U5^ zOd}6o{+1z1>DzYj{Pgj+y~!Os2Xyb?xr4MviN`1L*Mmt7V5xC@cupe%xh8{&)yF31o9t;8N*gm4K=E&OUOYXscj^gIlX)Tp5{{K4QLH7 zO0(h~>mQpoZ8ED;$$bWsEO~I!0t2O0vWe+MXksLjsOwT?UWw?3Qe8{h$kYQ8tuqz6 zGE7}lTj#>bhE|2tq~$6YX-HT}kOP^=L|fl6%-Cy6*VIVOQbB?mq@|>}D&--uNtvTD z;y|K9A4%`lC=<0;AkS=CD!D=+#?nfrlv=YwxLEG8u%=xUJ~v^^VV9V>H5Dy|Ri;G- zO=~lFo(WAzOm0@XGy)#)MJRM0mO_W4HDxg=k}Y3|W~; zwUm7nLtiSP*X%vY6D-k3OlEg>whPa{vXUh}jea&M&A)DCXeHJsz;p_E#oxmRz?;gh z$)LB86E&k3c}_1|up2c6kGBXUwrPa&q_r$ZsUJDeuzosgriXT=^4uetGsDZUGf2Jj z8Rwm&)|N!v9lVLKL=*%0EdKn5uSXAj2*59jUYiOFOq4Qn6rCyL3~B`OunE6Fe?c;u~=#wG$q1y^r0dRGQsyx*`O+I6MZ1fLyW8bB8*bptL&d-Wvr zJoGt&s&;B}!(uwS;GM9OB;|1T2|vgL3qlyn#1;W5qXq{CW=LkLs@2Ld*MUE&nE_2t z?Y3srQqk(%GWnqdp4za)$rB5bA}c~0N;j~YOV)zgF)G2w9Nd57B_YTK1JLKZk-}nT zfD#f4Tg_o`fE~k_iUB@H+QVMMQ%Gw!VdDk-34-IT#}p#{zM*-mefb8e5S-Fk*}^j~ zW9<10s7#O;2f>6fzaQL;V0KfEjDFa4#7nlpxv}8Xc|~RT zp3sv=PsUH5Jv{pP^?1w?GLZv8?%zB8|ERo8`Tcu?v+~>{ItC;Ygtt_X&%|>w3GrXm zZHgiBLd&02J{`vPUC8LvHqF)1czgxz?BeV`7)qeqig87#nNSljyUVK=ZqIklcRZN6 zO;*Ps?nlX6*Ij+;LEM@06adMDMG0$5=nioG9LQj*c>ci)Xj!cw+{`9Earb*2>VXMp!C~B6^&go!*kU6;5)G`C6GjA>s zIYNbwe7F20a2${)JL-=;{BQOD--CuFW{RjjgO=@Pe-SKUvpnBZXgJ?xu8~x~@tl9& z51%@&Nc+0Hd7dP7IC%a2l5iACLZ?&R$JXTw>|$kbDq?Z*ddX0Q6rg|rXgHBpkdYEH zBq2gL5S;MT?ey)<=XN^!>CC%mcEzeU!p!%=a5UcpIlT0BcaMILYb%%g1)tl( ziD+}%?JiTp= JFUVJ4{RNv4n704` literal 0 HcmV?d00001 diff --git a/release/tutorial/videocasting.html b/release/tutorial/videocasting.html new file mode 100644 index 0000000000000000000000000000000000000000..876be30f68d9e96226f8fdef930c6f1e5a74e1da GIT binary patch literal 5284 zcmcIoZExE+627k~(El*i;gT&7OKF?z?X|WSNt56Tbho)C+oGQeTB0p(BvBP9yZ-n0 z3`tpXoNd|z&V8{=k(`-lW}X>x{N()I>zhwk7xeF&-`>*IA7^jhyryWBBp+YAPLlJR zbN}KvKBAjOR7P2)D^VoL#qSYCxwZAnBw4Li@#;man?-W-K6!ufdX(F;I6g`Wt&NN` zn?=*dkH$RczNN_Uy*DnU6~udt^D=Ry)>sm$>eoZ1PzuJUXzoIl3jgfZp z$Ia#F7v6PmY?UqK^h{pqERzkL>$EMgiC|5~iGK^}N$$mtXF6LGZ#jwne&jw8%@(OH zbc2z(`$SZz>NZTcyo_iWexF`Ed;a_wujSm9qFJbFazs|wn`i&9Qkl*1#{bHtTI6MVhf=rW6qBv2dSV)r$r+(J+ zd0bbEh(rMxhp&2DrsG7g&U?LRgi|lO&b8I4Fc#K5AbU9Vj_l#9UN$+fg2`JJFI6VL zQ|fT)XW-KtJbcp&y~p4o)-z?TZW@H<1J?Ev@7UVE_?FOZ4=+lgiU$O`Id^2av2Tj; z!Mw*&nIJ4V#av+XQwl4k8{3NYUrzqfZ@CrgKJvF>J%qc9AQ!vDk9*@9L8lhgB>J;O z?9A67ib5DOi7MTcqL9%P6CXdKzxa&vj6{1t=qz z)EY^8PVcX;X)a}EkouI#LM=f&7{rfsB& z>7%kaZ76K5TM~_=28;!{8V{+2jDcD<7nV{{(TqpsN@gq;3mXV6>lWxkS!5O&3r$3m zk*pL}h#Q{PvKC86~PfDvIE}nZ(vX|2Yh1nHw+A9QqK3 zu_pHXia27LMdu#M{x{cNI6|Yx}Zv~P$sKPuMSc9xtYMA(`2Z{bq8xSaF~bwbk2#uF_H`9 z4>qa_Ei#xA;CJsh)Hy6j*{!e+P;-VnfHkikDJ#n#LfVH{0PgXln;fa)65r@DBzp)* zLq8SjR#Lnwmrnr^k{_8|9pK9toho5r(uzq0_;4I^2jv|BG{I`p8OljrY2=t_D{uhp z3zX%S@=p%+Dc!L+-bAqT3(p&*jV`$DVwYx(SomOJ6@09Qe2eK430GsO!8! zHvdpkpZKKS&gqUJMG9(TewTEy;d9vPFd0&0Kx6LTDD<{np1c7bbmj7tSs05NZWl)z zc6C;l+SMLp1s1aX40uSbgLj-RJMs@Y39ga;YKi&TL(vfnaCukJ8!pzBw3}p@Bj*rF z1wsW(EWdJBii+Md7Lz^-7u*5!*|$XjH8ao*Xi}O^QCjj zHmu{>^pilMkCU0B-7SB)H&3W;G_wZ6+MgCUR5+bQqoiH4!kEE5tuHxXu%&YK$Mmuh z(JbZ(DwSxE2~ZBT&G=H}>L9RnZ$gbVpbtQ@y+v0gJO1&s9v1p7JzK%2z8G_yAOrvw zBUlT|z|&7`fn&lT_30rr0;i-QApy&+T(59QU|<~KZ!#7;ln!ZE1yNXneC+x1P9X}% zHBqbBPm0%!LX3_faYkP|o3A}$Nn=bB+~btU6OkDHc4TJ!*+{5#En0yg2IEgFH-qHI72M(%LP<~$QD z%;ZuQ;HqX|ptsnU+T_DC{}4>_C!feW-j8jcBVCO7kcmK%IM@s<@NxVd9fI#2UW6vW zvp*JhTg|3tXaO>{Sjgty1o(@NmUdg>!A`!*>$9fsU6CmzcYs@oguZo6E95)fR;ZRC zED=m-i%^9=x@v4(=Xgl(r6~OVhxDHo&ESn<4me#Z-%K9Tb*|If71!QNH0gP$U8b#T zjmCm?d5)`vO*H|R^qqT$izk7*#y@`4aj^M+=HE{EvingYe>ndJcO~5Ec{jV%b57uF zi~ltBuV3!Zn0+^E;u3M+0KD0H(#T?fQ9rnQ6M#yPp%J!VO=bwj-q*?j`?<=4)_f_@ zt`C_bY@A{F|GqP?9&YNA23US~+8l4Cjn5jc>3k$iY8*QKkM6Qz=S+$fTW8UK9sR&r zl + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/BePodder.rsrc b/resources/BePodder.rsrc new file mode 100644 index 0000000000000000000000000000000000000000..f3b839074b3123ca4e6ee6d932f58c6155fe7587 GIT binary patch literal 3775 zcmWFvW?*0t@ONPaQZ69O1|-M;AiWGgy)T&|W@Ioz*dXEmKmZb_1)GJBfnht)V37H1 z*cljDAl5K!0J2vwK{ydy3=Hy6@p2%$2g+vVW?*21x(g&kOLvZ%PrEcQ8n&ZhJDLVY z)4)hb1E4AmShd0dsNMzvr__M_l$6vW1>e+^%tQsp^z@?C^u&_wBeNwO3g`4EKXGb8l!M%rJ<#zp)QcHRB%dF@XSljFDl3{N-RlD!E44) zmP{-t$jMAjEXmBz)34Ai%S+L#NOjSJrBnuk#!jZjMux4sjDt8gABf$%EZubT(QED% z-rAQB`fzOgb<82MTu*OGC9hlLo+$GjTYg=P;Vs$YWu0iy7y00^-1>??m-6DN6FZJ=Ej^SjcOih&X;Uf7s^mxc7k<{wFI>SB z>SFzTiwXY$0rP;sL?&iN2FASP%rrI@h7eW;V0&;T5dUXlWMj4nIR*)TAj4ySsH=4f zsExQE)KX+%IKvDiq?lMv=^gC`VmToGd1BGAz>~Gd0*{{nV)3KhK>QPkCLuz1# zgSm@?3FaoCpP=rcwp$pOcKq8h1B}(TAKboZYvA@p+h&4j2Brfqwgy7*wwe2Tcg#4D zy!{}EW?Q-kPy9X-oIkz%AX|i$OF4FvPb8Lh$zDgL`(JIIOfY2}DbA0gF`u zM)77P79fie$Z7|(nBXjCIEw|!Vq|26v)JG)b~uXz&fafU_haEVqCFM^L>2!u$+Q zuKvMRjsXGjZa$9g!QhS&sB;tsRRpSp1QCkDT!Vr={r%v|f_*)GLFRzER=fyh!Jh7L wB_ZLCK_DfdqLzyxslckBGznN%z~%j%J;Q)f;3Am|VuYtNk`*7#=Lmr00YMkEfdBvi literal 0 HcmV?d00001 diff --git a/resources/Icons.rsrc b/resources/Icons.rsrc new file mode 100644 index 0000000000000000000000000000000000000000..b8bd6a7795c212e70cfff74dcaf086cca13ac160 GIT binary patch literal 66994 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 literal 0 HcmV?d00001 diff --git a/sources-experimental/Action.h b/sources-experimental/Action.h new file mode 100644 index 0000000..87521fa --- /dev/null +++ b/sources-experimental/Action.h @@ -0,0 +1,26 @@ +#ifndef _Action_h_ +#define _Action_h_ + +#include +#include + +#define ActionID bigtime_t + +class Action +{ + public: + Action(){fActionID=0;}; + virtual ~Action(){}; + + virtual status_t Perform(BMessage* errors) = 0; + virtual BString GetDescription() = 0; + + //general purpose ID.. + void SetActionID(ActionID id){ fActionID=id;} + ActionID GetActionID(){ return fActionID;} + + private: + ActionID fActionID; +}; + +#endif diff --git a/sources-experimental/ActionAsync.cpp b/sources-experimental/ActionAsync.cpp new file mode 100644 index 0000000..06c8a38 --- /dev/null +++ b/sources-experimental/ActionAsync.cpp @@ -0,0 +1,13 @@ +#include "ActionAsync.h" + + +ActionAsync::ActionAsync(BHandler *target ,uint32 what ){ + SetTargetAndWhat(target,what); +} + + +void +ActionAsync::SetTargetAndWhat(BHandler *tar,uint32 what){ + SetTarget(tar); + SetMessage(new BMessage(what)); +} diff --git a/sources-experimental/ActionAsync.h b/sources-experimental/ActionAsync.h new file mode 100644 index 0000000..b6669de --- /dev/null +++ b/sources-experimental/ActionAsync.h @@ -0,0 +1,15 @@ +#ifndef _ActionAsync_h_ +#define _ActionAsync_h_ + +#include "Action.h" +#include + +class ActionAsync : public Action , public BInvoker +{ + public: + ActionAsync(BHandler *target = NULL ,uint32 what = 0); + + void SetTargetAndWhat(BHandler *tar,uint32 what); +}; + +#endif diff --git a/sources-experimental/ActionAsyncWrapper.cpp b/sources-experimental/ActionAsyncWrapper.cpp new file mode 100644 index 0000000..0e28368 --- /dev/null +++ b/sources-experimental/ActionAsyncWrapper.cpp @@ -0,0 +1,15 @@ +#include "ActionAsyncWrapper.h" + + +ActionAsyncWrapper::ActionAsyncWrapper(Action* action){ + SetTargetAndWhat(NULL,0); + fAction = action; +} + +status_t +ActionAsyncWrapper::Perform(BMessage* errors) { + if(fAction) + return fAction->Perform(errors); + else + return B_ERROR; +} diff --git a/sources-experimental/ActionAsyncWrapper.h b/sources-experimental/ActionAsyncWrapper.h new file mode 100644 index 0000000..9120b07 --- /dev/null +++ b/sources-experimental/ActionAsyncWrapper.h @@ -0,0 +1,19 @@ +#ifndef _ActionAsyncWrapper_h_ +#define _ActionAsyncWrapper_h_ + +#include "ActionAsync.h" +#include + +class ActionAsyncWrapper : public ActionAsync +{ + public: + ActionAsyncWrapper(Action* action); + + status_t Perform(BMessage* errors); + + private: + Action* fAction; + +}; + +#endif diff --git a/sources-experimental/ActionDelete.cpp b/sources-experimental/ActionDelete.cpp new file mode 100644 index 0000000..eb33fdd --- /dev/null +++ b/sources-experimental/ActionDelete.cpp @@ -0,0 +1,27 @@ +#include "ActionDelete.h" +#include "Logger.h" +#include + +ActionDelete::ActionDelete(BString who,bool recoursive) { + fRecoursive = recoursive; + fWho=who; +} + +status_t +ActionDelete::Perform(BMessage* errors){ + + BString commandline; + commandline << "rm "; + if(fRecoursive) + commandline << "-r "; + commandline << "\"" << fWho << "\""; + LOG("ActionDelete",liDebug,"\n\nPerforming action [%s]\n\n",commandline.String() ); + int retcode = system(commandline.String()); + + if(retcode!=0 ){ + if(errors) errors->AddString("error","Can't delete!"); + return B_ERROR; + } + + return B_OK; +} diff --git a/sources-experimental/ActionDelete.h b/sources-experimental/ActionDelete.h new file mode 100644 index 0000000..c562e4d --- /dev/null +++ b/sources-experimental/ActionDelete.h @@ -0,0 +1,22 @@ +#ifndef _ActionDelete_h_ +#define _ActionDelete_h_ + +#include "Action.h" +#include + +class ActionDelete : public Action +{ + public: + ActionDelete(BString fWho,bool recoursive); + + + status_t Perform(BMessage* errors); + BString GetDescription() { return BString("ActionDelete"); } + + private: + int del(); + + BString fWho; + bool fRecoursive; +}; +#endif diff --git a/sources-experimental/ActionDownload.cpp b/sources-experimental/ActionDownload.cpp new file mode 100644 index 0000000..3fdf7e8 --- /dev/null +++ b/sources-experimental/ActionDownload.cpp @@ -0,0 +1,335 @@ +#include "ActionDownload.h" +#include +#include +#include +#include +//#include "Logger.h" + +#include "DownloadManager.h" +extern DownloadManager* download_manager; + + +ActionDownload::ActionDownload(BString URL, entry_ref dest, + bool allowResume, + BString fileType, + BLooper *target, + uint32 msg + ):ActionAsync(target,msg), + + fDest(dest), + fAllowResume(allowResume), + fFileType(fileType) +{ + //try to find username and password + + /*int32 dobleslash=URL.FindFirst("//"); + int32 doblepoint=URL.FindFirst(":",dobleslash); + int32 at=URL.FindFirst("@"); + + if(at>0){ + + if(doblepoint>0) { //with pwd + URL.CopyInto(fUsername,dobleslash+2,doblepoint-dobleslash-2); + URL.CopyInto(fPassword,doblepoint+1,at - doblepoint-1); + } + else + URL.CopyInto(fUsername,dobleslash+2,at - dobleslash-2); + + URL.Remove(dobleslash+2,at - dobleslash-1); + printf("// %ld : %ld @ %ld %s\n",dobleslash,doblepoint,at,URL.String()); + + } + */ + fUrl = URL; + + file = NULL; + curl=NULL; + resuming = 0.0; + SetShouldStop(false); +// LOG("ActionDownload",liDebug,"downloading URL=%s, to %s",URL.String(),BPath(&dest).Path()); +} + + +status_t +ActionDownload::openFile(BMessage* errors){ + + uint32 openMode = 0; + + if(fAllowResume) + openMode = B_WRITE_ONLY | B_CREATE_FILE | B_OPEN_AT_END; + else + openMode = B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE; + + if(file) return B_ERROR; + + file = new BFile(&fDest,openMode); + + if(!file || file->InitCheck()!=B_OK) + { + BString err("Can't open file!"); + errors->AddInt32("status",ERROR_OPENFILE); + errors->AddString("error",err); + return B_ERROR; + } + + + + + return B_OK; +} + + +status_t +ActionDownload::Perform(BMessage* errors){ + + + //is it these the right place? + fillMessage(this,errors); + // + + CURLcode res; + status_t status = B_OK; + + curl = curl_easy_init(); + + if(!curl) { + BString err("Internal error (CURL can't' init)!"); + errors->AddInt32("status",ERROR_CURL_INIT); + errors->AddString("error",err); + return B_ERROR; + } + + /* BString fullUrl; + if(fUsername != "") { + + if(fPassword == "") fPassword.SetTo("x"); + + fUrl.MoveInto(fullUrl,0,fUrl.FindFirst("//")+2); + fullUrl << fUsername << ":" << fPassword << "@"; + fullUrl << fUrl; + } + else + fullUrl=fUrl; + + printf("fullUrl %s\n",fullUrl.String()); + */ + + curl_easy_setopt(curl, CURLOPT_URL, fUrl.String()); + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, callback); + curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, this ); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS,FALSE); + + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,save_file); + curl_easy_setopt(curl, CURLOPT_WRITEDATA,this); + + curl_easy_setopt(curl, CURLOPT_PASSWDFUNCTION,passwd); + curl_easy_setopt(curl, CURLOPT_PASSWDDATA,this); + + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION , 1); //follow the white link! + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER , FALSE); //https + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST , FALSE); //https + + curl_easy_setopt(curl, CURLOPT_FAILONERROR , 1); + + download_manager->FinishCurl(curl); + + //RESUME + if(fAllowResume){ + BNode stat(&fDest); + // file->Seek(SEEK_END,0); + // size_t resume = (size_t)file->Position(); + off_t size = 0; + stat.GetSize(&size); + + size_t resume = size; + + + if(resume>0){ + curl_easy_setopt(curl, CURLOPT_RESUME_FROM, resume); + resuming = (double)resume; + } + } + + BMessage connect(*Message()); + // connect.what = Command(); + connect.AddInt32("status",OK_CONNECTING); + //Target()->PostMessage(&connect); + Invoke(&connect); + + + + + res = curl_easy_perform(curl); + + if(res !=0) + { + BString err("Can't connect!"); + errors->AddInt32("status",ERROR_PERFORMING); + errors->AddString("error",err); + errors->AddInt32("curl_error",res); + errors->AddBool("should_stop",ShouldStop()); + status = B_ERROR; + } + else + { + errors->AddInt32("status",OK_DOWNLOADED); + } + + curl_easy_cleanup(curl); + + errors->AddString("path",GetLocalPath()); + errors->AddRef("entry",&fDest); + + + + if(fFileType != "") + { + printf("Setting file type to: %s\n", fFileType.String()); + BNodeInfo(file).SetType(fFileType.String()); + } + else + { + printf("Ready to call update_mime_info(%s, false, true, false);\n",BPath(&fDest).Path()); + update_mime_info(BPath(&fDest).Path(),false,true,false); + } + delete file; + file = NULL; + + if(res == CURLE_BAD_DOWNLOAD_RESUME || res == CURLE_HTTP_RANGE_ERROR) { + // sarebbe bello chiedere.. va be per ora ci riprova e basta! + // cosa chiede? che alternative avrebbe se no l'utente? + fAllowResume = false; + errors->MakeEmpty(); + Perform(errors); + } +// else +// if(res!=0) { +// debugger("Found"); +// errors->MakeEmpty(); +// Perform(errors); + // } + + return status; +} + +BString +ActionDownload::GetDescription(){ + return "HTTP File download"; +} + +BString +ActionDownload::GetLocalPath(){ + return BPath(&fDest).Path(); +} + +void +ActionDownload::fillMessage(ActionDownload* ad,BMessage* msg){ + //fill with common fileds + int32 what=msg->what; //preserve original what. + *msg = ad->extraInfo; + + msg->AddInt64("sid",ad->GetActionID()); + msg->AddString("url",ad->fUrl); + + msg->what=what; +} + + + +void +ActionDownload::sendProgressX(ActionDownload* ad,double max,double current){ + + + BMessage *msg=ad->Message(); + msg->MakeEmpty(); + + fillMessage(ad,msg); + + + + msg->AddInt32("status",OK_PROGRESS); + msg->AddFloat("max_progress",max); + msg->AddFloat("current_progress",current); + //perc + float div = (current / max ) * 100; + + msg->AddInt32("percentage_progress",(int32)floor(div)); + + double speed = 0; + if(curl_easy_getinfo(ad->curl,CURLINFO_SPEED_DOWNLOAD,&speed) == CURLE_OK) + msg->AddFloat("download_speed",speed); + + + //TOTALE: + if(curl_easy_getinfo(ad->curl,CURLINFO_CONTENT_LENGTH_DOWNLOAD,&speed) == CURLE_OK) + msg->AddFloat("total_size",speed); + + // ATTUALE: CURLINFO_SIZE_DOWNLOAD + if(curl_easy_getinfo(ad->curl,CURLINFO_SIZE_DOWNLOAD,&speed) == CURLE_OK) + msg->AddFloat("actual_size",speed); + + char *array = NULL; + + + if(curl_easy_getinfo(ad->curl,CURLINFO_EFFECTIVE_URL,&array) == CURLE_OK) + msg->AddString("effective_url",BString(array)); + + //Andrea: this method is no more used, is the caller (of this class) who decided the filetype, + // if empty we ask the system to try to identify.. see end of Perform + /* + if(ad->fFileType == "" && curl_easy_getinfo(ad->curl,CURLINFO_CONTENT_TYPE,&array) == CURLE_OK) { + ad->fFileType.SetTo(array); + BNodeInfo(ad->file).SetType(ad->fFileType.String()); + msg->AddString("filetype",BString(array)); + }*/ + + ad->Invoke(); +} + +/* +void +ActionDownload::sendError(BLooper* looper,uint32 amsg,Status st,BString descr){ + BMessage msg(amsg); + msg.AddInt32("status",st); + msg.AddString("error",descr); + looper->PostMessage(&msg); +} +*/ +// + +int +ActionDownload::callback(void *data, + double dltotal, + double dlnow, + double , + double ) +{ + ActionDownload *ad=((ActionDownload*)data); + + //LOG("ActionDownload",liDebug,"callback total %f, now %f", dltotal,dlnow); + + if(ad->Target()) + sendProgressX(ad,ad->resuming+dltotal,ad->resuming+dlnow); + return 0; +} + +size_t +ActionDownload::save_file( void *ptr, size_t size, size_t nmemb, void *data){ + ActionDownload *ad=((ActionDownload*)data); + + if(!ad->file) { + BMessage errors; //how to report these errors?? + if(ad->openFile(&errors) != B_OK) return 0; + } + BFile* file=ad->file; + if(ad->ShouldStop()) return 0; + return file->Write(ptr,size*nmemb); +} + +int +ActionDownload::passwd (void *clientp, const char *prompt, char *buffer, int buflen){ + return 0; +} + + +//. diff --git a/sources-experimental/ActionDownload.h b/sources-experimental/ActionDownload.h new file mode 100644 index 0000000..6d20ffc --- /dev/null +++ b/sources-experimental/ActionDownload.h @@ -0,0 +1,88 @@ +#ifndef _ActionDownload_h_ +#define _ActionDownload_h_ + +#include "ActionAsync.h" +#include +#include +#include +#include "curl/curl.h" + +class ActionDownload : public ActionAsync +{ + public: + ActionDownload(BString URL, entry_ref dest,bool allowResume, BString fileType, BLooper *target = NULL ,uint32 msg = 0); + ~ActionDownload(){}; + + status_t Perform(BMessage* errors); + BString GetDescription(); + BString GetLocalPath(); + + //void SetLooper(BLooper *loop,uint32 msg){ fTarget=loop; fMsg=msg;}; + + //for compaatibility: + void SetExtraData(BString extra){ + extraInfo.AddString("extra",extra); + } + + void SetKey(BString key, BString data){ + extraInfo.AddString(key.String(),data); + } + + void SetRef(BString key, entry_ref *ref){ + extraInfo.AddRef(key.String(),ref); + } + + status_t GetRef(BString key, entry_ref* ref){ + return extraInfo.FindRef(key.String(),ref); + } + + + BString GetKey(BString key){ + BString data; + extraInfo.FindString(key.String(),&data); + return data; + } + + + void SetShouldStop(bool stop){ fShouldStop=stop;} + bool ShouldStop(){ return fShouldStop; } + + enum Status { + ERROR_OPENFILE, // 0 + ERROR_CURL_INIT, // 1 + ERROR_PERFORMING, // 2 + OK_CONNECTING, // 3 + OK_PROGRESS, // 4 + OK_DOWNLOADED // 5 + }; + +private: + + + status_t openFile(BMessage*); + + static void fillMessage(ActionDownload*,BMessage*); + static void sendProgressX(ActionDownload*,double max,double current); + + //curl callbacks: + static size_t save_file ( void *ptr, size_t size, size_t nmemb, void *stream); + static int callback (void *clientp,double dltotal,double dlnow,double , double); + static int passwd (void *clientp, const char *prompt, char *buffer, int buflen); + + + CURL* curl; + BString fUrl; //from. + entry_ref fDest; + + BMessage extraInfo; + bool fShouldStop; + BFile* file; + double resuming; + bool fAllowResume; + + BString fUsername; + BString fPassword; + BString fFileType; +}; + +#endif diff --git a/sources-experimental/ActionHTTPContent.cpp b/sources-experimental/ActionHTTPContent.cpp new file mode 100644 index 0000000..c92a111 --- /dev/null +++ b/sources-experimental/ActionHTTPContent.cpp @@ -0,0 +1,88 @@ +#include "ActionHTTPContent.h" +#include +#include +#include + + +#include "DownloadManager.h" +extern DownloadManager* download_manager; + + + +ActionHTTPContent::ActionHTTPContent(BString url){ + curl = NULL; + SetShouldStop(false); + SetUrl(url); +} + +ActionHTTPContent::~ActionHTTPContent(){ +}; + +status_t +ActionHTTPContent::Perform(BMessage* errors){ + + + + CURLcode res; + status_t status = B_OK; + + curl = curl_easy_init(); + + if(!curl) { + BString err("Internal error (CURL can't' init)!"); + return B_ERROR; + } + + curl_easy_setopt(curl, CURLOPT_URL, fUrl.String()); + + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,save_file); + curl_easy_setopt(curl, CURLOPT_WRITEDATA,this); + + + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION , 1); //follow the white link! + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER , FALSE); //https + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST , FALSE); //https + + curl_easy_setopt(curl, CURLOPT_FAILONERROR , 1); + + download_manager->FinishCurl(curl); + + + + res = curl_easy_perform(curl); + + if(res ==0) + AfterPerforming(errors); + + curl_easy_cleanup(curl); + return status; +} + +BString +ActionHTTPContent::GetDescription(){ + return "HTTP Content"; +} + + +size_t +ActionHTTPContent::save_file( void *ptr, size_t size, size_t nmemb, void *data){ + ActionHTTPContent *ad=((ActionHTTPContent*)data); + + + if(ad->ShouldStop()) return 0; + + ad->content.Append((const char*)ptr, size*nmemb); + + return size*nmemb; +} + + + + +void +ActionHTTPContent::AfterPerforming(BMessage* errors){ + if(content != "") + errors->AddString("content",content); +} + +//. diff --git a/sources-experimental/ActionHTTPContent.h b/sources-experimental/ActionHTTPContent.h new file mode 100644 index 0000000..a37495c --- /dev/null +++ b/sources-experimental/ActionHTTPContent.h @@ -0,0 +1,42 @@ +#ifndef _ActionHTTPContent_h_ +#define _ActionHTTPContent_h_ + +#include "ActionAsync.h" +#include +#include + +#include +#include "curl/curl.h" + + +class ActionHTTPContent : public ActionAsync +{ + public: + ActionHTTPContent(BString url); + ~ActionHTTPContent(); + + status_t Perform(BMessage* errors); + BString GetDescription(); + + void SetShouldStop(bool stop){ fShouldStop=stop;} + bool ShouldStop(){ return fShouldStop; } + + virtual void AfterPerforming(BMessage* errors) ; + + void SetUrl(BString url) { fUrl =url; }; + + +private: + + + BString content; + + //curl callbacks: + static size_t save_file ( void *ptr, size_t size, size_t nmemb, void *stream); + + CURL* curl; + BString fUrl; //from. + bool fShouldStop; +}; + +#endif diff --git a/sources-experimental/AddWindow.cpp b/sources-experimental/AddWindow.cpp new file mode 100644 index 0000000..31f709e --- /dev/null +++ b/sources-experimental/AddWindow.cpp @@ -0,0 +1,141 @@ + +#include "AddWindow.h" +#include "Application.h" + +#include +#include "BPLocale.h" +#include +#include +#include +#include +#include +#include +#include +#include "MainWindow.h" +#include "BPAlert.h" +#include "PBox.h" + +extern MainWindow* main_window; + + +AddWindow::AddWindow() : + BWindow(BRect(250,70,640,270),"AddWindow", B_MODAL_WINDOW, B_NOT_RESIZABLE|B_NOT_ZOOMABLE|B_ASYNCHRONOUS_CONTROLS) +{ + + + BButton* but; + BButton* but2; + + BFont font=*(be_plain_font); + + + BRect r(Bounds()); + + BBox *box = new BBox(r,"url_bbox", B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW, B_FANCY_BORDER); + box->SetBorder(B_PLAIN_BORDER); + + AddChild(box); + BRect rect(0, 0, 390, 165); + + BMessage templ; + templ.AddString("name", "Add Subscription"); + BMessage settings; + settings.AddString("name", "rss_url"); + settings.AddString("description", "Feed URL"); + settings.AddInt32("type", B_STRING_TYPE); + settings.AddBool("multi_line", true); + templ.AddMessage("setting", &settings); + BMessage values; + + text = new PBox(rect, templ, values, "rss_url"); + text->SetBorder(B_PLAIN_BORDER); + + box->AddChild(text); + + + + addrect = box->Bounds(); + addrect.InsetBy(25, 20); + addrect.top = addrect.bottom - 12; + addrect.left = addrect.right - font.StringWidth(_T("Cancel")) - 30; + box->AddChild(but = new BButton(addrect,"",_T("Cancel"),new BMessage('can'))); + + addrect.right = addrect.left - 15; + addrect.left = addrect.right - font.StringWidth(_T("Add")) - 30; + box->AddChild(but2 = new BButton(addrect,"",_T("Add"),new BMessage('sav'))); + + + //controlliamo se c'e' qualcosa nella clipboard? + const char *clip_text = NULL; + bool addButton = false; + int32 textLen; + BString url; + BMessage *clip = (BMessage *)NULL; + if (be_clipboard->Lock() ){ + clip = be_clipboard->Data(); + + if ( clip && ( clip->FindData("text/plain", B_MIME_TYPE,(const void **)&clip_text, &textLen) == B_OK )){ + url.SetTo(clip_text,textLen); + + if(url.FindFirst("http://") == 0) + addButton = true; + else + if(url.FindFirst("pcast://") == 0) + addButton = true; + else + if(url.FindFirst("feed://") == 0) + addButton = true; + } + be_clipboard->Unlock(); + } + + if(addButton==true){ + addrect.right = addrect.left - 15; + addrect.left = addrect.right - font.StringWidth(_T("Paste")) - 30; + BMessage* msg=new BMessage('past'); + msg->AddString("url",url); + BButton* clip_but; + box->AddChild(clip_but = new BButton(addrect,"",_T("Paste"),msg)); + } + + MoveTo(BPAlert::AlertPosition(Bounds().Width(),Bounds().Height())); + + + BTextView *textView = (BTextView*)FindView("rss_url"); + if (textView){ + textView->MakeFocus(true); + } +} + + +void +AddWindow::MessageReceived(BMessage *mess){ + + + if(mess->what == 'can'){ + BMessenger(this).SendMessage(B_QUIT_REQUESTED); + } + else + if(mess->what == 'sav'){ + BTextView *textView = (BTextView*)FindView("rss_url"); + if (textView){ + BMessage msg(DOWNLOAD_CHANNEL); + msg.AddString("url",textView->Text()); + BMessenger(main_window).SendMessage(&msg); + BMessenger(this).SendMessage(B_QUIT_REQUESTED); + } + } + else + if(mess->what== 'past'){ + BString url; + mess->FindString("url",&url); + BTextView *textView = (BTextView*)FindView("rss_url"); + if (textView){ + textView->SetText(url.String()); + } + } + else BWindow::MessageReceived(mess); +} + + + diff --git a/sources-experimental/AddWindow.cpp_OR b/sources-experimental/AddWindow.cpp_OR new file mode 100644 index 0000000..ae22d4f --- /dev/null +++ b/sources-experimental/AddWindow.cpp_OR @@ -0,0 +1,146 @@ + +#include "AddWindow.h" +#include "Application.h" + +#include +#include "BPLocale.h" +#include +#include +#include +#include +#include +#include +#include +#include "MainWindow.h" +#include "BPAlert.h" + + +extern MainWindow* main_window; + + +AddWindow::AddWindow() : + BWindow(BRect(250,70,640,220),"AddWindow", B_MODAL_WINDOW, B_NOT_RESIZABLE|B_NOT_ZOOMABLE|B_ASYNCHRONOUS_CONTROLS) +{ + + + BButton* but; + BButton* but2; + + +// const rgb_color bgcolor = {255,215,96,255}; + const rgb_color boxcolor = {255,233,167,255}; +//#ifdef ZETA +// SetWindowColor(bgcolor); +//#endif + + BFont font=*(be_plain_font); + + + BRect r(Bounds()); + //r.InsetBy(0,15); + + BBox *box = new BBox(r,"url_bbox", B_FOLLOW_LEFT_RIGHT, B_FANCY_BORDER); + + box->SetLabel(_T("Insert the rss feed url!")); + box->SetBorder(B_PLAIN_BORDER); + box->SetViewColor(boxcolor); + + AddChild(box); + + + + BStringView* txt = new BStringView(BRect(20,15,370,65),"url-",_T("URL:")); + box->AddChild(txt); + txt->SetViewColor(boxcolor); + txt->ResizeToPreferred(); + + BRect rect(20,txt->Frame().bottom+1,370 - B_V_SCROLL_BAR_WIDTH ,95); + BRect rr= rect.OffsetToCopy(0,0); + //rr = + rr.InsetBy(BPoint(2,2)); + text = new BTextView(rect,"",rr,B_FOLLOW_LEFT_RIGHT,B_WILL_DRAW | B_NAVIGABLE); + BScrollView* scroller = new BScrollView("scroller",text,B_FOLLOW_LEFT_RIGHT,B_WILL_DRAW | B_NAVIGABLE,false,true); + //text->SetWordWrap(false); + box->AddChild(scroller); + //text->SetDivider(30); + //text->SetText(""); + //text->SetViewColor(boxcolor); + //text->MakeFocus(true); + + + addrect = box->Bounds(); + addrect.InsetBy(25, 20); + addrect.top = addrect.bottom - 12; + addrect.left = addrect.right - font.StringWidth(_T("Cancel")) - 30; + box->AddChild(but = new BButton(addrect,"",_T("Cancel"),new BMessage('can'))); + but->SetViewColor(boxcolor); + + addrect.right = addrect.left - 15; + addrect.left = addrect.right - font.StringWidth(_T("Add")) - 30; + box->AddChild(but2 = new BButton(addrect,"",_T("Add"),new BMessage('sav'))); + but2->SetViewColor(boxcolor); + + + //controlliamo se c'e' qualcosa nella clipboard? + const char *clip_text = NULL; + bool addButton = false; + int32 textLen; + BString url; + BMessage *clip = (BMessage *)NULL; + if (be_clipboard->Lock() ){ + clip = be_clipboard->Data(); + + if ( clip && ( clip->FindData("text/plain", B_MIME_TYPE,(const void **)&clip_text, &textLen) == B_OK )){ + url.SetTo(clip_text,textLen); + + if(url.FindFirst("http://") == 0) + addButton = true; + else + if(url.FindFirst("pcast://") == 0) + addButton = true; + else + if(url.FindFirst("feed://") == 0) + addButton = true; + } + be_clipboard->Unlock(); + } + + if(addButton==true){ + addrect.right = addrect.left - 15; + addrect.left = addrect.right - font.StringWidth(_T("Paste")) - 30; + BMessage* msg=new BMessage('past'); + msg->AddString("url",url); + BButton* clip_but; + box->AddChild(clip_but = new BButton(addrect,"",_T("Paste"),msg)); + clip_but->SetViewColor(boxcolor); + } + + MoveTo(BPAlert::AlertPosition(Bounds().Width(),Bounds().Height())); +} + + +void +AddWindow::MessageReceived(BMessage *mess){ + + + if(mess->what == 'can'){ + BMessenger(this).SendMessage(B_QUIT_REQUESTED); + } + else + if(mess->what == 'sav'){ + BMessage msg(DOWNLOAD_CHANNEL); + msg.AddString("url",text->Text()); + BMessenger(main_window).SendMessage(&msg); + BMessenger(this).SendMessage(B_QUIT_REQUESTED); + } + else + if(mess->what== 'past'){ + BString url; + mess->FindString("url",&url); + text->SetText(url.String()); + } + else BWindow::MessageReceived(mess); +} + + + diff --git a/sources-experimental/AddWindow.h b/sources-experimental/AddWindow.h new file mode 100644 index 0000000..415f18c --- /dev/null +++ b/sources-experimental/AddWindow.h @@ -0,0 +1,25 @@ +#include + +#include + +#define DOWNLOAD_CHANNEL 'addu' + +class PBox; + +class AddWindow: public BWindow +{ + + + + + public: + AddWindow(); + void MessageReceived(BMessage *mess); + + PBox* text; + BRect addrect; + + + +}; + diff --git a/sources-experimental/Archive.h b/sources-experimental/Archive.h new file mode 100644 index 0000000..b6f6cfb --- /dev/null +++ b/sources-experimental/Archive.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef _Archive_H_ +#define _Archive_H_ + +#include "Store.h" +#include "Retriver.h" +#include "ElementListener.h" + +class Archive : public Store, public Retriver, public ElementListener { + + public: + + // from Store + virtual void SetKey(ItemProperty key,void* data,ssize_t size) = 0; + virtual void SetKeyString(ItemProperty key,const char* data) = 0; + virtual void SetKeyInt32(ItemProperty key,int32 data) = 0; + + + //from Retriver + virtual ssize_t GetData(ItemProperty key,const void** data)= 0; + virtual int32 CountData()= 0; + virtual BString GetDataString(ItemProperty key)= 0; + virtual int32 GetDataInt32(ItemProperty key)= 0; + + //from ElementListener + virtual void KeyModified(int32 key, void* data, ssize_t numBytes) = 0; + +}; + +#endif + +//.. diff --git a/sources-experimental/AttributeDumper.cpp b/sources-experimental/AttributeDumper.cpp new file mode 100644 index 0000000..0e87ea0 --- /dev/null +++ b/sources-experimental/AttributeDumper.cpp @@ -0,0 +1,201 @@ +#include "AttributeDumper.h" +#include "ItemProperty.h" +#include "TypeConstants.h" +#include "AttributeMap.h" + +#include +#include +#include +#include +#include +#include "FileStatus.h" +#include "Utils.h" + +// from the BeBook: +// The value of an indexed attribute can be, at most, 255 bytes. +// from the ITunesRSS format: +// All fields will be truncated to 255 unicode characters, except for + +#define INDEX_LIMIT_LENGHT 255 + +AttributeDumper::AttributeDumper(entry_ref* ref) { + + fRef=*ref; + //BFile *fFile = new BFile(&fRef,B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); + fNode = new BNode(ref); //fFile; +} +/* +AttributeDumper::AttributeDumper(node_ref* nref) { + + BDirectory *fDir = new BDirectory(nref); + fNode = fDir; +} +*/ +AttributeDumper::AttributeDumper(entry_ref* ref,bool asdir){ + + fNode = NULL; + + //new name + BString filename; + filename << real_time_clock_usecs(); + // + + BDirectory dir(ref); + + fPath.SetTo(&dir,NULL); + fPath.Append(filename.String()); + + if(!asdir) + { + + BFile *fFile = new BFile(fPath.Path(),B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); + fNode = fFile; + + BNodeInfo(fNode).SetType(MIME_ITEM); + + get_ref_for_path(fPath.Path(),&fRef); + } + else + { + BDirectory *fDir = new BDirectory(dir); + dir.CreateDirectory(fPath.Path(),fDir); + fNode = fDir; + + BNodeInfo(fNode).SetType(MIME_CHANNEL); + + printf("New directory Path [%s]\n",fPath.Path()); + + get_ref_for_path(fPath.Path(),&fRef); + } + + +} +AttributeDumper::~AttributeDumper(){ + if(fNode) delete fNode; +} +void +AttributeDumper::KeyModified(int32 key, void* data, ssize_t numBytes){ + + + + switch(key) + { + case ITEM_TITLE: + _writeAttr(ATTR_ITEM_TITLE,BString((const char*)data,numBytes)); + break; + case ITEM_GUID: + _writeAttr(ATTR_ITEM_GUID,BString((const char*)data,numBytes)); + break; + case ITEM_LINK: + _writeAttr(ATTR_ITEM_LINK,BString((const char*)data,numBytes)); + break; + case ITEM_CATEGORY: + _writeAttr(ATTR_CATEGORY,BString((const char*)data,numBytes)); + break; + + case ITEM_KEYWORDS: + _writeAttr(ATTR_ITEM_KEYWORDS,BString((const char*)data,numBytes)); + break; + + case ITEM_PUBDATE: + { + time_t when = *((time_t*)data); + if(fNode) fNode->WriteAttr(ATTR_ITEM_PUBDATE,B_TIME_TYPE,0,&when,sizeof(when)); + } + break; + case ITEM_ENCLOSURE_LENGTH: + { + off_t size = *((off_t*)data); + if(fNode) fNode->WriteAttr(ATTR_ENCLOSURE_SIZE,B_TIME_TYPE,0,&size,sizeof(size)); + } + break; + + case ITEM_ENCLOSURE_LOCALPATH: + _writeAttr(ATTR_ENCLOSURE_PATH,BString((const char*)data,numBytes)); + break; + + case ITEM_ENCLOSURE_URL: + _writeAttr(ATTR_ENCLOSURE_URL,BString((const char*)data,numBytes)); + break; + case ITEM_ENCLOSURE_TYPE: + _writeAttr(ATTR_ENCLOSURE_TYPE,BString((const char*)data,numBytes)); + break; + case ITEM_ENCLOSURE_FILE_STATUS:{ + FileStatus fs = *((FileStatus*)data); + if(fNode) fNode->WriteAttr(ATTR_ITEM_STATUS,B_INT32_TYPE,0,&fs,sizeof(FileStatus)); + } + break; + + case ITEM_DESCRIPTION: + _writeAttr(ATTR_ITEM_DESCRIPTION,BString((const char*)data,numBytes),false); + break; + + // CHANNEL: + + case CHANNEL_TITLE: + _writeAttr(ATTR_TITLE,BString((const char*)data,numBytes)); + break; + case CHANNEL_WEBLINK: + _writeAttr(ATTR_WEBLINK,BString((const char*)data,numBytes)); + break; + case CHANNEL_URL: + _writeAttr(ATTR_URL,BString((const char*)data,numBytes)); + break; + case CHANNEL_CATEGORY: + _writeAttr(ATTR_CATEGORY,BString((const char*)data,numBytes)); + break; + + case CHANNEL_IMAGE_DATA: + _addBitmap((BBitmap*)data); + break; + case CHANNEL_DESCRIPTION: + _writeAttr(ATTR_DESCRIPTION,BString((const char*)data,numBytes),false); + break; + case CHANNEL_NEWITEMS: + { +// int32 c = *((int32*)data); + + } + break; + case CHANNEL_RSS_FILE_STATUS: + { +// int32 c = *((int32*)data); + + } + break; + default: + break; + }; + +} + +void +AttributeDumper::_writeAttr(const char* name,BString data,bool cut){ + if(cut) data.Truncate(INDEX_LIMIT_LENGHT); + if(fNode) fNode->WriteAttr(name,B_STRING_TYPE,0,data.String(),data.Length()); + +} + +status_t +AttributeDumper::_addBitmap(BBitmap *icon) { + + + char *buffer = NULL; + int32 size = -1; + BMessage flattenedIcon; + status_t ret = B_ERROR; + BMessage iconMsg; + + if (icon->Archive(&flattenedIcon) != B_OK) return ret; + + size = flattenedIcon.FlattenedSize(); + buffer = (char *)calloc(size, sizeof(char)); + if (flattenedIcon.Flatten(buffer, size) == B_OK) { + if(fNode) ret = fNode->WriteAttr(ATTR_IMAGE, B_MESSAGE_TYPE, 0, buffer, size); + }; + + free(buffer); + return ret; +}; + +//__ diff --git a/sources-experimental/AttributeDumper.h b/sources-experimental/AttributeDumper.h new file mode 100644 index 0000000..1af5127 --- /dev/null +++ b/sources-experimental/AttributeDumper.h @@ -0,0 +1,40 @@ +#ifndef AttributeDumper_H_ +#define AttributeDumper_H_ + +//Dumps ItemProperty as file attribute. + +#include "ElementListener.h" + +#include +#include +#include +#include + +class AttributeDumper : public ElementListener { + +public: + AttributeDumper(entry_ref* ref); + //AttributeDumper(node_ref* nref); + + //create the file: + AttributeDumper(entry_ref*,bool asdir); + + + + virtual ~AttributeDumper(); + + void KeyModified(int32 key, void* data, ssize_t numBytes); + + BPath GetPath(){ return fPath; } + void GetNodeRef(node_ref* ref){ if(fNode) fNode->GetNodeRef(ref); } + void GetEntryRef(entry_ref* ref){ *ref=fRef; } +private: + void _writeAttr(const char* name,BString data,bool cut = true); + status_t _addBitmap(BBitmap* icon); + + BNode* fNode; + entry_ref fRef; + BPath fPath; +}; + +#endif diff --git a/sources-experimental/AttributeExtractor.cpp b/sources-experimental/AttributeExtractor.cpp new file mode 100644 index 0000000..6453ff0 --- /dev/null +++ b/sources-experimental/AttributeExtractor.cpp @@ -0,0 +1,138 @@ +#include "AttributeExtractor.h" +#include "FileStatus.h" +#include "AttributeMap.h" +#include +#include +#include +#include +#include "Utils.h" + +void +AttributeExtractor::Parse(BNode *node,bool deep){ + + char buf[B_ATTR_NAME_LENGTH]; + + node->RewindAttrs(); + + while (node->GetNextAttrName(buf) == B_OK) { + //printf("> Attr name: %s\n", buf); + BString attr(buf); + + if(attr.ICompare(ATTR_TITLE)==0){ + size_t r = node->ReadAttr(buf,0,0,buf,B_ATTR_NAME_LENGTH); + buf[r]='\0'; + NotifyNotifier(CHANNEL_TITLE,buf,r); + } + else + if(attr.ICompare(ATTR_WEBLINK)==0){ + size_t r = node->ReadAttr(buf,0,0,buf,B_ATTR_NAME_LENGTH); + buf[r]='\0'; + NotifyNotifier(CHANNEL_WEBLINK,buf,r); + } + else + if(attr.ICompare(ATTR_IMAGE)==0){ + + //new style + + char* buffer; + int32 size; + status_t err = ReadAttributeData(node,ATTR_IMAGE,&buffer,&size); + + if(err !=B_OK ) return; + + BMessage iconMsg; + + if (iconMsg.Unflatten(buffer) != B_OK) { + free(buffer); + return ; + }; + BBitmap* icon = new BBitmap(&iconMsg); + if(!icon) { + free(buffer); + return; + } + + NotifyNotifier(CHANNEL_IMAGE_DATA,(void*)icon,sizeof(BBitmap*)); + + free(buffer); + delete icon; + + + } + + else if(attr.ICompare(ATTR_ITEM_TITLE)==0){ + size_t r = node->ReadAttr(buf,0,0,buf,B_ATTR_NAME_LENGTH); + buf[r]='\0'; + NotifyNotifier(ITEM_TITLE,buf,r); + } + else if(attr.ICompare(ATTR_URL)==0){ + size_t r = node->ReadAttr(buf,0,0,buf,B_ATTR_NAME_LENGTH); + buf[r]='\0'; + NotifyNotifier(CHANNEL_URL,buf,r); + } + else if(attr.ICompare(ATTR_ITEM_GUID)==0){ + size_t r = node->ReadAttr(buf,0,0,buf,B_ATTR_NAME_LENGTH); + buf[r]='\0'; + NotifyNotifier(ITEM_GUID,buf,r); + } + else if(attr.ICompare(ATTR_ENCLOSURE_URL)==0){ + size_t r = node->ReadAttr(buf,0,0,buf,B_ATTR_NAME_LENGTH); + buf[r]='\0'; + NotifyNotifier(ITEM_ENCLOSURE_URL,buf,r); + } + else if(attr.ICompare(ATTR_ENCLOSURE_PATH)==0){ + size_t r = node->ReadAttr(buf,0,0,buf,B_ATTR_NAME_LENGTH); + buf[r]='\0'; + NotifyNotifier(ITEM_ENCLOSURE_LOCALPATH,buf,r); + } + else if(attr.ICompare(ATTR_ENCLOSURE_TYPE)==0){ + size_t r = node->ReadAttr(buf,0,0,buf,B_ATTR_NAME_LENGTH); + buf[r]='\0'; + NotifyNotifier(ITEM_ENCLOSURE_TYPE,buf,r); + } + + else if(attr.ICompare(ATTR_ITEM_PUBDATE)==0){ + size_t r = node->ReadAttr(buf,0,0,buf,sizeof(time_t)); + //time_t time; + //memcpy(&time,buf,sizeof(time)); + //printf("EX DEBUG TIME %ld\n",time); + NotifyNotifier(ITEM_PUBDATE,(void*)buf,r); + } + else if(attr.ICompare(ATTR_ITEM_STATUS)==0){ + size_t r = node->ReadAttr(buf,0,0,buf,sizeof(FileStatus)); + NotifyNotifier(ITEM_ENCLOSURE_FILE_STATUS,(void*)buf,r); + } + else if(attr.ICompare(ATTR_ENCLOSURE_SIZE)==0){ + size_t r = node->ReadAttr(buf,0,0,buf,B_ATTR_NAME_LENGTH); + NotifyNotifier(ITEM_ENCLOSURE_LENGTH,(void*)buf,r); + } + //this doesn't need to be extracted: + if(deep){ + if(attr.ICompare(ATTR_ITEM_DESCRIPTION)==0){ + //new style + + char* buffer; + int32 size; + status_t err = ReadAttributeString(node,ATTR_ITEM_DESCRIPTION,&buffer,&size); + + if(err !=B_OK ) return; + NotifyNotifier(ITEM_DESCRIPTION,(void*)buffer,size); + free(buffer); + } + else if(attr.ICompare(ATTR_ITEM_LINK)==0){ + size_t r = node->ReadAttr(buf,0,0,buf,B_ATTR_NAME_LENGTH); + buf[r]='\0'; + NotifyNotifier(ITEM_LINK,buf,r); + } + else if(attr.ICompare(ATTR_DESCRIPTION)==0){ + char* buffer; + int32 size; + status_t err = ReadAttributeString(node,ATTR_DESCRIPTION,&buffer,&size); + if(err !=B_OK ) return; + NotifyNotifier(CHANNEL_DESCRIPTION,(void*)buffer,size); + free(buffer); + } + + } + } +} diff --git a/sources-experimental/AttributeExtractor.h b/sources-experimental/AttributeExtractor.h new file mode 100644 index 0000000..4dfac2f --- /dev/null +++ b/sources-experimental/AttributeExtractor.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef AttributeExtractor_H_ +#define AttributeExtractor_H_ + +#include + +#include "Extractor.h" + + + +class AttributeExtractor : public Extractor +{ + +public: + + void Parse(BNode* node, bool deep = false); + +}; +#endif diff --git a/sources-experimental/AttributeMap.h b/sources-experimental/AttributeMap.h new file mode 100644 index 0000000..a4f74c1 --- /dev/null +++ b/sources-experimental/AttributeMap.h @@ -0,0 +1,38 @@ +#ifndef AttributeMap_H_ +#define AttributeMap_H_ + +#define MIME_ITEM "application/bp-item" +#define MIME_CHANNEL "application/bp-channel" +#define MIME_ARCHIVED_CHANNEL "application/bp-archived-channel" + +#define ATTR_TITLE "bp:title" +#define ATTR_URL "bp:link" +#define ATTR_WEBLINK "bp:weblink" +#define ATTR_IMAGE "bp:image" +#define ATTR_CATEGORY "bp:category" +#define ATTR_DESCRIPTION "bp:description" + +#define ATTR_ITEM_TITLE "bp:item_title" +#define ATTR_ITEM_STATUS "bp:item_status" +#define ATTR_ITEM_GUID "bp:item_guid" +#define ATTR_ITEM_PUBDATE "bp:item_pubdate" +#define ATTR_ITEM_LINK "bp:item_link" +#define ATTR_ITEM_KEYWORDS "bp:item_keywords" + + +#define ATTR_ITEM_DESCRIPTION "bp:item_description" + +#define ATTR_ENCLOSURE_URL "bp:enclosure_url" +#define ATTR_ENCLOSURE_PATH "bp:enclosure_path" +#define ATTR_ENCLOSURE_SIZE "bp:enclosure_size" +#define ATTR_ENCLOSURE_TYPE "bp:enclosure_type" + + +#define ATTR_COLUMNS_STATE "_pb/columns" +#define ATTR_EXTRA_STATE "_pb/extras" +#define ATTR_CACHE "pb:cache" +#define ATTR_GROUPS "pb:groups" + + +#endif +//-- diff --git a/sources-experimental/AutoFiletypeMap.h b/sources-experimental/AutoFiletypeMap.h new file mode 100644 index 0000000..a380295 --- /dev/null +++ b/sources-experimental/AutoFiletypeMap.h @@ -0,0 +1,50 @@ +#ifndef _AutoFiletypeMap_H_ +#define _AutoFiletypeMap_H_ + +#define MEDIAPLAYER 0 +#define SOUNDPLAY 1 +#define VLC 2 +#define NONE 3 + + +struct coppia { + const char* extension; + const int application; + const char* alert; +}; + + +const coppia autotypes[]= { + {".3gp",VLC,_T("alert_3gp")}, + {".3g2",VLC,_T("alert_3gp")}, + {".avi",MEDIAPLAYER,NULL}, + {".flv",VLC,NULL}, + {".m3u",SOUNDPLAY,NULL}, + {".m4a",VLC,NULL}, + {".m4b",VLC,NULL}, + {".m4p",VLC,NULL}, + {".m4v",VLC,NULL}, + {".mov",VLC,NULL}, + {".mp4",VLC,NULL}, + {".swf",NONE,_T("alert_swf")}, + {".wma",VLC,NULL}, + {".wmv",VLC,NULL} +}; + +int32 +FindBestApplication(entry_ref* ref,BString &alert){ + + int count = sizeof(autotypes)/sizeof(coppia); + + for(int i=0;iname); + int32 last=name.IFindLast(autotypes[i].extension); + if(last>0) { + alert.SetTo(autotypes[i].alert); + return autotypes[i].application; + } + } + return -1; +} + +#endif diff --git a/sources-experimental/BPAlert.cpp b/sources-experimental/BPAlert.cpp new file mode 100644 index 0000000..839a63d --- /dev/null +++ b/sources-experimental/BPAlert.cpp @@ -0,0 +1,708 @@ +// Standard Includes ----------------------------------------------------------- +#include + +// System Includes ------------------------------------------------------------- +#include +#include +#include +#include + +#include "BPAlert.h" +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +//#define DEBUG_ALERT +#ifdef DEBUG_ALERT +#define FTRACE(x) fprintf(x) +#else +#define FTRACE(x) /* nothing */ +#endif + +// Default size of the Alert window. +#define DEFAULT_RECT BRect(0, 0, 310, 75) +#define max(LHS, RHS) ((LHS) > (RHS) ? (LHS) : (RHS)) + +// Globals --------------------------------------------------------------------- +static const unsigned int kAlertButtonMsg = 'ALTB'; +static const int kSemTimeOut = 50000; + +static const int kButtonBottomOffset = 9; +static const int kDefButtonBottomOffset = 6; +static const int kButtonRightOffset = 6; +static const int kButtonSpaceOffset = 6; +static const int kButtonOffsetSpaceOffset = 26; +static const int kButtonMinOffsetSpaceOffset = kButtonOffsetSpaceOffset / 2; +static const int kButtonLeftOffset = 62; +static const int kButtonUsualWidth = 75; + +static const int kWindowIconOffset = 27; +static const int kWindowMinWidth = 310; +static const int kWindowMinOffset = 12; +static const int kWindowOffsetMinWidth = 335; + +static const int kIconStripeWidth = 30; + +static const int kTextLeftOffset = 10; +static const int kTextIconOffsetSpace = kIconStripeWidth; //kWindowIconOffset + kIconStripeWidth - 2; +static const int kTextTopOffset = 6; +static const int kTextRightOffset = 10; +static const int kTextBottomOffset = 45; + +//------------------------------------------------------------------------------ +class TAlertView : public BView { + public: + TAlertView(BRect frame); + TAlertView(BMessage* archive); + ~TAlertView(); + + static TAlertView* Instantiate(BMessage* archive); + status_t Archive(BMessage* archive, bool deep = true); + + virtual void Draw(BRect updateRect); + + // These functions (or something analogous) are missing from libbe.so's + // dump. I can only assume that the bitmap is a public var in the + // original implementation -- or BPAlert is a friend of TAlertView. + // Neither one is necessary, since I can just add these. + void SetBitmap(BBitmap* Icon) { fIconBitmap = Icon; } + BBitmap* Bitmap() { return fIconBitmap; } + + private: + BBitmap* fIconBitmap; +}; + +//------------------------------------------------------------------------------ +// I'm making a guess based on the name and TextEntryAlert's implementation that +// this is a BMessageFilter. I'm not sure, but I think I actually prefer how +// TextEntryAlert does it, but there are clearly no message filtering functions +// on BPAlert so here we go. +class _BPAlertFilter_ : public BMessageFilter { + public: + _BPAlertFilter_(BPAlert* Alert); + ~_BPAlertFilter_(); + + virtual filter_result Filter(BMessage* msg, BHandler** target); + + private: + BPAlert* fAlert; +}; + + +static float +width_from_label(BButton *button) +{ + // BButton::GetPreferredSize() does not return the minimum width + // required to fit the label. Thus, the width is computed here. + return button->StringWidth(button->Label()) + 20.0f; +} + + +// #pragma mark - BPAlert + + +BPAlert::BPAlert(const char *title, const char *text, const char *button1, + const char *button2, const char *button3, button_width width, + BBitmap* icon) + : BWindow(DEFAULT_RECT, title, B_MODAL_WINDOW, B_NOT_RESIZABLE) +{ + InitObject(text, button1, button2, button3, width, B_EVEN_SPACING, icon); +} + + +BPAlert::BPAlert(const char *title, const char *text, const char *button1, + const char *button2, const char *button3, button_width width, + button_spacing spacing, BBitmap* icon) + : BWindow(DEFAULT_RECT, title, B_MODAL_WINDOW, + B_NOT_CLOSABLE | B_NOT_RESIZABLE) +{ + InitObject(text, button1, button2, button3, width, spacing, icon); +} + + +BPAlert::~BPAlert() +{ + // Probably not necessary, but it makes me feel better. + if (fAlertSem >= B_OK) + delete_sem(fAlertSem); +} + + +BPAlert::BPAlert(BMessage* data) + : BWindow(data) +{ + fInvoker = NULL; + fAlertSem = -1; + fAlertVal = -1; + + fTextView = (BTextView*)FindView("_tv_"); + + fButtons[0] = (BButton*)FindView("_b0_"); + fButtons[1] = (BButton*)FindView("_b1_"); + fButtons[2] = (BButton*)FindView("_b2_"); + + if (fButtons[2]) + SetDefaultButton(fButtons[2]); + else if (fButtons[1]) + SetDefaultButton(fButtons[1]); + else if (fButtons[0]) + SetDefaultButton(fButtons[0]); + + TAlertView* master = (TAlertView*)FindView("_master_"); + if (master) + master->SetBitmap(InitIcon()); + + // Get keys + char key; + for (int32 i = 0; i < 3; ++i) { + if (data->FindInt8("_but_key", i, (int8*)&key) == B_OK) + fKeys[i] = key; + } + + int32 temp; + // Get alert type + //if (data->FindInt32("_atype", &temp) == B_OK) + // fMsgType = (alert_type)temp; + + // Get button width + if (data->FindInt32("_but_width", &temp) == B_OK) + fButtonWidth = (button_width)temp; + + AddCommonFilter(new _BPAlertFilter_(this)); +} + + +BArchivable* +BPAlert::Instantiate(BMessage* data) +{ + if (!validate_instantiation(data, "BPAlert")) + return NULL; + + return new BPAlert(data); +} + + +status_t +BPAlert::Archive(BMessage* data, bool deep) const +{ + BWindow::Archive(data, deep); + + // Stow the text + data->AddString("_text", fTextView->Text()); + + // Stow the alert type + //data->AddInt32("_atype", fMsgType); + + // Stow the button width + data->AddInt32("_but_width", fButtonWidth); + + // Stow the shortcut keys + if (fKeys[0] || fKeys[1] || fKeys[2]) { + // If we have any to save, we must save something for everyone so it + // doesn't get confusing on the unarchive. + data->AddInt8("_but_key", fKeys[0]); + data->AddInt8("_but_key", fKeys[1]); + data->AddInt8("_but_key", fKeys[2]); + } + + return B_OK; +} + + +void +BPAlert::SetShortcut(int32 index, char key) +{ + if (index >= 0 && index < 3) + fKeys[index] = key; +} + + +char +BPAlert::Shortcut(int32 index) const +{ + if (index >= 0 && index < 3) + return fKeys[index]; + + return 0; +} + + +int32 +BPAlert::Go() +{ + fAlertSem = create_sem(0, "AlertSem"); + if (fAlertSem < B_OK) { + Quit(); + return -1; + } + + // Get the originating window, if it exists + BWindow* window = + dynamic_cast(BLooper::LooperForThread(find_thread(NULL))); + + Show(); + + // Heavily modified from TextEntryAlert code; the original didn't let the + // blocked window ever draw. + if (window) { + status_t err; + for (;;) { + do { + err = acquire_sem_etc(fAlertSem, 1, B_RELATIVE_TIMEOUT, + kSemTimeOut); + // We've (probably) had our time slice taken away from us + } while (err == B_INTERRUPTED); + + if (err == B_BAD_SEM_ID) { + // Semaphore was finally nuked in MessageReceived + break; + } + window->UpdateIfNeeded(); + } + } else { + // No window to update, so just hang out until we're done. + while (acquire_sem(fAlertSem) == B_INTERRUPTED) { + } + } + + // Have to cache the value since we delete on Quit() + int32 value = fAlertVal; + if (Lock()) + Quit(); + + //for(int i=0;i<3;i++) + //if(fButtons[i]) + //printf("fButtons %d %f %f\n",i,fButtons[i]->Frame().left,fButtons[i]->Frame().top); + + return value; +} + + +status_t +BPAlert::Go(BInvoker* invoker) +{ + fInvoker = invoker; + Show(); + return B_OK; +} + + +void +BPAlert::MessageReceived(BMessage* msg) +{ + if (msg->what != kAlertButtonMsg) + return BWindow::MessageReceived(msg); + + int32 which; + if (msg->FindInt32("which", &which) == B_OK) { + if (fAlertSem < B_OK) { + // Semaphore hasn't been created; we're running asynchronous + if (fInvoker) { + BMessage* out = fInvoker->Message(); + if (out && (out->ReplaceInt32("which", which) == B_OK + || out->AddInt32("which", which) == B_OK)) + fInvoker->Invoke(); + } + PostMessage(B_QUIT_REQUESTED); + } else { + // Created semaphore means were running synchronously + fAlertVal = which; + + // TextAlertVar does release_sem() below, and then sets the + // member var. That doesn't make much sense to me, since we + // want to be able to clean up at some point. Better to just + // nuke the semaphore now; we don't need it any more and this + // lets synchronous Go() continue just as well. + delete_sem(fAlertSem); + fAlertSem = -1; + } + } +} + + +void +BPAlert::FrameResized(float newWidth, float newHeight) +{ + BWindow::FrameResized(newWidth, newHeight); +} + + +BButton* +BPAlert::ButtonAt(int32 index) const +{ + if (index >= 0 && index < 3) + return fButtons[index]; + + return NULL; +} + + +BTextView* +BPAlert::TextView() const +{ + return fTextView; +} + + +BHandler* +BPAlert::ResolveSpecifier(BMessage* msg, int32 index, + BMessage* specifier, int32 form, const char* property) +{ + return BWindow::ResolveSpecifier(msg, index, specifier, form, property); +} + + +status_t +BPAlert::GetSupportedSuites(BMessage* data) +{ + return BWindow::GetSupportedSuites(data); +} + + +void +BPAlert::DispatchMessage(BMessage* msg, BHandler* handler) +{ + BWindow::DispatchMessage(msg, handler); +} + + +void +BPAlert::Quit() +{ + BWindow::Quit(); +} + + +bool +BPAlert::QuitRequested() +{ + return BWindow::QuitRequested(); +} + + +BPoint +BPAlert::AlertPosition(float width, float height) +{ + BPoint result(100, 100); + + BWindow* window = + dynamic_cast(BLooper::LooperForThread(find_thread(NULL))); + + BScreen screen(window); + BRect screenRect(0, 0, 640, 480); + if (screen.IsValid()) + screenRect = screen.Frame(); + + // Horizontally, we're smack in the middle + result.x = (screenRect.Width() / 2.0) - (width / 2.0); + + // This is probably sooo wrong, but it looks right on 1024 x 768 + result.y = (screenRect.Height() / 4.0) - ceil(height / 3.0); + + return result; +} + + +status_t +BPAlert::Perform(perform_code d, void* arg) +{ + return BWindow::Perform(d, arg); +} + + +void BPAlert::_ReservedAlert1() {} +void BPAlert::_ReservedAlert2() {} +void BPAlert::_ReservedAlert3() {} + + +void +BPAlert::InitObject(const char* text, const char* button0, const char* button1, + const char* button2, button_width width, button_spacing spacing, + BBitmap* icon) +{ + fInvoker = NULL; + fAlertSem = -1; + fAlertVal = -1; + fButtons[0] = fButtons[1] = fButtons[2] = NULL; + fTextView = NULL; + fKeys[0] = fKeys[1] = fKeys[2] = 0; + fIcon = icon; + fButtonWidth = width; + + // Set up the "_master_" view + TAlertView* masterView = new TAlertView(Bounds()); + AddChild(masterView); + masterView->SetBitmap(InitIcon()); + + // Must have at least one button + //if (button0 == NULL) { + // debugger("BPAlert's must have at least one button."); + // button0 = ""; + //} + + int kTextIconOffset = 0; + + //here xeD mod + if(masterView->Bitmap()) + kTextIconOffset = masterView->Bitmap()->Bounds().right + kTextIconOffsetSpace; + + BMessage ProtoMsg(kAlertButtonMsg); + ProtoMsg.AddInt32("which", 0); + // Set up the buttons + int buttonCount = 0; + fButtons[buttonCount] = new BButton(BRect(0, 0, 0, 0), "_b0_", button0, + new BMessage(ProtoMsg), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + masterView->AddChild(fButtons[buttonCount]); + if(button0==NULL) fButtons[buttonCount] ->Hide(); + + ++buttonCount; + + if (button1) { + ProtoMsg.ReplaceInt32("which", 1); + fButtons[buttonCount] = new BButton(BRect(0, 0, 0, 0), "_b1_", button1, + new BMessage(ProtoMsg), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + + masterView->AddChild(fButtons[buttonCount]); + ++buttonCount; + } + if (button2) { + ProtoMsg.ReplaceInt32("which", 2); + fButtons[buttonCount] = new BButton(BRect(0, 0, 0, 0), "_b2_", button2, + new BMessage(ProtoMsg), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + + masterView->AddChild(fButtons[buttonCount]); + ++buttonCount; + } + + SetDefaultButton(fButtons[buttonCount - 1]); + + // Find the widest button only if the widest value needs to be known. + float maxWidth = 0; + if (fButtonWidth == B_WIDTH_FROM_WIDEST) { + for (int i = 0; i < buttonCount; ++i) { + float temp = width_from_label(fButtons[i]); + maxWidth = max(maxWidth, temp); + } + } + + for (int i = buttonCount - 1; i >= 0; --i) { + // Determine the button's size + float buttonWidth = 0, buttonHeight = 0; + fButtons[i]->GetPreferredSize(&buttonWidth, &buttonHeight); + if (fButtonWidth == B_WIDTH_FROM_WIDEST) + buttonWidth = maxWidth; + else if (fButtonWidth == B_WIDTH_FROM_LABEL) + buttonWidth = width_from_label(fButtons[i]); + else // B_WIDTH_AS_USUAL + buttonWidth = max(buttonWidth, kButtonUsualWidth); + fButtons[i]->ResizeTo(buttonWidth, buttonHeight); + + // Determine the button's placement + float buttonX, buttonY; + buttonY = Bounds().bottom - buttonHeight; + if (i == buttonCount - 1) { + // The right-most button + buttonX = Bounds().right - fButtons[i]->Frame().Width() - + kButtonRightOffset; + buttonY -= kDefButtonBottomOffset; + + } else { + buttonX = fButtons[i + 1]->Frame().left - + fButtons[i]->Frame().Width() - kButtonSpaceOffset; + buttonY -= kButtonBottomOffset; + if (i == 0) { + if (spacing == B_OFFSET_SPACING) { + if (buttonCount == 3) + buttonX -= kButtonOffsetSpaceOffset; + else { + // If there are two buttons, the left wall of + // button0 needs to line up with the left wall + // of the TextView. + buttonX = (masterView->Bitmap()) ? + kTextIconOffset : kTextLeftOffset; + if (fButtons[i + 1]->Frame().left - + (buttonX + fButtons[i]->Frame().Width()) < + kButtonMinOffsetSpaceOffset) { + // Recompute buttonX using min offset space + // if using the current buttonX would not + // provide enough space or cause an overlap. + buttonX = fButtons[i + 1]->Frame().left - + fButtons[i]->Frame().Width() - + kButtonMinOffsetSpaceOffset; + } + } + } else if (buttonCount == 3) + buttonX -= 3; + } + } + + fButtons[i]->MoveTo(buttonX, buttonY); + } // for (int i = buttonCount - 1; i >= 0; --i) + + if(buttonCount - 1 >0){ + //relocate the 0 button + float y1=fButtons[0]->Frame().top -(fButtons[buttonCount - 1]->Frame().Height()/2.0) + (fButtons[0]->Frame().Height()/2.0); + fButtons[buttonCount - 1]->MoveTo(fButtons[buttonCount - 1]->Frame().left,y1); + + } + // Adjust the window's width, if necessary + float totalWidth = kButtonRightOffset; + totalWidth += fButtons[buttonCount - 1]->Frame().right - + fButtons[0]->Frame().left; + if (masterView->Bitmap()) + totalWidth += kIconStripeWidth + kWindowIconOffset; + else + totalWidth += kWindowMinOffset; + + if (spacing == B_OFFSET_SPACING) { + totalWidth -= 2; + if (buttonCount == 3) + totalWidth = max(kWindowOffsetMinWidth, totalWidth); + else + totalWidth = max(kWindowMinWidth, totalWidth); + } else { + totalWidth += 5; + totalWidth = max(kWindowMinWidth, totalWidth); + } + ResizeTo(totalWidth, Bounds().Height()); + + // Set up the text view + BRect TextViewRect(kTextLeftOffset, kTextTopOffset, + Bounds().right - kTextRightOffset, + Bounds().bottom - kTextBottomOffset); + if (masterView->Bitmap()) + TextViewRect.left = kTextIconOffset; + + fTextView = new BTextView(TextViewRect, "_tv_", TextViewRect, + B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW); + masterView->AddChild(fTextView); + + fTextView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + fTextView->SetText(text, strlen(text)); + fTextView->MakeEditable(false); + fTextView->MakeSelectable(false); + fTextView->SetWordWrap(true); + + // Now resize the TextView vertically so that all the text is visible + float textHeight = fTextView->TextHeight(0, fTextView->CountLines()); + TextViewRect.OffsetTo(0, 0); + textHeight -= TextViewRect.Height(); + ResizeBy(0, textHeight); + fTextView->ResizeBy(0, textHeight); + TextViewRect.bottom += textHeight; + fTextView->SetTextRect(TextViewRect); + + AddCommonFilter(new _BPAlertFilter_(this)); + + MoveTo(AlertPosition(Frame().Width(), Frame().Height())); +} + + +BBitmap* +BPAlert::InitIcon() +{ return fIcon; } + + +//------------------------------------------------------------------------------ +// #pragma mark - TAlertView + + +TAlertView::TAlertView(BRect frame) + : BView(frame, "TAlertView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW), + fIconBitmap(NULL) +{ + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); +} + + +TAlertView::TAlertView(BMessage* archive) + : BView(archive), + fIconBitmap(NULL) +{ +} + + +TAlertView::~TAlertView(){} + + +TAlertView* +TAlertView::Instantiate(BMessage* archive) +{ + if (!validate_instantiation(archive, "TAlertView")) + return NULL; + + return new TAlertView(archive); +} + + +status_t +TAlertView::Archive(BMessage* archive, bool deep) +{ + return BView::Archive(archive, deep); +} + + +void +TAlertView::Draw(BRect updateRect) +{ + // Here's the fun stuff + if (fIconBitmap) { + BRect StripeRect = Bounds(); + StripeRect.right = kIconStripeWidth; + SetHighColor(tint_color(ViewColor(), B_DARKEN_1_TINT)); + FillRect(StripeRect); + + //SetDrawingMode(B_OP_OVER); + SetDrawingMode(B_OP_ALPHA); + DrawBitmapAsync(fIconBitmap, BPoint(18, 6)); + SetDrawingMode(B_OP_COPY); + } +} + + +//------------------------------------------------------------------------------ +// #pragma mark - _BPAlertFilter_ + + +_BPAlertFilter_::_BPAlertFilter_(BPAlert* Alert) + : BMessageFilter(B_KEY_DOWN), + fAlert(Alert) +{ +} + + +_BPAlertFilter_::~_BPAlertFilter_() +{ +} + + +filter_result +_BPAlertFilter_::Filter(BMessage* msg, BHandler** target) +{ + if (msg->what == B_KEY_DOWN) { + char byte; + if (msg->FindInt8("byte", (int8*)&byte) == B_OK) { + for (int i = 0; i < 3; ++i) { + if (byte == fAlert->Shortcut(i) && fAlert->ButtonAt(i)) { + char space = ' '; + fAlert->ButtonAt(i)->KeyDown(&space, 1); + + return B_SKIP_MESSAGE; + } + } + } + } + + return B_DISPATCH_MESSAGE; +} diff --git a/sources-experimental/BPAlert.h b/sources-experimental/BPAlert.h new file mode 100644 index 0000000..31136a8 --- /dev/null +++ b/sources-experimental/BPAlert.h @@ -0,0 +1,119 @@ +/******************************************************************************* +/ +/ File: Alert.h +/ +/ Description: BPAlert displays a modal alert window. +/ +/ Copyright 1993-98, Be Incorporated, All Rights Reserved +/ +*******************************************************************************/ + +#ifndef _ALERT_H +#define _ALERT_H + +#include +#include + +class BBitmap; +class BButton; +class BInvoker; +class BTextView; + +enum button_spacing { + B_EVEN_SPACING = 0, + B_OFFSET_SPACING +}; + +/*----------------------------------------------------------------*/ +/*----- BPAlert class ---------------------------------------------*/ + +class BPAlert : public BWindow +{ +public: + + BPAlert( const char *title, + const char *text, + const char *button1, + const char *button2 = NULL, + const char *button3 = NULL, + button_width width = B_WIDTH_AS_USUAL, + BBitmap* icon = NULL); + BPAlert( const char *title, + const char *text, + const char *button1, + const char *button2, + const char *button3, + button_width width, + button_spacing spacing, + BBitmap* type = NULL); +virtual ~BPAlert(); + +/* Archiving */ + BPAlert(BMessage *data); +static BArchivable *Instantiate(BMessage *data); +virtual status_t Archive(BMessage *data, bool deep = true) const; + +/* BPAlert guts */ + void SetShortcut(int32 button_index, char key); + char Shortcut(int32 button_index) const; + + int32 Go(); + status_t Go(BInvoker *invoker); + +virtual void MessageReceived(BMessage *an_event); +virtual void FrameResized(float new_width, float new_height); + BButton *ButtonAt(int32 index) const; + BTextView *TextView() const; + +virtual BHandler *ResolveSpecifier(BMessage *msg, + int32 index, + BMessage *specifier, + int32 form, + const char *property); +virtual status_t GetSupportedSuites(BMessage *data); + +virtual void DispatchMessage(BMessage *msg, BHandler *handler); +virtual void Quit(); +virtual bool QuitRequested(); + +static BPoint AlertPosition(float width, float height); + +/*----- Private or reserved -----------------------------------------*/ +virtual status_t Perform(perform_code d, void *arg); + +private: +friend class _BPAlertFilter_; + +virtual void _ReservedAlert1(); +virtual void _ReservedAlert2(); +virtual void _ReservedAlert3(); + + void InitObject(const char *text, + const char *button1, + const char *button2 = NULL, + const char *button3 = NULL, + button_width width = B_WIDTH_AS_USUAL, + button_spacing spacing = B_EVEN_SPACING, + BBitmap* icon = NULL); + BBitmap *InitIcon(); + + sem_id fAlertSem; + int32 fAlertVal; + BButton *fButtons[3]; + BTextView *fTextView; + char fKeys[3]; + BBitmap* fIcon; + button_width fButtonWidth; + BInvoker *fInvoker; + uint32 _reserved[4]; +}; + +/*-------------------------------------------------------------*/ +/*-------------------------------------------------------------*/ + +// functions to display HTML alerts with Opera + +status_t TellTellBrowser(BMessage*m); +status_t TellTellBrowser(BMessage*m,BMessage*r); + +#endif /* _ALERT_H */ diff --git a/sources-experimental/BPEpisode.cpp b/sources-experimental/BPEpisode.cpp new file mode 100644 index 0000000..5641526 --- /dev/null +++ b/sources-experimental/BPEpisode.cpp @@ -0,0 +1,37 @@ +#include "BPEpisode.h" +#include "Utils.h" +#include "AttributeMap.h" + + +BPEpisode::BPEpisode(entry_ref* ref):BNode(ref){ +} + +FileStatus +BPEpisode::GetStatus(){ + return (FileStatus)ReadAttributeInt32(this,ATTR_ITEM_STATUS); +} + +void +BPEpisode::SetStatus(FileStatus status){ + WriteAttributeInt32(this,ATTR_ITEM_STATUS,(int32)status); + NotifyListener(ITEM_ENCLOSURE_FILE_STATUS,(void*)&status,sizeof(status)); +} + +BString +BPEpisode::EnclosureLocalPath(){ + return ReadAttributeString(this,ATTR_ENCLOSURE_PATH); +} + +BString +BPEpisode::EnclosureLink(){ + return ReadAttributeString(this,ATTR_ENCLOSURE_URL); +} + +BString +BPEpisode::Guid(){ + return ReadAttributeString(this,ATTR_ITEM_GUID); +} +BString +BPEpisode::EnclosureType(){ + return ReadAttributeString(this,ATTR_ENCLOSURE_TYPE); +} diff --git a/sources-experimental/BPEpisode.h b/sources-experimental/BPEpisode.h new file mode 100644 index 0000000..5f22e63 --- /dev/null +++ b/sources-experimental/BPEpisode.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2007 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef BPEpisode_H_ +#define BPEpisode_H_ + +#include + +#include "Extractor.h" +#include "FileStatus.h" +#include "Notifier.h" + +class BPEpisode : public BNode , public Notifier { + + public: + BPEpisode(entry_ref*); + + FileStatus GetStatus(); + void SetStatus(FileStatus); //NOTIFY! + + BString EnclosureLocalPath(); + BString EnclosureLink(); + BString Guid(); + BString EnclosureType(); + +}; +#endif diff --git a/sources-experimental/BPLocale.h b/sources-experimental/BPLocale.h new file mode 100644 index 0000000..82c9c43 --- /dev/null +++ b/sources-experimental/BPLocale.h @@ -0,0 +1,19 @@ +#ifndef _BPLocale_H +#define _BPLocale_H + +#ifdef ZETA + #include + #ifndef _TT + #define _TT(A) _T(A) + #endif +#else + #ifndef _T + #include "R5Locale.h" + #define _TT(A) findKey(A) + #define _T(A) A + #endif +#endif + +#endif + +//end. diff --git a/sources-experimental/BPSettingsWindow.cpp b/sources-experimental/BPSettingsWindow.cpp new file mode 100644 index 0000000..ba17a37 --- /dev/null +++ b/sources-experimental/BPSettingsWindow.cpp @@ -0,0 +1,275 @@ +#include "BPSettingsWindow.h" +#include "SettingsTextView.h" + +#include +#include +#include "BPLocale.h" +#include +#include +#include +#include +#include "PBox.h" +#include +#include "Setting.h" +extern Setting podder_settings; + +//#include "LicenceInfo.h" +//extern LicenceInfo linfo; + + +BPSettingsWindow::BPSettingsWindow() : + SettingsWindow(&podder_settings,be_app,APPLY_SETTINGS) +{ + + BMessage data; + + podder_settings.FindMessage(SETTINGS_FILETYPE,&data); + BBox* abox = CreateFileTypeBox(data); + AddBox(_T("FileType") ,abox); + data.MakeEmpty(); + + + podder_settings.FindMessage(SETTINGS_CHANNELS,&data); + //if(!linfo.Valid()) data.MakeEmpty(); + abox = CreateChannelsBox(data); + AddBox(_T("Channels"), abox); + //if(!linfo.Valid()) { FillOfValue(abox); FixLabel(abox); } + data.MakeEmpty(); + + //downloads + podder_settings.FindMessage(SETTINGS_DOWNLOAD,&data); + //if(!linfo.Valid()) data.MakeEmpty(); + abox = CreateDownloadBox(data); + AddBox(_T("Download"),abox); + //if(!linfo.Valid()) { FillOfValue(abox); FixLabel(abox); } + data.MakeEmpty(); + + // Proxy + podder_settings.FindMessage(SETTINGS_PROXY,&data); + //if(!linfo.Valid()) data.MakeEmpty(); + abox = CreateProxyBox(data); + AddBox(_T("Proxy"), abox); + //if(!linfo.Valid()) { FillOfValue(abox); FixLabel(abox); } + data.MakeEmpty(); + + // Updates + podder_settings.FindMessage(SETTINGS_UPDATES,&data); + abox = CreateUpdateBox(data); + AddBox(_T("Updates"), abox); + data.MakeEmpty(); + + + //slist->Select(0); + Select(0); + +} + + +void +BPSettingsWindow::FillOfValue(BView* box){ //this name is fake! ;) + int32 count = box->CountChildren(); + for(int i=0;iChildAt(i)); + + if(dynamic_cast(box)) + (dynamic_cast(box))->SetEnabled(false); + + if(dynamic_cast(box)) + (dynamic_cast(box))->SetEnabled(false); +} + +void +BPSettingsWindow::FixLabel(BView* box){ //this name is fake! :p + BView* child = box->FindView("pbox_title"); + + if(!child) + return; + SettingsTextView* stw=dynamic_cast(child); + if(!stw) return; + + BString text = stw->Text(); + text << " " << _T("(only in registred version!)"); + + stw->SetText(text.String()); + +} +BBox* +BPSettingsWindow::CreateGeneralBox(BMessage data){ + /* + BMessage main_msg; + + BMessage num_download; + num_download.AddString("name","starton_workspace"); + num_download.AddString("description", _T("Max Downloads")); + num_download.AddInt32("type",B_INT32_TYPE); + num_download.AddInt32("valid_value",1); + num_download.AddInt32("valid_value",2); + num_download.AddInt32("valid_value",3); + num_download.AddInt32("valid_value",4); + num_download.AddInt32("valid_value",5); + num_download.AddInt32("default", 1); + + main_msg.AddMessage("setting", &num_download); + main_msg.AddString("name",_T("Downloads")); + + + PBox *proxy=new PBox(dxrect,main_msg,data,SETTINGS_ GENERAL); + return (BBox*)proxy;*/ + return NULL; +} + +BBox* +BPSettingsWindow::CreateUpdateBox(BMessage data) { + BMessage main_msg; + BMessage setting; + setting.AddString("name","check_updates"); + setting.AddString("description", _T("Check for updates at startup")); + setting.AddInt32("type",B_BOOL_TYPE); + setting.AddBool("default", true); + + main_msg.AddMessage("setting", &setting); + main_msg.AddString("name",_T("Updates")); + + PBox *proxy=new PBox(BRect(0,0,0,0),main_msg,data,SETTINGS_UPDATES); + return (BBox*)proxy; +} + +BBox* +BPSettingsWindow::CreateDownloadBox(BMessage data){ + + BMessage main_msg; + + BMessage num_download; + num_download.AddString("name","max_downloads"); + num_download.AddString("description", _T("Max Downloads")); + num_download.AddInt32("type",B_INT32_TYPE); + num_download.AddInt32("valid_value",1); + num_download.AddInt32("valid_value",2); + num_download.AddInt32("valid_value",3); + num_download.AddInt32("valid_value",4); + num_download.AddInt32("valid_value",5); + num_download.AddInt32("default", 1); + + main_msg.AddMessage("setting", &num_download); + main_msg.AddString("name",_T("Downloads")); + + + PBox *proxy=new PBox(BRect(0,0,0,0),main_msg,data,SETTINGS_DOWNLOAD); + return (BBox*)proxy; +} + + +BBox* +BPSettingsWindow::CreateFileTypeBox(BMessage data){ + + // ATTENZIONE NON CAMBIARE QUESTI SETTATGGI + // SE NON SI MODIFICANO LE RISPETTIVE CLASSI DI LOAD_SETTIINGS + + BMessage setting; + setting.AddString("name","browser"); + setting.AddString("description", _T("Browser")); + setting.AddInt32("type",B_STRING_TYPE); + setting.AddString("valid_value","Firefox"); //0 + setting.AddString("valid_value","NetPositive"); //1 + setting.AddString("valid_value","System Default"); //2 + setting.AddString("default", "NetPositive"); + + BMessage setting2; + setting2.AddString("name","player"); + setting2.AddString("description", _T("Player")); + setting2.AddInt32("type",B_STRING_TYPE); + setting2.AddString("valid_value","MediaPlayer"); + setting2.AddString("valid_value","SoundPlay"); + setting2.AddString("valid_value","VideoLAN"); + setting2.AddString("valid_value","Auto"); + setting2.AddString("default", "Auto"); + + BMessage main_msg; + main_msg.AddMessage("setting", &setting); + main_msg.AddMessage("setting", &setting2); + + main_msg.AddString("name",_T("FileType")); + + + PBox *proxy=new PBox(BRect(0,0,0,0),main_msg,data,SETTINGS_FILETYPE); + return (BBox*)proxy; +} + +BBox* +BPSettingsWindow::CreateChannelsBox(BMessage data){ + + BMessage setting; + setting.AddString("name","check_startup"); + setting.AddString("description", _T("Check all channels on startup")); + setting.AddInt32("type",B_BOOL_TYPE); + + BMessage setting2; + setting2.AddString("name","check_time"); + setting2.AddString("description", _T("Check the channel every")); + setting2.AddInt32("type",B_STRING_TYPE); + setting2.AddString("valid_value",_T("never")); + setting2.AddString("valid_value",_T("5 minutes")); + setting2.AddString("valid_value",_T("15 minutes")); + setting2.AddString("valid_value",_T("30 minutes")); + setting2.AddString("valid_value",_T("1 hour")); + setting2.AddString("valid_value",_T("2 hour")); + setting2.AddString("default", _T("never")); + + BMessage main_msg; + main_msg.AddMessage("setting", &setting); + main_msg.AddMessage("setting", &setting2); + main_msg.AddString("name",_T("Channels")); + + + PBox *proxy=new PBox(BRect(0,0,0,0),main_msg,data,SETTINGS_CHANNELS); + return (BBox*)proxy; +} + +BBox* +BPSettingsWindow::CreateProxyBox(BMessage data){ + + BMessage main_msg; + + BMessage enable_proxy; + enable_proxy.AddString("name","enable"); + enable_proxy.AddString("description", _T("Enable Proxy")); + enable_proxy.AddInt32("type",B_BOOL_TYPE); + enable_proxy.AddString("enable_control","address"); + enable_proxy.AddString("enable_control","port"); + enable_proxy.AddString("enable_control","username"); + enable_proxy.AddString("enable_control","password"); + + BMessage address; + address.AddString("name","address"); + address.AddString("description", _T("Address")); + address.AddInt32("type",B_STRING_TYPE); + + BMessage port; + port.AddString("name","port"); + port.AddString("description", _T("Port")); + port.AddInt32("type",B_INT32_TYPE); + + BMessage res; + res.AddString("name","username"); + res.AddString("description", _T("Username")); + res.AddInt32("type",B_STRING_TYPE); + + BMessage year; + year.AddString("name","password"); + year.AddString("description", _T("Password")); + year.AddInt32("type",B_STRING_TYPE); + year.AddBool("is_secret",true); + + main_msg.AddMessage("setting", &enable_proxy); + main_msg.AddMessage("setting", &address); + main_msg.AddMessage("setting", &port); + main_msg.AddMessage("setting", &res); + main_msg.AddMessage("setting", &year); + main_msg.AddString("name",_T("Proxy")); + + + PBox *proxy=new PBox(BRect(0,0,0,0),main_msg,data,SETTINGS_PROXY); + + return (BBox*)proxy; +} + diff --git a/sources-experimental/BPSettingsWindow.h b/sources-experimental/BPSettingsWindow.h new file mode 100644 index 0000000..1822033 --- /dev/null +++ b/sources-experimental/BPSettingsWindow.h @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SettingsWindow.h" + +#define SETTINGS_MAINWINDOW "main_window_setting" +#define SETTINGS_FILETYPE "filetype_setting" +#define SETTINGS_PROXY "proxy_setting" +#define SETTINGS_DOWNLOAD "download_setting" +#define SETTINGS_CHANNELS "channels_setting" +#define SETTINGS_GENERAL "general_setting" +#define SETTINGS_UPDATES "updates_setting" + +#define SETTINGS_GROUPS "groups_setting" + + +class BPSettingsWindow: public SettingsWindow +{ + + + + + public: + BPSettingsWindow(); + + + + + + private: + + + + BBox* CreateGeneralBox(BMessage); + BBox* CreateFileTypeBox(BMessage); + BBox* CreateChannelsBox(BMessage); + BBox* CreateProxyBox(BMessage); + BBox* CreateDownloadBox(BMessage); + + BBox* CreateUpdateBox(BMessage); + + + + void FillOfValue(BView*); //this name is fake! ;) + void FixLabel(BView*); //this name is fake! :p + }; diff --git a/sources-experimental/BitmapTextRender.h b/sources-experimental/BitmapTextRender.h new file mode 100644 index 0000000..1d7ef16 --- /dev/null +++ b/sources-experimental/BitmapTextRender.h @@ -0,0 +1,92 @@ +#ifndef _BitmapTextRender_H_ +#define _BitmapTextRender_H_ + +#include "TextRender.h" +#include "Bitmap.h" +#include +#include + +#include +#include +#include +#include + + +#define kIconSpace 3.0 + +/* + ATTENZIONE + + This class owns the Bitmap pointer! + It deletes the pointer as soon as you change it or you set it to NULL. + +*/ + +class BitmapTextRender : public TextRender +{ + public: + + BitmapTextRender():TextRender(){ + fHeight = 0; + fWidth = 0; + fBitmap=NULL; + }; + + void LoadBitmap(const char* filename){ + if(fBitmap!=NULL) delete fBitmap; + + + if(filename!=NULL) + fBitmap = BTranslationUtils::GetBitmap(filename); + else + fBitmap = NULL; + + if(fBitmap){ + fHeight = fBitmap->Bounds().Height(); + fWidth = fBitmap->Bounds().Width(); + } + else { + fHeight = 0; + fWidth = 0; + } + + } + + virtual ~BitmapTextRender() {}; + + void Render(BView *target,const char* txt,int16 num,BPoint pos,BRect r) { + + if(!fBitmap) return; + + target->SetDrawingMode( B_OP_ALPHA ); + target->DrawBitmapAsync( fBitmap,BPoint(r.left + kIconSpace, r.top )); + //target->DrawBitmapAsync( pointer,BPoint(r.left + kIconSpace, r.top + ((r.Height()/2.0) - 8) )); //- fHeight + (fHeight/4) + 2) + target->StrokeRect(r); + target->SetDrawingMode( B_OP_OVER ); + }; + + + + + float Size(float maxwidth){ return fWidth + 1 + kIconSpace + kIconSpace;} + + void GetHeight(font_height *h){ + h->ascent=fHeight/2; + h->descent=fHeight/2; + h->leading=0; + }; + + void + GetEscapements(const char * /*charArray*/, int32 numChars,float escapementArray[]) { + escapementArray[0]=1; + for(int i=1;iMakeFocus(true); + } + private: + BBitmap* fMap; +}; + +#endif +//--- diff --git a/sources-experimental/BitmapWindow.cpp b/sources-experimental/BitmapWindow.cpp new file mode 100644 index 0000000..9c11762 --- /dev/null +++ b/sources-experimental/BitmapWindow.cpp @@ -0,0 +1,24 @@ +#include "BitmapWindow.h" + +#include "Utils.h" +#include +#include "BPLocale.h" +#include "BitmapView.h" + +BitmapWindow::BitmapWindow(BBitmap* image) : + BWindow(BRect(162,50,848,700),_T("Channel Image"), B_TITLED_WINDOW,B_NOT_RESIZABLE| B_NOT_ZOOMABLE|B_ASYNCHRONOUS_CONTROLS|B_WILL_DRAW) +{ + ResizeTo(image->Bounds().Width(),image->Bounds().Height()); + AddChild(new BitmapView(image->Bounds(),image)); +} + + +//bool +//BitmapWindow::QuitRequested(){ +// return true; +//} + + + + + diff --git a/sources-experimental/BitmapWindow.h b/sources-experimental/BitmapWindow.h new file mode 100644 index 0000000..1365a1f --- /dev/null +++ b/sources-experimental/BitmapWindow.h @@ -0,0 +1,13 @@ +#include "Application.h" +#include +#include +#include + +class BitmapWindow: public BWindow +{ + + + public: + BitmapWindow(BBitmap* image); +// bool QuitRequested(); +}; diff --git a/sources-experimental/ChannelSettingsWindow.cpp b/sources-experimental/ChannelSettingsWindow.cpp new file mode 100644 index 0000000..187bcce --- /dev/null +++ b/sources-experimental/ChannelSettingsWindow.cpp @@ -0,0 +1,83 @@ +#include "ChannelSettingsWindow.h" +#include "SettingsTextView.h" + +#include +#include +#include "BPLocale.h" +#include +#include +#include +#include +#include "PBox.h" +#include + + + +ChannelSettingsWindow::ChannelSettingsWindow(BMessage* s,BHandler* h) : + SettingsWindow(s,h,APPLY_CHANNEL_SETTINGS) { + + AddBox(_T("Remove") ,CreateBox(*s)); + Select(0); +} + + + + +BBox* +ChannelSettingsWindow::CreateBox(BMessage data) { + BMessage main_msg; + + BMessage when; + when.AddString("name","when_delete"); + when.AddString("description", _T("WHEN?")); + when.AddInt32("type",B_STRING_TYPE); + when.AddString("valid_value","never"); //0 + when.AddString("valid_value","After a chek"); //1 + when.AddString("valid_value","When there are new episodes"); //2 + when.AddString("valid_value","System Default"); //3 + when.AddString("default", "never"); + + main_msg.AddMessage("setting", &when); + + + BMessage what_new; + what_new.AddString("name","what_delete_new"); + what_new.AddString("description", _T("Episodes nuovi")); + what_new.AddInt32("type",B_BOOL_TYPE); + what_new.AddBool("default", false); + main_msg.AddMessage("setting", &what_new); + + + what_new.MakeEmpty(); + what_new.AddString("name","what_delete_read"); + what_new.AddString("description", _T("Episodes letti (o con errore)")); + what_new.AddInt32("type",B_BOOL_TYPE); + what_new.AddBool("default", false); + main_msg.AddMessage("setting", &what_new); + + what_new.MakeEmpty(); + what_new.AddString("name","what_delete_downloaded"); + what_new.AddString("description", _T("Episodes scaricati")); + what_new.AddInt32("type",B_BOOL_TYPE); + what_new.AddBool("default", false); + main_msg.AddMessage("setting", &what_new); + + + BMessage who; + who.AddString("name","who_delete"); + who.AddString("description", _T("WHO?")); + who.AddInt32("type",B_STRING_TYPE); + who.AddString("valid_value","Tutti gli episodes presenti"); //0 + who.AddString("valid_value","Episodes piu vecchi di 1 giorno"); //1 + who.AddString("valid_value","Episodes piu vecchi di 3 giorni"); //2 + who.AddString("valid_value","Episodes piu vecchi di 1 settimana"); //3 + who.AddString("valid_value","Episodes piu vecchi di 1 mese"); //4 + who.AddString("default", "Tutti gli episodes presenti"); + + main_msg.AddMessage("setting", &who); + + main_msg.AddString("name",_T("Remove")); + PBox *proxy=new PBox(BRect(0,0,0,0),main_msg,data,SETTINGS_CHANNEL); + return (BBox*)proxy; +} + diff --git a/sources-experimental/ChannelSettingsWindow.h b/sources-experimental/ChannelSettingsWindow.h new file mode 100644 index 0000000..7e0622c --- /dev/null +++ b/sources-experimental/ChannelSettingsWindow.h @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SettingsWindow.h" + +#define SETTINGS_CHANNEL "channel_setting" +#define APPLY_CHANNEL_SETTINGS 'achs' + +class ChannelSettingsWindow: public SettingsWindow +{ + + + + + public: + ChannelSettingsWindow(BMessage*,BHandler*); + + + + + + private: + + + + BBox* CreateBox(BMessage); + }; diff --git a/sources-experimental/Cursors.cpp b/sources-experimental/Cursors.cpp new file mode 100644 index 0000000..144c297 --- /dev/null +++ b/sources-experimental/Cursors.cpp @@ -0,0 +1,167 @@ +//****************************************************************************************************** +//**** PROJECT HEADER FILES +//****************************************************************************************************** +#include "Cursors.h" + + +//****************************************************************************************************** +//**** CONSTANT DEFINITIONS +//****************************************************************************************************** +uint8 c_v_resize_cursor_data[68] = +{ + 16,1,7,7, + 0,0, //0000000000000000 + 1,0, //0000000100000000 + 1,0, //0000000100000000 + 1,0, //0000000100000000 + 1,0, //0000000100000000 + 17,16, //0001000100010000 + 49,24, //0011000100011000 + 113,28, //0111000100011100 + 49,24, //0011000100011000 + 17,16, //0001000100010000 + 1,0, //0000000100000000 + 1,0, //0000000100000000 + 1,0, //0000000100000000 + 1,0, //0000000100000000 + 0,0, //0000000000000000 + 0,0, //0000000000000000 + + 3,128, //0000001110000000 + 3,128, //0000001110000000 + 3,128, //0000001110000000 + 3,128, //0000001110000000 + 27,176, //0001101110110000 + 59,184, //0011101110111000 + 123,188,//0111101110111100 + 251,190,//1111101110111110 + 123,188,//0111101110111100 + 59,184, //0011101110111000 + 27,176, //0001101110110000 + 3,128, //0000001110000000 + 3,128, //0000001110000000 + 3,128, //0000001110000000 + 3,128, //0000001110000000 + 0,0 //0000000000000000 +}; + +uint8 c_h_resize_cursor_data[68] = +{ + 16,1,7,7, + 0,0, //0000000000000000 + 1,0, //0000000100000000 + 3,128, //0000001110000000 + 7,192, //0000011111000000 + 0,0, //0000000000000000 + 0,0, //0000000000000000 + 0,0, //0000000000000000 + 127,252,//0111111111111100 + 0,0, //0000000000000000 + 0,0, //0000000000000000 + 0,0, //0000000000000000 + 7,192, //0000011111000000 + 3,128, //0000001110000000 + 1,0, //0000000100000000 + 0,0, //0000000000000000 + 0,0, //0000000000000000 + + 1,0, //0000000100000000 + 3,128, //0000001110000000 + 7,192, //0000011111000000 + 15,224, //0000111111100000 + 15,224, //0000111111100000 + 0,0, //0000000000000000 + 255,254,//1111111111111110 + 255,254,//1111111111111110 + 255,254,//1111111111111110 + 0,0, //0000000000000000 + 15,224, //0000111111100000 + 15,224, //0000111111100000 + 7,192, //0000011111000000 + 3,128, //0000001110000000 + 1,0, //0000000100000000 + 0,0 //0000000000000000 +}; + +/* +uint8 c_crosshairs_cursor_data[68] = +{ + 16,1,7,7, + 0,0, //0000000000000000 + 1,0, //0000000100000000 + 1,0, //0000000100000000 + 1,0, //0000000100000000 + 1,0, //0000000100000000 + 1,0, //0000000100000000 + 0,0, //0000000000000000 + 125,124,//0111110101111100 + 0,0, //0000000000000000 + 1,0, //0000000100000000 + 1,0, //0000000100000000 + 1,0, //0000000100000000 + 1,0, //0000000100000000 + 1,0, //0000000100000000 + 0,0, //0000000000000000 + 0,0, //0000000000000000 + + 3,128, //0000001110000000 + 3,128, //0000001110000000 + 3,128, //0000001110000000 + 3,128, //0000001110000000 + 3,128, //0000001110000000 + 3,128, //0000001110000000 + 255,254,//1111111111111110 + 255,254,//1111111111111110 + 255,254,//1111111111111110 + 3,128, //0000001110000000 + 3,128, //0000001110000000 + 3,128, //0000001110000000 + 3,128, //0000001110000000 + 3,128, //0000001110000000 + 3,128, //0000001110000000 + 0,0 //0000000000000000 +}; + +uint8 c_magnify_cursor_data[68] = +{ + 16,1,6,6, + 0,0, //0000000000000000 + 7,0, //0000011100000000 + 24,192, //0001100011000000 + 32,32, //0010000000100000 + 32,32, //0010000000100000 + 64,16, //0100000000010000 + 64,16, //0100000000010000 + 64,16, //0100000000010000 + 32,32, //0010000000100000 + 32,32, //0010000000100000 + 24,240, //0001100011110000 + 7,56, //0000011100111000 + 0,28, //0000000000011100 + 0,14, //0000000000001110 + 0,4, //0000000000000100 + 0,0, //0000000000000000 + + 7,0, //0000011100000000 + 31,192, //0001111111000000 + 63,224, //0011111111100000 + 120,240,//0111100011110000 + 112,112,//0111000001110000 + 224,56, //1110000000111000 + 224,56, //1110000000111000 + 224,56, //1110000000111000 + 112,112,//0111000001110000 + 120,240,//0111100011110000 + 63,248, //0011111111111000 + 31,252, //0001111111111100 + 7,62, //0000011100111110 + 0,31, //0000000000011111 + 0,14, //0000000000001110 + 0,4, //0000000000000100 +}; +*/ +const void* c_v_resize_cursor = c_v_resize_cursor_data; +const void* c_h_resize_cursor = c_h_resize_cursor_data; +//const void* c_crosshairs_cursor = c_crosshairs_cursor_data; +//const void* c_magnify_cursor = c_magnify_cursor_data; + diff --git a/sources-experimental/Cursors.h b/sources-experimental/Cursors.h new file mode 100644 index 0000000..8053187 --- /dev/null +++ b/sources-experimental/Cursors.h @@ -0,0 +1,20 @@ +#ifndef _SGB_CURSORS_H_ +#define _SGB_CURSORS_H_ + + +//****************************************************************************************************** +//**** SYSTEM HEADER FILES +//****************************************************************************************************** +#include + + +//****************************************************************************************************** +//**** CONSTANT DEFINITIONS +//****************************************************************************************************** +extern const void* c_v_resize_cursor; +extern const void* c_h_resize_cursor; +//extern const void* c_crosshairs_cursor; +//extern const void* c_magnify_cursor; + + +#endif //_SGB_CURSORS_H_ diff --git a/sources-experimental/DirectoryItem.h b/sources-experimental/DirectoryItem.h new file mode 100644 index 0000000..392be01 --- /dev/null +++ b/sources-experimental/DirectoryItem.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#define DirectoryItem_H_ +#define DirectoryItem_H_ + +#include "IconTextItem.h" + +class DirectoryItem : public IconTextItem { + + public: + DirectoryItem(const char *text, BBitmap *icon = NULL,const char *linkz = NULL,BPoint spiaz=BPoint(0,0)) + :IconTextItem(text,icon) + { fLink.SetTo(linkz); SetSpiaz(spiaz); } + + BString Link(){ return fLink; } + private: + BString fLink; + + +}; diff --git a/sources-experimental/DirectoryWindow.cpp b/sources-experimental/DirectoryWindow.cpp new file mode 100644 index 0000000..22a79cf --- /dev/null +++ b/sources-experimental/DirectoryWindow.cpp @@ -0,0 +1,460 @@ + +#include "DirectoryWindow.h" +#include "Utils.h" +#include +#include +#include "BPLocale.h" +#include + +#include "DirectoryItem.h" +#include +#include +#include + +#include "Logger.h" +#include "Utils.h" + +static BBitmap* fItemIcon; +static BBitmap* fFolderIcon; //? +extern BMessage Directory_list; //? + + +#include "MainWindow.h" +extern MainWindow* main_window; + + +#include "BPLocale.h" + +//generic map + +#include +#include "Utils.h" + +#include "ActionDownload.h" +#include "DownloadManager.h" + +#include "PercentageWindow.h" + +extern DownloadManager download_manager; + +static KeyMap fDirectoryTrees; + +#define back_color 101,154,206,255 + +DirectoryWindow::DirectoryWindow(const char* opml_name,BString opml_url): + BWindow(BRect(350,100,750,700),opml_name, B_TITLED_WINDOW,B_ASYNCHRONOUS_CONTROLS) +{ + fAlert = NULL; + + SetSizeLimits(400,1280,150,1024); + + fOpmlName.SetTo( opml_name); + fOpmlURL = opml_url; + + + if(fFolderIcon == NULL) + fFolderIcon = LoadIcon("folder"); + + if(fItemIcon == NULL) + fItemIcon= LoadIcon("02.png"); + + BBox *bgbox=new BBox(Bounds(),"back",B_FOLLOW_ALL,B_WILL_DRAW,B_PLAIN_BORDER); + AddChild(bgbox); + + alist=new BOutlineListView(BRect(15,15,370,530), "ListView1",B_SINGLE_SELECTION_LIST,B_FOLLOW_ALL,B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE); + + + // (240,240,129); + + alist->SetLowColor(back_color); //101,154,206); + alist->SetViewColor(back_color); //101,154,206); //53,140,42) 101,154,206 + alist->SetHighColor(0,0,0); + alist->SetFontSize(12); + + + bgbox->AddChild(new BScrollView("PodcastScroll", alist, B_FOLLOW_ALL, 0, false, true)); + + BBox *viewd=new BBox(BRect(20,551,390,600),NULL, B_FOLLOW_BOTTOM | B_FOLLOW_RIGHT,B_WILL_DRAW,B_NO_BORDER); + bgbox->AddChild(viewd); + + + BButton *button1= new BButton(BRect(0,0,100,30),"noname",_T("Collapse All"),new BMessage('refr'), B_FOLLOW_ALL); + viewd->AddChild(button1); +#ifdef ZETA + button1->SetToolTipText(_T("Collapse all categories in the directory list")); +#endif + /*BButton *button2= new BButton(BRect(130,0,230,30),"noname",_T("Preview"),new BMessage('prev'), B_FOLLOW_ALL); + viewd->AddChild(button2); +#ifdef ZETA + button2->SetToolTipText(_T("Checkout a podcast before downloading it")); +#endif */ + BButton *button3= new BButton(BRect(260,0,360,30),"noname",_T("Subscribe"),new BMessage('subs'), B_FOLLOW_ALL); + viewd->AddChild(button3); +#ifdef ZETA + button3->SetToolTipText(_T("Add the selected podcast to the Subscription list")); +#endif + alist->SetInvocationMessage(new BMessage('invo')); + + PostMessage('refr'); +} + +void +DirectoryWindow::StartDownload(BString url){ + + //show the alert + fAlert= new PercentageWindow("BePodder",_T("Downloading"), LoadIcon("enqueued-32.png")); + fAlert->Go(this,B_QUIT_REQUESTED); + entry_ref dest; + get_ref_for_path(tmpnam(NULL),&dest); + ActionDownload* action = new ActionDownload(url,dest, false, "", this,'info'); + + download_manager.SingleThreadAction(action); +} + +/*void +DirectoryWindow::~DirectoryWindow(){ + + OPMLParser parser; + while(fDirectoryTrees.CountItems()) + { + OPMLTree tree=fDirectoryTrees.ValueAt(0); + parser. + RemoveItemsAt(0); + } + +}*/ + +void +DirectoryWindow::MessageReceived(BMessage *mess2){ + + switch(mess2->what){ + case 'info': + DownloadInfo(mess2); + break; + case 'refr': + { + //BPath path("http://"); + //path.Append("directories"); + //path.Append(fOpmlName.String()); + + //BString url("http://www.funkyideasoft.com/directories/bepodder_podcast_opml.tar.gz"); + + OPMLTree* tree = fDirectoryTrees.ValueFor(fOpmlURL); + if(tree) { +// OPMLParser parser; +// OPMLTree* tree = parser.Parse(path.Path()); + ApplyTree(tree); +// parser.DeleteOPMLTree(tree); + } + else + StartDownload(fOpmlURL); + + /*BPath path(GetAppRelativePath().String()); + path.Append("directories"); + path.Append(fOpmlName.String()); + OPMLParser parser; + OPMLTree* tree = parser.Parse(path.Path()); + if(tree) + { + ApplyTree(tree); + parser.DeleteOPMLTree(tree); + }*/ + //else error! + + + + + + + } + break; + case 'subs': + { + DirectoryItem* item=(DirectoryItem*)alist->ItemAt(alist->CurrentSelection()); + if(!item) return; + if(item->Link() == "") return; + + //send message to main_window! + BMessage msg('addu'); + msg.AddString("url",item->Link()); + BMessenger(main_window).SendMessage(&msg); + //BMessenger(this).SendMessage(B_QUIT_REQUESTED); + } + break; + case 'invo': + { + // mess2->PrintToStream(); + int32 index=mess2->FindInt32("index"); + BListItem* item=alist->ItemAt(index); + if(alist->CountItemsUnder(item,true) > 0){ + if(!item->IsExpanded()) + alist->Expand(item); + else + alist->Collapse(item); + } + else + { + //send message to main_window! + BMessage msg('addu'); + msg.AddString("url",((DirectoryItem*)item)->Link()); + BMessenger(main_window).SendMessage(&msg); + } + + } + break; + default: + BWindow :: MessageReceived(mess2); + break; + } +} +void +DirectoryWindow::ApplyTree(OPMLTree* tree){ + + alist->MakeEmpty(); + + if(!tree->foglie) return; //should never happen! + +// OPMLParser pa; +// pa.PrintToStream(tree->foglie->ItemAt(0),0); + + _addItem(NULL,tree->foglie->ItemAt(0)); + + DirectoryItem* item=(DirectoryItem*)alist->ItemAt(0); + if(!item) return; + alist->Expand(item); + alist->Select(0); + alist->MakeFocus(true); +} + +void +DirectoryWindow::_addItem(BListItem* root,OPMLTree* foglia){ + + BBitmap* icon = fFolderIcon; + BPoint spiaz(0,0); + + if(!foglia->foglie) + icon = fItemIcon; + else + spiaz.y=+3; + + DirectoryItem *leaf = new DirectoryItem(foglia->description.String(), icon ,foglia->link.String(),spiaz); + if(root) + { + alist->AddUnder(leaf,root); + if(root->IsExpanded()) alist->Collapse(root); + LOG("DirectoryWindow", liDebug ,"Added Item [%s] under [%s]",foglia->description.String(),((IconTextItem *)root)->Text()); + } + else + { + alist->AddItem(leaf,alist->CountItems()); + LOG("DirectoryWindow", liDebug ,"Added Item [%s]",foglia->description.String()); + + } + + + + if(!foglia->foglie) return; + + + for(int32 i=foglia->foglie->CountItems() -1 ; i>=0 ; i--){ + OPMLTree* subfoglia = foglia->foglie->ItemAt(i); + _addItem(leaf,subfoglia); + } + +} + +void +DirectoryWindow::DownloadInfo(BMessage* msg){ + + ActionDownload::Status status = (ActionDownload::Status)msg->FindInt32("status"); + BString extra; + + switch(status){ + case ActionDownload::OK_DOWNLOADED: + + // done. + + + { + if(fAlert && fAlert->Lock()) + fAlert->Quit(); + //BMessenger(fAlert).SendMessage(B_QUIT_REQUESTED); + + + msg->PrintToStream(); + + BString filename; + if(msg->FindString("path",&filename) == B_OK){ + + + const char* newName=tmpnam(NULL); + + filename.Prepend("tar -xzvOf "); + filename << " > " << newName; + + system(filename.String()); + + OPMLParser parser; + OPMLTree* tree = parser.Parse(newName); + + unlink(newName); + msg->FindString("path",&filename); + unlink(filename.String()); + + if(tree) { + ApplyTree(tree); + BString url; + if(msg->FindString("url",&url)==B_OK) + fDirectoryTrees.AddItem(url,tree); + else + parser.DeleteOPMLTree(tree); + } + + } + } + break; + + case ActionDownload::OK_CONNECTING: + //item->SetFileStatus(CONNECTING); + break; + case ActionDownload::OK_PROGRESS: + { + + int32 perc; +// float speed; + + + if(msg->FindInt32("percentage_progress",&perc)==B_OK){ +// BString per; +// per << "Downloading " << perc << "%"; +// SetDescription(per.String()); + if(fAlert) fAlert->SetPercentage(perc); + } + + + } + break; + + case ActionDownload::ERROR_PERFORMING: + { + + + int32 error=msg->FindInt32("curl_error"); + + switch(error){ + case CURLE_COULDNT_CONNECT: + SetError(_T("Can't connect!")); + break; + case CURLE_HTTP_PORT_FAILED: + SetError(_T("Http port failed!")); + break; + case CURLE_COULDNT_RESOLVE_HOST: + SetError(_T("Can't resolve host!")); + break; + case CURLE_HTTP_NOT_FOUND: + SetError(_T("Not found!")); + break; + + case CURLE_WRITE_ERROR: + { + bool stopped = msg->FindBool("should_stop"); + + if(!stopped) + //item->SetFileStatus(STOPPED); + //else + { + //item->SetFileStatus(ERROR); + SetError("Write error!"); + } + } + break; + + case CURLE_BAD_DOWNLOAD_RESUME: + //item->SetFileStatus(ERROR); + SetError("Bad resume!"); + break; + case CURLE_ABORTED_BY_CALLBACK: + //item->SetFileStatus(ERROR); + SetError("Aborted by Callback!"); + break; + case CURLE_HTTP_RANGE_ERROR: + //item->SetFileStatus(ERROR); + SetError("Can't resume! (range error)"); + break; + case CURLE_FTP_ACCESS_DENIED: + //item->SetFileStatus(ERROR); + SetError("Access Denied!"); + break; + case CURLE_FTP_USER_PASSWORD_INCORRECT: + //item->SetFileStatus(ERROR); + SetError("User or Password Incorrect!"); + break; + + default: + { + //item->SetFileStatus(ERROR); + BString ser("Other error (cUrl code: "); + ser << error << " )"; + SetError(ser.String()); + } + break; + } + + deletePath(msg); + + } + break; + + case ActionDownload::ERROR_CURL_INIT: + SetError("cUrl init error!"); + deletePath(msg); + break; + + case ActionDownload::ERROR_OPENFILE: + //item->SetFileStatus(ERROR); + SetError("Can't open file!"); + deletePath(msg); + break; + default: + { + //item->SetFileStatus(ERROR); + BString ser("Other error (status code: "); + ser << (long)status << " )"; + SetError(ser.String()); + deletePath(msg); + } + break; + } +} + +void +DirectoryWindow::deletePath(BMessage* msg){ + BString path; + if(msg->FindString("path",&path)==B_OK) + unlink(path.String()); + +} + +void +DirectoryWindow::SetError(const char* tex){ + if(fAlert && fAlert->Lock()) + fAlert->Quit(); + + BString t(fOpmlName); + t << " : " << tex; + BPAlert *error=new BPAlert("BePodder",t.String(),"ok",NULL,NULL,B_WIDTH_AS_USUAL, LoadIcon("delete-32.png")); + error->Go(); + PostMessage(B_QUIT_REQUESTED); + +} + +//void +//DirectoryWindow::SetDescription(const char* tex){ +// if(fAlert && fAlert->Lock()){ +// BString t(fOpmlName); +// t << " : " << tex; +// fAlert->TextView()->SetText(t.String()); +// fAlert->Unlock(); +// } +//} +//-- diff --git a/sources-experimental/DirectoryWindow.h b/sources-experimental/DirectoryWindow.h new file mode 100644 index 0000000..e723a4a --- /dev/null +++ b/sources-experimental/DirectoryWindow.h @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "OPMLParser.h" + +#include "BPAlert.h" + +#include "KeyMap.h" + +class PercentageWindow; + +class DirectoryWindow: public BWindow +{ + + + + + public: + DirectoryWindow(const char* opml_name,BString opml_url); //,const rgb_color back_color); + // ~DirectoryWindow(); + + void MessageReceived(BMessage *mess2); + + + + +private: + + PercentageWindow* fAlert; + + void StartDownload(BString url); + + + void DownloadInfo(BMessage*); + + + //void SetDescription(const char*); + void SetError(const char* tex); + void ApplyTree(OPMLTree*); + + void deletePath(BMessage* msg); + + void _addItem(BListItem* root,OPMLTree*); + BOutlineListView *alist; + + BString fOpmlName; + BString fOpmlURL; + + + +}; + diff --git a/sources-experimental/DownloadListItem.cpp b/sources-experimental/DownloadListItem.cpp new file mode 100644 index 0000000..8930795 --- /dev/null +++ b/sources-experimental/DownloadListItem.cpp @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#include "DownloadListItem.h" +#include "ItemProperty.h" + +#include +#include "BPLocale.h" + +#include "Utils.h" +#include "curl/curl.h" +#include "FileStatus.h" +#include "ColumnListView.h" +#include "ColumnTypes.h" +#include "DownloadListView.h" +#include "EpisodeListItem.h" +#include "SubscriptionListItem.h" + +DownloadListItem::DownloadListItem(SubscriptionListItem* ch):BRow(16.0) +{ + int index = 0; + time_t time = 0; + + SetField( iconfield = new BBitmapField(NULL) , index++); + SetField( channel = new BStringField(NULL) , index++); + SetField( field = new BStringField(NULL) , index++); + SetField( new BDateField(&time) , index++); + SetField( sizefield = new BSizeField(0), index++); + SetField( fieldStaus = new FileStatusField(NEW) , index++); + + + if(ch){ + channel->SetString(ch->GetTitle().String()); + } + + fShouldMeRemoved = false; + + fLinked=NULL; + fRss.AddElementListener(this); + +} + +void +DownloadListItem::LinkToEpisode(EpisodeListItem* item){ + if(fLinked!=NULL) + debugger("DownloadListItem::fLinked !=NULL, should never happen."); + fLinked=item; + fRss.AddElementListener(fLinked); +} + +void +DownloadListItem::Unlink(){ + if(fLinked) + fRss.RemoveElementListener(fLinked); + fLinked=NULL; +} + + +void +DownloadListItem::KeyModified(int32 key, void* data,ssize_t size) +{ + switch(key){ + + case ITEM_TITLE: + field->SetString((const char*)data); + break; + case ITEM_PUBDATE: + { + time_t when = *((time_t*)data); + SetField( new BDateField(&when), 3 ); + } + + break; + + case ITEM_ENCLOSURE_LENGTH: + { + off_t size= *((off_t*)data); + sizefield-> SetSize(size); + } + break; + + case ITEM_ENCLOSURE_FILE_STATUS: + { + + // BString sdata; + int32 val=*((int*)data); + FileStatus status = (FileStatus)val; + + switch(status) + { + case NOT_DOWNLOADED: + case NEW: + case NO_ENCLOSURE: + iconfield->SetBitmap(NULL); + break; + case DOWNLOADED: + iconfield->SetBitmap(LoadIcon("done-micro.png")); + break; + case STOPPED: + iconfield->SetBitmap(LoadIcon("stopped-micro.png")); + break; + case DOWNLOADING: + iconfield->SetBitmap(LoadIcon("download-micro.png")); + break; + case ENQUEQUED: + iconfield->SetBitmap(LoadIcon("enqueued-micro.png")); + break; + case CONNECTING: break; //just use the last one! + default: + iconfield->SetBitmap(LoadIcon("error-micro.png")); + //sdata.SetTo(_T("error")); + break; + } + + fieldStaus->SetFileStatus(status); + if(fList) + fList->UpdateRow(this); + } + break; + case ITEM_ENCLOSURE_FILE_PERCENTAGE: + { + int32 val=*((int*)data); + fieldStaus->SetFilePercentage(val,fLatestSpeed); + } + break; + case ITEM_ENCLOSURE_DOWNLOAD_SPEED: + fLatestSpeed= *((float*)data); + break; + + + default: + break; + }; + +} + +DownloadListItem::~DownloadListItem(){ +} + +float +DownloadListItem::GetLastSpeed(){ + return fLatestSpeed; +} +int32 +DownloadListItem::GetPercentage(){ + return fieldStaus->GetPercentage(); +} + diff --git a/sources-experimental/DownloadListItem.h b/sources-experimental/DownloadListItem.h new file mode 100644 index 0000000..198e8cf --- /dev/null +++ b/sources-experimental/DownloadListItem.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef _DownloadListItem_H +#define _DownloadListItem_H + +#include "ColumnListView.h" +#include "ColumnTypes.h" + +#include "ElementListener.h" + +#include "FileStatusColumn.h" + +#include +#include "RssItem.h" + +class DownloadListView; +class EpisodeListItem; +class SubscriptionListItem; + +class DownloadListItem : public BRow, public ElementListener +{ + public: + DownloadListItem(SubscriptionListItem* channel); + ~DownloadListItem(); + + + void KeyModified(int32 key, void* data,ssize_t size); + + + entry_ref fRef; + RssItem fRss; + + + void LinkToEpisode(EpisodeListItem* item); + void Unlink(); + + float GetLastSpeed(); + int32 GetPercentage(); + + //test + bool fShouldMeRemoved; + + private: + + BBitmapField* iconfield; + BStringField* field; + BStringField* channel; + BSizeField* sizefield; + FileStatusField* fieldStaus; + EpisodeListItem* fLinked; + + + float fLatestSpeed; + +}; + +#endif diff --git a/sources-experimental/DownloadListView.cpp b/sources-experimental/DownloadListView.cpp new file mode 100644 index 0000000..b9ce2e1 --- /dev/null +++ b/sources-experimental/DownloadListView.cpp @@ -0,0 +1,123 @@ +#include "DownloadListView.h" +#include "SubscriptionColumn.h" + +#include "MyColumnTypes.h" +#include +#include "BPLocale.h" +#include +#include + +#include "FileStatusColumn.h" +#include "DownloadListItem.h" + +DownloadListView::DownloadListView(BRect r): +BColumnListView(r,"DownloadListView",B_FOLLOW_ALL, B_WILL_DRAW|B_NAVIGABLE,B_FANCY_BORDER,true) +{ + BColumn *icon = new BMyBitmapColumn(_T("Icon"),16,16,16); + BColumn *channel = new BStringColumn(_T("Subscription"),140,10,500,5,B_ALIGN_LEFT); + BColumn *title = new BStringColumn(_T("Title"),140,10,500,5,B_ALIGN_LEFT); + BColumn *date = new BPositiveDateColumn(_T("Date"),70,10,150,B_ALIGN_LEFT); + BColumn *size = new BPositiveSizeColumn(_T("Size"),80,10,150,B_ALIGN_LEFT); + + int index = 0; + AddColumn(icon,index++); + AddColumn(channel,index++); + AddColumn(title,index++); + AddColumn(date,index++); + AddColumn(size,index++); + AddColumn(new FileStatusColumn(_T("Status"), + 200,110,400,0,B_ALIGN_LEFT), + index++); + //SetColumnFlags(B_ALLOW_COLUMN_RESIZE); + SetColumnFlags((column_flags)(B_ALLOW_COLUMN_REMOVE|B_ALLOW_COLUMN_RESIZE|B_ALLOW_COLUMN_POPUP|B_ALLOW_COLUMN_MOVE)); + SetSelectionMode(B_SINGLE_SELECTION_LIST); + SetSortingEnabled(true); + SetSortColumn(date,false,false); + + BView* sview = new BView(BRect(0,0,100,B_H_SCROLL_BAR_HEIGHT-1),NULL,B_FOLLOW_ALL_SIDES,B_WILL_DRAW); + sview->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + + fCounter = new BStringView(BRect(2,1,98,B_H_SCROLL_BAR_HEIGHT-2),"",""); + fCounter->SetFontSize(10); + fCounter->SetViewColor( ui_color(B_PANEL_BACKGROUND_COLOR) ); + + sview->AddChild(fCounter); + AddStatusView(sview); + + const rgb_color greyBox = {255,234,130 }; + SetColor(B_COLOR_SELECTION,greyBox); + SetColor(B_COLOR_SELECTION_TEXT,Color(B_COLOR_TEXT)); + + const rgb_color white={255,255,255,255}; + SetColor(B_COLOR_BACKGROUND,white); + + + SetSortingEnabled(true); + ClearSortColumns(); + //SetSortColumn(ColumnAt(index),true,true); + + + //messages + + BMessage* selected=new BMessage(DOWNLOAD_SELECTED); + selected->AddInt32("buttons",0); + + SetSelectionMessage(selected); + + SetInvocationMessage(new BMessage(DOWNLOAD_INVOKED)); +} + +void +DownloadListView::SelectionChanged(){ + uint32 buttons = 0; + + BMessage *msg = Window()->CurrentMessage(); + + if(msg) //don't remove. + msg->FindInt32("buttons", (int32 *)&buttons) ; + + + DownloadListItem* dli =(DownloadListItem*) CurrentSelection(); + if(!dli) return; + + if(SelectionMessage()){ + + SelectionMessage()->ReplaceInt32("buttons",buttons); + SelectionMessage()->AddRef("entry_ref",&dli->fRef); + + } + BColumnListView::SelectionChanged(); +} + +void +DownloadListView::ResetSelectionMessage(){ + + if(SelectionMessage()){ + + SelectionMessage()->ReplaceInt32("buttons",0); + SelectionMessage()->RemoveName("entry_ref"); + + } +} + +void +DownloadListView::AddRow(BRow* row, BRow *parent){ + BColumnListView::AddRow(row,parent); + UpdateCount(); +} +void +DownloadListView::AddRow(BRow* row, int32 index, BRow *parent){ + BColumnListView::AddRow(row,index,parent); + UpdateCount(); +} + +void +DownloadListView::UpdateCount(){ + BString text; + text << CountRows(); + fCounter->SetText(text.String()); +} + + +//-- diff --git a/sources-experimental/DownloadListView.h b/sources-experimental/DownloadListView.h new file mode 100644 index 0000000..0099144 --- /dev/null +++ b/sources-experimental/DownloadListView.h @@ -0,0 +1,31 @@ +#ifndef _DownloadListView_H_ +#define _DownloadListView_H_ + +#include "ColumnListView.h" +#include "FileStatusColumn.h" +#include + +#define DOWNLOAD_SELECTED 'dwse' +#define DOWNLOAD_INVOKED 'dwin' + +class DownloadListView : public BColumnListView +{ + public: + DownloadListView(BRect r); + + void SelectionChanged(); + void AddRow(BRow*, BRow *parent = 0); + void AddRow(BRow*, int32 index, BRow *parent = 0); + + void ResetSelectionMessage(); + + private: + void UpdateCount(); + BStringView* fCounter; + + +}; + +#endif + +//. diff --git a/sources-experimental/DownloadManager.cpp b/sources-experimental/DownloadManager.cpp new file mode 100644 index 0000000..6d0655e --- /dev/null +++ b/sources-experimental/DownloadManager.cpp @@ -0,0 +1,161 @@ +#include "DownloadManager.h" +#include + +#define DEFAULT_CHANNELS_DOWNLOAD 3 +#define DEFAULT_ITEMS_DOWNLOAD 1 + +DownloadManager::DownloadManager(BLooper* target){ + + queue[CHANNELS_QUEUE] = new QueueFileDownload("qSubscriptions",DEFAULT_CHANNELS_DOWNLOAD,target,DOWNLOAD_CHANNEL_INFO); + queue[ITEMS_QUEUE] = new QueueFileDownload("qEnclosures",DEFAULT_ITEMS_DOWNLOAD,target,DOWNLOAD_ITEM_INFO); + queue[EXTRA_QUEUE] = new QueueFileDownload("qExtra",1,target,DOWNLOAD_EXTRA_INFO); +} + +void +DownloadManager::Enqueue(QueueType type,ActionDownload* ad){ + queue[type]->AddAction(ad); +} + +void +DownloadManager::TryStopCurrentAction(QueueType type,BString key,BString value){ + + if(queue[type]->Lock()){ + for(int i=0;iCountThreads();i++) { + ActionDownload *ad = (ActionDownload*)queue[type]->CurrentAction(i); + + if(ad && ad->GetKey(key).Compare(value.String()) ==0 ) + ad->SetShouldStop(true); + } + + queue[type]->Unlock(); + } +} + +bool +DownloadManager::RemoveFromQueue(QueueType type ,BString key,BString value){ + if(queue[type]->Lock()){ + + for(int32 i=0;iCountActions();i++){ + ActionDownload *ad = (ActionDownload*)queue[type]->ActionAt(i); + if(ad->GetKey(key).Compare(value.String()) ==0 ){ + queue[type]->RemoveActionAt(i); + queue[type]->Unlock(); + return true; + } + } + + for(int i=0;iCountThreads();i++) { + ActionDownload *ad = (ActionDownload*)queue[type]->CurrentAction(i); + + if(ad && ad->GetKey(key).Compare(value.String()) ==0 ) + ad->SetShouldStop(true); + } + queue[type]->Unlock(); + return false; + } + return false; +} + +void +DownloadManager::RemoveQueue(QueueType type,BList* removed){ + + + queue[type]->Lock(); + + while(queue[type]->CountActions()) + { + //ActionDownload *ad = (ActionDownload*) + queue[type]->ActionAt(0); + queue[type]->RemoveActionAt(0); + } + + // *************************************** + // we did not unlock + // so no one can add new item. + // *************************************** + + for(int i=0;iCountThreads();i++) { + if(queue[type]->CurrentAction(i)) + removed->AddItem( (void*)queue[type]->CurrentAction(i)); + } +} + +void +DownloadManager::LoadProxySetting(BMessage* data){ + + bool value; + + enabled=false; + address.SetTo(""); + userpwd.SetTo(""); + port = 0; + + + if(data->FindBool("enable",&value)==B_OK) + enabled=value; + + if(!enabled) return; + + BString username,password; + data->FindString("username",&username); + data->FindInt32("port",&port); + data->FindString("address",&address); + data->FindString("password",&password); + if(username !="" || password !="") + userpwd << username << ":" << password; + +} + + +void +DownloadManager::LoadDownloadSetting(BMessage* data){ + + //here magic stuff! :=) + int32 number = 1; + if(data->FindInt32("max_downloads",&number) == B_OK){ + queue[ITEMS_QUEUE]->SetDownloadCount(number); + } +} + +thread_id +DownloadManager::SingleThreadAction(ActionAsync* action,bool autoResume){ + + thread_id id = spawn_thread(DownloadManager::SingleThreadPerform,"single_action_thread",B_NORMAL_PRIORITY,(void*)action); + if(autoResume) resume_thread(id); + return id; +} + +int32 +DownloadManager::SingleThreadPerform(void* a){ + + ActionAsync* ad=(ActionAsync*)a; + + // perform the action + BMessage err; + + //status_t status = + ad->Perform(&err); + // do post-perform! + + if(ad->Target()){ + err.what=ad->Command(); + //BMessenger(ad->Looper()).SendMessage(&err); + ad->Invoke(&err); + } + return 0; +} + + +void +DownloadManager::FinishCurl(CURL* curl){ + if(!enabled) return; + + curl_easy_setopt(curl, CURLOPT_PROXY, address.String()); + curl_easy_setopt(curl, CURLOPT_PROXYPORT, port); + curl_easy_setopt(curl, CURLOPT_PROXYTYPE , CURLPROXY_HTTP); + //curl_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_BASIC ); + if(userpwd != "") { + curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD , userpwd.String() ); + //println("auth %s\n",userpwd.String()); + } +} diff --git a/sources-experimental/DownloadManager.h b/sources-experimental/DownloadManager.h new file mode 100644 index 0000000..14dd4c4 --- /dev/null +++ b/sources-experimental/DownloadManager.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef DownloadManager_H_ +#define DownloadManager_H_ + +#include "ActionDownload.h" +#include "QueueFileDownload.h" +#include +#include +#include "curl/curl.h" + +#define DOWNLOAD_CHANNEL_INFO 'addc' +#define DOWNLOAD_ITEM_INFO 'adde' +#define DOWNLOAD_EXTRA_INFO 'extr' +class DownloadManager { + + public: + DownloadManager(BLooper* target); + + enum QueueType { + CHANNELS_QUEUE =0, + ITEMS_QUEUE, + EXTRA_QUEUE + }; + + void Enqueue(QueueType,ActionDownload*); + + void TryStopCurrentAction(QueueType,BString key,BString value); + + bool RemoveFromQueue(QueueType,BString key,BString value); + + void RemoveQueue(QueueType,BList* removed); + + void LoadProxySetting(BMessage* data); + void LoadDownloadSetting(BMessage* data); + + + + + thread_id SingleThreadAction(ActionAsync* action,bool autoResume=true); + + void FinishCurl(CURL* curl); + +private: + + static int32 SingleThreadPerform(void* a); + + QueueFileDownload * queue[3]; + + //proxy + int32 port; + BString address; + BString userpwd; + bool enabled; + +}; + +#endif diff --git a/sources-experimental/ElementListener.h b/sources-experimental/ElementListener.h new file mode 100644 index 0000000..2ca84d9 --- /dev/null +++ b/sources-experimental/ElementListener.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * Interface for something that reacts aftwer a change +*/ + +#ifndef _ElementListener_h_ +#define _ElementListener_h_ + +#include + +class ElementListener +{ + public: + virtual void KeyModified(int32 key, void* data,ssize_t numBytes) = 0; +}; +#endif diff --git a/sources-experimental/ElementNotifier.cpp b/sources-experimental/ElementNotifier.cpp new file mode 100644 index 0000000..2685e8f --- /dev/null +++ b/sources-experimental/ElementNotifier.cpp @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#include "ElementNotifier.h" +#include + +void +ElementNotifier::SetElementListener(ElementListener* list) +{ + fListener = list; +} + +void +ElementNotifier::NotifyListener(ItemProperty key,void* data,ssize_t size) +{ + fListener->KeyModified(key,data,size); +} diff --git a/sources-experimental/ElementNotifier.h b/sources-experimental/ElementNotifier.h new file mode 100644 index 0000000..a4431ae --- /dev/null +++ b/sources-experimental/ElementNotifier.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef ElementNotifier_H_ +#define ElementNotifier_H_ + +#include +#include +#include +#include + +#include "ElementListener.h" +#include + + +#include "ItemProperty.h" + + + +class ElementNotifier +{ + +public: + + void SetElementListener(ElementListener*); + + + protected: + + ElementListener* fListener; + void NotifyListener(ItemProperty key,void* data,ssize_t); + +}; +#endif diff --git a/sources-experimental/EntryIterator.cpp b/sources-experimental/EntryIterator.cpp new file mode 100644 index 0000000..f6fb907 --- /dev/null +++ b/sources-experimental/EntryIterator.cpp @@ -0,0 +1,457 @@ + +#include +#include +#include + +#include +#include + +#include "EntryIterator.h" +#include "NodeWalker.h" +#include "ObjectList.h" + +TWalkerWrapper::TWalkerWrapper(TWalker *walker) + : fWalker(walker), + fStatus(B_OK) +{ +} + +TWalkerWrapper::~TWalkerWrapper() +{ + delete fWalker; +} + +status_t +TWalkerWrapper::InitCheck() const +{ + return fStatus; +} + +status_t +TWalkerWrapper::GetNextEntry(BEntry *entry, bool traverse) +{ + fStatus = fWalker->GetNextEntry(entry, traverse); + return fStatus; +} + +status_t +TWalkerWrapper::GetNextRef(entry_ref *ref) +{ + fStatus = fWalker->GetNextRef(ref); + return fStatus; +} + +int32 +TWalkerWrapper::GetNextDirents(struct dirent *buffer, size_t length, int32 count) +{ + int32 result = fWalker->GetNextDirents(buffer, length, count); + fStatus = result < 0 ? result : (result ? B_OK : B_ENTRY_NOT_FOUND); + return result; +} + +status_t +TWalkerWrapper::Rewind() +{ + return fWalker->Rewind(); +} + +int32 +TWalkerWrapper::CountEntries() +{ + return fWalker->CountEntries(); +} + +EntryListBase::EntryListBase() + : fStatus(B_OK) +{ +} + +status_t +EntryListBase::InitCheck() const +{ + return fStatus; +} + +dirent * +EntryListBase::Next(dirent *ent) +{ + return (dirent *)((char *)ent + ent->d_reclen + sizeof(dirent)); +} + +CachedEntryIterator::CachedEntryIterator(BEntryList *iterator, int32 numEntries, + bool sortInodes) + : fIterator(iterator), + fEntryRefBuffer(NULL), + fCacheSize(numEntries), + fNumEntries(0), + fIndex(0), + fDirentBuffer(NULL), + fCurrentDirent(NULL), + fSortInodes(sortInodes), + fSortedList(NULL), + fEntryBuffer(NULL) +{ +} + + +CachedEntryIterator::~CachedEntryIterator() +{ + delete [] fEntryRefBuffer; + free(fDirentBuffer); + delete fSortedList; + delete [] fEntryBuffer; +} + +status_t +CachedEntryIterator::GetNextEntry(BEntry *result, bool traverse) +{ + ASSERT(!fDirentBuffer); + ASSERT(!fEntryRefBuffer); + + if (!fEntryBuffer) { + fEntryBuffer = new BEntry [fCacheSize]; + ASSERT(fIndex == 0 && fNumEntries == 0); + } + if (fIndex >= fNumEntries) { + // fill up the buffer or stop if error; keep error around + // and return it when appropriate + fStatus = B_OK; + for (fNumEntries = 0; fNumEntries < fCacheSize; fNumEntries++) { + fStatus = fIterator->GetNextEntry(&fEntryBuffer[fNumEntries], + traverse); + if (fStatus != B_OK) + break; + } + fIndex = 0; + } + *result = fEntryBuffer[fIndex++]; + if (fIndex > fNumEntries) + // we are at the end of the cache we loaded up, time to return + // an error, if we had one + return fStatus; + + return B_OK; +} + +status_t +CachedEntryIterator::GetNextRef(entry_ref *ref) +{ + ASSERT(!fDirentBuffer); + ASSERT(!fEntryBuffer); + + if (!fEntryRefBuffer) { + fEntryRefBuffer = new entry_ref[fCacheSize]; + ASSERT(fIndex == 0 && fNumEntries == 0); + } + + if (fIndex >= fNumEntries) { + // fill up the buffer or stop if error; keep error around + // and return it when appropriate + fStatus = B_OK; + for (fNumEntries = 0; fNumEntries < fCacheSize; fNumEntries++) { + fStatus = fIterator->GetNextRef(&fEntryRefBuffer[fNumEntries]); + if (fStatus != B_OK) + break; + } + fIndex = 0; + } + *ref = fEntryRefBuffer[fIndex++]; + if (fIndex > fNumEntries) + // we are at the end of the cache we loaded up, time to return + // an error, if we had one + return fStatus; + + return B_OK; +} + + +static int +CompareInode(const dirent *ent1, const dirent *ent2) +{ + if (ent1->d_ino < ent2->d_ino) + return -1; + else if (ent1->d_ino == ent2->d_ino) + return 0; + else + return 1; +} + +int32 +CachedEntryIterator::GetNextDirents(struct dirent *ent, size_t size, + int32 count) +{ + ASSERT(!fEntryRefBuffer); + if (!fDirentBuffer) { + fDirentBuffer = (dirent *)malloc(kDirentBufferSize); + ASSERT(fIndex == 0 && fNumEntries == 0); + ASSERT(size > sizeof(dirent) + B_FILE_NAME_LENGTH); + } + + if (!count) + return 0; + + if (fIndex >= fNumEntries) { + // we are out of stock, cache em up + fCurrentDirent = fDirentBuffer; + uint32 bufferRemain = kDirentBufferSize; + for (fNumEntries = 0; fNumEntries < fCacheSize; ) { + int32 count = fIterator->GetNextDirents(fCurrentDirent, + bufferRemain, 1); + + if (count <= 0) + break; + + fNumEntries += count; + + int32 currentDirentSize = fCurrentDirent->d_reclen + (ssize_t)sizeof(dirent); + bufferRemain -= currentDirentSize; + if (bufferRemain < (sizeof(dirent) + B_FILE_NAME_LENGTH)) + // cant fit a big entryRef in the buffer, just bail + // and start from scratch + break; + + fCurrentDirent = (dirent *)((char *)fCurrentDirent + currentDirentSize); + } + fCurrentDirent = fDirentBuffer; + if (fSortInodes) { + if (!fSortedList) + fSortedList = new BObjectList(fCacheSize); + else + fSortedList->MakeEmpty(); + + for (int32 count = 0; count < fNumEntries; count++) { + fSortedList->AddItem(fCurrentDirent, 0); + fCurrentDirent = Next(fCurrentDirent); + } + fSortedList->SortItems(CompareInode); + fCurrentDirent = fDirentBuffer; + } + fIndex = 0; + } + if (fIndex >= fNumEntries) + // we are done, no more dirents left + return 0; + + if (fSortInodes) + fCurrentDirent = fSortedList->ItemAt(fIndex); + + fIndex++; + uint32 currentDirentSize = fCurrentDirent->d_reclen + sizeof(dirent); + ASSERT(currentDirentSize <= size); + if (currentDirentSize > size) + return 0; + + memcpy(ent, fCurrentDirent, currentDirentSize); + + if (!fSortInodes) + fCurrentDirent = (dirent *)((char *)fCurrentDirent + currentDirentSize); + + return 1; +} + +status_t +CachedEntryIterator::Rewind() +{ + fIndex = 0; + fNumEntries = 0; + fCurrentDirent = NULL; + fStatus = B_OK; + + delete fSortedList; + fSortedList = NULL; + + return fIterator->Rewind(); +} + +int32 +CachedEntryIterator::CountEntries() +{ + return fIterator->CountEntries(); +} + +void +CachedEntryIterator::SetTo(BEntryList *iterator) +{ + fIndex = 0; + fNumEntries = 0; + fStatus = B_OK; + fIterator = iterator; +} + +CachedDirectoryEntryList::CachedDirectoryEntryList(const BDirectory &dir) + : CachedEntryIterator(0, 40, true), + fDir(dir) +{ + fStatus = fDir.InitCheck(); + SetTo(&fDir); +} + +CachedDirectoryEntryList::~CachedDirectoryEntryList() +{ +} + + +DirectoryEntryList::DirectoryEntryList(const BDirectory &dir) + : fDir(dir) +{ + fStatus = fDir.InitCheck(); +} + +status_t +DirectoryEntryList::GetNextEntry(BEntry *entry, bool traverse) +{ + fStatus = fDir.GetNextEntry(entry, traverse); + return fStatus; +} + +status_t +DirectoryEntryList::GetNextRef(entry_ref *ref) +{ + fStatus = fDir.GetNextRef(ref); + return fStatus; +} + +int32 +DirectoryEntryList::GetNextDirents(struct dirent *buffer, size_t length, + int32 count) +{ + fStatus = fDir.GetNextDirents(buffer, length, count); + return fStatus; +} + +status_t +DirectoryEntryList::Rewind() +{ + fStatus = fDir.Rewind(); + return fStatus; +} + +int32 +DirectoryEntryList::CountEntries() +{ + return fDir.CountEntries(); +} + + +EntryIteratorList::EntryIteratorList() + : fList(5, true), + fCurrentIndex(0) +{ +} + +EntryIteratorList::~EntryIteratorList() +{ + int32 count = fList.CountItems(); + for (;count; count--) { + // workaround for BEntryList not having a proper destructor + BEntryList *entry = fList.RemoveItemAt(count - 1); + EntryListBase *fixedEntry = dynamic_cast(entry); + + if (fixedEntry) + delete fixedEntry; + else + delete entry; + } +} + + +void +EntryIteratorList::AddItem(BEntryList *walker) +{ + fList.AddItem(walker); +} + +status_t +EntryIteratorList::GetNextEntry(BEntry *entry, bool traverse) +{ + for (;;) { + if (fCurrentIndex >= fList.CountItems()) { + fStatus = B_ENTRY_NOT_FOUND; + break; + } + + fStatus = fList.ItemAt(fCurrentIndex)->GetNextEntry(entry, traverse); + if (fStatus != B_ENTRY_NOT_FOUND) + break; + + fCurrentIndex++; + } + return fStatus; +} + +status_t +EntryIteratorList::GetNextRef(entry_ref *ref) +{ + for (;;) { + if (fCurrentIndex >= fList.CountItems()) { + fStatus = B_ENTRY_NOT_FOUND; + break; + } + + fStatus = fList.ItemAt(fCurrentIndex)->GetNextRef(ref); + if (fStatus != B_ENTRY_NOT_FOUND) + break; + + fCurrentIndex++; + } + return fStatus; +} + +int32 +EntryIteratorList::GetNextDirents(struct dirent *buffer, size_t length, int32 count) +{ + int32 result = 0; + for (;;) { + if (fCurrentIndex >= fList.CountItems()) { + fStatus = B_ENTRY_NOT_FOUND; + break; + } + + result = fList.ItemAt(fCurrentIndex)->GetNextDirents(buffer, length, count); + if (result > 0) { + fStatus = B_OK; + break; + } + + fCurrentIndex++; + } + return result; +} + +status_t +EntryIteratorList::Rewind() +{ + fCurrentIndex = 0; + int32 count = fList.CountItems(); + for (int32 index = 0; index < count; index++) + fStatus = fList.ItemAt(index)->Rewind(); + + return fStatus; +} + +int32 +EntryIteratorList::CountEntries() +{ + int32 result = 0; + + int32 count = fList.CountItems(); + for (int32 index = 0; index < count; index++) + result += fList.ItemAt(fCurrentIndex)->CountEntries(); + + return result; +} + + +CachedEntryIteratorList::CachedEntryIteratorList() + : CachedEntryIterator(0, 10, true) +{ + fStatus = B_OK; + SetTo(&fIteratorList); +} + +void +CachedEntryIteratorList::AddItem(BEntryList *walker) +{ + fIteratorList.AddItem(walker); +} + diff --git a/sources-experimental/EntryIterator.h b/sources-experimental/EntryIterator.h new file mode 100644 index 0000000..247b5db --- /dev/null +++ b/sources-experimental/EntryIterator.h @@ -0,0 +1,157 @@ +#ifndef __ENTRY_ITERATOR__ +#define __ENTRY_ITERATOR__ + +#include +#include "ObjectList.h" +#include "NodeWalker.h" + + + +class EntryListBase : public BEntryList { + // this is what BEntryList should have been +public: + EntryListBase(); + virtual ~EntryListBase() {} + + virtual status_t InitCheck() const; + + virtual status_t GetNextEntry(BEntry *entry, bool traverse = false) = 0; + virtual status_t GetNextRef(entry_ref *ref) = 0; + virtual int32 GetNextDirents(struct dirent *buffer, size_t length, + int32 count = INT_MAX) = 0; + + virtual status_t Rewind() = 0; + virtual int32 CountEntries() = 0; + + static dirent *Next(dirent *); + +protected: + status_t fStatus; +}; + +class TWalkerWrapper : public EntryListBase { + // this is to be able to use TWalker polymorfically as BEntryListBase +public: + TWalkerWrapper(TWalker *walker); + virtual ~TWalkerWrapper(); + + virtual status_t InitCheck() const; + virtual status_t GetNextEntry(BEntry *entry, bool traverse = false); + virtual status_t GetNextRef(entry_ref *ref); + virtual int32 GetNextDirents(struct dirent *buffer, size_t length, + int32 count = INT_MAX); + virtual status_t Rewind(); + virtual int32 CountEntries(); + +protected: + TWalker *fWalker; + status_t fStatus; +}; + +const int32 kDirentBufferSize = 10 * 1024; + +class CachedEntryIterator : public EntryListBase { +public: + // takes any iterator and runs it through a cache of a specified size + // used to cluster entry_ref reads together, away from node accesses + // + // each chunk of iterators in the cache are then returned in an order, + // sorted by their i-node number -- this turns out to give quite a bit + // better performance over just using the order in which they show up using + // the default BEntryList iterator subclass + + CachedEntryIterator(BEntryList *iterator, int32 numEntries, + bool sortInodes = false); + // CachedEntryIterator does not get to own the + virtual ~CachedEntryIterator(); + + virtual status_t GetNextEntry(BEntry *entry, bool traverse = false); + virtual status_t GetNextRef(entry_ref *ref); + virtual int32 GetNextDirents(struct dirent *buffer, size_t length, + int32 count = INT_MAX); + + virtual status_t Rewind(); + virtual int32 CountEntries(); + + virtual void SetTo(BEntryList *iterator); + // CachedEntryIterator does not get to own the + +private: + BEntryList *fIterator; + entry_ref *fEntryRefBuffer; + int32 fCacheSize; + int32 fNumEntries; + int32 fIndex; + + dirent *fDirentBuffer; + dirent *fCurrentDirent; + bool fSortInodes; + BObjectList *fSortedList; + + BEntry *fEntryBuffer; +}; + +class DirectoryEntryList : public EntryListBase { +public: + DirectoryEntryList(const BDirectory &); + + virtual status_t GetNextEntry(BEntry *entry, bool traverse = false); + virtual status_t GetNextRef(entry_ref *ref); + virtual int32 GetNextDirents(struct dirent *buffer, size_t length, + int32 count = INT_MAX); + + virtual status_t Rewind(); + virtual int32 CountEntries(); + +private: + BDirectory fDir; +}; + +class CachedDirectoryEntryList : public CachedEntryIterator { + // this class is to work around not being able to delete + // BEntryList polymorfically - need to have a special + // caching entry list iterator for directories +public: + CachedDirectoryEntryList(const BDirectory &); + virtual ~CachedDirectoryEntryList(); + +private: + BDirectory fDir; +}; + +class EntryIteratorList : public EntryListBase { + // This wraps up several BEntryList style iterators and + // iterates them all, going from one to the other as it finishes + // up each of them +public: + EntryIteratorList(); + virtual ~EntryIteratorList(); + + void AddItem(BEntryList *); + // list gets to own walkers + + virtual status_t GetNextEntry(BEntry *entry, bool traverse = false); + virtual status_t GetNextRef(entry_ref *ref); + virtual int32 GetNextDirents(struct dirent *buffer, size_t length, + int32 count = INT_MAX); + + virtual status_t Rewind(); + virtual int32 CountEntries(); + +protected: + BObjectList fList; + int32 fCurrentIndex; +}; + +class CachedEntryIteratorList : public CachedEntryIterator { +public: + CachedEntryIteratorList(); + void AddItem(BEntryList *); + +protected: + EntryIteratorList fIteratorList; +}; + + + +#endif diff --git a/sources-experimental/EpisodeListItem.cpp b/sources-experimental/EpisodeListItem.cpp new file mode 100644 index 0000000..2d06167 --- /dev/null +++ b/sources-experimental/EpisodeListItem.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#include "EpisodeListItem.h" +#include "ItemProperty.h" + +#include +#include "BPLocale.h" + +#include "Utils.h" +#include "curl/curl.h" +#include "FileStatus.h" +#include "ColumnListView.h" +#include "ColumnTypes.h" + + +EpisodeListItem::EpisodeListItem():BRow(16.0),isNew(false) +{ + int index = 0; + time_t time = 0; + fLatestSpeed = 0; + + SetField( iconfield = new BBitmapField(NULL) , index++); + SetField( field = new BStringField(NULL) , index++); + SetField( new BDateField(&time) , index++); + SetField( sizefield = new BSizeField(0), index++); + SetField( fieldStaus = new FileStatusField(NEW) , index++); + + //fRss.AddElementListener(this); +} + + +void +EpisodeListItem::KeyModified(int32 key, void* data,ssize_t size) +{ + switch(key) + { + + case ITEM_TITLE: + { + field->SetString((const char*)data); + } + break; + case ITEM_PUBDATE: + { + time_t when = *((time_t*)data); + SetField( new BDateField(&when), 2 ); + } + + break; + + case ITEM_ENCLOSURE_LENGTH: + { + off_t size= *((off_t*)data); + sizefield-> SetSize(size); + } + break; + + case ITEM_ENCLOSURE_URL: + + if( fieldStaus->GetFileStatus()== NEW ) + iconfield->SetBitmap(LoadIcon("clip.png")); + break; + + case ITEM_ENCLOSURE_FILE_STATUS: + { + + // BString sdata; + int32 val=*((int*)data); + FileStatus status = (FileStatus)val; + + if(status!=NEW) + SetIsNew(false); + else + SetIsNew(true); + + switch(status) + { + case NEW: + break; + + case NOT_DOWNLOADED: + iconfield->SetBitmap(LoadIcon("clip.png")); + break; + + case NO_ENCLOSURE: + iconfield->SetBitmap(NULL); + break; + + case DOWNLOADED: + iconfield->SetBitmap(LoadIcon("done-micro.png")); + break; + case STOPPED: + iconfield->SetBitmap(LoadIcon("stopped-micro.png")); + break; + case DOWNLOADING: + iconfield->SetBitmap(LoadIcon("download-micro.png")); + break; + case ENQUEQUED: + iconfield->SetBitmap(LoadIcon("enqueued-micro.png")); + break; + case CONNECTING: break;//just use the last one! + default: + iconfield->SetBitmap(LoadIcon("error-micro.png")); + //sdata.SetTo(_T("error")); + break; + } + + fieldStaus->SetFileStatus(status); + //test + if(fList) + fList->UpdateRow(this); + } + break; + case ITEM_ENCLOSURE_FILE_PERCENTAGE: + { + int32 val=*((int*)data); + fieldStaus->SetFilePercentage(val,fLatestSpeed); + } + break; + case ITEM_ENCLOSURE_DOWNLOAD_SPEED: + fLatestSpeed= *((float*)data); + break; + + default: + break; + }; + + + +} + +EpisodeListItem::~EpisodeListItem(){ +} + +void +EpisodeListItem::DrawBackground( BRect _rect, BView* parent, bool _is_selected, bool _is_focus ) { + +// BRow::DrawBackground(_rect,parent,_is_selected,_is_focus); + if(isNew) { + parent->SetHighColor(0,0,0); + parent->FillRect(BRect(_rect.left + 6, _rect.top + 6,_rect.left + 9,_rect.top + 9)); + } +} + diff --git a/sources-experimental/EpisodeListItem.h b/sources-experimental/EpisodeListItem.h new file mode 100644 index 0000000..31461ea --- /dev/null +++ b/sources-experimental/EpisodeListItem.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef _EpisodeListItem_H +#define _EpisodeListItem_H + +#include "ColumnListView.h" +#include "ColumnTypes.h" + +#include "ElementListener.h" + +#include "FileStatusColumn.h" + +#include "RssItem.h" +#include + +class EpisodeListItem : public BRow, public ElementListener +{ + public: + EpisodeListItem(); + ~EpisodeListItem(); + + void KeyModified(int32 key, void* data,ssize_t size); + void DrawBackground( BRect _rect, BView* _target_view, bool _is_selected, bool _is_focus ); + + bool IsNew(){ return isNew; } + + off_t GetEnclosureSize(){ return sizefield->Size(); }; + const char* GetTitle(){ return field->String(); }; + time_t GetDate(){ return ((BDateField*)GetField(2))->UnixTime(); }; + + entry_ref fRef; + + private: + void SetIsNew(bool set){ isNew = set; } + + BBitmapField* iconfield; + BStringField* field; + BSizeField* sizefield; + FileStatusField* fieldStaus; + + bool isNew; + float fLatestSpeed; +}; + +#endif diff --git a/sources-experimental/EpisodeListView.cpp b/sources-experimental/EpisodeListView.cpp new file mode 100644 index 0000000..45aa204 --- /dev/null +++ b/sources-experimental/EpisodeListView.cpp @@ -0,0 +1,128 @@ +#include "EpisodeListView.h" +#include "SubscriptionColumn.h" + +#include "MyColumnTypes.h" +#include +#include "BPLocale.h" +#include +#include +#include "EpisodeListItem.h" +#include "FileStatusColumn.h" +#include "Colors.h" +#include "ImageButton.h" + +class StatusView : public BView { + public: + StatusView(BRect r); + void SetCount(int32); + private: + BStringView* fCounter; +}; + +StatusView::StatusView(BRect r):BView(r,NULL,B_FOLLOW_ALL_SIDES,B_WILL_DRAW){ + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + BRect rect(Bounds()); + rect.InsetBy(2,2); + fCounter = new BStringView(rect,"",""); + fCounter->SetFontSize(10); + BFont font; + fCounter->GetFont(&font); + font_height fh; + font.GetHeight(&fh); + fCounter->ResizeBy(20,fh.descent); + fCounter->MoveBy(-20,fh.descent); + fCounter->SetViewColor( ui_color(B_PANEL_BACKGROUND_COLOR) ); + AddChild(fCounter); + + rect=Bounds(); + rect.left = fCounter->Bounds().right + 1; + //AddChild(new ImageButton(rect,"name",NULL)); + +} + +void +StatusView::SetCount(int32 count){ + BString text; + text << count; + fCounter->SetText(text.String()); +} + +EpisodeListView::EpisodeListView(BRect r): +BColumnListView(r,"EpisodeListView",B_FOLLOW_ALL, B_WILL_DRAW|B_NAVIGABLE,B_FANCY_BORDER,true) +{ + BColumn *icon = new BMyBitmapColumn(_T("Icon"),16,16,16); + BColumn *title = new BStringColumn(_T("Title"),140,10,500,B_TRUNCATE_MIDDLE,B_ALIGN_LEFT); + BColumn *date = new BPositiveDateColumn(_T("Date"),70,10,150,B_ALIGN_LEFT); + BColumn *size = new BPositiveSizeColumn(_T("Size"),80,10,150,B_ALIGN_LEFT); + + int index = 0; + AddColumn(icon,index++); + AddColumn(title,index++); + AddColumn(date,index++); + AddColumn(size,index++); + AddColumn(new FileStatusColumn(_T("Status"),200,110,400,0,B_ALIGN_LEFT),index++); + + SetColumnFlags((column_flags)(B_ALLOW_COLUMN_REMOVE|B_ALLOW_COLUMN_RESIZE|B_ALLOW_COLUMN_POPUP|B_ALLOW_COLUMN_MOVE)); + SetSelectionMode(B_MULTIPLE_SELECTION_LIST); + SetSortingEnabled(true); + SetSortColumn(date,false,false); + + AddStatusView(fStatusView=new StatusView(BRect(0,0,100,B_H_SCROLL_BAR_HEIGHT-1))); + + SetColor(B_COLOR_BACKGROUND,White); + + SetColor(B_COLOR_SELECTION, ui_color(B_MENU_SELECTION_BACKGROUND_COLOR)); + + //FIX make sense? + #ifdef ZETA + SetColor(B_COLOR_SELECTION_TEXT,ui_color(B_MENU_SELECTED_ITEM_TEXT_COLOR)); + #else + SetColor(B_COLOR_SELECTION_TEXT,White); + #endif + +} + +void +EpisodeListView::SelectionChanged(){ + uint32 buttons = 0; + + BMessage *msg = Window()->CurrentMessage(); + + if(msg) //don't remove. + msg->FindInt32("buttons", (int32 *)&buttons) ; + + if(SelectionMessage()) + SelectionMessage()->ReplaceInt32("buttons",buttons); + +// EpisodeListItem* sel = (EpisodeListItem*)CurrentSelection(); + +// SelectionMessage()->RemoveName("entry_ref"); +// SelectionMessage()->AddRef("entry_ref",&sel->fRef); + + BColumnListView::SelectionChanged(); +} + + +void +EpisodeListView::AddRow(BRow* row, BRow *parent){ + BColumnListView::AddRow(row,parent); + UpdateCount(); +} +void +EpisodeListView::RemoveRow(BRow* row){ + BColumnListView::RemoveRow(row); + UpdateCount(); +} +void +EpisodeListView::AddRow(BRow* row, int32 index, BRow *parent){ + BColumnListView::AddRow(row,index,parent); + UpdateCount(); +} + +void +EpisodeListView::UpdateCount(){ + fStatusView->SetCount(CountRows()); +} + + +//-- diff --git a/sources-experimental/EpisodeListView.h b/sources-experimental/EpisodeListView.h new file mode 100644 index 0000000..8f94b70 --- /dev/null +++ b/sources-experimental/EpisodeListView.h @@ -0,0 +1,27 @@ +#ifndef _EpisodeListView_H_ +#define _EpisodeListView_H_ + +#include "ColumnListView.h" +#include "FileStatusColumn.h" +#include + +class StatusView; + +class EpisodeListView : public BColumnListView { + + public: + EpisodeListView(BRect r); + + void SelectionChanged(); + void AddRow(BRow*, BRow *parent = 0); + void AddRow(BRow*, int32 index, BRow *parent = 0); + void RemoveRow(BRow*); + + private: + void UpdateCount(); + StatusView* fStatusView; +}; + +#endif + +//. diff --git a/sources-experimental/Extractor.cpp b/sources-experimental/Extractor.cpp new file mode 100644 index 0000000..e3dd032 --- /dev/null +++ b/sources-experimental/Extractor.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#include "Extractor.h" +#include + +void +Extractor::SetNotifier(Notifier* list) +{ + fNotifier = list; +} + +void +Extractor::NotifyNotifier(ItemProperty key,void* data,ssize_t size){ + fNotifier->SetKey(key,data,size); +} + +void +Extractor::NotifyString(ItemProperty key,const char* data){ + fNotifier->SetKeyString(key,data); +} + +void +Extractor::NotifyInt32(ItemProperty key,int32 data){ + fNotifier->SetKeyInt32(key,data); +} + diff --git a/sources-experimental/Extractor.h b/sources-experimental/Extractor.h new file mode 100644 index 0000000..4363dd3 --- /dev/null +++ b/sources-experimental/Extractor.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef Extractor_H_ +#define Extractor_H_ + +#include "Notifier.h" +#include "ItemProperty.h" + + + +class Extractor +{ + +public: + + void SetNotifier(Notifier*); + + + protected: + + Notifier* fNotifier; + void NotifyNotifier(ItemProperty key,void* data,ssize_t); + void NotifyString(ItemProperty key,const char* data); + void NotifyInt32(ItemProperty key,int32 data); + +}; +#endif diff --git a/sources-experimental/FileStatus.h b/sources-experimental/FileStatus.h new file mode 100644 index 0000000..2b35583 --- /dev/null +++ b/sources-experimental/FileStatus.h @@ -0,0 +1,23 @@ +#ifndef FileStatus_H_ +#define FileStatus_H_ + +enum FileStatus { + // IMPORTANTE + // aggiungere nuovi stati in fondo a meno che non + // sapete esattamente che pasticcio riskiate di fare! + + ERROR = -1, + NOT_DOWNLOADED, // persistent. + ENQUEQUED, + DOWNLOADING, + DOWNLOADED, //persistent. + STOPPED, //should be persistent. + NOT_FOUND, + CANT_CONNECT, + CONNECTING, //no really a status.. + NEW, //I hate this! :) *8* + BAD_FORMAT, //if channel is not a valid rss file. + NO_ENCLOSURE //simple *10* + +}; +#endif diff --git a/sources-experimental/FileStatusColumn.cpp b/sources-experimental/FileStatusColumn.cpp new file mode 100644 index 0000000..45f6ddc --- /dev/null +++ b/sources-experimental/FileStatusColumn.cpp @@ -0,0 +1,318 @@ + +#include "FileStatusColumn.h" +#include "BPLocale.h" + +#include "Utils.h" +#include "stdio.h" + +#define kTEXT_MARGIN 8 +#define kSPACE_TEXT 0 + + +const int64 kKB_SIZE = 1024; +const int64 kMB_SIZE = 1048576; +const int64 kGB_SIZE = 1073741824; +const int64 kTB_SIZE = kGB_SIZE * kKB_SIZE; + + static BBitmap* fBar1 = NULL; + static BBitmap* fBar2 = NULL; + static BBitmap* fBack = NULL; + +//===================================================================== + +FileStatusField::FileStatusField(FileStatus status) + :fWidth(0), + fString(""), + fClippedString("") +{ + SetFileStatus(status); + SetFilePercentage(0); + SwapBitmap(); +} + +void FileStatusField::SetFileStatus(FileStatus status) +{ + + + if(status!=fStatus) + { + + fWidth = 0; + fClippedString.SetTo(""); + fStatus=status; + SwapBitmap(); + + + switch(fStatus){ + case NO_ENCLOSURE: + fOriginalStatus.SetTo(" "); + break; + case NEW: + fOriginalStatus.SetTo(_T("new")); + break; + case NOT_DOWNLOADED: + fOriginalStatus.SetTo(_TT("not down")); + break; + case DOWNLOADED: + fOriginalStatus.SetTo(_T("downloaded")); + break; + case ERROR: + fOriginalStatus.SetTo(_T("error")); + break; + case STOPPED: + fOriginalStatus.SetTo(_T("stopped")); + break; + case NOT_FOUND: + fOriginalStatus.SetTo(_T("not found")); + break; + case CANT_CONNECT: + fOriginalStatus.SetTo(_T("can't connect")); + break; + case DOWNLOADING: + fOriginalStatus.SetTo(_T("downloading")); + break; + case ENQUEQUED: + fOriginalStatus.SetTo(_T("enquequed")); + break; + case CONNECTING: + fOriginalStatus.SetTo(_T("connecting")); + break; + default: + fOriginalStatus.SetTo(_T("error")); + break; + } + fString=fOriginalStatus; + if(fStatus==STOPPED){ + //pervert game + int perv=fPercentage; + SetFilePercentage(0); + SetFilePercentage(perv); + } + } + +} + +void +FileStatusField::SetFilePercentage(int per,float speed) +{ + if(fPercentage==per) return; + + fWidth = 0; + SwapBitmap(); + fClippedString.SetTo(""); + fPercentage=per; + + if(fStatus == STOPPED || + fStatus == DOWNLOADING ) + { + BString sp; + sp << per << "% " ; + + if(speed>0 && fStatus == DOWNLOADING ) + { + + float size=speed; + char str[256]; + if (size < kKB_SIZE) + { + sprintf(str, "%Ld b/s", size); + } + else + { + const char* suffix; + float float_value; + if (size >= kTB_SIZE) + { + suffix = "TB/s"; + float_value = (float)size / kTB_SIZE; + } + else if (size >= kGB_SIZE) + { + suffix = "GB/s"; + float_value = (float)size / kGB_SIZE; + } + else if (size >= kMB_SIZE) + { + suffix = "MB/s"; + float_value = (float)size / kMB_SIZE; + } + else + { + suffix = "k/s"; + float_value = (float)size / kKB_SIZE; + } + + sprintf(str, "%.2f %s", float_value, suffix); + // strip off an insignificant zero so we don't get readings + // such as 1.00 + char *period = 0; + char *tmp (NULL); + for (tmp = str; *tmp; tmp++) + { + if (*tmp == '.') + period = tmp; + } + if (period && period[1] && period[2] == '0') + // move the rest of the string over the insignificant zero + for (tmp = &period[2]; *tmp; tmp++) + *tmp = tmp[1]; + + + sp << str << " "; //speed; + } + sp << fOriginalStatus; + fString = sp; + } + } +} + +void +FileStatusField::SwapBitmap(){ + + if(fBar==fBar1) fBar=fBar2; + else fBar=fBar1; + +} + +//-------------------------------------------------------------------- + +void FileStatusField::SetString(const char* val) +{ + fString = val; + fClippedString = ""; + fWidth = 0; +} + + +//-------------------------------------------------------------------- + +const char* FileStatusField::String() const +{ + return fString.String(); +} + + +//-------------------------------------------------------------------- + +void FileStatusField::SetWidth(float width) +{ + fWidth = width; +} + +//-------------------------------------------------------------------- + +float FileStatusField::Width() +{ + return fWidth; +} + + +//-------------------------------------------------------------------- + +void FileStatusField::SetClippedString(const char* val) +{ + fClippedString = val; +} + + +//-------------------------------------------------------------------- + +const char* FileStatusField::ClippedString() +{ + return fClippedString.String(); +} + + +//===================================================================== + +FileStatusColumn::FileStatusColumn(const char* title, float width, float minWidth, + float maxWidth, uint32 truncate, alignment align) + :BTitledColumn(title, width, minWidth, maxWidth, align), + fTruncate(truncate) +{ + if(fBar1 ==NULL) fBar1=LoadIcon("fullbar1.png"); + if(fBar2==NULL) fBar2=LoadIcon("fullbar2.png"); + if(fBack==NULL) fBack=LoadIcon("graybar.png"); +} + + +//-------------------------------------------------------------------- + +void FileStatusColumn::DrawField(BField* _field, BRect rect, BView* parent) +{ + + FileStatusField* field = static_cast(_field); + + float width = rect.Width() - (2 * kTEXT_MARGIN); + float basePoint = 0; + + if(field->GetFileStatus() == STOPPED || + field->GetFileStatus() == DOWNLOADING ) + { + basePoint = 100 + kSPACE_TEXT; + } + + if (width - basePoint != field->Width()) + { + BString out_string(field->String()); + + parent->TruncateString(&out_string, fTruncate, width + 2 - basePoint); + field->SetClippedString(out_string.String()); + field->SetWidth(width - basePoint); + } + + if(basePoint>0){ + + DrawBar(parent,rect,field->GetPercentage(),field->Bar()); + } + rect.left +=basePoint; + DrawString(field->ClippedString(), parent, rect); +} + + + +void +FileStatusColumn::DrawBar(BView* parent,BRect rect,int number,BBitmap* fBar) +{ + + + parent->PushState(); + parent->SetDrawingMode( B_OP_ALPHA ); + parent->SetBlendingMode( B_PIXEL_ALPHA, B_ALPHA_OVERLAY); + + BRect graphRect(rect); + graphRect.right = graphRect.left+99; + graphRect.top +=2; + graphRect.bottom = graphRect.top + 11; + + parent->DrawBitmap(fBack,graphRect); //BPoint(rect.right,rect.top)); + + + BRect sourceRect(fBar->Bounds()); + sourceRect.right = sourceRect.left + number; + + BRect destRect(graphRect); + destRect.right = destRect.left + number; + parent->DrawBitmap(fBar,sourceRect,destRect); //sourceRect,destRect); + + parent->PopState(); + +} + + +//-------------------------------------------------------------------- + +int FileStatusColumn::CompareFields(BField* field1, BField* field2) +{ + return(ICompare(((FileStatusField*)field1)->String(), + (((FileStatusField*)field2)->String()))); +} + + +//-------------------------------------------------------------------- + +bool FileStatusColumn::AcceptsField(const BField *field) const +{ + return static_cast(dynamic_cast(field)); +} + diff --git a/sources-experimental/FileStatusColumn.h b/sources-experimental/FileStatusColumn.h new file mode 100644 index 0000000..3717d66 --- /dev/null +++ b/sources-experimental/FileStatusColumn.h @@ -0,0 +1,77 @@ +#ifndef _FileStatusColumn_H +#define _FileStatusColumn_H + +#include "ColumnListView.h" +#include "ColumnTypes.h" +#include +#include +#include +#include "FileStatus.h" + + +//===================================================================== +// Field and column classes a FileStatus. + +class FileStatusField : public BField +{ + public: + FileStatusField (FileStatus status); + + void SetFileStatus(FileStatus file); + void SetFilePercentage(int per,float speed = 0); + + void SetString (const char* string); + const char* String () const; + void SetClippedString (const char* string); + const char* ClippedString (); + void SetWidth (float); + float Width (); + FileStatus GetFileStatus(){ return fStatus;} + int GetPercentage(){return fPercentage;} + //bool HasChanged() { return fChanged; } + //void SetChanged(bool val) { fChanged = val;} + BBitmap* Bar(){ return fBar; } + private: + + void SwapBitmap(); + + float fWidth; + BString fString; + BString fClippedString; + BString fOriginalStatus; + FileStatus fStatus; + int fPercentage; + BBitmap *fBar; + +}; + +class FileStatusColumn : public BTitledColumn +{ + public: + FileStatusColumn (const char *title, + float width, + float minWidth, + float maxWidth, + uint32 truncate, + alignment align = B_ALIGN_LEFT); + virtual void DrawField (BField* field, + BRect rect, + BView* parent); + virtual int CompareFields (BField* field1, + BField* field2); + virtual bool AcceptsField (const BField* field) const; + + + //void SwapBitmap(); + + + + + private: + void DrawBar(BView* parent,BRect rect,int perc,BBitmap* fBar); + uint32 fTruncate; + //BBitmap* fBar; + +}; + +#endif diff --git a/sources-experimental/GreenBoxTextRender.cpp b/sources-experimental/GreenBoxTextRender.cpp new file mode 100644 index 0000000..74d4f1a --- /dev/null +++ b/sources-experimental/GreenBoxTextRender.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#include "GreenBoxTextRender.h" + + + + +GreenBoxTextRender::GreenBoxTextRender(){ + fFont = *be_fixed_font; + fBackColor = greyBox; +}; + +GreenBoxTextRender::GreenBoxTextRender(BFont font,const rgb_color color){ + fFont = font; + fBackColor = color; +}; + +GreenBoxTextRender::~GreenBoxTextRender(){ +} + +void +GreenBoxTextRender::Render(BView *target,const char* txt,int16 num,BPoint pos,BRect rect){ + target->SetFont(&fFont); + target->DrawString(txt,num,pos); + +} + +void +GreenBoxTextRender::GetHeight(font_height *height){ + fFont.GetHeight(height); + height->ascent += 2; + height->descent +=2; +} + +void +GreenBoxTextRender::GetEscapements(const char charArray[], int32 numChars,float escapementArray[]){ + fFont.GetEscapements(charArray,numChars,escapementArray); +} + +float +GreenBoxTextRender::Size(float maxwidth){ + return fFont.Size(); +} + + + void + GreenBoxTextRender::MarginAfterTheText(BView *target,rgb_color view_color, BRect rect){ + // Margin after fText + target->SetDrawingMode (B_OP_COPY); + //rect.right -=5; + target->SetLowColor (fBackColor); + target->FillRect (rect, B_SOLID_LOW); + } diff --git a/sources-experimental/GreenBoxTextRender.h b/sources-experimental/GreenBoxTextRender.h new file mode 100644 index 0000000..0dfb021 --- /dev/null +++ b/sources-experimental/GreenBoxTextRender.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + + +#ifndef _GreenBoxTextRender_H_ +#define _GreenBoxTextRender_H_ + +#include +#include +#include "TextRender.h" + +const rgb_color greyBox = {255,234,130,255}; //200,203,235 255,234,130 185,185,185 233,233,223 + +class GreenBoxTextRender : public TextRender +{ + public: + GreenBoxTextRender(); + GreenBoxTextRender(BFont font,const rgb_color color); + virtual ~GreenBoxTextRender(); + + void Render(BView *target,const char*,int16 num,BPoint pos,BRect rect); + void GetHeight(font_height *height); + void GetEscapements(const char charArray[], int32 numChars,float escapementArray[]); + float Size(float maxwidth); + // + void MarginAfterTheText(BView *target,rgb_color view_color, BRect rect); + + + private: + BFont fFont; + rgb_color fBackColor; +}; +#endif diff --git a/sources-experimental/GroupItem.cpp b/sources-experimental/GroupItem.cpp new file mode 100644 index 0000000..f6cda03 --- /dev/null +++ b/sources-experimental/GroupItem.cpp @@ -0,0 +1,24 @@ +#include "GroupItem.h" +#include "SubscriptionColumn.h" + +#define ALTEZZA_SMALL 16 + +GroupItem::GroupItem(const char* label, GroupItem* parentGroup):BRow(ALTEZZA_SMALL) { + SetField( new PositionableField(label), 0 ); + f_Parent = parentGroup; +} + +BString +GroupItem::GroupName(){ + return ((PositionableField*)GetField(0))->String(); +} + +void +GroupItem::SetGroupName(BString name){ + ((PositionableField*)GetField(0))->SetString(name.String()); +} + +GroupItem* +GroupItem::GetParentItem(){ + return f_Parent; +} diff --git a/sources-experimental/GroupItem.h b/sources-experimental/GroupItem.h new file mode 100644 index 0000000..c04baca --- /dev/null +++ b/sources-experimental/GroupItem.h @@ -0,0 +1,23 @@ +#ifndef _GroupItem_H_ +#define _GroupItem_H_ + +#include "ColumnListView.h" +#include "ColumnTypes.h" + + +class GroupItem : public BRow { + + public: + GroupItem(const char* label, GroupItem* parentGroup); + + BString GroupName(); + void SetGroupName(BString); + + GroupItem* GetParentItem(); + + private: + + GroupItem* f_Parent; +}; + +#endif diff --git a/sources-experimental/HelpTextView.h b/sources-experimental/HelpTextView.h new file mode 100644 index 0000000..8853ccf --- /dev/null +++ b/sources-experimental/HelpTextView.h @@ -0,0 +1,58 @@ +#include +#include +//#include "HelpView.h" + + +class HelpTextView : public BView +{ + public: + HelpTextView(BRect frame, char *name, BString testo, BPoint posizione, int grandezza_font, BFont tipo); + virtual void AttachedToWindow(); + virtual void Draw(BRect updateRect); + BString fText; + BPoint point; + BFont font; + int size; + + + + + + + + + +}; + +HelpTextView::HelpTextView(BRect rect, char *name, BString testo, BPoint posizione,int grandezza_font, BFont tipo) + : BView(rect, name, B_FOLLOW_ALL, B_WILL_DRAW) +{ +fText=testo; +point=posizione; +size=grandezza_font; +font=tipo; + + + SetViewColor(159,181,202); + +} + +void HelpTextView::AttachedToWindow() +{ + + SetFont(&font, B_FONT_FAMILY_AND_STYLE); + SetFontSize(size); +} + + +void HelpTextView::Draw(BRect updateRect) +{ + MovePenTo(BPoint(point)); + SetHighColor(0,0,0); + SetLowColor(159,181,202); + + + DrawString(fText.String()); + +} + diff --git a/sources-experimental/HelpWindow.cpp b/sources-experimental/HelpWindow.cpp new file mode 100644 index 0000000..da11340 --- /dev/null +++ b/sources-experimental/HelpWindow.cpp @@ -0,0 +1,168 @@ +#include "HelpWindow.h" + + +#include +#include +#include + +#include +#include +#include "BPLocale.h" +#include + +#include "libfish/HelpViewer.h" +#include "Utils.h" + + + + + +HelpWindow::HelpWindow() : + BWindow(BRect(300,100,780,475),_T("Getting Started"), B_TITLED_WINDOW,B_NOT_RESIZABLE| B_NOT_ZOOMABLE|B_ASYNCHRONOUS_CONTROLS|B_WILL_DRAW){ + + BRect rect(Bounds()); + rect.bottom *= 0.87; + + AddChild(hv=new HelpViewer(rect)); + + rect.top = rect.bottom+1; + rect.bottom = Bounds().bottom; + BBox *box; + AddChild(box=new BBox(rect,"")); + + BFont font(be_plain_font); + + + BRect arect; + arect = box->Bounds(); + arect.InsetBy(33, 20); + arect.top = arect.bottom - 17; + arect.left = arect.right - font.StringWidth(_T("Next")) - 35; //anche qui va il _T() altrimenti considera sempre la dimensione di Next e non della stringa tradotta + next = new BButton(arect, "", _T("Next"), new BMessage('next')); + next->SetFont(&font); + box->AddChild(next); + + arect.right = arect.left - 17; + arect.left = arect.right - font.StringWidth(_T("Prev")) - 35; + back= new BButton(arect, "", _T("Prev"), new BMessage('prev')); + back->SetFont(&font); + box->AddChild(back); + + arect = box->Bounds(); + arect.InsetBy(33, 20); + arect.top = arect.bottom - 17; + arect.right = arect.left + font.StringWidth(_T("Index")) + 35; + BButton *index= new BButton(arect, "", _T("Index"), new BMessage('inde')); + box->AddChild(index); + + + rgb_color black = {0,0,0,255}; + rgb_color white = {255,255,255,255}; + hv->SetForeColor(black) ; + hv->SetBackColor(white); + + + BString where(GetAppRelativePath()); + #ifdef ZETA + where << "/help.xml"; + #else + where << "/helpR5.xml"; + #endif + hv->LoadFile(where.String()); + hv->SetGotoHandler(this); + hv->SetOpenUrlHandler(be_app); + + Selected = -1; + SetPage(0); + +} + + +void +HelpWindow::SetPage(BString id){ + if(Lock()){ + hv->SearchSetPage(id); + Unlock(); + } +} + +void +HelpWindow::SetPage(int newindex){ + + if(Selected == newindex) return; + if(newindex >= hv->CountPage()) return; + + Selected = newindex; + hv->SetPage(Selected); + + next->SetEnabled(true); + back->SetEnabled(true); + + if(Selected == hv->CountPage() - 1) + { + + next->SetEnabled(false); + } + + if(Selected == 0) + { + back->SetEnabled(false); + } + +} + +/* +bool +HelpWindow::QuitRequested() +{ + be_app->PostMessage(B_QUIT_REQUESTED); + return true; +} +*/ +void +HelpWindow::MessageReceived(BMessage* message) +{ + switch(message->what) + { + case 'inde': + SetPage(BString("index")); + break; + case 'next': + SetPage(Selected+1); + break; + case 'prev': + SetPage(Selected-1); + break; + case HELPVIEWER_GOTO: + { + + int32 newindex; + if(message->FindInt32("selected",&newindex)==B_OK){ + + if(Selected == newindex) return; + if(newindex >= hv->CountPage()) return; + Selected = newindex; + + + next->SetEnabled(true); + back->SetEnabled(true); + if(Selected == hv->CountPage() - 1) + { + next->SetEnabled(false); + } + if(Selected == 0) + { + back->SetEnabled(false); + } + } + + } + break; + default: + BWindow::MessageReceived(message); + break; + + } +} + +//. diff --git a/sources-experimental/HelpWindow.h b/sources-experimental/HelpWindow.h new file mode 100644 index 0000000..b33df32 --- /dev/null +++ b/sources-experimental/HelpWindow.h @@ -0,0 +1,31 @@ +#ifndef HelpWindow_H +#define HelpWindow_H + +#include + +class HelpViewer; +class BButton; + +class HelpWindow: public BWindow +{ + + + + public: + HelpWindow(); + void MessageReceived(BMessage* message); + void SetPage(BString id); + + + private: + + int Selected; + void SetPage(int i); + HelpViewer* hv; + BButton *back; + BButton *next; +}; + +#endif + +//sas diff --git a/sources-experimental/IABPChannel.cpp b/sources-experimental/IABPChannel.cpp new file mode 100644 index 0000000..3772b74 --- /dev/null +++ b/sources-experimental/IABPChannel.cpp @@ -0,0 +1,294 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +//actions for channels + +//#include "SubscriptionListItem.h" +#include "IABPChannel.h" +#include "MainWindow.h" +#include "MainController.h" +#include +#include "ChannelSettingsWindow.h" + +//extern BMessage podder_settings; + +#define LOCKWINDOW if(fView->Lock()){ +#define UNLOCKWINDOWERROR { fView->Unlock(); return B_ERROR; } +#define UNLOCKWINDOW fView->Unlock();} + +//------------------------------------------------------------------------------------------------------------------- + + +IABPChannelAddRequest::IABPChannelAddRequest(MainController* controller, MainWindow* view ):IActionBP(controller,view){ + + SetIcon(IAction::SIZE_16,LoadIcon("emblem-add.png")); + SetIcon(IAction::SIZE_48,LoadIcon("add-channel-file.png")); + SetIcon(IAction::SIZE_48_PRESSED,LoadIcon("add-channel-file-down.png")); + + SetLabel(_T("Add Channel")); + +} + +BString +IABPChannelAddRequest::GetDescription(){ + return _T("Add the podcast to the Subscriptions list"); +} + + +status_t +IABPChannelAddRequest::Perform(BMessage*){ + AddWindow *url = new AddWindow(); + url->Show(); + return B_OK; +} + +char +IABPChannelAddRequest::Shortcut(uint32 *modifiers) const { + if(modifiers) + *modifiers = B_COMMAND_KEY | B_SHIFT_KEY; + return 'A'; +} + +//------------------------------------------------------------------------------------------------------------------- + +IABPChannelRemove::IABPChannelRemove(MainController* controller ,MainWindow* view):IActionBP(controller,view){ + + SetIcon(IAction::SIZE_16,LoadIcon("delete-micro.png")); + SetIcon(IAction::SIZE_48,LoadIcon("delete-channel-file.png")); + SetIcon(IAction::SIZE_48_PRESSED,LoadIcon("delete-channel-file-down.png")); + + SetLabel(_T("Remove Channel")); + +} + +BString +IABPChannelRemove::GetDescription(){ + return _T("Delete the podcast from the Subscriptions list"); +} + + +status_t +IABPChannelRemove::Perform(BMessage*){ + + + + SubscriptionListItem* row=fView->GetSelectedSubscription(); + if(!row) return B_ERROR; + + + //TODO: studiare la disposizione dei pulsanti! + + BString text; + + text << _TT("alert2a"); + text << row->GetTitle(); + text << _TT("alert2b"); + + BPAlert* remove = new BPAlert("Remove a Channel", text.String(),_T("Delete"),_T("Archive"),_T("Cancel"),B_WIDTH_AS_USUAL,LoadIcon("delete-channel-file.png")); + int32 result=remove->Go(); + + LOCKWINDOW + if(result==1) + fController->ArchiveChannel(row->fRef); + else + if(result==0){ + BPAlert* wait = new BPAlert("Remove a Channel", "\nRemoving..",NULL,NULL,NULL,B_WIDTH_AS_USUAL,LoadIcon("delete-channel-file.png")); + fView->UpdateIfNeeded(); + wait->Go(NULL); + + status_t result = fController->DeleteChannel(row->fRef); + + wait->PostMessage(B_QUIT_REQUESTED); + + if(result !=B_OK){ + wait = new BPAlert("Remove a Channel", "\nAn error occured while removing!",_T("Ok"),NULL,NULL,B_WIDTH_AS_USUAL,LoadIcon("delete-channel-file.png")); + + wait->Go(); + } + + + } + UNLOCKWINDOW + + return B_OK; +} + +char +IABPChannelRemove::Shortcut(uint32 *modifiers) const { + if(modifiers) + *modifiers = B_COMMAND_KEY | B_SHIFT_KEY; + return 'R'; +} + +//------------------------------------------------------------------------------------------------------------------- + +IABPChannelCheck::IABPChannelCheck(MainController* controller,MainWindow* view):IActionBP(controller,view){ + + SetIcon(IAction::SIZE_16,LoadIcon("refresh-micro.png")); + SetIcon(IAction::SIZE_48,LoadIcon("refresh-channel-file.png")); + SetIcon(IAction::SIZE_48_PRESSED,LoadIcon("refresh-channel-file-down.png")); + + SetLabel(_T("Check Channel")); + +} + +BString +IABPChannelCheck::GetDescription(){ + return _T("Check the selected podcast for new items"); +} + + +status_t +IABPChannelCheck::Perform(BMessage*){ + LOCKWINDOW + SubscriptionListItem* row=fView->GetSelectedSubscription(); + if(!row) UNLOCKWINDOWERROR + + fController->CheckChannel(row->fRef); + UNLOCKWINDOW + return B_OK; +} + +char +IABPChannelCheck::Shortcut(uint32 *modifiers) const { + if(modifiers) + *modifiers = B_COMMAND_KEY | B_SHIFT_KEY; + return 'C'; +} + +//------------------------------------------------------------------------------------------------------------------- + +IABPChannelWWW::IABPChannelWWW(MainController* controller,MainWindow* view):IActionBP(controller,view){ + + SetIcon(IAction::SIZE_16,LoadIcon("www-micro.png")); + SetIcon(IAction::SIZE_48,LoadIcon("www-channel-file.png")); + SetIcon(IAction::SIZE_48_PRESSED,LoadIcon("www-channel-file-down.png")); + + SetLabel(_T("Open Homepage")); + +} + +BString +IABPChannelWWW::GetDescription(){ + return _T("Show the podcast homepage"); +} + + +status_t +IABPChannelWWW::Perform(BMessage*){ + + SubscriptionListItem* row=fView->GetSelectedSubscription(); + if(!row || row->GetWeblink()=="" ) return B_ERROR; + + fController->OpenURL(row->GetWeblink()); + return B_OK; +} + +char +IABPChannelWWW::Shortcut(uint32 *modifiers) const { + if(modifiers) + *modifiers = B_COMMAND_KEY | B_SHIFT_KEY; + return 'H'; +} + +//------------------------------------------------------------------------------------------------------------------- + + +IABPChannelEnclosureFolder::IABPChannelEnclosureFolder(MainController* controller,MainWindow* view):IActionBP(controller,view){ + SetIcon(IAction::SIZE_16,LoadIcon("folder")); + + SetLabel(_T("Open Enclosures folder")); + +} + +BString +IABPChannelEnclosureFolder::GetDescription(){ + return _T("Open Enclosures folder"); +} + + +status_t +IABPChannelEnclosureFolder::Perform(BMessage*){ + LOCKWINDOW + SubscriptionListItem* row=fView->GetSelectedSubscription(); + if(row) + fController->FolderSelectedChannel(row->fRef); + UNLOCKWINDOW + return B_OK; +} + +char +IABPChannelEnclosureFolder::Shortcut(uint32 *modifiers) const { + if(modifiers) + *modifiers = B_COMMAND_KEY ; + return 'O'; +} + + +//------------------------------------------------------------------------------------------------------------------- + +IABPChannelCheckAll::IABPChannelCheckAll(MainController* controller,MainWindow* view):IActionBP(controller,view){ + + SetIcon(IAction::SIZE_16,LoadIcon("refresh-mini-all.png")); + //SetIcon(IAction::SIZE_48,LoadIcon("refresh-channel-file.png")); + //SetIcon(IAction::SIZE_48_PRESSED,LoadIcon("refresh-channel-file-down.png")); + + SetLabel(_T("Check All Channels")); + +} + +BString +IABPChannelCheckAll::GetDescription(){ + return _T("Check all the podcasts for new items"); +} + + +status_t +IABPChannelCheckAll::Perform(BMessage*){ + fView->PostMessage(CHECK_ALL); + return B_OK; +} + +char +IABPChannelCheckAll::Shortcut(uint32 *modifiers) const { + if(modifiers) + *modifiers = B_COMMAND_KEY | B_SHIFT_KEY; + return 'N'; +} + +//------------------------------------------------------------------------------------------------------------------- + +IABPChannelShowImage::IABPChannelShowImage(MainController* controller,MainWindow* view):IActionBP(controller,view){ + SetIcon(IAction::SIZE_16,LoadIcon("image")); + //SetIcon(IAction::SIZE_48,LoadIcon("refresh-channel-file.png")); + //SetIcon(IAction::SIZE_48_PRESSED,LoadIcon("refresh-channel-file-down.png")); + SetLabel(_T("Show Channel Image")); +} + +BString +IABPChannelShowImage::GetDescription(){ + return _T("Show Channel Image"); +} + + +status_t +IABPChannelShowImage::Perform(BMessage*){ + LOCKWINDOW + SubscriptionListItem* row=fView->GetSelectedSubscription(); + if(row) + fController->ShowChannelImage(row->fRef); + //if(!row->extraSetting) row->extraSetting=new BMessage(); + //ChannelSettingsWindow* csw=new ChannelSettingsWindow(row->extraSetting,fView); + //csw->Show(); + + UNLOCKWINDOW + return B_OK; +} + +char +IABPChannelShowImage::Shortcut(uint32 *modifiers) const { + return 0; +} diff --git a/sources-experimental/IABPChannel.h b/sources-experimental/IABPChannel.h new file mode 100644 index 0000000..fa251cc --- /dev/null +++ b/sources-experimental/IABPChannel.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef _IABPChannel_h_ +#define _IABPChannel_h_ + +#include "IActionBP.h" +#include "Utils.h" +#include "AddWindow.h" + +#include "BPLocale.h" + +//request for the AddWindow + +//------------------------------------------------------------------------------------------------------------------- +class IABPChannelAddRequest : public IActionBP +{ + public: + + IABPChannelAddRequest(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; + +}; + +//------------------------------------------------------------------------------------------------------------------- +class IABPChannelRemove : public IActionBP +{ + public: + + IABPChannelRemove(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; +}; + +//------------------------------------------------------------------------------------------------------------------- +class IABPChannelCheck : public IActionBP +{ + public: + + IABPChannelCheck(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; + +}; + +//------------------------------------------------------------------------------------------------------------------- + +class IABPChannelWWW: public IActionBP +{ + public: + + IABPChannelWWW(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; + +}; + +//------------------------------------------------------------------------------------------------------------------- + +class IABPChannelEnclosureFolder: public IActionBP +{ + public: + + IABPChannelEnclosureFolder(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; + +}; + +//------------------------------------------------------------------------------------------------------------------- + +class IABPChannelCheckAll: public IActionBP +{ + public: + + IABPChannelCheckAll(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; + +}; + +//------------------------------------------------------------------------------------------------------------------- + +class IABPChannelShowImage: public IActionBP +{ + public: + + IABPChannelShowImage(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; + +}; + + + +#endif diff --git a/sources-experimental/IABPDownload.cpp b/sources-experimental/IABPDownload.cpp new file mode 100644 index 0000000..4d2db53 --- /dev/null +++ b/sources-experimental/IABPDownload.cpp @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +//actions for items + +#include "IABPDownload.h" +#include "MainWindow.h" +#include "MainController.h" + +#define LOCKWINDOW if(fView->Lock()){ +#define UNLOCKWINDOWERROR { fView->Unlock(); return B_ERROR; } +#define UNLOCKWINDOW fView->Unlock();} + + +IABPDownloadRemove::IABPDownloadRemove(MainController* controller,MainWindow* view):IActionBP(controller,view){ + + SetIcon(IAction::SIZE_16,LoadIcon("emblem-remove.png")); + //SetIcon(IAction::SIZE_48,LoadIcon("emblem-delete.png")); + //SetIcon(IAction::SIZE_48_PRESSED,LoadIcon("emblem-delete-down.png")); + + SetLabel(_T("Remove from this list")); +} + +BString +IABPDownloadRemove::GetDescription(){ + return _T(""); +} + + +status_t +IABPDownloadRemove::Perform(BMessage*){ + + LOCKWINDOW + DownloadListItem* row=fView->GetSelectedDownload(); + if(row) + fController->RemoveDownload(row->fRef); + UNLOCKWINDOW + return B_OK; +} + +char +IABPDownloadRemove::Shortcut(uint32 *modifiers) const { + return 0; +} + +//------------------------------------------------------------------------------------------------------------------- + + +IABPDownloadStop::IABPDownloadStop(MainController* controller, MainWindow* view):IActionBP(controller,view){ + + SetIcon(IAction::SIZE_16,LoadIcon("stopped-micro.png")); + SetIcon(IAction::SIZE_48,LoadIcon("emblem-stop.png")); + SetIcon(IAction::SIZE_48_PRESSED,LoadIcon("emblem-stop-down.png")); + + SetLabel(_T("Stop download")); +} + +BString +IABPDownloadStop::GetDescription(){ + return _T("Stop the item download"); +} + + +status_t +IABPDownloadStop::Perform(BMessage*){ + + LOCKWINDOW + DownloadListItem* row=fView->GetSelectedDownload(); + if(row) + fController->StopDownloadItem(row->fRef); + UNLOCKWINDOW + + return B_OK; +} + +char +IABPDownloadStop::Shortcut(uint32 *modifiers) const { + /*if(modifiers) + *modifiers = B_COMMAND_KEY; + return 'S'; + */ + return 0; +} + +//------------------------------------------------------------------------------------------------------------------- + + +IABPDownloadDownload::IABPDownloadDownload(MainController* controller,MainWindow* view):IActionBP(controller,view){ + + SetIcon(IAction::SIZE_16,LoadIcon("download-micro.png")); + SetIcon(IAction::SIZE_48,LoadIcon("emblem-download.png")); + SetIcon(IAction::SIZE_48_PRESSED,LoadIcon("emblem-download-down.png")); + + SetLabel(_T("(Re)start download")); +} + +BString +IABPDownloadDownload::GetDescription(){ + return _T("Download the selected episode"); +} + + +status_t +IABPDownloadDownload::Perform(BMessage*){ + LOCKWINDOW + DownloadListItem* row=fView->GetSelectedDownload(); + if(row) + fController->DownloadItem(row->fRef); + UNLOCKWINDOW + return B_OK; +} + + +char +IABPDownloadDownload::Shortcut(uint32 *modifiers) const { + /*if(modifiers) + *modifiers = B_COMMAND_KEY; + return 'D';*/ + return (char)NULL; +} + + +//------------------------------------------------------------------------------------------------------------------- + + +IABPDownloadPlay::IABPDownloadPlay(MainController* controller,MainWindow* view):IActionBP(controller,view){ + + SetIcon(IAction::SIZE_16,LoadIcon("play-micro.png")); + SetIcon(IAction::SIZE_48,LoadIcon("emblem-play.png")); + SetIcon(IAction::SIZE_48_PRESSED,LoadIcon("emblem-play-down.png")); + + SetLabel(_T("Play enclosure")); +} + +BString +IABPDownloadPlay::GetDescription(){ + return _T("Play the selected episode"); +} + + +status_t +IABPDownloadPlay::Perform(BMessage*){ + LOCKWINDOW + DownloadListItem* row=fView->GetSelectedDownload(); + if(row) + fController->PlayItem(row->fRef); + UNLOCKWINDOW + + return B_OK; +} + +char +IABPDownloadPlay::Shortcut(uint32 *modifiers) const { + /*if(modifiers) + *modifiers = B_COMMAND_KEY; + return 'E'; + */ + + return (char)NULL; +} + + +//------------------------------------------------------------------------------------------------------------------- + +IABPDownloadFindItem::IABPDownloadFindItem(MainController* controller,MainWindow* view):IActionBP(controller,view){ + + SetIcon(IAction::SIZE_16,LoadIcon("emblem-jump.png")); + //SetIcon(IAction::SIZE_48,LoadIcon("www-channel-file.png")); + //SetIcon(IAction::SIZE_48_PRESSED,LoadIcon("www-channel-file-down.png")); + + SetLabel(_T("Find this Item")); + +} + +BString +IABPDownloadFindItem::GetDescription(){ + return _T(""); +} + + +status_t +IABPDownloadFindItem::Perform(BMessage*){ + LOCKWINDOW + DownloadListItem* row=fView->GetSelectedDownload(); + if(row) + fController->FindItem(row->fRef); + UNLOCKWINDOW + return B_OK; +} + + +char +IABPDownloadFindItem::Shortcut(uint32 *modifiers) const { + //if(modifiers) + // *modifiers = B_COMMAND_KEY; + return (char)NULL; +} + + diff --git a/sources-experimental/IABPDownload.h b/sources-experimental/IABPDownload.h new file mode 100644 index 0000000..cf16448 --- /dev/null +++ b/sources-experimental/IABPDownload.h @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef _IABPDownload_h_ +#define _IABPDownload_h_ + +#include "IActionBP.h" +#include "Utils.h" +#include "BPLocale.h" + + +//------------------------------------------------------------------------------------------------------------------- +class IABPDownloadRemove : public IActionBP +{ + public: + + IABPDownloadRemove(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; + +}; + +//------------------------------------------------------------------------------------------------------------------- +class IABPDownloadStop : public IActionBP +{ + public: + + IABPDownloadStop(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; + +}; + +//------------------------------------------------------------------------------------------------------------------- +class IABPDownloadDownload : public IActionBP +{ + public: + + IABPDownloadDownload(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; +}; + +//------------------------------------------------------------------------------------------------------------------- +class IABPDownloadPlay: public IActionBP +{ + public: + + IABPDownloadPlay(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; + +}; + +//------------------------------------------------------------------------------------------------------------------- + +class IABPDownloadFindItem: public IActionBP +{ + public: + + IABPDownloadFindItem(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; + +}; + +//------------------------------------------------------------------------------------------------------------------- +/* +class IABPDownloadEnclosureFolder: public IActionBP +{ + public: + + IABPDownloadEnclosureFolder(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; + +}; +*/ +#endif diff --git a/sources-experimental/IABPGroup.cpp b/sources-experimental/IABPGroup.cpp new file mode 100644 index 0000000..7a047b0 --- /dev/null +++ b/sources-experimental/IABPGroup.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2007 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +//actions for groups + +#include "IABPGroup.h" +#include "MainWindow.h" +#include "MainController.h" +#include "TextControlFloater.h" + +#include + +#define LOCKWINDOW if(fView->Lock()){ +#define UNLOCKWINDOWERROR { fView->Unlock(); return B_ERROR; } +#define UNLOCKWINDOW fView->Unlock();} + + + +//------------------------------------------------------------------------------------------------------------------- + +IABPGroupCheck::IABPGroupCheck(MainController* controller,MainWindow* view):IActionBP(controller,view){ + + SetIcon(IAction::SIZE_16,LoadIcon("refresh-micro.png")); + //SetIcon(IAction::SIZE_48,LoadIcon("refresh-channel-file.png")); + //SetIcon(IAction::SIZE_48_PRESSED,LoadIcon("refresh-channel-file-down.png")); + + SetLabel(_T("Check Channels of Group")); + +} + +BString +IABPGroupCheck::GetDescription(){ + return _T("Check the podcasts of the selected group for new items"); +} + + +status_t +IABPGroupCheck::Perform(BMessage*){ + LOCKWINDOW + GroupItem* group=fView->GetSelectedGroup(); + if(!group) UNLOCKWINDOWERROR + int32 count = fView->CountSubscriptionOfGroup(group); + for(int i=0;iGetSubscriptionOfGroup(i,group); + if(row) + fController->CheckChannel(row->fRef); + } + UNLOCKWINDOW + return B_OK; +} + +char +IABPGroupCheck::Shortcut(uint32 *modifiers) const { + return 0; +// if(modifiers) +// *modifiers = B_COMMAND_KEY | B_SHIFT_KEY; +// return 'C'; +} + +//------------------------------------------------------------------------------------------------------------------- + +IABPGroupAdd::IABPGroupAdd(MainController* controller,MainWindow* view):IActionBP(controller,view){ + + SetIcon(IAction::SIZE_16,LoadIcon("emblem-add.png")); + SetLabel(_T("Add a Group")); + +} + +BString +IABPGroupAdd::GetDescription(){ + return _T("Add a new Group"); +} + + +status_t +IABPGroupAdd::Perform(BMessage*){ + LOCKWINDOW + fController->AddNewGroup(NULL); + UNLOCKWINDOW + return B_OK; +} + +char +IABPGroupAdd::Shortcut(uint32 *modifiers) const { + return 0; +} + + +//------------------------------------------------------------------------------------------------------------------- + +IABPGroupRename::IABPGroupRename(MainController* controller,MainWindow* view):IActionBP(controller,view){ + + SetIcon(IAction::SIZE_16,LoadIcon("emblem-add.png")); //fix this icon.. + SetLabel(_T("Rename a Group")); + +} + +BString +IABPGroupRename::GetDescription(){ + return _T("Rename the selected Group"); +} + + +status_t +IABPGroupRename::Perform(BMessage*){ + LOCKWINDOW + GroupItem* group=fView->GetSelectedGroup(); + if(!group) UNLOCKWINDOWERROR + BRect rect; + if(fView->GetScreenGroupRect(group,&rect)){ + BMessage *info=new BMessage(GROUP_NAME_CHANGE); + info->AddString("oldname",group->GroupName()); + new TextControlFloater(rect,B_ALIGN_LEFT,be_plain_font,group->GroupName().String(),BMessenger(fView),info); + } + UNLOCKWINDOW + return B_OK; +} + +char +IABPGroupRename::Shortcut(uint32 *modifiers) const { + return 0; +} + +//------------------------------------------------------------------------------------------------------------------- + + +IABPGroupRemove::IABPGroupRemove(MainController* controller,MainWindow* view):IActionBP(controller,view){ + + SetIcon(IAction::SIZE_16,LoadIcon("delete-micro.png")); + //SetIcon(IAction::SIZE_48,LoadIcon("emblem-delete.png")); + //SetIcon(IAction::SIZE_48_PRESSED,LoadIcon("emblem-delete-down.png")); + + SetLabel(_T("Remove a Group")); +} + +BString +IABPGroupRemove::GetDescription(){ + return _T("Remove a group and delete all the channels"); +} + + +status_t +IABPGroupRemove::Perform(BMessage*){ + + GroupItem* group=fView->GetSelectedGroup(); + if(!group) return B_ERROR; + + int32 count = fView->CountSubscriptionOfGroup(group); + + LOCKWINDOW + + if(count>0) { + BString text; + text << _TT("alert1_fix.."); + text << "\n\n" << count << " " << "channels" << "\n"; + + BPAlert* remove = new BPAlert("Remove an Group", text.String(),_T("Delete"),_T("Cancel"),NULL,B_WIDTH_AS_USUAL,LoadIcon("emblem-delete.png")); + int32 result=remove->Go(); //sync.. + + if(result==0){ + BPAlert* wait = new BPAlert("Remove a Group", "\nRemoving..",NULL,NULL,NULL,B_WIDTH_AS_USUAL,LoadIcon("delete-32.png")); + wait->Go(NULL); //async.. + + for(int i=0;iGetSubscriptionOfGroup(i,group); + if(row) + fController->DeleteChannel(row->fRef); + } + wait->PostMessage(B_QUIT_REQUESTED); + } + } + + fController->RemoveGroup(group->GroupName()); + + UNLOCKWINDOW + + return B_OK; +} + +char +IABPGroupRemove::Shortcut(uint32 *modifiers) const { + return 0; +} diff --git a/sources-experimental/IABPGroup.h b/sources-experimental/IABPGroup.h new file mode 100644 index 0000000..6b491b8 --- /dev/null +++ b/sources-experimental/IABPGroup.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2007 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef _IABPGroup_h_ +#define _IABPGroup_h_ + +#include "IActionBP.h" +#include "Utils.h" +#include "BPLocale.h" + +#define GROUP_NAME_CHANGE 'grnc' + +//------------------------------------------------------------------------------------------------------------------- +class IABPGroupCheck : public IActionBP +{ + public: + + IABPGroupCheck(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; + +}; + +//------------------------------------------------------------------------------------------------------------------- +class IABPGroupAdd : public IActionBP +{ + public: + + IABPGroupAdd(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; + +}; + +//------------------------------------------------------------------------------------------------------------------- +class IABPGroupRename : public IActionBP +{ + public: + + IABPGroupRename(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; + +}; + +//------------------------------------------------------------------------------------------------------------------- +class IABPGroupRemove : public IActionBP +{ + public: + + IABPGroupRemove(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; + +}; + +#endif diff --git a/sources-experimental/IABPItem.cpp b/sources-experimental/IABPItem.cpp new file mode 100644 index 0000000..de858ae --- /dev/null +++ b/sources-experimental/IABPItem.cpp @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +//actions for items + +#include "IABPItem.h" +#include "MainWindow.h" +#include "MainController.h" + +#define LOCKWINDOW if(fView->Lock()){ +#define UNLOCKWINDOWERROR { fView->Unlock(); return B_ERROR; } +#define UNLOCKWINDOW fView->Unlock();} + +//------------------------------------------------------------------------------------------------------------------- + + +IABPItemRemove::IABPItemRemove(MainController* controller,MainWindow* view):IActionBP(controller,view){ + + SetIcon(IAction::SIZE_16,LoadIcon("delete-micro.png")); + SetIcon(IAction::SIZE_48,LoadIcon("emblem-delete.png")); + SetIcon(IAction::SIZE_48_PRESSED,LoadIcon("emblem-delete-down.png")); + + SetLabel(_T("Remove Item")); +} + +BString +IABPItemRemove::GetDescription(){ + return _T("Delete the item and the enclosure"); +} + + +status_t +IABPItemRemove::Perform(BMessage*){ + + EpisodeListItem* row=fView->GetSelectedEpisode(); + if(!row) return B_ERROR; + + BString firstTitle(row->GetTitle() ); + + BList selection; + selection.AddItem((void*)row); + while(row != NULL){ + row=fView->GetSelectedEpisode(row); + if(row) + selection.AddItem((void*)row); + } + + + BString text; + text << _TT("alert1"); + if(selection.CountItems() == 1) + text << "\n\n" << firstTitle << "\n"; + else + text << "\n\n" << selection.CountItems() << " " << "episodes\n"; + + BPAlert* remove = new BPAlert("Remove an Item", text.String(),_T("Delete"),_T("Cancel"),NULL,B_WIDTH_AS_USUAL,LoadIcon("emblem-delete.png")); + int32 result=remove->Go(); //sync.. + + LOCKWINDOW + + EpisodeListView* elv= fView->GetEpisodeListView(); + int32 removed=0; + + if(result==0){ + + BPAlert* wait = new BPAlert("Remove a Item", "\nRemoving..",NULL,NULL,NULL,B_WIDTH_AS_USUAL,LoadIcon("delete-32.png")); + wait->Go(NULL); //async.. + + for(int i=0;iDeleteEpisode(row->fRef)) removed--; + elv->RemoveRow(row); //FIX: nnn c'e' un metodo in fView? + delete row; //goodbye + } + + wait->PostMessage(B_QUIT_REQUESTED); + + elv->DeselectAll(); + SubscriptionListItem* sub=fView->GetSelectedSubscription(); + if(sub) { + sub->AddNewCount(removed); + fController->SetSelectedItem(NULL,&sub->fRef); + } + else + fController->SetSelectedItem(NULL,NULL); + } + + UNLOCKWINDOW + return B_OK; +} + +char +IABPItemRemove::Shortcut(uint32 *modifiers) const { + if(modifiers) + *modifiers = B_COMMAND_KEY; + return 'R'; +} + +//------------------------------------------------------------------------------------------------------------------- + + +IABPItemStop::IABPItemStop(MainController* controller,MainWindow* view):IActionBP(controller,view){ + + SetIcon(IAction::SIZE_16,LoadIcon("stopped-micro.png")); + SetIcon(IAction::SIZE_48,LoadIcon("emblem-stop.png")); + SetIcon(IAction::SIZE_48_PRESSED,LoadIcon("emblem-stop-down.png")); + + SetLabel(_T("Stop download")); +} + +BString +IABPItemStop::GetDescription(){ + return _T("Stop the item download"); +} + + +status_t +IABPItemStop::Perform(BMessage*){ + + LOCKWINDOW + + EpisodeListItem* row=fView->GetSelectedEpisode(); + while(row != NULL){ + fController->StopDownloadItem(row->fRef); + row=fView->GetSelectedEpisode(row); + } + + UNLOCKWINDOW + return B_OK; +} + +char +IABPItemStop::Shortcut(uint32 *modifiers) const { + if(modifiers) + *modifiers = B_COMMAND_KEY; + return 'S'; +} + +//------------------------------------------------------------------------------------------------------------------- + + +IABPItemDownload::IABPItemDownload(MainController* controller,MainWindow* view):IActionBP(controller,view){ + + SetIcon(IAction::SIZE_16,LoadIcon("download-micro.png")); + SetIcon(IAction::SIZE_48,LoadIcon("emblem-download.png")); + SetIcon(IAction::SIZE_48_PRESSED,LoadIcon("emblem-download-down.png")); + + SetLabel(_T("(Re)start download")); +} + +BString +IABPItemDownload::GetDescription(){ + return _T("Download the selected episode"); +} + + +status_t +IABPItemDownload::Perform(BMessage*){ + + LOCKWINDOW + EpisodeListItem* row=fView->GetSelectedEpisode(); + while(row != NULL){ + fController->DownloadItem(row->fRef,row); + row=fView->GetSelectedEpisode(row); + } + UNLOCKWINDOW + return B_OK; +} + + +char +IABPItemDownload::Shortcut(uint32 *modifiers) const { + if(modifiers) + *modifiers = B_COMMAND_KEY; + return 'D'; +} + + +//------------------------------------------------------------------------------------------------------------------- + + +IABPItemPlay::IABPItemPlay(MainController* controller,MainWindow* view):IActionBP(controller,view){ + + SetIcon(IAction::SIZE_16,LoadIcon("play-micro.png")); + SetIcon(IAction::SIZE_48,LoadIcon("emblem-play.png")); + SetIcon(IAction::SIZE_48_PRESSED,LoadIcon("emblem-play-down.png")); + + SetLabel(_T("Play enclosure")); +} + +BString +IABPItemPlay::GetDescription(){ + return _T("Play the selected episode"); +} + + +status_t +IABPItemPlay::Perform(BMessage*){ + + LOCKWINDOW + EpisodeListItem* row=fView->GetSelectedEpisode(); + while(row != NULL){ + fController->PlayItem(row->fRef); + row=fView->GetSelectedEpisode(row); + } + UNLOCKWINDOW + + return B_OK; +} + +char +IABPItemPlay::Shortcut(uint32 *modifiers) const { + if(modifiers) + *modifiers = B_COMMAND_KEY; + return 'E'; +} + + +//------------------------------------------------------------------------------------------------------------------- + +IABPItemWWW::IABPItemWWW(MainController* controller,MainWindow* view):IActionBP(controller,view){ + + SetIcon(IAction::SIZE_16,LoadIcon("www-micro.png")); + SetIcon(IAction::SIZE_48,LoadIcon("www-channel-file.png")); + SetIcon(IAction::SIZE_48_PRESSED,LoadIcon("www-channel-file-down.png")); + + SetLabel(_T("Open Web Page")); + +} + +BString +IABPItemWWW::GetDescription(){ + return _T("Show the news homepage"); +} + + +status_t +IABPItemWWW::Perform(BMessage*){ + + EpisodeListItem* row=fView->GetSelectedEpisode(); + while(row != NULL){ + fController->WWWItem(row->fRef); + row=fView->GetSelectedEpisode(row); + } + return B_OK; +} + + +char +IABPItemWWW::Shortcut(uint32 *modifiers) const { + if(modifiers) + *modifiers = B_COMMAND_KEY; + return 'H'; +} + diff --git a/sources-experimental/IABPItem.h b/sources-experimental/IABPItem.h new file mode 100644 index 0000000..c59199f --- /dev/null +++ b/sources-experimental/IABPItem.h @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef _IABPItem_h_ +#define _IABPItem_h_ + +#include "IActionBP.h" +#include "Utils.h" +#include "BPLocale.h" + + +//------------------------------------------------------------------------------------------------------------------- +class IABPItemRemove : public IActionBP +{ + public: + + IABPItemRemove(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; + +}; + +//------------------------------------------------------------------------------------------------------------------- +class IABPItemStop : public IActionBP +{ + public: + + IABPItemStop(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; + +}; + +//------------------------------------------------------------------------------------------------------------------- +class IABPItemDownload : public IActionBP +{ + public: + + IABPItemDownload(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; +}; + +//------------------------------------------------------------------------------------------------------------------- +class IABPItemPlay: public IActionBP +{ + public: + + IABPItemPlay(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; + +}; + +//------------------------------------------------------------------------------------------------------------------- + +class IABPItemWWW: public IActionBP +{ + public: + + IABPItemWWW(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; + +}; + +//------------------------------------------------------------------------------------------------------------------- + +class IABPItemEnclosureFolder: public IActionBP +{ + public: + + IABPItemEnclosureFolder(MainController* controller = NULL,MainWindow* view = NULL); + + BString GetDescription(); + + status_t Perform(BMessage*); + + char Shortcut(uint32 *modifiers = NULL) const; + +}; + +#endif diff --git a/sources-experimental/IAction.h b/sources-experimental/IAction.h new file mode 100644 index 0000000..4b7d893 --- /dev/null +++ b/sources-experimental/IAction.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef _IAction_h_ +#define _IAction_h_ + +#include "Action.h" +#include + +class IAction : public Action +{ + public: + + enum IconType { + SIZE_16 = 0, + SIZE_48, + SIZE_48_PRESSED, + //.... add other there! + SIZE_HOWMANY + }; + + IAction():Action(){ memset(fIcons,0, sizeof(BBitmap*) * SIZE_HOWMANY); }; + + virtual ~IAction(){}; + + BBitmap* GetIcon(IconType type){ return fIcons[type]; } + void SetIcon(IconType type,BBitmap* icon){ fIcons[type]=icon; } + + BString GetLabel() { return fLabel;} + void SetLabel(BString label){ fLabel=label;} + + BMessage * CopyMessage() { return new BMessage(*fMessage);} + BMessage * GetMessage() { return fMessage;} + void SetMessage(BMessage* msg){ fMessage=msg;} + + virtual BString GetDescription(){ return "";}; + + virtual char Shortcut(uint32 *) const { return 0; } + + private: + BBitmap* fIcons[SIZE_HOWMANY]; + BString fLabel; + BMessage* fMessage; +}; + +#endif diff --git a/sources-experimental/IActionBP.h b/sources-experimental/IActionBP.h new file mode 100644 index 0000000..3a32eef --- /dev/null +++ b/sources-experimental/IActionBP.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef _IActionBP_h_ +#define _IActionBP_h_ + +#include "IAction.h" + +class MainController; +class MainWindow; + +class IActionBP : public IAction +{ + public: + + IActionBP(MainController* controller = NULL,MainWindow* view = NULL):IAction(){ + fController=controller; + fView=view; + }; + + virtual ~IActionBP(){}; + + + protected: + MainController* fController; + MainWindow* fView; + +}; + +#endif diff --git a/sources-experimental/IActionManager.h b/sources-experimental/IActionManager.h new file mode 100644 index 0000000..0c39ca2 --- /dev/null +++ b/sources-experimental/IActionManager.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef _IActionManager_H_ +#define _IActionManager_H_ + +#include "IAction.h" + +#include +#include +#include + +#define PERFORM_ACTION 'peac' + +class IActionManager { + + public: + + IActionManager(int maxSize){ + fActions=(IAction**)malloc(maxSize*sizeof(Action*)); + memset(fActions,0,maxSize*sizeof(Action*)); + } + virtual ~IActionManager(){ + free(fActions); + } + + void SetAction(int pos,IAction* action){ + fActions[pos]=action; + } + IAction* GetAction(int pos){ + return fActions[pos]; + } + + static BMessage* MessageForAction(int pos){ + BMessage* msg=new BMessage(PERFORM_ACTION); + msg->AddInt16("action_position",pos); + return msg; + } + + static BHandler* TargetForAction(int /*pos*/){ + return be_app; + } + + virtual void Perform(BMessage* msg) { + int16 pos; + if(msg->FindInt16("action_position",&pos)!=B_OK) return; + + IAction *action=GetAction(pos); + if(!action) return; + + action->Perform(msg); + } + + + + void FireAction(int pos){ + be_app->PostMessage(MessageForAction(pos),TargetForAction(pos)); + } + private: + + IAction** fActions; + +}; +#endif diff --git a/sources-experimental/IActionManagerBP.cpp b/sources-experimental/IActionManagerBP.cpp new file mode 100644 index 0000000..a2521b5 --- /dev/null +++ b/sources-experimental/IActionManagerBP.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#include "IActionManagerBP.h" +#include "IABPChannel.h" +#include "IABPItem.h" +#include "IABPDownload.h" +#include "IABPGroup.h" + + +IActionManagerBP::IActionManagerBP():IActionManager(IACTION_COUNT){ +} + +void +IActionManagerBP::init(MainController* c,MainWindow* w){ + + + SetAction(IACTION_CHANNEL_ADD_REQUEST,new IABPChannelAddRequest()); + SetAction(IACTION_CHANNEL_REMOVE, new IABPChannelRemove(c,w)); + SetAction(IACTION_CHANNEL_CHECK, new IABPChannelCheck(c,w)); + SetAction(IACTION_CHANNEL_WWW, new IABPChannelWWW(c,w)); + SetAction(IACTION_CHANNEL_ENCLOSURE_FOLDER,new IABPChannelEnclosureFolder(c,w)); + SetAction(IACTION_CHANNEL_CHECK_ALL, new IABPChannelCheckAll(c,w)); + SetAction(IACTION_CHANNEL_SHOW_IMAGE, new IABPChannelShowImage(c,w)); + + SetAction(IACTION_ITEM_REMOVE,new IABPItemRemove(c,w)); + SetAction(IACTION_ITEM_STOP,new IABPItemStop(c,w)); + SetAction(IACTION_ITEM_DOWNLOAD,new IABPItemDownload(c,w)); + SetAction(IACTION_ITEM_PLAY,new IABPItemPlay(c,w)); + SetAction(IACTION_ITEM_WWW,new IABPItemWWW(c,w)); + + + SetAction(IACTION_DOWNLOAD_PLAY,new IABPDownloadPlay(c,w)); + SetAction(IACTION_DOWNLOAD_DOWNLOAD,new IABPDownloadDownload(c,w)); + SetAction(IACTION_DOWNLOAD_STOP,new IABPDownloadStop(c,w)); + SetAction(IACTION_DOWNLOAD_FIND_ITEM,new IABPDownloadFindItem(c,w)); + SetAction(IACTION_DOWNLOAD_REMOVE,new IABPDownloadRemove(c,w)); + + SetAction(IACTION_GROUP_CHECK,new IABPGroupCheck(c,w)); + SetAction(IACTION_GROUP_ADD,new IABPGroupAdd(c,w)); + SetAction(IACTION_GROUP_RENAME,new IABPGroupRename(c,w)); + SetAction(IACTION_GROUP_REMOVE,new IABPGroupRemove(c,w)); + + for(int i=0;iSetMessage(IActionManager::MessageForAction(i)); +} +IActionManagerBP::~IActionManagerBP(){ + //delete all off them! +} + + +//details.. +void +IActionManagerBP::SetAction(pb_actions pos,IActionBP* action){ + IActionManager::SetAction(pos,action); +} + +IActionBP* +IActionManagerBP::GetAction(pb_actions pos){ + return (IActionBP*)IActionManager::GetAction(pos); +} + +IActionBP* +IActionManagerBP::GetAction(int pos){ + return (IActionBP*)IActionManager::GetAction(pos); +} + diff --git a/sources-experimental/IActionManagerBP.h b/sources-experimental/IActionManagerBP.h new file mode 100644 index 0000000..ec6dabc --- /dev/null +++ b/sources-experimental/IActionManagerBP.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef _IActionManagerBP_H_ +#define _IActionManagerBP_H_ + +#include "IActionBP.h" + +#include "IActionManager.h" + +enum pb_actions { + ACTION_CHANNEL, + IACTION_CHANNEL_ADD_REQUEST = 0, + IACTION_CHANNEL_REMOVE, + IACTION_CHANNEL_CHECK, + IACTION_CHANNEL_WWW, + IACTION_CHANNEL_ENCLOSURE_FOLDER, + IACTION_CHANNEL_CHECK_ALL, + IACTION_CHANNEL_SHOW_IMAGE, + + IACTION_ITEM_REMOVE, + IACTION_ITEM_STOP, + IACTION_ITEM_DOWNLOAD, + IACTION_ITEM_PLAY, + IACTION_ITEM_WWW, + + IACTION_DOWNLOAD_PLAY, + IACTION_DOWNLOAD_DOWNLOAD, + IACTION_DOWNLOAD_STOP, + IACTION_DOWNLOAD_FIND_ITEM, + IACTION_DOWNLOAD_REMOVE, + + IACTION_GROUP_CHECK, + IACTION_GROUP_ADD, + IACTION_GROUP_RENAME, + IACTION_GROUP_REMOVE, + + //Don't remove this! + IACTION_COUNT + }; + + +class IActionManagerBP : public IActionManager { + + public: + + + IActionManagerBP(); + ~IActionManagerBP(); + + + void init(MainController*,MainWindow*); + + + + IActionBP* GetAction(pb_actions pos); + + IActionBP* GetAction(int pos); + + private: + void SetAction(pb_actions pos,IActionBP* action); + +}; +#endif diff --git a/sources-experimental/IActionMenuItem.cpp b/sources-experimental/IActionMenuItem.cpp new file mode 100644 index 0000000..9d61c9e --- /dev/null +++ b/sources-experimental/IActionMenuItem.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#include "IActionMenuItem.h" + +IActionMenuItem::IActionMenuItem(IAction* action) +:IconMenuItem(action->GetIcon(IAction::SIZE_16), + action->GetLabel().String(), + "", + action->CopyMessage(), + false) +{ + //done. :) + uint32 mod; + const char charz = action->Shortcut(&mod); + SetShortcut(charz,mod); +}; + + +//-- diff --git a/sources-experimental/IActionMenuItem.h b/sources-experimental/IActionMenuItem.h new file mode 100644 index 0000000..c8e7dc8 --- /dev/null +++ b/sources-experimental/IActionMenuItem.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef IActionMenuItem_H_ +#define IActionMenuItem_H_ + +#include "IconMenuItem.h" +#include "IAction.h" + +class IActionMenuItem : public IconMenuItem { + + public: + IActionMenuItem(IAction*); + +}; + +#endif diff --git a/sources-experimental/IconMenuItem.cpp b/sources-experimental/IconMenuItem.cpp new file mode 100644 index 0000000..92df3bc --- /dev/null +++ b/sources-experimental/IconMenuItem.cpp @@ -0,0 +1,107 @@ +//------------------------------------------------------------------------------ +// I N C L U D E S +//------------------------------------------------------------------------------ + +#include "IconMenuItem.h" + +const float kIconTextPadding = 5.0; +const float kEdgePadding = 4.0; +const float kTickSpacing = 4.0; + +//------------------------------------------------------------------------------ +// I M P L E M E N T A T I O N +//------------------------------------------------------------------------------ + +IconMenuItem::IconMenuItem(BBitmap* icon, const char *label, const char *extra, + BMessage *msg, bool ownIcon) : + BMenuItem(label, msg), + fIcon(icon), + fExtra(extra), + fLabel(label), + fOwnIcon(ownIcon), + fCreatedIcon(false) { + + if (fIcon == NULL) { + fCreatedIcon = true; + fIcon = new BBitmap(BRect(0, 0, 15, 15), B_COLOR_8_BIT, true); + char *bits = (char *)fIcon->Bits(); + int32 length = fIcon->BitsLength(); + for (int32 i = 0; i < length; i++) bits[i] = B_TRANSPARENT_MAGIC_CMAP8; + }; + + be_plain_font->GetHeight(&fFontHeight); + fFontHeightTotal = fFontHeight.ascent + fFontHeight.descent + fFontHeight.leading; + + _CalculateOffsets(); +}; + +IconMenuItem::~IconMenuItem() { + if ((fOwnIcon == true) || (fCreatedIcon == true)) delete fIcon; +}; + +void IconMenuItem::_CalculateOffsets(void) { + fBounds = fIcon->Bounds(); + + if (fFontHeightTotal > fBounds.Height()) fBounds.bottom = fFontHeightTotal; + fBounds.bottom += kEdgePadding; + + float width = be_plain_font->StringWidth(fLabel.String()); + + fBounds.right += width + kIconTextPadding + kTickSpacing + kEdgePadding; +}; + +void IconMenuItem::GetContentSize(float* width, float* height) { +// BMenuItem::GetContentSize(width, height); +// *width += 20; +// *height += 3; + *width = fBounds.Width(); + *height = fBounds.Height(); +} + +void IconMenuItem::DrawContent() { + + BPoint drawPoint(ContentLocation()); + drawPoint.x += 20; + Menu()->MovePenTo(drawPoint); + BMenuItem::DrawContent(); + + BPoint where(ContentLocation()); + where.y = Frame().top; + + /*if (IsEnabled()) + Menu()->SetDrawingMode(B_OP_OVER); + else + Menu()->SetDrawingMode(B_OP_BLEND); + */ + drawing_mode mode=Menu()->DrawingMode(); + Menu()->SetDrawingMode(B_OP_ALPHA); + Menu()->DrawBitmapAsync(fIcon, where); + Menu()->SetDrawingMode(mode); + /*BRect b = Frame(); + BMenu *parent = Menu(); + BPoint loc = parent->PenLocation(); + + //test code: clean the canvas before using + //parent->PushState(); + + //parent->SetLowColor(parent->ViewColor()); + parent->FillRect(b,B_SOLID_LOW); + + parent->SetDrawingMode(B_OP_ALPHA); + + b.OffsetBy(0, kEdgePadding); + b.left = loc.x; + + BRect iconPos = b; + iconPos.right = b.left + fIcon->Bounds().Width(); + iconPos.bottom = iconPos.top + fIcon->Bounds().Height(); + parent->DrawBitmap(fIcon, iconPos); + + parent->MovePenTo(loc.x + fIcon->Bounds().Width() + kEdgePadding, + loc.y + fFontHeight.ascent + kEdgePadding); + parent->SetDrawingMode( B_OP_OVER ); + //parent->SetLowColor(parent->ViewColor()); + parent->DrawString(fLabel.String()); + //parent->PopState(); + */ +}; diff --git a/sources-experimental/IconMenuItem.h b/sources-experimental/IconMenuItem.h new file mode 100644 index 0000000..20ea36d --- /dev/null +++ b/sources-experimental/IconMenuItem.h @@ -0,0 +1,48 @@ +#ifndef ICON_MENU_ITEM_H +#define ICON_MENU_ITEM_H + +//------------------------------------------------------------------------------ +// I N C L U D E S +//------------------------------------------------------------------------------ + +#include +#include +#include +#include + +//------------------------------------------------------------------------------ +// D E C L A R A T I O N S +//------------------------------------------------------------------------------ + +class BBitmap; +class BRect; + +class IconMenuItem : public BMenuItem { + public: + IconMenuItem(BBitmap* icon, const char *label, + const char *extra, BMessage *msg = NULL, bool ownIcon = true); + + virtual ~IconMenuItem(); + + const char *Extra(void) { return fExtra.String(); }; + + protected: + virtual void GetContentSize(float* width, float* height); + virtual void DrawContent(); + + private: + void _CalculateOffsets(void); + + BBitmap *fIcon; + BString fExtra; + BString fLabel; + BRect fBounds; + + float fFontHeightTotal; + font_height fFontHeight; + + bool fOwnIcon; + bool fCreatedIcon; +}; + +#endif diff --git a/sources-experimental/IconTextItem.cpp b/sources-experimental/IconTextItem.cpp new file mode 100644 index 0000000..0aaedc5 --- /dev/null +++ b/sources-experimental/IconTextItem.cpp @@ -0,0 +1,77 @@ +#include "IconTextItem.h" + +const float kEdgeOffset = 2.0; +const rgb_color kHighlight = {140, 140, 140, 255}; + +IconTextItem::IconTextItem(const char *text, BBitmap *icon) + : fIcon(NULL), + fIconHeight(0), + fIconWidth(0) { + fText = text; + fIcon = icon; +}; + +IconTextItem::~IconTextItem(void) { + delete fIcon; +}; + +void IconTextItem::DrawItem(BView *owner, BRect frame, bool complete) { + if (IsSelected() || complete) { + rgb_color color; + rgb_color origHigh; + + origHigh = owner->HighColor(); + + if (IsSelected()) { + color = kHighlight; + } else { + color = owner->ViewColor(); + }; + + owner->SetHighColor(color); + BRect fr(frame); + owner->FillRect(fr); + owner->SetHighColor(origHigh); + } + + if (fIcon) { + owner->SetDrawingMode(B_OP_ALPHA); + owner->DrawBitmap(fIcon, BPoint(frame.left + kEdgeOffset,frame.bottom - kEdgeOffset - fIconHeight) + fSpiaz); + owner->SetDrawingMode(B_OP_COPY); + }; + + if (IsSelected()) owner->SetDrawingMode(B_OP_OVER); + + owner->MovePenTo(frame.left + kEdgeOffset + fIconWidth + kEdgeOffset + 5, frame.bottom - fFontOffset); + owner->DrawString(fText.String()); +}; + +const char *IconTextItem::Text(void) const { + return fText.String(); +}; + +const BBitmap *IconTextItem::Icon(void) const { + return fIcon; +}; + +void IconTextItem::Update(BView */*owner*/, const BFont *font) { + font_height fontHeight; + font->GetHeight(&fontHeight); + fFontHeight = fontHeight.descent + fontHeight.leading + fontHeight.ascent; + + if (fIcon) { + fIconHeight = fIcon->Bounds().Height() + 1; + fIconWidth = fIcon->Bounds().Width(); + + if (fIconHeight > fFontHeight) { + SetHeight(fIconHeight + (kEdgeOffset * 2)); + fFontOffset = ((fIconHeight - fFontHeight) / 2) + (kEdgeOffset * 2); + } else { + SetHeight(fFontHeight + (kEdgeOffset * 2)); + fFontOffset = kEdgeOffset; + }; + } else { + SetHeight(fFontHeight + (kEdgeOffset * 2)); + fFontOffset = kEdgeOffset; + }; +}; diff --git a/sources-experimental/IconTextItem.h b/sources-experimental/IconTextItem.h new file mode 100644 index 0000000..b7bbd55 --- /dev/null +++ b/sources-experimental/IconTextItem.h @@ -0,0 +1,34 @@ +#ifndef ICONTEXTITEM_H +#define ICONTEXTITEM_H + +#include +#include +#include +#include +#include + + +class IconTextItem : public BListItem { + public: + + IconTextItem(const char *text, BBitmap *icon = NULL); + ~IconTextItem(void); + + virtual void DrawItem(BView *owner, BRect frame, bool complete); + virtual void Update(BView *owner, const BFont *font); + const char *Text(void) const; + const BBitmap *Icon(void) const; + + void SetSpiaz(BPoint p){ fSpiaz = p;} + + private: + BBitmap *fIcon; + BString fText; + float fFontHeight; + float fIconHeight; + float fIconWidth; + float fFontOffset; + BPoint fSpiaz; +}; + +#endif diff --git a/sources-experimental/IconTextRender.h b/sources-experimental/IconTextRender.h new file mode 100644 index 0000000..6984d55 --- /dev/null +++ b/sources-experimental/IconTextRender.h @@ -0,0 +1,73 @@ +#ifndef _IconTextRender_H_ +#define _IconTextRender_H_ + +#include "TextRender.h" +#include "Bitmap.h" +#include +#include + +#include +#include +#include +#include + +#define kIconSpace 3.0 + +class IconTextRender : public TextRender +{ + public: + + IconTextRender():TextRender(){ + fHeight = 0; // icon->Bounds().Height() + 1; + fWidth = 0; + }; + + virtual ~IconTextRender() {}; + + void Render(BView *target,const char* txt,int16 num,BPoint /*pos*/,BRect r) { + + BBitmap *pointer =NULL; + BString key(txt,num); + + if( fKeyBit.FindPointer(key.String(),(void**)&pointer) !=B_OK ) { + return; + } + if(!pointer) return; + + target->SetDrawingMode( B_OP_ALPHA ); + target->DrawBitmapAsync( pointer,BPoint(r.left + kIconSpace, r.top )); + //target->DrawBitmapAsync( pointer,BPoint(r.left + kIconSpace, r.top + ((r.Height()/2.0) - 8) )); //- fHeight + (fHeight/4) + 2) + target->SetDrawingMode( B_OP_OVER ); + }; + + + void + AddIcon(const char* key,BBitmap* icon){ + fKeyBit.AddPointer(key,icon); + } + + float Size(float/* maxwidth*/){ return fWidth + 1 + kIconSpace + kIconSpace;} + + void GetHeight(font_height *h){ + h->ascent=fHeight/2; + h->descent=fHeight/2; + h->leading=0; + }; + + void + GetEscapements(const char * /*charArray*/, int32 numChars,float escapementArray[]) { + escapementArray[0]=1; + for(int i=1;i +#include + + +#include "Utils.h" +#include "IActionBP.h" +#include "IActionManagerBP.h" + +ImageButton::ImageButton( BRect rect, const char * name, BMessage * msg,BBitmap * bitmap = NULL, BBitmap * bitmap_down = NULL , const char * label = NULL) +: BControl(rect,name,label,msg,B_FOLLOW_NONE,B_WILL_DRAW) +{ + fBitmap = bitmap; + eBitmap = bitmap_down; + fMouseUp = false; + fMouseDown = false; + fMouseOver = false; + fDrawBackground = true; + fInset = BPoint(4,2); + SetViewColor(B_TRANSPARENT_COLOR); + #ifdef ZETA + if(label) SetToolTipText(label); + SetDoubleBuffering(true); + #endif +} + + +ImageButton::ImageButton( BRect rect, const char* name, IAction* action) +: BControl(rect,name,action->GetLabel().String(),action->CopyMessage(),B_FOLLOW_NONE,B_WILL_DRAW) +{ + + fBitmap = action->GetIcon(IActionBP::SIZE_48); + eBitmap = action->GetIcon(IActionBP::SIZE_48_PRESSED); //bitmap_down; + fMouseUp = false; + fMouseDown = false; + fMouseOver = false; + fDrawBackground = true; + fInset = BPoint(4,2); + + SetTarget(IActionManager::TargetForAction(0)); + #ifdef ZETA + SetToolTipText(action->GetDescription().String()); + SetDoubleBuffering(true); + #endif + SetViewColor(B_TRANSPARENT_COLOR); + +} + + +ImageButton::~ImageButton(){ +} + +void +ImageButton::MouseDown( BPoint /*where*/ ) +{ + SetMouseEventMask( B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS ); + + fMouseDown = true; + + Invalidate(); +} + +void +ImageButton::MouseMoved( BPoint /*where*/, uint32 transition, const BMessage * /*msg*/ ) +{ + switch ( transition ) + { + case B_ENTERED_VIEW: + + fMouseOver = true; + Invalidate(); + break; + case B_EXITED_VIEW: + + fMouseOver = false; + Invalidate(); + break; + } + +} + +void +ImageButton::MouseUp( BPoint where ) +{ + if ( fMouseDown && Bounds().Contains(where) ){ + Invoke(); + } + + fMouseDown = false; + + Invalidate(); +} + +void +ImageButton::SetBitmap(BBitmap* bitmap) +{ + fBitmap = bitmap; +} + +void +ImageButton::DrawbackgroundColor(bool draw) +{ + fDrawBackground = draw; +} + +void +ImageButton::Draw( BRect ) +{ + BRect plain(Bounds()); + plain.InsetBy(fInset.x,fInset.y); + plain.bottom--; + BBitmap* draw=fBitmap; + + SetDrawingMode( B_OP_ALPHA ); //can be moved? + + if ( fMouseDown ) { + SetHighColor( 242,227,0); + draw=eBitmap; + } + else + SetHighColor( 255,255,255); + + if (fDrawBackground) + FillRect( plain ); + + if (draw) + DrawBitmap(draw, BPoint( 0,0 )); +} diff --git a/sources-experimental/ImageButton.h b/sources-experimental/ImageButton.h new file mode 100644 index 0000000..1859430 --- /dev/null +++ b/sources-experimental/ImageButton.h @@ -0,0 +1,37 @@ +#ifndef ImageButton_H +#define ImageButton_H + +#include +#include +#include + +class IAction; + +class ImageButton : public BControl +{ + public: + + ImageButton( BRect rect, const char * name, BMessage * msg, BBitmap * bitmap, BBitmap * bitmap_down, const char * label ); + ImageButton( BRect rect, const char* name, IAction* action); + virtual ~ImageButton(); + + virtual void MouseDown( BPoint ); + virtual void MouseMoved( BPoint, uint32, const BMessage * ); + virtual void MouseUp( BPoint ); + + virtual void Draw( BRect ); + + void SetInsetPoint(BPoint p) { fInset = p;} + + void SetBitmap(BBitmap*); + void DrawbackgroundColor(bool); + + private: + bool fMouseDown, fMouseOver, fMouseUp; + BBitmap * fBitmap; + BBitmap * eBitmap; + BPoint fInset; + bool fDrawBackground; +}; + +#endif diff --git a/sources-experimental/ItemProperty.h b/sources-experimental/ItemProperty.h new file mode 100644 index 0000000..fac48d7 --- /dev/null +++ b/sources-experimental/ItemProperty.h @@ -0,0 +1,54 @@ +#ifndef _ItemProperty_H_ +#define _ItemProperty_H_ + +//revision 0.1 // 20 sett 2005 + +enum ItemProperty { + + IP_SYSTEM_ID_LOW, // a system id is a 64bit number. + IP_SYSTEM_ID_HIGH, // you need 2 key (of int32) to store/retrive the value. + + ITEM_TITLE, // "title" + ITEM_PUBDATE, // "pubDate" + ITEM_GUID, // "guid" + ITEM_LINK, // "link"//? + ITEM_AUTHOR, + ITEM_BLOCK, + ITEM_CATEGORY, + ITEM_DURATION, + ITEM_EXPLICIT, // "Yes" or "No" + ITEM_KEYWORDS, + ITEM_SUBTITLE, //-------| + ITEM_DESCRIPTION, //-------| Are these the same info? + ITEM_SUMMARY, //-------| + ITEM_ENCLOSURE_URL, + ITEM_ENCLOSURE_TYPE, + ITEM_ENCLOSURE_LENGTH, + ITEM_ENCLOSURE_LOCALPATH, + ITEM_ENCLOSURE_FILE_STATUS, //see FileStatus.h + ITEM_ENCLOSURE_FILE_PERCENTAGE, + ITEM_ENCLOSURE_DOWNLOAD_SPEED, + ITEM_ENCLOSURE_DOWNLOADED, + + CHANNEL_URL, //feed url! + CHANNEL_TITLE, + CHANNEL_DESCRIPTION, + CHANNEL_RSS_FILE_STATUS, //see FileStatus.h + CHANNEL_NEWITEMS, + CHANNEL_WEBLINK, // channel home page! + CHANNEL_COPYRIGHT, + CHANNEL_BLOCK, + CHANNEL_CATEGORY, + CHANNEL_EXPLICIT, + CHANNEL_KEYWORDS, + CHANNEL_OWNER, + CHANNEL_SUBTITLE, + CHANNEL_SUMMARY, + CHANNEL_IMAGE_URL, + CHANNEL_IMAGE_LOCALPATH, //NOT USED! + CHANNEL_IMAGE_DATA, +}; + + + +#endif diff --git a/sources-experimental/ItemRunView.h b/sources-experimental/ItemRunView.h new file mode 100644 index 0000000..55e4af2 --- /dev/null +++ b/sources-experimental/ItemRunView.h @@ -0,0 +1,100 @@ +#ifndef ItemRunView_H_ +#define ItemRunView_H_ + +#include "runview/RunView.h" +#include "BitmapView.h" +#include + +#define BORDER_SIZE 5 + +class ItemRunView : public RunView { + + public: + + ItemRunView(BRect r, + const char * n, + Theme * t, + uint32 a, + uint32 b) + :RunView(r,n,t,a,b){ + fImage=NULL; + AddChild(viewer = new BitmapView(BRect(1,1,2,2),NULL)); + LoadBitmap(NULL); + } + + void TextResized(BRect r) + { + //printf("Bottom line %f (value %f)\n",r.bottom,r.top); + if(fImage) + viewer->MoveTo(BORDER_SIZE,r.bottom - r.top + BORDER_SIZE); + } + + + void FrameResized (float w , float h) + { + w = w -BORDER_SIZE*2; //BORDER! + + if(fImage) + { + if(fImage->Bounds().Width() > w) + viewer->ResizeTo(w, w *proportion ); + else + viewer->ResizeTo(fImage->Bounds().Width(), fImage->Bounds().Height()); + } + RunView::FrameResized(w+2*BORDER_SIZE,h); + } + + + float ExtraTextSize() + { + + if(!viewer->IsHidden()) + return viewer->Bounds().Height() + BORDER_SIZE; + else + return 0; + } + + + void LoadBitmap(const char* filename) + { + + if(fImage) + delete fImage; + + fImage = NULL; + + if(filename!=NULL) + fImage = BTranslationUtils::GetBitmap(filename); + + + viewer->SetBitmap(fImage); + + if(fImage) + { + if(viewer->IsHidden()) viewer->Show(); + proportion = fImage->Bounds().Height() / fImage->Bounds().Width(); + float w = Bounds().Width() - BORDER_SIZE*2; + + if(fImage->Bounds().Width() > w) { + viewer->ResizeTo(w, w * proportion ); + } + else + viewer->ResizeTo(fImage->Bounds().Width(), fImage->Bounds().Height()); + } + else + { + if(!viewer->IsHidden()) viewer->Hide(); + } + + + } + + private: + BitmapView* viewer; + BBitmap* fImage; + float proportion; + +}; + +#endif + diff --git a/sources-experimental/Jamfile b/sources-experimental/Jamfile new file mode 100644 index 0000000..05eeb8f --- /dev/null +++ b/sources-experimental/Jamfile @@ -0,0 +1,117 @@ + +SubDir TOP sources ; + +SubDirHdrs $(OBJECTS_DIR) sources ; + +if $(OSPLAT) = X86 { + C++FLAGS += -Wno-sign-compare -Wno-overloaded-virtual ; +} + +if ZETA in $(DEFINES) { + echo "ZETA VERSION (NO MORE SUPPORTED)" ; + BP_LIBS = libs/libfunky.a libs/librunview.a libs/libfish.a libs/libclv.a libs/libcurl.a libs/libxml2.a be root translation tracker iconv ssl crypto z ; + LINKLIBS = -lsocket -lbind -lzeta ; + + +} else { + echo "Haiku VERSION (compiled for net_server)" ; + BP_LIBS = libs/libfunky.a libs/librunview.a libs/libfish.a libs/libclv.a curl xml2 be root translation tracker iconv ssl crypto z ; + LINKLIBS = -lnetwork -lstdc++ ; +} + +echo "Extra library" ; +echo $(LINKLIBS) ; + +SAVED_DEFINES = $(DEFINES) ; + +DEFINES = $(SAVED_DEFINES) ; +#DEFINES += ZETA ; + +SubDirSysHdrs /boot/home/config/include ; +SubDirSysHdrs $(TOP)/include/ ; +SubDirSysHdrs $(TOP)/include/r5-only ; +SubDirSysHdrs $(TOP)/include/curl ; +SubDirSysHdrs $(TOP)/include/runview ; +SubDirSysHdrs $(TOP)/include/lbxml ; +SubDirSysHdrs $(TOP)/include/libfunky ; +SubDirSysHdrs $(TOP)/include/libclv ; +SubDirSysHdrs $(TOP)/include/libfish ; +SubDirSysHdrs $(TOP)/sources/ ; + +LINKFLAGS += -L/boot/home/config/lib ; +#LINKFLAGS += -L$(TOP)/libs/ ; +LINKFLAGS += -L/boot/develop/headers/be ; + + +# +Application BePodder : + ActionAsync.cpp + ActionAsyncWrapper.cpp + ActionDelete.cpp + ActionDownload.cpp + ActionHTTPContent.cpp + AddWindow.cpp + AttributeDumper.cpp + AttributeExtractor.cpp + BitmapWindow.cpp + BPAlert.cpp + BPEpisode.cpp + BPSettingsWindow.cpp + ChannelSettingsWindow.cpp + Cursors.cpp + DirectoryWindow.cpp + DownloadListItem.cpp + DownloadListView.cpp + DownloadManager.cpp + ElementNotifier.cpp + EntryIterator.cpp + EpisodeListItem.cpp + EpisodeListView.cpp + Extractor.cpp + FileStatusColumn.cpp + GreenBoxTextRender.cpp + GroupItem.cpp + HelpWindow.cpp + htmlparse.cpp + IABPChannel.cpp + IABPDownload.cpp + IABPGroup.cpp + IABPItem.cpp + IActionManagerBP.cpp + IActionMenuItem.cpp + IconMenuItem.cpp + IconTextItem.cpp + ImageButton.cpp + Logger.cpp + Main.cpp + MainController.cpp + MainWindow.cpp + MemoryArchive.cpp + MyColumnTypes.cpp + NodeWalker.cpp + Notifier.cpp + OPMLParser.cpp + PercentageView.cpp + PercentageWindow.cpp + QueueFileDownload.cpp + QueueMultiActions.cpp + R5Locale.cpp + RssChannel.cpp + RssItem.cpp + SectionSelector.cpp + SettingsWindow.cpp + SplitPane.cpp + StackedView.cpp + StripeView.cpp + SubscriptionColumn.cpp + SubscriptionListItem.cpp + SubscriptionListView.cpp + TextControlFloater.cpp + TheApp.cpp + TitleTextRender.cpp + XMLChannelExtractor.cpp + XMLItemExtractor.cpp + : $(BP_LIBS) + ; +# + diff --git a/sources-experimental/Logger.cpp b/sources-experimental/Logger.cpp new file mode 100644 index 0000000..5e22e70 --- /dev/null +++ b/sources-experimental/Logger.cpp @@ -0,0 +1,153 @@ +#include "Logger.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LogName "bepodder.log" + +log_importance g_verbosity_level = liQuiet; + +bool _has_checked_for_tty = false; + +void +check_for_tty() +{ + if ( _has_checked_for_tty ) + return; + + _has_checked_for_tty = true; + + if ( !isatty(STDOUT_FILENO) ) + { // redirect output to ~/im_kit.log if not run from Terminal + BPath path; + + if (find_directory(B_USER_DIRECTORY,&path,true,NULL) != B_OK) + // This should never fail.. + return; + + path.Append(LogName); + + close(STDOUT_FILENO); + open( path.Path(), O_WRONLY|O_CREAT|O_APPEND|O_TEXT); + chmod( path.Path(), 0x600 ); + } +} + +bool _has_loaded_log_level = false; + +void +load_log_level() +{ + /* + if ( _has_loaded_log_level ) + return; + + _has_loaded_log_level = true; + + BMessage settings; + if ( im_load_client_settings("im_server", &settings) != B_OK ) + { + printf("load_log_level: im_server settings not found\n"); + return; + } + + const char * level=NULL; + if ( settings.FindString("log_level", &level) == B_OK ) + { + // check for the various levels.. + if ( strcmp(level, "Debug") == 0 ) { + g_verbosity_level = liDebug; + } else + if ( strcmp(level, "Low") == 0 ) { + g_verbosity_level = liLow; + } else + if ( strcmp(level, "Medium") == 0 ) { + g_verbosity_level = liMedium; + } else + if ( strcmp(level, "High") == 0 ) { + g_verbosity_level = liHigh; + } else + if ( strcmp(level, "Quiet") == 0 ) { + g_verbosity_level = liQuiet; + } else + g_verbosity_level = liHigh; + } + */ +} + +const char * gLogLevelText[] = { + "debug", + "low", + "medium", + "high" +}; + +// Note: if you change something in this LOG, +// make sure to change the LOG below as the code +// unfortunately isn't shared. :/ +void LOG(const char * module, log_importance level, const char *message, const BMessage *msg, ...) { + va_list varg; + va_start(varg, msg); + char buffer[2048]; + vsprintf(buffer, message, varg); + + load_log_level(); + + if ( level > liHigh ) + { + level = liHigh; + } + + if ( level < g_verbosity_level ) + return; + + check_for_tty(); + + char timestr[64]; + time_t now = time(NULL); + strftime(timestr,sizeof(timestr),"%Y-%m-%d %H:%M", localtime(&now) ); + + printf("%s %s (%s): %s\n", module, timestr, gLogLevelText[level], buffer); + if ( msg ) + { + printf("BMessage for last message:\n"); + msg->PrintToStream(); + } + + fflush(stdout); +} + +void LOG(const char * module, log_importance level, const char *message, ...) { + va_list varg; + va_start(varg, message); + char buffer[2048]; + vsprintf(buffer, message, varg); + + load_log_level(); + + if ( level > liHigh ) + { + level = liHigh; + } + + if ( level < g_verbosity_level ) + return; + + check_for_tty(); + + char timestr[64]; + time_t now = time(NULL); + strftime(timestr,sizeof(timestr),"%Y-%m-%d %H:%M", localtime(&now) ); + + printf("%s %s (%s): %s\n", module, timestr, gLogLevelText[level], buffer); + + fflush(stdout); +} diff --git a/sources-experimental/Logger.h b/sources-experimental/Logger.h new file mode 100644 index 0000000..27d31e8 --- /dev/null +++ b/sources-experimental/Logger.h @@ -0,0 +1,41 @@ +#ifndef HELPERS_H +#define HELPERS_H + +#include +#include +#include +#include + +#define TRACE_CLASS Tracer tr(__PRETTY_FUNCTION__) +class Tracer +{ + private: + BString str; + + public: + Tracer( const char * _str ) + : str(_str) + { + printf("%s\n",str.String()); + }; + ~Tracer() + { + printf("-%s\n",str.String() ); + }; +}; + +enum log_importance { + liDebug = 0, // debug + liLow, // lots and lots of messages + liMedium, // enough to follow what's happening + liHigh, // general idea + liQuiet = 100 // Don't say a word. Don't use this when calling LOG(), it's for reducing output. +}; + +extern void LOG( const char * module, log_importance level, const char * msg, const BMessage *, ...); +extern void LOG( const char * module, log_importance level, const char * msg, ...); + +// if level < g_verbosity_level then LOG() doesn't print the msg +extern log_importance g_verbosity_level; + +#endif diff --git a/sources-experimental/Main.cpp b/sources-experimental/Main.cpp new file mode 100644 index 0000000..f7573fe --- /dev/null +++ b/sources-experimental/Main.cpp @@ -0,0 +1,19 @@ + +#include "TheApp.h" +#include + +int +main() +{ +#ifndef ZETA + int i = access ( "/boot/beos/system/lib/libzeta.so", F_OK ); + if ( i == 0 ){ + system("alert \"This version is for BeOS.R5/Haiku not for ZETA\nPlease download the right version!\""); + return 0; + } +#endif + + TheApp app("application/x-vnd.xeD.BePodder"); + app.Run(); + return 0; +} diff --git a/sources-experimental/MainController.cpp b/sources-experimental/MainController.cpp new file mode 100644 index 0000000..e3a4aba --- /dev/null +++ b/sources-experimental/MainController.cpp @@ -0,0 +1,1907 @@ +#include "MainController.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "AttributeExtractor.h" +#include "AttributeDumper.h" +#include "MemoryArchive.h" +#include "XMLChannelExtractor.h" + +#include "AttributeMap.h" +#include "ItemProperty.h" + +#include "curl/curl.h" + +#include "Utils.h" +#include "DownloadManager.h" +#include "MainWindow.h" +#include "Logger.h" + +#include "ActionDelete.h" +#include "DownloadListItem.h" +#include "Setting.h" +#include "BPSettingsWindow.h" +#include "BitmapWindow.h" + +#include "BPLocale.h" +#include "EntryIterator.h" + +#include "AutoFiletypeMap.h" + +#include "BPEpisode.h" + +DownloadManager* download_manager; + +//#include "LicenceInfo.h" +//extern LicenceInfo linfo; + +//messages: +#define DOWNLOAD_ITEM 'invD' +#define DOWNLOAD_CHANNEL 'addu' + +#define VLC_SIGNATURE "application/x-vnd.videolan-vlc" +#define SOUNDPLAY_SIGNATURE "application/x-vnd.marcone-soundplay" + +#ifdef ZETA + #define MEDIAPLAYER_SIGNATURE "application/x-vnd.YT-MediaPlayer" +#else + #define MEDIAPLAYER_SIGNATURE "application/x-vnd.Haiku-MediaPlayer" + // THIS SHOULD BE FIXED! "application/x-vnd.Be.MediaPlayer" +#endif + + + + + + +//a tendere qui dovrebbe essere +//instaziato il model +MainController::MainController(MainWindow* view, MainModel* model){ + fView = view; + fModel = model; + download_manager = new DownloadManager(fView); + check_time = 0; + check_timer = NULL; + check_onstart = false; + //extraParams.SetTo(""); +} + +void +MainController::LoadSettings(const char* type,BMessage* data){ + + + + BString stype(type); + if(stype.Compare(SETTINGS_PROXY) == 0 ){ + download_manager->LoadProxySetting(data); + + } + else + if(stype.Compare(SETTINGS_DOWNLOAD) == 0 ){ + download_manager->LoadDownloadSetting(data); + } + else + if(stype.Compare(SETTINGS_FILETYPE) == 0){ + + browser_id = 2; //System Default. + player_id = 3; //Auto. + int32 ret; + if(data->FindInt32("browser_index",&ret) == B_OK) + browser_id = ret; + + if(data->FindInt32("player_index",&ret) == B_OK) + player_id = ret; + + } + else + if(stype.Compare(SETTINGS_CHANNELS) == 0 ){ + //one second: 1 000 000; + bigtime_t minute = 1000000 * 60; + + if(check_timer!=NULL) + delete check_timer; + + switch(data->FindInt32("check_time_index")) + { + case 0: + check_time=0; + break; + case 1: + check_time= minute * 5 ; //5 mins + break; + case 2: + check_time= minute * 15 ; //15 mins + break; + case 3: + check_time= minute * 30; //30 mins + break; + case 4: + check_time=minute * 60; //1h + break; + case 5: + check_time= minute * 120; //2h + break; + } + + check_onstart = data->FindBool("check_startup"); + + printf("Check every %lld microseconds..\n",check_time); + + if(check_time>0) + check_timer= new BMessageRunner(fView,new BMessage(CHECK_ALL),check_time); + + + } + + +} + +/* +void +MainController::DownloadSelectedItem(){ + + //ANNOTAZIONI: se si lascia solo DownloadItem(REF) si può pensare alla multiselezione. + + EpisodeListItem* sel = fView->GetSelectedEpisode(); + if(!sel) return; + + + if(DownloadItem( sel->fRef,sel )==B_OK) { + } + + //QUI: inserire il collegamento con SEL e Refresh dell' episodio. +} +*/ +status_t +MainController::DownloadItem(entry_ref ref,EpisodeListItem* epi) { + + //start a item download. + //------------------------------------------------------------------ + + //download view (only if there's already one) + DownloadListItem* item=fModel->findDownload(ref); + + BString enclosure_path; + BString enclosure_link; + BString enclosure_type = ""; + FileStatus status; + + if(item) + { + enclosure_path=item->fRss.EnclosureLocalPath(); + enclosure_link=item->fRss.EnclosureLink(); + enclosure_type=item->fRss.FileType(); + status=item->fRss.GetFileStatus(); + } + else + { + BPEpisode bpe(&ref); + if(bpe.InitCheck()!=B_OK) return B_ERROR; + enclosure_path=bpe.EnclosureLocalPath(); + enclosure_link=bpe.EnclosureLink(); + enclosure_type=bpe.EnclosureType(); + status= bpe.GetStatus(); + } + + if(enclosure_path == "" || enclosure_link == "") return B_ERROR; + + + + bool resume = false; + + if( status == NOT_DOWNLOADED || + status == STOPPED ) + { + + resume = (status == STOPPED ); + + BPath path(&ref); + if(path.GetParent(&path)!=B_OK) return B_ERROR; + + BDirectory dir; + path.Append("enclosures"); + + if(dir.SetTo(path.Path()) == B_ENTRY_NOT_FOUND) + if(dir.CreateDirectory(path.Path(),&dir)!=B_OK) return B_ERROR; + + + if(dir.InitCheck()!=B_OK) return B_ERROR; + + path.Append(enclosure_path.String()); + + entry_ref enclosure_ref; + get_ref_for_path(path.Path(),&enclosure_ref); + ActionDownload *ac=new ActionDownload(enclosure_link,enclosure_ref,resume, enclosure_type); + + ac->SetRef("episode_ref",&ref); + + + + + if( item ==NULL) { + item = new DownloadListItem(NULL); + AttributeExtractor an; + //HERE: we have to move data from ref to item->fRss. + an.SetNotifier(&item->fRss); + BNode bpe(&ref); + an.Parse(&bpe); + + item->fRef=ref; + fModel->addDownload(ref,item); + + if(epi) + item->LinkToEpisode(epi); + + fView->AddDownload(item); + + } + + ac->SetExtraData(item->fRss.Guid()); + item->fRss.SetFileStatus(ENQUEQUED); + download_manager->Enqueue(DownloadManager::ITEMS_QUEUE,ac); + + return B_OK; + } + + return B_OK; +} + +void +MainController::InfoDownloadItem(BMessage* msg){ + + entry_ref ref; + if( msg->FindRef("episode_ref",&ref) != B_OK) return; + + DownloadListItem* item=fModel->findDownload(ref); + if(!item) return; + + ActionDownload::Status status = (ActionDownload::Status)msg->FindInt32("status"); + + RssItem* rss = &item->fRss; + if(!rss) return; + + switch(status){ + case ActionDownload::OK_DOWNLOADED: + { + + AttributeDumper dumper(&ref); + + rss->AddElementListener(&dumper); + rss->SetFileStatus(DOWNLOADED);//actually save the rss-file + rss->RemoveElementListener(&dumper); + + //FIX: test questo if. + if(fModel->fSelectedItem.InitCheck()==B_OK && fModel->fSelectedItem == BNode(&ref) ) { + UpdateSelected(); + } + } + break; + case ActionDownload::OK_CONNECTING: + rss->SetFileStatus(CONNECTING); + break; + case ActionDownload::OK_PROGRESS: + { + + int32 perc; + if(msg->FindInt32("percentage_progress",&perc)==B_OK) { + item->fRss.SetDownloadSpeed(msg->FindFloat("download_speed")); + item->fRss.SetFilePercentage(perc); + } + + rss->SetFileStatus(DOWNLOADING); + + //item->SetFilePercentageAndSpeed(perc,msg->FindFloat("download_speed")); + } + break; + + case ActionDownload::ERROR_PERFORMING: + { + + int32 error=msg->FindInt32("curl_error"); + + switch(error){ + case CURLE_COULDNT_CONNECT: + case CURLE_HTTP_PORT_FAILED: + case CURLE_COULDNT_RESOLVE_HOST: + rss->SetFileStatus(CANT_CONNECT); + break; + case CURLE_HTTP_NOT_FOUND: + rss->SetFileStatus(NOT_FOUND); + break; + + case CURLE_WRITE_ERROR: + { + bool stopped = msg->FindBool("should_stop"); + + if(stopped){ + AttributeDumper dumper(&ref); + rss->AddElementListener(&dumper); + rss->SetFileStatus(STOPPED); //actually save the rss-file + rss->RemoveElementListener(&dumper); + } + + if(item->fShouldMeRemoved) + RealRemoveDownload(item); + + } + break; + + case CURLE_BAD_DOWNLOAD_RESUME: + case CURLE_ABORTED_BY_CALLBACK: + + default: + rss->SetFileStatus(ERROR); + break; + } + } + break; + + case ActionDownload::ERROR_CURL_INIT: + case ActionDownload::ERROR_OPENFILE: + default: + rss->SetFileStatus(ERROR); + break; + } +} + + +status_t +MainController::StopDownloadItem(entry_ref ref){ + + DownloadListItem* item=fModel->findDownload(ref); + if(!item) return B_ERROR; + + BString guid(item->fRss.Guid()); + if(guid == "") return B_ERROR; + + FileStatus status = item->fRss.GetFileStatus(); + + //------------------------------------------------------------------ + + if(status== DOWNLOADING){ + download_manager->TryStopCurrentAction(DownloadManager::ITEMS_QUEUE,"extra",guid); + } + else + if(status == ENQUEQUED){ + bool result=download_manager->RemoveFromQueue(DownloadManager::ITEMS_QUEUE,"extra",guid); + if(result) + item->fRss.SetFileStatus(NOT_DOWNLOADED); //this iclude also refresh of donwload item AND (if linked) the episodeListItem. + } + + return B_OK; +} + + + +status_t +MainController::PlayItem(entry_ref ref){ + + BPEpisode bpe(&ref); + + if(bpe.InitCheck()!=B_OK) return B_ERROR; + + BString enclosure_path(bpe.EnclosureLocalPath()); + + if(enclosure_path == "" ) + WWWItem(ref); + + //------------------------------------------------------------------ + BPath path(&ref); + if(path.GetParent(&path)!=B_OK) return B_ERROR; + + BDirectory dir; + path.Append("enclosures"); + + if(dir.SetTo(path.Path()) == B_ENTRY_NOT_FOUND) return B_ERROR; + + path.Append(enclosure_path.String()); + + BString filetype(bpe.EnclosureType()); + OpenFile(path.Path(),filetype); + + return B_OK; +} + +void +MainController::ShowChannelImage(entry_ref ref){ + + //TODO: add image extractor from FileAttribute. (?) + + //new style + BNode dir(&ref); + if(dir.InitCheck()!=B_OK ) return; + + char* buffer; + int32 size; + status_t err = ReadAttributeData(&dir,ATTR_IMAGE,&buffer,&size); + + if(err !=B_OK ) return; + + BMessage iconMsg; + + if (iconMsg.Unflatten(buffer) != B_OK) { + free(buffer); + return ; + }; + BBitmap* icon = new BBitmap(&iconMsg); + if(!icon) { + free(buffer); + return; + } + + (new BitmapWindow(icon))->Show(); +} + + +void +MainController::SetSelectedItem(entry_ref* ref,entry_ref *nref){ + + //debugger("SEL"); + + if(BNode(ref) == fModel->fSelectedItem && + BDirectory(nref) == fModel->fSelectedChannel ) { + return; + } + + if(nref) + fModel->fSelectedChannel.SetTo(nref); + else + fModel->fSelectedChannel.Unset(); + + if(ref) + fModel->fSelectedItem.SetTo(ref); + else + fModel->fSelectedItem.Unset(); + + + SubscriptionListItem* row=fView->GetSelectedSubscription(); + if(!row) return; + + EpisodeListItem* sel = fView->GetSelectedEpisode(); + + if(sel && sel->IsNew()){ + BPEpisode bpe(&sel->fRef); + bpe.AddElementListener(sel); + BString enclosure(bpe.EnclosureLink()); + if(enclosure != "") + bpe.SetStatus(NOT_DOWNLOADED); + else + bpe.SetStatus(NO_ENCLOSURE); + + row->AddNewCount(-1); + fView->RefreshSubscription(row); + } + + UpdateSelected(); +} + +void +MainController::UpdateSelected() { + + //reloads the MemoryArchive and update view. + MemoryArchive* archive=&fModel->fCurrentSelectedItem; + + archive->MakeEmpty(); + + AttributeExtractor extractor; + freeNotifier.AddElementListener(archive); + extractor.SetNotifier(&freeNotifier); + + if(fModel->fSelectedChannel.InitCheck()==B_OK){ + extractor.Parse(&fModel->fSelectedChannel,true); + } + + if(fModel->fSelectedItem.InitCheck()==B_OK) { + extractor.Parse(&fModel->fSelectedItem,true); + } + + freeNotifier.RemoveElementListener(archive); + fView->ShowDescription(archive); +} + + +/* +void +MainController::SetSelectedChannel(BString url){ + + ChannelInfo* ci = fModel->fChInfo.ValueFor(url); + if(!ci) return; + + if(!ci->row) return; + + EpisodeListView* dx_list= ci->elv; + if(!dx_list) return; + + EpisodeListItem* sel = (EpisodeListItem*)dx_list->CurrentSelection(); + + fModel->fCurrentSelectedChannel.MakeEmpty(); + MemoryArchive* archive=&fModel->fCurrentSelectedChannel; + + AttributeExtractor extractor; + freeNotifier.AddElementListener(archive); + extractor.SetNotifier(&freeNotifier); + + + if(ci->row!=NULL){ + BDirectory dir(&ci->nref); + if(dir.InitCheck()==B_OK){ + extractor.Parse(&dir,true); + } + } + + freeNotifier.RemoveElementListener(archive); + //fView->ShowDescription(archive); +} +*/ + +status_t +MainController::FindItem(entry_ref ref){ + + //FIX DA CONTROLLARE + + BPath path(&ref); + path.GetParent(&path); + entry_ref parent; + get_ref_for_path(path.Path(),&parent); + + int32 count=fModel->fChInfo.CountItems(); + SubscriptionListItem* row=NULL; + + for(int i=0;ifChInfo.ValueAt(i); + BDirectory dir(&row->fRef); + if( BNode(&dir,NULL) == BNode(&parent)) + break; + else + row=NULL; + } + + if(!row) return B_ERROR; + + EpisodeListView* dx_list= fView->GetEpisodeListView(); + if(!dx_list) return B_ERROR; + + + // FIX come faccio a selezionare questo? + // dovrei fare una bella cosa: se è la view visibile allora lo seleziono, + // altrimenti bisogna notificare a fView di selezionare il canale E di preparare quel ref per essere + // il selezionato. + + //dx_list->DeselectAll(); + //dx_list->AddToSelection(sel); + fView->SelectSubscription(row); + return B_OK; +} + + +void +MainController::WWWItem(entry_ref ref){ + + BPEpisode bpe(&ref); + + BString link=bpe.EnclosureLink(); + if(link == "") return; + + OpenURL(link); +} + +bool +MainController::DeleteEpisode(entry_ref ref){ + + //FIX: da testare! + + DownloadListItem* item = fModel->findDownload(ref); + + if(item){ + StopDownloadItem(ref); + RealRemoveDownload(item); + } + + //cancellare l'enclosure + BPEpisode bpe(&ref); + FileStatus status=bpe.GetStatus(); + BString enclosure_path=bpe.EnclosureLocalPath(); + if(enclosure_path != ""){ + BPath path(&ref); + if(path.GetParent(&path)==B_OK){ + path.Append("enclosures"); + path.Append(enclosure_path.String()); + unlink(path.Path()); + } + } + + //cancellare l' file-item + BPath file_item(&ref); + unlink(file_item.Path()); + + //FIX: attenzione questo metodo non 'tocca' + // la grafica (fView) perchè lo fa invece la action.. + // si discosta dal resto.. ma è sbagliato, o forse anche + // altre action dovrebbero essere così 'agressive' ? + return (status == NEW ); +} + + +status_t +MainController::RemoveDownload(entry_ref ref){ + + DownloadListItem* dli=fModel->findDownload(ref); + if(!dli || dli->fShouldMeRemoved) return B_ERROR; + + dli->fShouldMeRemoved=true; + StopDownloadItem(ref); + return B_OK; +} + +void +MainController::RealRemoveDownload(DownloadListItem* dli){ + dli->Unlink(); + fModel->removeDownload(dli->fRef); + fView->RemoveDownload(dli); + delete dli; +} + + +const MemoryArchive* +MainController::GetSelectedItem(){ + return &fModel->fCurrentSelectedItem; +} + +void +MainController::FolderSelectedChannel(entry_ref nref){ + + //use preferred application. + BString app = PathFolderChannel(nref); + const char *args[] = { app.String(), 0 }; + be_roster->Launch("application/x-vnd.Be-directory", 1, const_cast(args)); + printf("trying to open %s\n", app.String()); +} + + +BString +MainController::PathFolderChannel(entry_ref nref){ + + SubscriptionListItem* row=fModel->fChInfo.ValueFor(nref); + if(!row) return "impossible"; + + BPath path(&row->fRef); + path.Append("enclosures"); + + BEntry check(path.Path()); + if(check.InitCheck()== B_OK && !check.Exists()) + path.SetTo(&row->fRef); + + return path.Path(); +} + +void +MainController::DownloadChannel(BMessage* msg){ + + BString url; + if(msg->FindString("url",&url)!=B_OK || url == "" ) return; + + //FIX test di url già presente! + int32 count=fModel->fChInfo.CountItems(); + for(int32 i=0;ifChInfo.ValueAt(i)->GetURL().ICompare(url)==B_OK) return; //URL già presente! + + /*if(!linfo.Valid() && count > 10) + { + + BString text(_T("You can only add up to 10 channels in this unregistred BePodder version.\n Please register your copy\n")); + BPAlert* about = new BPAlert("Sorry", text.String() ,_T("Web Site"),_T("Close"),NULL,B_WIDTH_AS_USUAL,LoadIcon("logo-64.png")); + int ret=about->Go(); + if(ret==0){ + OpenURL("http://www.funkyideasoft.com/bepodder.html"); + } + return; + }*/ + + + AttributeDumper dumper(&fModel->archive_ref,true); + entry_ref nref; + dumper.GetEntryRef(&nref); + + SubscriptionListItem* row= new SubscriptionListItem(nref); + fView->AddSubscription(row,NULL); + fView->ScrollToSubscripion(row); + row->SetPreferredPosition(fView->IndexOfSubscription(row)); + + RssChannel* channel = &row->fChannel; + channel->AddElementListener(&dumper); //in order to save as attribute + + channel->SetTitle(url.String()); + channel->SetURL(url.String()); + channel->SetFileStatus(NOT_DOWNLOADED); + + channel->RemoveElementListener(&dumper); + + fModel->fChInfo.AddItem(nref,row); + CheckChannel(nref); +} + +void +MainController::InfoDownloadChannel(BMessage* msg){ + + //info di download di un channel. + + + entry_ref nref; + + if(msg->FindRef("channel_ref",&nref)!=B_OK) return; + + + SubscriptionListItem* row = fModel->fChInfo.ValueFor(nref); + if(!row) return; + + + RssChannel* channel= &row->fChannel; + + + ActionDownload::Status status = (ActionDownload::Status)msg->FindInt32("status"); + + //LOG("MainController",liDebug,"InfoChannel status %ld",status); + + + switch(status){ + + + + case ActionDownload::OK_DOWNLOADED: + { + + MemoryArchive c_archive; + AttributeDumper dumper(&row->fRef); + + channel->AddElementListener(&dumper); //update the channel file. + channel->AddElementListener(&c_archive); //temp info in memory. + + channel->SetFileStatus(DOWNLOADED); + + BString path; + msg->FindString("path",&path); + + XMLChannelExtractor ext; + ext.SetNotifier(channel); + BList *list = ext.Parse(path.String()); + + if(!list) { + + channel->SetFileStatus(BAD_FORMAT); + channel->RemoveElementListener(&dumper); + channel->RemoveElementListener(&c_archive); + + fView->RefreshSubscription(row); + return; //check (delete di qualcosa?) + } + + + // come procedere (non mi delizia la cosa) + // abbiamo N files nella directory e K file nella lista. + // scorriamo UNA VOLTA gli N file e leggiamo l'attributo GUID. + // lo confrontiamo con tutti gli elementi K. + // se match, lo eliminiamo dalla lista se no lo lasciamo. + BDirectory dir(&row->fRef); + EntryListBase *result = new CachedDirectoryEntryList(dir); + + result->Rewind(); + entry_ref ref; + + //FIX: + /* + bool delNew=false; + bool delOld=false; + + if(row->extraSetting) { + BMessage del; + if(row->extraSetting->FindMessage("channel_setting",&del) == B_OK){ + del.FindBool("what_delete_new",&delNew); + del.FindBool("what_delete_read",&delOld); + del.PrintToStream(); + } + } + + int32 removed=0; + bool forceUpdate=false; + */ + + while( list->CountItems() > 0 && result->GetNextRef(&ref) == B_OK ){ + + BPEpisode bpe(&ref); + + //qui ho diritto di vita o di morte sul file selezionato.. prima cosa riepilogo i settaggi che ho: + //bene, già qui abbiamo un problema: come ottengo quello che non ho? + //bha proviamo un pò.. + //debugger(";)"); + //if( (delNew && bpe.GetStatus() == NEW ) || + /*if (delOld && bpe.GetStatus() != DOWNLOADED ) { + + + if(DeleteEpisode(ref)) removed--; + forceUpdate = true; + + }*/ + + + BString guid(bpe.Guid()); + if(guid != "") { + int32 newCount = list->CountItems(); + for(int i=newCount - 1 ;i >= 0 ;i--){ + MemoryArchive *ma =(MemoryArchive*)list->ItemAt(i); + if(ma->GetDataString(ITEM_GUID).Compare(guid) == 0) { + list->RemoveItem(ma); + delete ma; + // break; // meglio toglierlo in caso nella lista esistano + elementi con lo stesso GUID (raro) + } + } + + + + } + } + + //FIX if(removed!=0) + // row->AddNewCount(removed); + + + int added=0; + + while(list->CountItems()){ + + MemoryArchive *ma =(MemoryArchive*)list->ItemAt(0); + //we have it, removes from the list: + list->RemoveItem(ma); + + + BString guid(ma->GetDataString(ITEM_GUID)); + + RssItem fake; + EpisodeListItem *ep=NULL; + + //new EPISODE file: + AttributeDumper dumper(&row->fRef,false); + fake.AddElementListener(&dumper); + + + if(row == fView->GetSelectedSubscription()) { + ep=new EpisodeListItem(); + fake.AddElementListener(ep); + } + + ma->FillListener(&fake); //save to file + + fake.RemoveElementListener(&dumper); + + if(ep){ + fake.RemoveElementListener(ep); + dumper.GetEntryRef(&ep->fRef); + fView->GetEpisodeListView()->AddRow(ep,0,(BRow*)NULL); + + } + added++; + } + + delete list; + + channel->RemoveElementListener(&dumper); + channel->RemoveElementListener(&c_archive); + + if(added > 0) { + row->SetIsNew(true); + channel->SetKeyInt32(CHANNEL_NEWITEMS,added); +//FIX:ask? dx_list->Refresh(); + } + + //we can check for an image link and maybe add the the LowPrority queue. + + BString imageLink(c_archive.GetDataString(CHANNEL_IMAGE_URL)); + if(imageLink != "" && !row->HasOwnImage()) + { + + BDirectory dir; //channel + if(dir.SetTo(&row->fRef)!=B_OK) return; + + BPath path(&dir,NULL); //path to channel + + path.Append("image"); + + entry_ref ref; + get_ref_for_path(path.Path(),&ref); + + ActionDownload* ac= new ActionDownload(imageLink,ref,false, "image"); + + ac->SetRef("channel_ref",&row->fRef); + ac->SetExtraData("image"); + + //low->AddAction(ac); + download_manager->Enqueue(DownloadManager::EXTRA_QUEUE,ac); + } + + //final touch; if this channel is the selected one then update Info panel + if(row == fView->GetSelectedSubscription()){ + //FIX + /* if(forceUpdate) { + è sbagliato tra laltro (mi sembra!) + fModel->fSelectedChannel.Unset(); + fModel->fSelectedItem.Unset(); + SwitchChannel(&row->fRef); + } + else*/ + fView->ShowDescription(&fModel->fCurrentSelectedItem); + + } + + + } + break; + case ActionDownload::OK_PROGRESS: + { + channel->SetFileStatus(DOWNLOADING); + int32 perc = 0; + if(msg->FindInt32("percentage_progress",&perc)==B_OK) + { + row->SetFilePercentage(perc); + } + } + break; + case ActionDownload::OK_CONNECTING: + channel->SetFileStatus(CONNECTING); + break; + case ActionDownload::ERROR_PERFORMING: + { + int32 error=msg->FindInt32("curl_error"); + + + switch(error){ + case CURLE_COULDNT_CONNECT: + case CURLE_HTTP_PORT_FAILED: + case CURLE_COULDNT_RESOLVE_HOST: + channel->SetFileStatus(CANT_CONNECT); + break; + case CURLE_HTTP_NOT_FOUND: + channel->SetFileStatus(NOT_FOUND); + break; + default: + channel->SetFileStatus(ERROR); + break; + } + } + break; + default: + channel->SetFileStatus(ERROR); //TODO: more verbose. + break; + + } //end switch + + fView->RefreshSubscription(row); +} + + +void +MainController::ParseArchive() +{ + //if(!linfo.Valid()) + // be_app->PostMessage('lic2',be_app); + + + BPath path(GetAppRelativePath().String()); + path.Append("archive"); + + BEntry e(path.Path(),true); + + if(e.InitCheck() !=B_OK) { + be_app->PostMessage(B_QUIT_REQUESTED); + printf("No valid archive directory! (%s) \n",path.Path()); + return; + } + + //se la directory non esiste cerca di crearla. + + if(!e.Exists()){ + BDirectory archive; + if( archive.CreateDirectory(path.Path(),&archive) != B_OK) { + be_app->PostMessage(B_QUIT_REQUESTED); + printf("Can't create archive directory! (%s) \n",path.Path()); + return; + } + } + + e.GetRef(&(fModel->archive_ref)); + + uint32 flags=0; + + if(fView->Lock()){ + flags = fView->Flags(); + fView->SetFlags( flags | B_NOT_RESIZABLE); + fView->Unlock(); + } + + bigtime_t start = real_time_clock_usecs(); + + + BDirectory dir(&fModel->archive_ref); + + //LOAD GROUPS: + + BMessage groups; + ReadAttributeMessage(&dir,ATTR_GROUPS,&groups); + LoadGroupSetting(&groups); + + //LOAD CACHE: + + BMessage cache; + ReadAttributeMessage(&dir,ATTR_CACHE,&cache); + + BEntry entry; + while(dir.GetNextEntry(&entry) == B_OK) + if(entry.InitCheck()==B_OK && entry.IsDirectory()){ + + /*if(!linfo.Valid() && fModel->fChInfo.CountItems() > 10) + break; + else*/ + CreateChannelItem(&entry,&cache); + } + + bigtime_t stop = real_time_clock_usecs(); + + printf("Parsing time %lld secs. \n",(stop-start)/1000000); + + cache.MakeEmpty(); + + WriteAttributeMessage(&dir,ATTR_CACHE,&cache); + + if(fView->Lock()){ + fView->SetFlags( flags ); + fView->Unlock(); + } + + if(check_onstart) + fView->PostMessage(new BMessage(CHECK_ALL)); + +} + +int32 +CountNewItems(entry_ref nref){ + + BDirectory dir(&nref); + dir.Rewind(); + const char* name="bp:item_status"; + int32 total = 0; + + entry_ref ref; + while(dir.GetNextRef(&ref) == B_OK) { + BNode node(&ref); + + status_t status = node.InitCheck(); + if (status < B_OK) continue; + int32 dest; + if( ReadAttributeInt32(&node,name,&dest) == B_OK && dest==8) + total++; + } + return total; +} + + +void +MainController::CreateChannelItem(BEntry* e,BMessage* cache) +{ + BNode node(e); + + if(!CheckMIME(MIME_CHANNEL,&node)) return; + + entry_ref nref; + e->GetRef(&nref); + + SubscriptionListItem *row=new SubscriptionListItem(nref); + + //parsing degli attribute.. + + AttributeExtractor an; + an.SetNotifier(&row->fChannel); + an.Parse(&node); + + //--- c'e' L'url? se no delete di tutto e ciao! ---// + + if(row->GetURL() == "") { + delete row; + return; + } + + + //check delle info di cache.. + time_t when=1; + time_t now=0; + if(node.GetModificationTime(&now)!=B_OK) now=0; + + BString key=row->GetURL(); + key << "_count"; + int32 count; + + if( cache->FindInt32(key.String(),&count)!=B_OK || + cache->FindInt32(row->GetURL().String(),&when)!=B_OK || when!=now) { + printf("Recaching for.. %s\n",row->GetURL().String()); + count=CountNewItems(row->fRef); + } + + row->AddNewCount(count); + + BMessage data; + if( ReadAttributeMessage(&node,ATTR_COLUMNS_STATE,&data) == B_OK) + row->columnsState = new BMessage(data); + + data.MakeEmpty(); + GroupItem* group=NULL; + if( ReadAttributeMessage(&node,ATTR_EXTRA_STATE,&data) == B_OK) + group=LoadExtraState(&data,row); + + + if(fView->Lock()){ + fView->SetSortingSubscriptions(true); + fView->AddSubscription(row,group); + fModel->fChInfo.AddItem(row->fRef,row); + fView->SetSortingSubscriptions(false); + fView->Unlock(); + } + +} + +void +MainController::OpenFile(const char* filename,BString filetype){ + + entry_ref ref; + get_ref_for_path(filename,&ref); + + BMessage refs(B_REFS_RECEIVED); + refs.AddRef("refs",&ref); + + + int b = -1; + + BString alert; + + if(player_id ==3) //auto + { + b = FindBestApplication(&ref,alert); + + if(alert != "") { + BPAlert *pop= new BPAlert("BePodder", alert.String() ,_T("Ok"),NULL,NULL,B_WIDTH_AS_USUAL,LoadIcon("logo-64.png")); + pop->Go(); + } + } + else + { + + if(filetype == "" || (filetype.FindFirst("audio/") >= 0 ) + || (filetype.FindFirst("video/") >= 0 ) ) + b = player_id; + } + + switch(b){ + case -1: + //use preferred application. + be_roster->Launch(&ref); + break; + case 0: + if(be_roster->Launch(MEDIAPLAYER_SIGNATURE,&refs)!=B_OK) + AlertBadPlayer(MEDIAPLAYER); + break; + case 1: + if(be_roster->Launch(SOUNDPLAY_SIGNATURE,&refs) !=B_OK) + AlertBadPlayer(SOUNDPLAY); + break; + case 2: + if(be_roster->Launch(VLC_SIGNATURE,&refs) !=B_OK) + AlertBadPlayer(VLC); + break; + default: + break; + }; +} + + +void +MainController::AlertBadPlayer(int32 p_id){ + + BString text(_T("Can't open the selected file with:\n\n")); + BString url; + + if ( p_id == MEDIAPLAYER) + { + text << "MediaPlayer"; + url.SetTo("http://www.haiku-os.com/"); + } + else + if ( p_id ==VLC) + { + text << "VideoLAN"; + url.SetTo("http://www.bebits.com/app/2119"); + } + else + if(p_id==SOUNDPLAY) + { + text << "SoundPlay"; + url.SetTo("http://www.bebits.com/app/156"); + } + + text << _T("\n\nPlease check if the application is installed in the right way.\n"); + + + BPAlert *pop= new BPAlert("BePodder", text.String() ,_T("Download it!"),_T("Close"),NULL,B_WIDTH_AS_USUAL,LoadIcon("logo-64.png")); + int32 ret=pop->Go(); + if(ret==0) + OpenURL(url); + + + +} + + +void +MainController::OpenURL(BString link){ + + BString app("text/html"); + + if ( browser_id == 0 ) //Firefox. + { + app.SetTo("application/Firefox"); + entry_ref ff; + if(be_roster->FindApp("application/Firefox",&ff) == B_OK) { + + BString path(BPath(&ff).Path()); + path.RemoveLast("-bin"); + path << " " << link << " &"; + system(path.String()); + } + else + if(be_roster->FindApp("application/x-vnd.Mozilla-Firefox",&ff) == B_OK) { + + BString path(BPath(&ff).Path()); + path.RemoveLast("-bin"); + path << " " << link << " &"; + system(path.String()); + } + else // Net+ + { + app.SetTo("application/x-vnd.Be-NPOS"); + const char *args[] = { link.String(), 0 }; + be_roster->Launch (app.String(), 1, const_cast(args)); + } + + + } + else + if ( browser_id == 2 ) // Default + { + app.SetTo("text/html"); + const char *args[] = { link.String(), 0 }; + be_roster->Launch (app.String(), 1, const_cast(args)); + } + + else // Net+ + { + app.SetTo("application/x-vnd.Be-NPOS"); + const char *args[] = { link.String(), 0 }; + be_roster->Launch (app.String(), 1, const_cast(args)); + } +} + +void +MainController::SaveGroupSetting(BMessage* grp){ + for(int32 i=0;i< fModel->fGroups.CountItems();i++) { + GroupItem* group=fModel->fGroups.ValueAt(i); + grp->AddString("group_name",group->GroupName()); + grp->AddBool("group_expanded",group->IsExpanded()); + } +} + +void +MainController::LoadGroupSetting(BMessage* grp){ + int i=0; + BString name; + bool expanded; + + while(grp->FindString("group_name",i,&name)==B_OK){ + grp->FindBool("group_expanded",i++,&expanded); + + AddSavedGroup(name.String(),expanded); + //FIX APPLY EXPAND OR NOT! + } +} + + +void +MainController::SaveColumnsState(BMessage* msg){ + + EpisodeListView* elv=fView->GetEpisodeListView(); + + msg->MakeEmpty(); + msg->AddRect("view_rect",elv->Bounds()); + + int32 count = elv->CountColumns(); + + for(int i=0;iColumnAt(i); + msg->AddFloat("width",col->Width()); + msg->AddBool("visible",col->IsVisible()); + msg->AddInt32("position",col->LogicalFieldNum()); + } + + BMessage superstate; + elv->SaveState(&superstate); + msg->AddMessage("state",&superstate); + +} + +void +MainController::LoadColumnsState(BMessage* msg){ + + EpisodeListView* elv=fView->GetEpisodeListView(); + elv->SetEditMode(true); + + BRect bounds = msg->FindRect("view_rect"); + if(bounds.top!=0 || bounds.left!=0 || bounds.right <= bounds.left) return; // safety? + + int32 count = elv->CountColumns(); + + for(int i=0;iFindInt32("position",i,&position) != B_OK) + position = i; + + BColumn *col = (BColumn*) elv->ColumnAt(position); + elv->SetColumnVisible(col,false); + + float w; + if(msg->FindFloat("width",i,&w)==B_OK) + col->SetWidth(w); + + bool visible; + + if(msg->FindBool("visible",i,&visible)== B_OK) + elv->SetColumnVisible(col,visible); + else + elv->SetColumnVisible(col,true); + + } + + + BMessage superstate; + if(msg->FindMessage("state",&superstate)==B_OK) + elv->LoadState(&superstate); + + + elv->GetTitleView()->ScrollTo(BPoint(bounds.Width(),0)); + elv->GetTitleView()->ScrollTo(BPoint(0,0)); + elv->GetScrollView()->ScrollTo(BPoint(0,0)); + + elv->SetEditMode(false); + +} + +void +MainController::SaveExtraState(BMessage* msg, SubscriptionListItem* row){ + + int32 index = fView->IndexOfSubscription(row); + msg->AddInt32("preferred_index", index); + BString group=fView->GroupOf(row); + + if(group !="") + msg->AddString("group_name", group); +} + +GroupItem* +MainController::LoadExtraState(BMessage* msg, SubscriptionListItem* row){ + int32 index = -1; + if(msg->FindInt32("preferred_index",&index) !=B_OK) index=-1; + row->SetPreferredPosition(index); + + BString group; + if(msg->FindString("group_name", &group)==B_OK) + return AddSavedGroup(group.String(),true); + + return NULL; +} + +void +MainController::ArchiveChannel(entry_ref nref){ + TRACE_CLASS; + + SubscriptionListItem* row = fModel->fChInfo.ValueFor(nref); + if(!row) return; + + BDirectory dir(&row->fRef); + BNodeInfo(&dir).SetType(MIME_ARCHIVED_CHANNEL); + + //remove from gui. + RemoveChannelFromUI(nref,row); +} + +status_t +MainController::DeleteChannel(entry_ref nref){ + + //FIX DA TESTARE + + //cancellare e togliere tutti i download che hanno un ref nel canale. + + SubscriptionListItem* row = fModel->fChInfo.ValueFor(nref); + if(!row) return B_ERROR; + + BDirectory dir(&nref); + EntryListBase *result = new CachedDirectoryEntryList(dir); + + result->Rewind(); + entry_ref ref; + + + while(result->GetNextRef(&ref) == B_OK ){ + DownloadListItem* item = fModel->findDownload(ref); + if(item) + RealRemoveDownload(item); + } + + + BPath path(&nref); + BString filename(path.Path()); + + //do it + LOG("MainController",liDebug,"Unlinking %s",filename.String()); + + ActionDelete del(filename,true); + status_t ret = del.Perform(NULL); + + if(ret !=B_OK ){ + LOG("MainController",liDebug,"Error %s",strerror(errno)); + return B_ERROR; + } + + RemoveChannelFromUI(nref,row); + return B_OK; +} + +void +MainController::RemoveChannelFromUI(entry_ref nref,SubscriptionListItem* row){ + fModel->fChInfo.RemoveItemFor(nref); + fView->RemoveSubscription(row); +// fView->RefreshSubscriptionLists(); //maybe not needed but it's ok.. +} + +void +MainController::CheckChannel(entry_ref nref){ + + SubscriptionListItem* row = fModel->fChInfo.ValueFor(nref); + if(!row) return; + + if( row->GetFileStatus()==ENQUEQUED || + row->GetFileStatus()==CONNECTING) return; + + BDirectory dir(&row->fRef); + + BPath apath(&dir,NULL); + apath.Append("rss.xml"); + + entry_ref ref; + get_ref_for_path(apath.Path(),&ref); + + BString url(row->GetURL()); + /* + check channel url. + replace pcast:// and feed:// + */ + if(url.FindFirst("pcast://") == 0) + url.ReplaceFirst("pcast://","http://"); + else + if(url.FindFirst("feed://") == 0) + url.ReplaceFirst("feed://","http://"); + + + ActionDownload* ac= new ActionDownload(url,ref,false, ""); + ac->SetActionID(real_time_clock_usecs()); + ac->SetRef("channel_ref",&row->fRef); + + //let's go.. + row->SetFileStatus(ENQUEQUED); + download_manager->Enqueue(DownloadManager::CHANNELS_QUEUE,ac); + + fView->RefreshSubscription(row); + +} + +void +MainController::CheckAllChannel(){ + + //the fView should be locked! + if(!fView->IsLocked()) return; + + int32 count =fModel->fChInfo.CountItems(); + + for(int i=0;ifChInfo.ValueAt(i); + if(row) + CheckChannel(row->fRef); + } + + +} + +void +MainController::InfoExtraDownload(BMessage* msg){ + + entry_ref nref; + if( msg->FindRef("channel_ref",&nref) != B_OK) return; + + SubscriptionListItem* row = fModel->fChInfo.ValueFor(nref); + if(!row) return; + + + RssChannel* channel=&row->fChannel; + if(!channel) return; + + ActionDownload::Status status = (ActionDownload::Status)msg->FindInt32("status"); + switch(status){ + + case ActionDownload::OK_DOWNLOADED: + { + entry_ref ref; + BString extra; + + msg->FindRef("entry",&ref); + msg->FindString("extra",&extra); + + if(extra.ICompare("image") == 0) + { + + BBitmap *logo = BTranslationUtils::GetBitmap(&ref); + if(!logo) return; + + + // what to do with this image? + AttributeDumper dump(&row->fRef); + row->fChannel.AddElementListener(&dump); + row->fChannel.SetKey(CHANNEL_IMAGE_DATA,(void*)logo,sizeof(BBitmap*)); + row->fChannel.RemoveElementListener(&dump); + delete logo; + + + } + + fView->RefreshSubscription(row); + } + default:break; + } +} + + +void +MainController::StoreStates(){ + + int32 count = fModel->fChInfo.CountItems(); + + BMessage cache; + BDirectory dir(&fModel->archive_ref); + + for(int i=0;ifChInfo.ValueAt(i); + if(!row) continue; + + BDirectory node(&row->fRef); + if(node.InitCheck()!=B_OK) continue; + + //do: write attribute! + + if(row->columnsState) + WriteAttributeMessage(&node,ATTR_COLUMNS_STATE,row->columnsState); + + + //now I can create the extra 'state' + BMessage extra; + SaveExtraState(&extra,row); + WriteAttributeMessage(&node,ATTR_EXTRA_STATE,&extra); + + //caching modification time... + time_t when; + if(node.GetModificationTime(&when)==B_OK) { + BString key=row->GetURL(); + cache.AddInt32(key.String(),when); + key << "_count"; + cache.AddInt32(key.String(),row->GetNewCount()); + } + } + + WriteAttributeMessage(&dir,ATTR_CACHE,&cache); + + + //STORE GROUPS: + BMessage groups; + SaveGroupSetting(&groups); + WriteAttributeMessage(&dir,ATTR_GROUPS,&groups); +} + +void +MainController::QuitRequested() { + + BList removed(5); + download_manager->RemoveQueue(DownloadManager::ITEMS_QUEUE,&removed); + + for(int i=0; i< removed.CountItems(); i++){ + + ActionDownload* down = (ActionDownload*) ( removed.ItemAt(i) ); + + entry_ref ref; + if(down->GetRef("entry_ref",&ref)!=B_OK) continue; + + BPEpisode bpe(&ref); + bpe.SetStatus(STOPPED); + + //FIX: forse bisogna scollegare l'item grafico? bho ma chi se ne frega.. stiamo quittando.. + } + + removed.MakeEmpty(); + + StoreStates(); +} + +void +MainController::AddNewGroup(const char* label){ + + GroupItem* gi=NULL; + BString text(label); + + int extra=0; + + do + { + text.SetTo(label); + + if(label==NULL) + text << _T("Group") << " " << fModel->fGroups.CountItems()+(extra++); + else + if(extra>0) + text << " " << extra; + + gi=fModel->fGroups.ValueFor(text); + extra++; + + } while(gi); + + //we have the name + + GroupItem* group=new GroupItem(text.String(), NULL); + fModel->fGroups.AddItem(text,group); + fView->AddGroup(group,true); +} + +void +MainController::RemoveGroup(BString name) { + GroupItem* new_g=fModel->fGroups.ValueFor(name); + if(!new_g) return; + + fView->RemoveGroup(new_g); + fModel->fGroups.RemoveItemFor(name); +} + +void +MainController::RenameGroup(BString oldname,BString newname) { + GroupItem* new_g=fModel->fGroups.ValueFor(newname); + if(new_g) return; + + GroupItem* old_g=fModel->fGroups.ValueFor(oldname); + if(!old_g) return; + + old_g->SetGroupName(newname); + + fModel->fGroups.RemoveItemFor(oldname); + fModel->fGroups.AddItem(newname,old_g); +} + + +GroupItem* +MainController::AddSavedGroup(BString text,bool expanded){ + + if(text == "") return NULL; + + GroupItem* gi=fModel->fGroups.ValueFor(text); + if(gi) return gi; //already present. + + GroupItem* group = new GroupItem(text.String(), NULL); + fModel->fGroups.AddItem(text,group); + + if(fView->Lock()){ + fView->AddGroup(group,expanded); + fView->Unlock(); + } + + return group; +} + +void +MainController::UnlinkDownloadItems(){ + int32 count=fModel->fDownloadList.CountItems(); + for(int i=0;ifDownloadList.ValueAt(i)->Unlink(); +} + +void +MainController::SwitchChannel(entry_ref* href) { + + //MainWindow DEVE essere Locked. + if(!fView->IsLocked()) return; + + SubscriptionListItem* row = NULL; + + if(href){ + + row = fModel->fChInfo.ValueFor(*href); + if( BDirectory(&row->fRef) == fModel->fSelectedChannel) return; + } + + + if(fModel->fSelectedChannel.InitCheck()==B_OK){ + + //giro del cazzo: + BEntry e; + entry_ref oldref; + fModel->fSelectedChannel.GetEntry(&e); + e.GetRef(&oldref); + + SubscriptionListItem* oldRow = fModel->fChInfo.ValueFor(oldref); + if(oldRow){ + //------> Save info on the ROW!.. + oldRow->SetIsNew(false); + if(!oldRow->columnsState) + oldRow->columnsState=new BMessage(); + + oldRow->columnsState->MakeEmpty(); + SaveColumnsState(oldRow->columnsState); + //FIX: manca salvataggio ultimo episode selezionato e anche scrollposition verticale! + //oldRow->lastSelected = fModel->fSelectedItem; + } + + } + + + UnlinkDownloadItems(); + fView->ClearEpisodeListView(); + +// RssChannel* channel=&row->fChannel; +// if(!channel) return; + + + //recall saved columns infos + if(row){ + + if(row->columnsState) + LoadColumnsState(row->columnsState); + + fValidThreads.clear(); + SetSelectedItem(NULL,&row->fRef); + ParseChannel(row->fRef); + } else { + + fValidThreads.clear(); + SetSelectedItem(NULL,NULL); + } + + +} + +void +MainController::ParseChannel(entry_ref ref) { + //crea thread, + // e via si parte. + + ParseParams *params = new ParseParams; + params->nref = ref; + params->fController = this; + + + thread_id addPosesThread = spawn_thread(&MainController::ParsingThread, "parser",B_DISPLAY_PRIORITY, params); + + if (addPosesThread >= B_OK) { + fValidThreads.insert(addPosesThread); + resume_thread(addPosesThread); + } + else + delete params; + + +} + +int32 +MainController::ParsingThread(void* data) { + //codice del thread. se + ParseParams *params = (ParseParams*)data; + MainController *fController=params->fController; + entry_ref ref = params->nref; + + + thread_id threadID = find_thread(NULL); + + BDirectory dir(&ref); + BEntry entry; + + while(dir.GetNextEntry(&entry) == B_OK && fController->fView->Lock() ) { + + if(fController->IsValidThread(threadID)){ + fController->AddEpisode(entry); + } + + fController->fView->Unlock(); + } + + delete params; + fController->fValidThreads.erase(threadID); + return 0; +} + + +bool +MainController::IsValidThread(thread_id currentThread) const { + return fValidThreads.find(currentThread) != fValidThreads.end(); +} + +void +MainController::AddEpisode(BEntry entry) { + + AttributeExtractor an; + + BNode item(&entry); + if(entry.InitCheck()==B_OK && !entry.IsDirectory() && CheckMIME(MIME_ITEM,&item) ) { + + RssItem fake; + + EpisodeListItem *ep=new EpisodeListItem(); + entry.GetRef(&ep->fRef); + fake.AddElementListener(ep); + + an.SetNotifier(&fake); + an.Parse(&item); + + + + //if the Rss doesn't have a UID? + if(fake.Guid() == "") { + delete ep; + return; + } + + DownloadListItem* dwn=fModel->fDownloadList.ValueFor(ep->fRef); + if(dwn) + { + dwn->LinkToEpisode(ep); + dwn->fRss.SetFileStatus(dwn->fRss.GetFileStatus()); + //TODO: altre info? + dwn->fRss.SetDownloadSpeed(dwn->GetLastSpeed()); + dwn->fRss.SetFilePercentage(dwn->GetPercentage()); + + } + else + { + + // check for percentage. + off_t total=ep->GetEnclosureSize(); + if(fake.GetFileStatus() == STOPPED && total>0){ + BPath path(&entry); + path.GetParent(&path); + path.Append("enclosure"); + path.Append(fake.EnclosureLocalPath().String()); + off_t size = 0; + entry.SetTo(path.Path()); + if(entry.InitCheck()==B_OK && entry.GetSize(&size)==B_OK && total>size ){ + fake.SetFilePercentage((int32)((size * 100/ total ))); + } + } + // end check for percentage. + } + + fView->AddEpisodeListItem(ep); + fake.RemoveElementListener(ep); //safety. + } +} diff --git a/sources-experimental/MainController.h b/sources-experimental/MainController.h new file mode 100644 index 0000000..e9db168 --- /dev/null +++ b/sources-experimental/MainController.h @@ -0,0 +1,136 @@ +#ifndef _MainController_ +#define _MainController_ + +#include "MainModel.h" +#include "Notifier.h" +#include + +class MainWindow; +class BMessageRunner; +class EpisodeListView; + +class MainController { + + public: + MainController(MainWindow* view, MainModel* model); + + //directory parser. + + void ParseArchive(); + + void CreateChannelItem(BEntry*,BMessage*); + + void InfoDownloadItem(BMessage* msg); + + void SetSelectedItem(entry_ref* ref,entry_ref *nref); //** cambiare nome! loadInfoItem(ref) **// + + const MemoryArchive* GetSelectedItem(); //anche questo è da eliminare.. chi lo usa?? + + /*** generic ***/ + + void WWWItem(entry_ref); + + bool DeleteEpisode(entry_ref); //true if the episode was NEW + + status_t PlayItem(entry_ref); + + status_t DownloadItem(entry_ref,EpisodeListItem* e=NULL); + + status_t StopDownloadItem(entry_ref); + + status_t FindItem(entry_ref); + + status_t RemoveDownload(entry_ref); + + + /***** Channels ***********/ + + + void ShowChannelImage(entry_ref); + void DownloadChannel(BMessage* msg); + void InfoDownloadChannel(BMessage* msg); + void FolderSelectedChannel(entry_ref nref); + + BString PathFolderChannel(entry_ref nref); + void ArchiveChannel(entry_ref nref); + status_t DeleteChannel(entry_ref nref); + + void CheckChannel(entry_ref nref); + void CheckAllChannel(); + void SwitchChannel(entry_ref* nref); + + + //groups + + void AddNewGroup(const char* label); + void RenameGroup(BString oldname,BString newname); + void RemoveGroup(BString name); + + void InfoExtraDownload(BMessage* msg); + + + + void OpenURL(BString link); + + void OpenFile(const char* filename,BString filetype); + + void QuitRequested(); + + void LoadSettings(const char* type,BMessage* data); + + private: + + void SaveGroupSetting(BMessage*); + void LoadGroupSetting(BMessage*); + void StoreStates(); + void RealRemoveDownload(DownloadListItem*); + void UpdateSelected(); + + void UnlinkDownloadItems(); + + GroupItem* AddSavedGroup(BString,bool); + + void RemoveChannelFromUI(entry_ref nref,SubscriptionListItem*); + + void LoadColumnsState(BMessage* msg); + void SaveColumnsState(BMessage* msg); + + + GroupItem* LoadExtraState(BMessage* msg, SubscriptionListItem*); + void SaveExtraState(BMessage* msg, SubscriptionListItem*); + + void AlertBadPlayer(int32 player_id); + + + MainWindow* fView; + MainModel* fModel; + Notifier freeNotifier; //di comodo! + + int32 player_id; + int32 browser_id; + + // timer + BMessageRunner* check_timer; + bigtime_t check_time; + bool check_onstart; + //BString extraParams; + + + void AddEpisode(BEntry); + + struct ParseParams { + entry_ref nref; + MainController* fController; + }; + + //void SaveCurrentChannelInfo(); + //MIX + BString selectedChannel; + std::set fValidThreads; + + bool IsValidThread(thread_id currentThread) const; + void ParseChannel(entry_ref nref); + static int32 ParsingThread(void* data); +}; + +#endif diff --git a/sources-experimental/MainModel.h b/sources-experimental/MainModel.h new file mode 100644 index 0000000..10403b2 --- /dev/null +++ b/sources-experimental/MainModel.h @@ -0,0 +1,63 @@ +#ifndef _MainModel_ +#define _MainModel_ + +#include +#include + +#include "SubscriptionListItem.h" +#include "DownloadListItem.h" +#include "MemoryArchive.h" +#include "GroupItem.h" + +#include "KeyMap.h" + +class MainModel { + + public: + + //the full 'list of channels: + KeyMap fChInfo; + + //the archive folder + entry_ref archive_ref; + + //groups + KeyMap fGroups; + + //current selected ITEM & CHANNEL + MemoryArchive fCurrentSelectedItem; + BNode fSelectedItem; + BDirectory fSelectedChannel; + + + // DOWNLOADS: + + // entry_ref (of the episode) <--> Object + KeyMap fDownloadList; + + void addDownload(entry_ref ref,DownloadListItem* obj) + { + fDownloadList.AddItem(ref,obj); + } + + DownloadListItem* findDownload(entry_ref ref) + { + bool found=false; + + DownloadListItem* obj=fDownloadList.ValueFor(ref,&found); + if(found) + return obj; + + return NULL; + } + + void removeDownload(entry_ref ref) + { + bool found; + fDownloadList.ValueFor(ref,&found); + if(found) + fDownloadList.RemoveItemFor(ref); + } +}; + +#endif diff --git a/sources-experimental/MainWindow.cpp b/sources-experimental/MainWindow.cpp new file mode 100644 index 0000000..a3420b6 --- /dev/null +++ b/sources-experimental/MainWindow.cpp @@ -0,0 +1,1504 @@ +#include "MainWindow.h" +#include "Application.h" +#include "BPSettingsWindow.h" +#include "AddWindow.h" +#include "DirectoryWindow.h" +#include "HelpWindow.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include "BPLocale.h" +#include + +#include "ColumnListView.h" +#include "ColumnTypes.h" + +#include "EpisodeListItem.h" +#include "SubscriptionListItem.h" + +#include "SplitPane.h" +#include "Utils.h" + +#include "IActionMenuItem.h" + +#include "MemoryArchive.h" +#include "htmlparse.h" +#include "ImageButton.h" +#include +#include "DownloadManager.h" + +#include "IconTextRender.h" +#include "TitleTextRender.h" +#include "GreenBoxTextRender.h" +//#include "BitmapTextRender.h" + +#include "curl/curl.h" +#include + +//#include "runview/RunView.h" +#include "ItemRunView.h" +#include "runview/Theme.h" + +#include "RVActionBP.h" +#include "RVActionBPOpenURL.h" + +#include "SectionSelector.h" + +#include "DownloadListView.h" +#include "DownloadListItem.h" +#include "MainController.h" +#include "IActionManagerBP.h" +#include "GroupItem.h" + +#include "IABPGroup.h" +#include "OPMLParser.h" + +#ifdef ZETA +#include +#endif + +//messages: + #define DOWNLOAD_ITEM 'invD' + #define DOWNLOAD_CHANNEL 'addu' + + + #define ITEM_SELECTED 'selD' + #define CHANGE_WORKSPACE 'wsch' + #define SET_FULLSCREEN 'full' + #define SHOW_SETTINGS 'setp' + #define SHOW_TOOLBAR 'notb' + #define SECTION_SELECTED 'sese' + + #define SHOW_HELP 'help' + #define WEB_PAGE 'webp' + + #define SHOW_DIRECTORY 'dish' + + #define IMPORT_OPML 'imop' + #define EXPORT_OPML 'exop' + #define PARSE_OPML 'paop' + +// file size: + const int64 kKB_SIZE = 1024; + const int64 kMB_SIZE = 1048576; + const int64 kGB_SIZE = 1073741824; + const int64 kTB_SIZE = kGB_SIZE * kKB_SIZE; + +//misc UI: + #define CHANNELS_BAR_X 7 + #define ITEMS_BAR_X 280 + #define BAR_Y 12 + + +// Singletons: + +//#include "LicenceInfo.h" +//extern LicenceInfo linfo; + +extern IActionManagerBP action_manager; + + +MainWindow::MainWindow() +: BWindow(BRect(100,100,970,607), "BePodder", B_DOCUMENT_WINDOW, B_ASYNCHRONOUS_CONTROLS){ + + #ifdef ZETA + AddIcon("folder",new BBitmap(GetTrackerIcon("application/x-vnd.Be-directory",16))); + AddIcon("image",new BBitmap(GetTrackerIcon("image/png",16))); + #else + BBitmap* folder=new BBitmap(BRect(0,0,15,15), 0, B_CMAP8); + BBitmap* image=new BBitmap(BRect(0,0,15,15), 0, B_CMAP8); + + BMimeType type("application/x-vnd.Be-directory"); + type.GetIcon(folder,B_MINI_ICON); + + BMimeType type2("image"); + type2.GetIcon(image,B_MINI_ICON); + + AddIcon("folder",folder); + AddIcon("image",image); + + #endif +} + +void +MainWindow::init(MainController* controller){ + + + SetController(controller); + + + rgb_color bgcolor = ui_color(B_PANEL_BACKGROUND_COLOR); +#ifdef ZETA + SetWindowColor(bgcolor); +#endif + + BRect rect(Bounds()); + rect.top = CreateMenuBar() + 1; + + view=new BBox(rect,NULL, B_FOLLOW_ALL, B_WILL_DRAW,B_NO_BORDER); +// view->SetViewColor(bgcolor); + AddChild(view); + + + + const BFont *font = be_plain_font; + rect = BRect(0,0,47,31); + + fChannelMenu = new BPopUpMenu("ChannelMenu"); + fChannelMenu->SetFont(font); + + + + const int COUNT = 4; + const int ChannelBar[COUNT] = + { + IACTION_CHANNEL_ADD_REQUEST, + IACTION_CHANNEL_REMOVE, + IACTION_CHANNEL_CHECK, + IACTION_CHANNEL_WWW + }; + + channelView=new BView(BRect(CHANNELS_BAR_X,BAR_Y,CHANNELS_BAR_X+47+66*(COUNT-1),BAR_Y+31),"",B_FOLLOW_NONE,B_WILL_DRAW); + channelView->SetViewColor(bgcolor); + view->AddChild(channelView); + + + //automatic for the people + int i; + for(i=0;iAddChild(tasto1); + rect.OffsetBy(66,0); + + fChannelMenu->AddItem(new IActionMenuItem(action_manager.GetAction(ChannelBar[i]))); + channels->AddItem(new IActionMenuItem(action_manager.GetAction(ChannelBar[i]))); + } + + //extras :) + fChannelMenu->AddSeparatorItem(); + fChannelMenu->AddItem(new IActionMenuItem(action_manager.GetAction(IACTION_CHANNEL_ENCLOSURE_FOLDER))); + fChannelMenu->AddItem(new IActionMenuItem(action_manager.GetAction(IACTION_CHANNEL_CHECK_ALL))); + fChannelMenu->AddSeparatorItem(); + fChannelMenu->AddItem(new IActionMenuItem(action_manager.GetAction(IACTION_CHANNEL_SHOW_IMAGE))); + fChannelMenu->SetTargetForItems(be_app); + + channels->AddSeparatorItem(); + channels->AddItem(new IActionMenuItem(action_manager.GetAction(IACTION_CHANNEL_ENCLOSURE_FOLDER))); + channels->AddItem(new IActionMenuItem(action_manager.GetAction(IACTION_CHANNEL_CHECK_ALL))); + channels->AddSeparatorItem(); + channels->AddItem(new IActionMenuItem(action_manager.GetAction(IACTION_CHANNEL_SHOW_IMAGE))); + channels->SetTargetForItems(be_app); + + rect = BRect(0,0,47,31); + rect.OffsetBy(338,0); + + fItemMenu = new BPopUpMenu("ItemMenu"); + fItemMenu->SetFont(font); + + const int COUNT2 = 4; + const int ItemBar[COUNT2] = + { + IACTION_ITEM_PLAY, + IACTION_ITEM_DOWNLOAD, + IACTION_ITEM_STOP, + IACTION_ITEM_REMOVE, + }; + + itemsView=new BView(BRect(ITEMS_BAR_X,BAR_Y,ITEMS_BAR_X+382+66*(COUNT2-1),BAR_Y+31),"",B_FOLLOW_LEFT_RIGHT,B_WILL_DRAW); + itemsView->SetViewColor(bgcolor); + //itemsView->SetDoubleBuffering(true); + view->AddChild(itemsView); + + //automatic for the people + for(i=0;iAddChild(tasto1); + rect.OffsetBy(66,0); + + + fItemMenu->AddItem(new IActionMenuItem(action_manager.GetAction(ItemBar[i]))); + items->AddItem(new IActionMenuItem(action_manager.GetAction(ItemBar[i]))); + } + + //extras :) + fItemMenu->AddSeparatorItem(); + fItemMenu->AddItem(new IActionMenuItem(action_manager.GetAction(IACTION_ITEM_WWW))); + fItemMenu->AddItem(new IActionMenuItem(action_manager.GetAction(IACTION_CHANNEL_ENCLOSURE_FOLDER))); + + items->AddSeparatorItem(); + items->AddItem(new IActionMenuItem(action_manager.GetAction(IACTION_ITEM_WWW))); + items->AddItem(new IActionMenuItem(action_manager.GetAction(IACTION_CHANNEL_ENCLOSURE_FOLDER))); + + fItemMenu->SetTargetForItems(be_app); + items->SetTargetForItems(be_app); + + // GROUPS MENU + + fGroupMenu = new BPopUpMenu("GroupsMenu"); + fGroupMenu->SetFont(font); + const int COUNT4 = 4; + const int groupBar[COUNT4] = + { + IACTION_GROUP_CHECK, + IACTION_GROUP_ADD, + IACTION_GROUP_RENAME, + IACTION_GROUP_REMOVE, + }; + + + //automatic for the people + for(i=0;iAddItem(new IActionMenuItem(action_manager.GetAction(groupBar[i]))); + groups->AddItem(new IActionMenuItem(action_manager.GetAction(groupBar[i]))); + } + + groups->SetTargetForItems(be_app); + fGroupMenu->SetTargetForItems(be_app); + + //DOWNLOAD MENU + + + fDownloadMenu = new BPopUpMenu("DownMenu"); + fDownloadMenu->SetFont(font); + + const int COUNT3 = 5; + const int downBar[COUNT3] = + { + IACTION_DOWNLOAD_PLAY, + IACTION_DOWNLOAD_STOP, + IACTION_DOWNLOAD_DOWNLOAD, + IACTION_DOWNLOAD_FIND_ITEM, + IACTION_DOWNLOAD_REMOVE + }; + + + //automatic for the people + for(i=0;iAddItem(new IActionMenuItem(action_manager.GetAction(downBar[i]))); + } + + fDownloadMenu->SetTargetForItems(be_app); + + + //BButton *tasto8= new BButton(BRect(725,11,835,41),"Send","Please feedback :)",new BMessage('send')); + //view->AddChild(tasto8); + //tasto8->SetToolTipText(_T("Submit bug and idea")); + + + //--------------------------------------------------------451 + + //fStack = new StackedView(BRect(451,52,840,300),"name",B_FOLLOW_ALL, B_WILL_DRAW|B_NAVIGABLE); + + theStack = new EpisodeListView(BRect(451,52,840,300)); + + BMessage* msg=new BMessage(DOWNLOAD_ITEM); + theStack->SetInvocationMessage(msg); + + msg=new BMessage(ITEM_SELECTED); + msg->AddInt32("buttons",0); + theStack->SetSelectionMessage(msg); + + + sx_list=new SubscriptionListView(BRect(0,0,210,377)); + + + + + + + fSelector=new SectionSelector(BRect(0,0,100,100),new BMessage(SECTION_SELECTED)); + fSelector->SetTarget(this); + + BRect k = Bounds(); + + dxsplit =new SplitPane(BRect(451,52,860,477),theStack,fSelector,B_FOLLOW_ALL); + dxsplit->SetViewInsetBy(BPoint(0,0)); + dxsplit->SetAlignment(B_HORIZONTAL); + dxsplit->SetViewColor(bgcolor); + dxsplit->SetBarPosition(BPoint(k.Width()/2.0f-170, k.Height()/2.0f+38)); + dxsplit->SetMinSizeOne(BPoint(0,84)); + dxsplit->SetMinSizeTwo(BPoint(0,161)); + + split =new SplitPane(BRect(10,52,860,477),sx_list,dxsplit,B_FOLLOW_ALL); + split->SetViewInsetBy(BPoint(0,0)); + split->SetViewColor(bgcolor); + split->SetBarPosition(BPoint(k.Width()/2.0f-170, k.Height()/2.0f)); + split->SetMinSizeOne(BPoint(200,0)); + split->SetMinSizeTwo(BPoint(200,0)); + + view->AddChild(split); + + BView* fakeView=new BView(fSelector->Bounds(),"fakeView",B_FOLLOW_ALL,B_WILL_DRAW); + fakeView->AddChild(down_list=new DownloadListView(fakeView->Bounds())); + + fSelector->AddSection("info0.png",CreateItemInfoView(), _T("Show Episode info") ); + fSelector->AddSection("info1.png",CreateChannelInfoView(), _T("Show Subscription info")); + fSelector->AddSection("info2.png",fakeView, _T("Show Downloads info") ); + fSelector->Select(0); +} + +BView* +MainWindow::CreateItemInfoView(){ + //RUN VIEW-------------------------------------------------------- + + Theme *fTheme = new Theme("ItemInfo_view", MAX_COLORS + 1, MAX_COLORS + 1, MAX_FONTS + 1); + + fTheme->WriteLock(); + fTheme->SetForeground(C_URL, 0, 13, 180); //0, 100, 180 + fTheme->SetBackground(C_URL, 255, 255, 255); + fTheme->SetForeground(C_TEXT, 0, 0, 0); + fTheme->SetBackground(C_TEXT, 255, 255, 255); + fTheme->SetForeground(C_SELECTION, 255, 255, 255); + fTheme->SetBackground(C_SELECTION, 0, 0, 0); + + fTheme->SetForeground(C_ACTION,greyBox.red,greyBox.green,greyBox.blue); + fTheme->SetBackground(C_ACTION,greyBox.red,greyBox.green,greyBox.blue); + + IconTextRender *itr; + fTheme->SetTextRender(F_EMOTICON,itr=new IconTextRender()); + + itr->AddIcon("folder ",LoadIcon("folder")); + itr->SetIconSize(16.0,16.0); + + fTheme->SetTextRender(F_ACTION,new TitleTextRender()); + fTheme->SetTextRender(F_TIMESTAMP,new GreenBoxTextRender()); + + + + // fTheme->SetTextRender(F_STYLE_0,btr = new BitmapTextRender()); + + fTheme->WriteUnlock(); + + BRect scrollRect(0,0,100,100 ); + + fItemText = new ItemRunView(scrollRect, "text", fTheme,B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_NAVIGABLE); + +#ifdef ZETA + fItemText->SetViewUIColor(B_UI_DOCUMENT_BACKGROUND_COLOR); + fItemText->SetLowUIColor(B_UI_DOCUMENT_BACKGROUND_COLOR); + fItemText->SetHighUIColor(B_UI_DOCUMENT_TEXT_COLOR); +#endif + + BScrollView *fTextScroll = new BScrollView("scroller", fItemText,B_FOLLOW_ALL_SIDES, 0,false, true, B_PLAIN_BORDER); + + + fItemText->AddAction("bepodder",new RVActionBP()); + fItemText->SetDefaultOpenURLAction(new RVActionBPOpenURL(fController)); + + return fTextScroll; +} + +BView* +MainWindow::CreateChannelInfoView(){ + + Theme *fTheme = new Theme("ChannelInfo_view", MAX_COLORS + 1, MAX_COLORS + 1, MAX_FONTS + 1); + + fTheme->WriteLock(); + + fTheme->SetForeground(C_URL, 0, 13, 180); //blue? //0, 100, 180 + fTheme->SetBackground(C_URL, 255, 255, 255); //white + + fTheme->SetForeground(C_TEXT, 0, 0, 0); + fTheme->SetBackground(C_TEXT, 255, 255, 255); + + fTheme->SetForeground(C_SELECTION, 255, 255, 255); + fTheme->SetBackground(C_SELECTION, 0, 0, 0); + + fTheme->SetForeground(C_ACTION,greyBox.red,greyBox.green,greyBox.blue); + fTheme->SetBackground(C_ACTION,greyBox.red,greyBox.green,greyBox.blue); + + IconTextRender *itr; + fTheme->SetTextRender(F_EMOTICON,itr=new IconTextRender()); + + BBitmap* bitmap = LoadIcon("feed.png"); + itr->AddIcon("feed ",bitmap); + itr->SetIconSize(bitmap->Bounds().Height(),bitmap->Bounds().Width()); + + fTheme->SetTextRender(F_ACTION,new TitleTextRender()); + fTheme->SetTextRender(F_TIMESTAMP,new GreenBoxTextRender()); + + fTheme->WriteUnlock(); + + BRect scrollRect(0,0,100,100 ); + + fChannelText = new RunView(scrollRect, "channel ", fTheme,B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_NAVIGABLE); +#ifdef ZETA + fChannelText->SetViewUIColor(B_UI_DOCUMENT_BACKGROUND_COLOR); + fChannelText->SetLowUIColor(B_UI_DOCUMENT_BACKGROUND_COLOR); + fChannelText->SetHighUIColor(B_UI_DOCUMENT_TEXT_COLOR); +#endif + BScrollView *fTextScroll = new BScrollView("scroller2", fChannelText,B_FOLLOW_ALL_SIDES, 0,false, true, B_PLAIN_BORDER); + + fChannelText->AddAction("bepodder",new RVActionBP()); + fChannelText->SetDefaultOpenURLAction(new RVActionBPOpenURL(fController)); + + return fTextScroll; + + +} + +float +MainWindow::CreateMenuBar(){ + + BMenuBar *poddermenubar = new BMenuBar(BRect(0,0,1,1),"Poddermenubar"); //,B_FOLLOW_RIGHT | B_FOLLOW_TOP,B_ITEMS_IN_ROW,true); + + + BMenu *podderfile = new BMenu(_T("File"),B_ITEMS_IN_COLUMN); + poddermenubar->AddItem(podderfile); + + BMenuItem* importOmpl = new BMenuItem(_T("Import OPML..") , new BMessage(IMPORT_OPML), 0, 0); + podderfile->AddItem(importOmpl); + + + BMenuItem *podderaboutitem = new BMenuItem(_T("About..."),new BMessage(B_ABOUT_REQUESTED),0,0); + podderaboutitem->SetTarget(be_app); + podderfile->AddItem(podderaboutitem); + + BMenuItem *quititem = new BMenuItem(_T("Quit"),new BMessage(B_QUIT_REQUESTED),'Q',0); + quititem->SetTarget(be_app); + podderfile->AddItem(quititem); + + BMenu *settingsfile = new BMenu(_T("Settings"),B_ITEMS_IN_COLUMN); + poddermenubar->AddItem(settingsfile); + + BMenuItem *podderpreferencesitem = new BMenuItem(_T("Preferences..."),new BMessage(SHOW_SETTINGS),'P',0); + settingsfile->AddItem(podderpreferencesitem); + + groups = new BMenu(_T("Groups"),B_ITEMS_IN_COLUMN); + poddermenubar->AddItem(groups); + + channels = new BMenu(_T("Subscriptions"),B_ITEMS_IN_COLUMN); + poddermenubar->AddItem(channels); + + items = new BMenu(_T("Episodes"),B_ITEMS_IN_COLUMN); + poddermenubar->AddItem(items); + + BMenu *directoryfile = new BMenu(_T("Lists"),B_ITEMS_IN_COLUMN); + poddermenubar->AddItem(directoryfile); + + + AddDirectoryItem(directoryfile,_T("Podcast List"),"http://www.funkyideasoft.com/directories/bepodder_podcasts.opml.tar.gz",'L'); + AddDirectoryItem(directoryfile,_T("Videoblog List"),"http://www.funkyideasoft.com/directories/bepodder_videoblog.opml.tar.gz",'M'); + AddDirectoryItem(directoryfile,_T("Imagefeeds List"),"http://www.funkyideasoft.com/directories/bepodder_imagefeeds.opml.tar.gz",'I'); + AddDirectoryItem(directoryfile,_T("Newsfeeds List"),"http://www.funkyideasoft.com/directories/bepodder_newsfeeds.opml.tar.gz",'N'); + AddDirectoryItem(directoryfile,_T("BitTorrentfeeds List"),"http://www.funkyideasoft.com/directories/bepodder_bittorrentfeeds.opml.tar.gz",'B'); + AddDirectoryItem(directoryfile,_T("Internationalfeeds List"),"http://www.funkyideasoft.com/directories/bepodder_internationalfeeds.opml.tar.gz",'J'); + + BMenu *podderview = new BMenu(_T("View"),B_ITEMS_IN_COLUMN); + poddermenubar->AddItem(podderview); + + fullscreenitem = new BMenuItem(_T("Full Screen"),new BMessage(SET_FULLSCREEN),'F',0); + podderview->AddItem(fullscreenitem); + fullscreenitem->SetMarked(false); + + notoolbar= new BMenuItem(_T("Toolbar"),new BMessage(SHOW_TOOLBAR),'T',0); + podderview->AddItem(notoolbar); + notoolbar->SetMarked(true); + + + ChannelSize = new BMenu(_T("Subscriptions View")); + podderview->AddItem(ChannelSize); + ChannelSize->SetRadioMode(true); + + BMenuItem* temp; + + temp= new BMenuItem(_T("Big Items"),new BMessage('bigg')); + ChannelSize->AddItem(temp); + temp->SetMarked(true); + + temp=new BMenuItem(_T("Small Items"),new BMessage('smal')); + ChannelSize->AddItem(temp); + temp->SetMarked(false); + + ChannelSize->SetEnabled(true); //linfo.Valid()); + + //-------------------------------------------------------------------------------------------------------------- + + + setworkspace= new BMenu(_T("Move BePodder on workspace:")); + podderview->AddItem(setworkspace); + + for(int i=0;iAddItem(workspace1 = new BMenuItem(text.String(), new BMessage(CHANGE_WORKSPACE), 0)); + if(i == current_workspace() ) + workspace1->SetMarked(true); + } + + + BMenu *helpfile = new BMenu(_T("Help"),B_ITEMS_IN_COLUMN); + poddermenubar->AddItem(helpfile); + + + BMessage *msg=new BMessage(SHOW_HELP); + BMenuItem *helpitem1 = new BMenuItem(_T("Getting Started"),msg,'G',0); + helpfile->AddItem(helpitem1); + + msg=new BMessage(SHOW_HELP); + msg->AddString("page","shortcuts"); + BMenuItem *shortcutitem = new BMenuItem(_T("Keyboard Shortcuts"),msg,'K',0); + helpfile->AddItem(shortcutitem); + + BMessage *webmsg=new BMessage(WEB_PAGE); + //full url (introduction.html) + BString where(GetAppRelativePath()); + where << "/tutorial/introduction.html"; + where.Prepend("file://"); + + webmsg->AddString("url",where.String()); + helpfile->AddItem( new BMenuItem(_T("Tutorials"),webmsg,0,0)); + + + helpfile->AddSeparatorItem(); + + webmsg=new BMessage(WEB_PAGE); + webmsg->AddString("url","http://www.funkyideasoft.com/support.html"); + helpfile->AddItem( new BMenuItem(_T("Online Support"),webmsg,0,0)); + + helpfile->AddSeparatorItem(); + BMenuItem* updates; + helpfile->AddItem(updates=new BMenuItem(_T("Check for updates"),new BMessage('ckup'),0,0)); + updates->SetTarget(be_app); + + AddChild(poddermenubar); + poddermenubar->ResizeToPreferred(); + + return poddermenubar->Bounds().bottom; + +} + +void +MainWindow::AddDirectoryItem(BMenu* directoryfile,const char *name,const char* url,char shortcut) { + + BMessage* msg=new BMessage(SHOW_DIRECTORY); + msg->AddString("name",name); + msg->AddString("url",url); + + directoryfile->AddItem(new BMenuItem(name,msg,shortcut,0)); +} + +void +MainWindow::SaveSetting(BMessage* data){ + + BRect rect(Frame()); + + if(fullscreenitem->IsMarked()) + rect = podderrect; + + data->AddFloat("window_x",rect.left); + data->AddFloat("window_y",rect.top); + data->AddFloat("window_w",rect.Width()); + data->AddFloat("window_h",rect.Height()); + + //splits + BMessage split_state; + split->GetState(split_state); + data->AddMessage("bar_position_state",&split_state); + + split_state.MakeEmpty(); + dxsplit->GetState(split_state); + data->AddMessage("dxbar_position_state",&split_state); + + //toolbar (visible?) + data->AddBool("toolbar_visible",notoolbar->IsMarked()); + + //fullscreen (on?) + data->AddBool("fullscreen",fullscreenitem->IsMarked()); + + + //default Subscription Items size: + data->AddInt32("channel_size",sx_list->ItemSize()); + + //debug.. + //data->PrintToStream(); + + +} + + +void +MainWindow::LoadSetting(BMessage* data){ + + //data->PrintToStream(); + + float x,y; + if(data->FindFloat("window_x",&x)==B_OK && data->FindFloat("window_y",&y)==B_OK){ + MoveTo(x,y); + podderrect.left=x; + podderrect.top=y; + } + if(data->FindFloat("window_w",&x)==B_OK && data->FindFloat("window_h",&y)==B_OK){ + ResizeTo(x,y); + podderrect.right=podderrect.left + x - 1; + podderrect.bottom=podderrect.top + y - 1; + } + + //fullscreen (on?) + bool result; + if(data->FindBool("fullscreen",&result) == B_OK){ + if(result) + SetFullscreen(result); + } + + //toolbar (visible?) + if(data->FindBool("toolbar_visible",&result) == B_OK){ + if(!result) + SetToolbarVisible(result); + } + + //splits + BMessage split_state; + if(data->FindMessage("bar_position_state",&split_state) == B_OK){ + split->SetState(&split_state); + } + split_state.MakeEmpty(); + if(data->FindMessage("dxbar_position_state",&split_state) == B_OK){ + dxsplit->SetState(&split_state); + } + + int32 size; + //default Subscription Items size: + if(data->FindInt32("channel_size",&size) == B_OK){ + sx_list->SetItemSize((SubscriptionSize)size); + ChannelSize->ItemAt(size)->SetMarked(true); + } + + ChannelSize->SetEnabled(true);//linfo.Valid()); +} + + +void MainWindow::MessageReceived(BMessage* msg) +{ + + + switch(msg->what) + { + + case 'bigg': + sx_list->SetItemSize(BIG); + break; + case 'smal': + sx_list->SetItemSize(SMALL); + break; + + case SHOW_SETTINGS: + { + BPSettingsWindow *Settings = new BPSettingsWindow(); + Settings->Show(); + } + break; + case SHOW_DIRECTORY: + { + BString name; + BString url; + msg->FindString("name",&name); + msg->FindString("url",&url); + DirectoryWindow *Directory = new DirectoryWindow(name.String(),url); + Directory->Show(); + } + break; + + case WEB_PAGE: + { + BString url; + if(msg->FindString("url",&url) == B_OK) + fController->OpenURL(url.String()); + } + break; + case SHOW_HELP: + { + + BPAlert *alert = new BPAlert("BePodder",_T("Loading Help..."),NULL,NULL,NULL,B_WIDTH_AS_USUAL, LoadIcon("enqueued-32.png")); + alert->Go(NULL); + + HelpWindow *help1 = new HelpWindow(); + help1->Show(); + + BString page; + if(msg->FindString("page",&page)==B_OK) + help1->SetPage(page); + + alert->PostMessage(B_QUIT_REQUESTED); + } + break; + + case SET_FULLSCREEN: + SetFullscreen(!fullscreenitem->IsMarked()); + break; + + case CHANGE_WORKSPACE: + { + msg->PrintToStream(); + uint32 index=(uint32)msg->FindInt32("index"); + + uint32 space = 0x1UL; + space <<= index; + + SetWorkspaces(space); + if( setworkspace->FindMarked() ) setworkspace->FindMarked()->SetMarked(false); + if(setworkspace->ItemAt(index)) setworkspace->ItemAt(index)->SetMarked(true); + } + break; + + case CHECK_ALL: + fController->CheckAllChannel(); + break; + + case ARCHIVE_PARSE: + { + //show the alert + BPAlert *alert = new BPAlert("BePodder",_TT("alert3"),NULL,NULL,NULL,B_WIDTH_AS_USUAL, LoadIcon("enqueued-32.png")); + alert->Go(NULL); + + + fController->ParseArchive(); + + if(sx_list->CountRows()>0) { + sx_list->AddToSelection(sx_list->RowAt(0)); + SubscriptionListItem* row=dynamic_cast(sx_list->RowAt(0)); + if(row) + fController->SetSelectedItem( NULL,&row->fRef); + } + //close the alert + alert->PostMessage(B_QUIT_REQUESTED); + + } + break; + + case DOWNLOAD_CHANNEL: + fController->DownloadChannel(msg); + break; + + case DOWNLOAD_CHANNEL_INFO: + fController->InfoDownloadChannel(msg); + break; + + case DOWNLOAD_ITEM_INFO: + fController->InfoDownloadItem(msg); + break; + + case CHANNEL_SELECTED: + { + SubscriptionListItem* row=dynamic_cast(sx_list->CurrentSelection()); + if(row) + SelectedSubscription(row,msg->FindInt32("buttons")); + + GroupItem* group=dynamic_cast(sx_list->CurrentSelection()); + if(group) + SelectGroup(group,msg->FindInt32("buttons")); + } + break; + + case ITEM_SELECTED: + { + + SubscriptionListItem* row=GetSelectedSubscription(); + if(!row) return; + + EpisodeListItem* episode=GetSelectedEpisode(); + if(!episode) return; + + fController->SetSelectedItem(&episode->fRef,&row->fRef); + + + EpisodeListView *elv=theStack; //FIX FOR GROUP MANAGE + if(!elv) return; + + if(msg->FindInt32("buttons")==B_SECONDARY_MOUSE_BUTTON){ + + BPoint point; + uint32 state; + elv->GetScrollView()->GetMouse(&point,&state); + + BPoint p2 = elv->GetScrollView()->ConvertToScreen(point); + p2.x -= 5.0; + p2.y -= 5.0; + + + if(fItemMenu->FindMarked()) + fItemMenu->FindMarked()->SetMarked(false); + + elv->SelectionMessage()->ReplaceInt32("buttons",0); + fItemMenu->Go(p2, true, true, true); + + } + } + break; + + case DOWNLOAD_SELECTED: + { + + if(msg->FindInt32("buttons")==B_SECONDARY_MOUSE_BUTTON){ + + BPoint point; + uint32 state; + down_list->GetScrollView()->GetMouse(&point,&state); + + BPoint p2 = down_list->GetScrollView()->ConvertToScreen(point); + p2.x -= 5.0; + p2.y -= 5.0; + + + if(fDownloadMenu->FindMarked()) + fDownloadMenu->FindMarked()->SetMarked(false); + + fDownloadMenu->Go(p2, true, true, true); + + } + + down_list->ResetSelectionMessage(); + } + break; + case SECTION_SELECTED: + ShowDescription((MemoryArchive*)fController->GetSelectedItem()); + break; + case DOWNLOAD_INVOKED: + action_manager.FireAction(IACTION_DOWNLOAD_DOWNLOAD); + break; + case DOWNLOAD_ITEM: + action_manager.FireAction(IACTION_ITEM_DOWNLOAD); + break; + + case DOWNLOAD_EXTRA_INFO: + fController->InfoExtraDownload(msg); + break; + + case SHOW_TOOLBAR: + SetToolbarVisible(!notoolbar->IsMarked()); + break; + + case GROUP_NAME_CHANGE: + { + BString oldname; + BString newname; + if( msg->FindString("oldname",&oldname) ==B_OK && + msg->FindString("_value",&newname)==B_OK ) + fController->RenameGroup(oldname,newname); + } + break; + + case IMPORT_OPML: + { + // select the OPML file, + BFilePanel *filePanel = new BFilePanel(B_OPEN_PANEL); + filePanel->SetMessage(new BMessage(PARSE_OPML)); + filePanel->SetTarget(BMessenger(this)); + filePanel->Show(); + //try to parse + + //foreach add to the window + } + case PARSE_OPML: + { + entry_ref ref; + + if(msg->FindRef("refs",&ref) == B_OK) + { + OPMLParser parser; + OPMLTree* tree = parser.Parse(BPath(&ref).Path()); + + if(!tree) return; //should never happen! + + RecursiveParseOpml(tree); + + +// BPAlert *alert = new BPAlert("BePodder",,_T("Error"),_T("Close"),NULL,B_WIDTH_AS_USUAL, LoadIcon("logo-64.png")); +// if(alert->Go()==0) +// fController->OpenURL("http://www.funkyideasoft.com/downloads.html"); + } + msg->PrintToStream(); + } + break; + + default: + BWindow :: MessageReceived(msg); + break; + } +} + +void MainWindow::RecursiveParseOpml(OPMLTree* branch) +{ + if(branch->foglie) + { + //it's a group. + for(int32 i=branch->foglie->CountItems() -1 ; i>=0 ; i--){ + OPMLTree* subfoglia = branch->foglie->ItemAt(i); + //fController->AddNewGroup(branch->description.String()); + RecursiveParseOpml(subfoglia); + } + + } + else + { + //it's a link + BMessage msg('addu'); + msg.AddString("url", branch->link); + BMessenger(this).SendMessage(&msg); + printf("sending url %s\n", branch->link.String()); + } +} + +//----------------------------------- + +/* +EpisodeListView* +MainWindow::CreateEpisodeListView(BString url){ + +// Lock(); +// BRect rect = fStack->Bounds(); +// Unlock(); +// +// //BRect rect(0,0,0,0); +// +// EpisodeListView* elv=new EpisodeListView(rect); +// +// BMessage* msg=new BMessage(DOWNLOAD_ITEM); +// msg->AddString("url",url); +// elv->SetInvocationMessage(msg); +// +// msg=new BMessage(ITEM_SELECTED); +// msg->AddString("url",url); +// msg->AddInt32("buttons",0); +// elv->SetSelectionMessage(msg); + + return theStack; +}*/ +/* +void +MainWindow::AddEpisodeListView(EpisodeListView* elv){ + //fStack->AddView(elv); +} +*/ +void +MainWindow::AddEpisodeListItem(EpisodeListItem* ep){ + theStack->AddRow(ep); +} + + +void +MainWindow::AddSubscription(SubscriptionListItem* row,GroupItem* grp){ + sx_list->AddRow(row ,sx_list->CountRows(),grp); +} + +void +MainWindow::ScrollToSubscripion(SubscriptionListItem* row){ + sx_list->ScrollTo(row); //auto-scroll to new item. +} + + void +MainWindow::RefreshSubscriptionLists(){ + sx_list->Refresh(); +} + +void +MainWindow::RefreshSubscription(SubscriptionListItem* row) { + sx_list->UpdateRow(row); +} + +void +MainWindow::AddGroup(GroupItem* group,bool expanded){ + sx_list->AddGroup(group); + sx_list->ExpandOrCollapse(group,expanded); +} + +BString +MainWindow::GroupOf(SubscriptionListItem* row){ + BRow *parent=NULL; + sx_list->FindParent(row,&parent,NULL); + if(!parent) return NULL; + + GroupItem* grp=dynamic_cast(parent); + if(!grp) return NULL; + + return grp->GroupName(); +} + + + +void +MainWindow::RemoveSubscription(SubscriptionListItem* row){ + + sx_list->DeselectAll(); + sx_list->RemoveRow(row); + if(sx_list->CountRows() > 0) + { + sx_list->AddToSelection(sx_list->RowAt(0)); + sx_list->SelectionChanged(); + } + else + ClearEpisodeListView(); + + delete row; +} + + +EpisodeListView* +MainWindow::GetEpisodeListView(){ + return theStack; +} + + +EpisodeListItem* +MainWindow::GetSelectedEpisode(EpisodeListItem* prev){ //indipendentemente dalla view su cui è posto! + return dynamic_cast(theStack->CurrentSelection(prev)); +} + + +void +MainWindow::RefreshEpisode(EpisodeListItem* row) { + theStack->UpdateRow(row); +} + + +void +MainWindow::SelectSubscription(int i){ + + Lock(); + if(sx_list->CountRows()>0) { + SubscriptionListItem* sel=dynamic_cast(sx_list->RowAt(i)); + SelectSubscription(sel); + } + Unlock(); +} + +void +MainWindow::SelectSubscription(SubscriptionListItem* sel){ + sx_list->DeselectAll(); + sx_list->AddToSelection(sel); + SelectedSubscription(sel); +} + +void +MainWindow::ClearEpisodeListView() { + theStack->Clear(); +} + +void +MainWindow::SelectedSubscription(SubscriptionListItem* row, int32 bottons){ + + if(!row) return; + + row->SetIsNew(false); + + fController->SwitchChannel(&row->fRef); + + if(bottons==B_SECONDARY_MOUSE_BUTTON){ + + BPoint point; + uint32 state; + sx_list->GetScrollView()->GetMouse(&point,&state); + + BPoint p2 = sx_list->GetScrollView()->ConvertToScreen(point); + p2.x -= 5.0; + p2.y -= 5.0; + + + if(fChannelMenu->FindMarked()) + fChannelMenu->FindMarked()->SetMarked(false); + + sx_list->SelectionMessage()->ReplaceInt32("buttons",0); + fChannelMenu->Go(p2, true, true, true); + } +} + +void +MainWindow::SelectGroup(GroupItem* grp, int32 bottons){ + + if(!grp) return; + + fController->SwitchChannel(NULL); + + if(bottons==B_SECONDARY_MOUSE_BUTTON){ + + BPoint point; + uint32 state; + sx_list->GetScrollView()->GetMouse(&point,&state); + + BPoint p2 = sx_list->GetScrollView()->ConvertToScreen(point); + p2.x -= 5.0; + p2.y -= 5.0; + + + if(fGroupMenu->FindMarked()) + fGroupMenu->FindMarked()->SetMarked(false); + + sx_list->SelectionMessage()->ReplaceInt32("buttons",0); + fGroupMenu->Go(p2, true, true, true); + } +} + +void +MainWindow::RemoveGroup(GroupItem* group){ + sx_list->RemoveRow(group); + delete group; +} + + + + +SubscriptionListItem* +MainWindow::GetSelectedSubscription(){ + return dynamic_cast(sx_list->CurrentSelection()); +} + +GroupItem* +MainWindow::GetSelectedGroup(){ + return dynamic_cast(sx_list->CurrentSelection()); +} + +bool +MainWindow::GetScreenGroupRect(GroupItem *row, BRect *outRect) { + BRect rect; + if(!sx_list->GetRowRect((const BRow *)row, &rect) ) return false; + *outRect= sx_list->GetScrollView()->ConvertToScreen(rect); + return true; + +} + +int32 +MainWindow::CountSubscriptionOfGroup(GroupItem* grp){ + return sx_list->CountRows(grp); +} + +SubscriptionListItem* +MainWindow::GetSubscriptionOfGroup(int32 i,GroupItem* grp){ + return dynamic_cast(sx_list->RowAt(i,grp)); +} + + +DownloadListItem* +MainWindow::GetSelectedDownload(){ + return dynamic_cast(down_list->CurrentSelection()); +} + +int32 +MainWindow::IndexOfSubscription(SubscriptionListItem* item){ + return sx_list->IndexOf((BRow*)item); +} + +void +MainWindow::SetSortingSubscriptions(bool value){ + sx_list->SetSortingEnabled(value); + sx_list->SetSortColumn(sx_list->ColumnAt(0),true,true); +} + +void +MainWindow::AddDownload(DownloadListItem* down){ + down_list->AddRow(down,(long int)0); +} + +void +MainWindow::RemoveDownload(DownloadListItem* item){ + down_list->RemoveRow(item); + delete item; +} + + + +bool +MainWindow::QuitRequested() { + be_app->PostMessage(B_QUIT_REQUESTED); + return false; +} + + +void +MainWindow::ShowDescription(MemoryArchive* archive){ + + + switch(fSelector->Selected()){ + case 0: + ShowItemDescription(archive); + break; + case 1: + ShowChannelDescription(archive); + break; + + default:break; + }; + +} + + +void +MainWindow::ShowItemDescription(MemoryArchive* archive){ + + + fItemText->Clear(); + ((ItemRunView*)fItemText)->LoadBitmap(NULL); + + BString itemTitle(archive->GetDataString(CHANNEL_TITLE) ); + BString webLink(archive->GetDataString(CHANNEL_WEBLINK)); + + if(itemTitle !="" ) + { + if( webLink != "" ) + fItemText->AppendURL(itemTitle.String(),webLink.String(),C_ACTION,F_TEXT); + else + fItemText->Append( itemTitle.String(),C_TEXT,C_ACTION,F_TIMESTAMP ); + } + time_t *curtime = 0; + if(archive->GetData(ITEM_PUBDATE,(const void**)&curtime) >0){ + + char dateString[256]; + tm time_data; + time_t datetime=*curtime; + localtime_r(&datetime, &time_data); + + //"%A, %B %d %Y, %I:%M:%S %p" + strftime(dateString, 256, "%a, %B %d %Y, %I:%M:%S %p", &time_data); + + fItemText->Append(" - ",C_TEXT,C_ACTION,F_TIMESTAMP); + fItemText->Append(dateString,C_TEXT,C_ACTION,F_TIMESTAMP); + } + else + fItemText->Append(" ",C_TEXT,C_ACTION,F_TIMESTAMP); + + fItemText->Append("\n",C_TEXT,C_TEXT,F_TEXT); + + if(archive->GetDataString(ITEM_TITLE) !="") + fItemText->Append(archive->GetDataString(ITEM_TITLE).String(),C_TEXT,C_TEXT,F_ACTION); + + if(archive->GetDataString(ITEM_LINK) != ""){ + fItemText->AppendURL(" [www]",archive->GetDataString(ITEM_LINK) .String(),F_TEXT); + } + fItemText->Append("\n",C_TEXT,C_TEXT,F_TEXT); + + const void* buffer = NULL; + ssize_t m_size = archive->GetData(ITEM_DESCRIPTION,&buffer); + + if( m_size>0){ + //do what you need to do. + char* copybuffer=(char*)malloc(m_size); + memcpy(copybuffer,buffer,m_size); + + m_size = parse_html(copybuffer,m_size); + BString data(copybuffer,m_size); + fItemText->Append(data.String(),C_TEXT,C_TEXT,F_TEXT); + + free(copybuffer); + } + BString url = archive->GetDataString(ITEM_ENCLOSURE_URL); + if( url != ""){ + + + + fItemText->Append("\n\n",C_TEXT,C_TEXT,F_TEXT); + + BString action("action://bepodder("); + action << (int)IACTION_CHANNEL_ENCLOSURE_FOLDER << ")"; + + fItemText->AppendURL("folder ",action.String(),C_ACTION,F_EMOTICON); + fItemText->AppendURL(_T("Enclosure: "),action.String(),C_ACTION,F_TEXT); + + BString local(archive->GetDataString(ITEM_ENCLOSURE_LOCALPATH)); + //path.Append(local.String()); + //folder_url.SetTo(path.Path()); + //fItemText->AppendURL(local.String(),folder_url.String(),C_ACTION,F_TEXT); + + BString bottom; + bottom << local; + + BString filetype(archive->GetDataString(ITEM_ENCLOSURE_TYPE) ); + if( filetype !="") + bottom << " (" << filetype<< ") " ; + + + off_t* len=0; + if( archive->GetData(ITEM_ENCLOSURE_LENGTH,(const void**)&len)>0 && len>0 ){ + off_t size=*len; + char str[256]; + if (size < kKB_SIZE) + { + sprintf(str, "%Ld bytes", size); + } + else + { + const char* suffix; + float float_value; + if (size >= kTB_SIZE) + { + suffix = "TB"; + float_value = (float)size / kTB_SIZE; + } + else if (size >= kGB_SIZE) + { + suffix = "GB"; + float_value = (float)size / kGB_SIZE; + } + else if (size >= kMB_SIZE) + { + suffix = "MB"; + float_value = (float)size / kMB_SIZE; + } + else + { + suffix = "KB"; + float_value = (float)size / kKB_SIZE; + } + + sprintf(str, "%.2f %s", float_value, suffix); + // strip off an insignificant zero so we don't get readings + // such as 1.00 + char *period = 0; + char *tmp (NULL); + for (tmp = str; *tmp; tmp++) + { + if (*tmp == '.') + period = tmp; + } + if (period && period[1] && period[2] == '0') + // move the rest of the string over the insignificant zero + for (tmp = &period[2]; *tmp; tmp++) + *tmp = tmp[1]; + } + bottom << " [" << str << "]" ; + } + fItemText->Append(bottom.String(),C_TEXT,C_ACTION,F_TIMESTAMP); + //fItemText->Append(" test.mp3 1234Kb (audio/mp3) downloaded",C_TEXT,C_ACTION,F_TIMESTAMP); + + + + // AUTO_SHOWER IMAGE. + //SE: filestatus = DOWNLOADED, SE filetype inzia on image/, SE localpath != "" allora carica e mostra... + + + FileStatus status = (FileStatus)archive->GetDataInt32(ITEM_ENCLOSURE_FILE_STATUS); + if( status == DOWNLOADED && + filetype.FindFirst("image/")==0 && + local != "" ) + { + fItemText->Append("\n",C_TEXT,C_TEXT,F_TEXT); + //Fullpath: + SubscriptionListItem* row=GetSelectedSubscription(); + if(row){ + BString fullPath=fController->PathFolderChannel(row->fRef); + fullPath << "/" << local; + ((ItemRunView*)fItemText)->LoadBitmap(fullPath.String()); + } + } + + + } + + fItemText->Append("\n",C_TEXT,C_TEXT,F_TEXT); + fItemText->ScrollTo(0,0); + +} + +void +MainWindow::ShowChannelDescription(MemoryArchive* archive){ + + //int fItemText; + + fChannelText->Clear(); + fChannelText->Append("\n",C_TEXT,C_TEXT,F_TEXT); + + if(archive->GetDataString(CHANNEL_TITLE) != "") + fChannelText->Append(archive->GetDataString(CHANNEL_TITLE).String(),C_TEXT,C_TEXT,F_ACTION); + + if(archive->GetDataString(CHANNEL_WEBLINK) != ""){ + fChannelText->AppendURL(" [www]",archive->GetDataString(CHANNEL_WEBLINK) .String(),F_TEXT); + } + fChannelText->Append("\n",C_TEXT,C_TEXT,F_TEXT); + + const void * buffer = NULL; + ssize_t size = archive->GetData(CHANNEL_DESCRIPTION,&buffer); + + if( size>0){ + char* copybuffer=(char*)malloc(size); + memcpy(copybuffer,buffer,size); + + size = parse_html(copybuffer,size); + BString data(copybuffer,size); + fChannelText->Append(data.String(),C_TEXT,C_TEXT,F_TEXT); + + free(copybuffer); + } + + size = archive->GetData(CHANNEL_IMAGE_DATA,(const void**)&buffer); + + if( size>0){ + BString action("action://bepodder("); + action << (int)IACTION_CHANNEL_SHOW_IMAGE << ")"; + fChannelText->Append("\n\n",C_TEXT,C_TEXT,F_TEXT); + fChannelText->AppendURL(_T("Show channel Image"),action.String(),C_TEXT,F_TEXT); + //free(buffer); + } + + fChannelText->Append("\n\n",C_TEXT,C_TEXT,F_TEXT); + fChannelText->AppendURL("feed ",archive->GetDataString(CHANNEL_URL) .String(),C_TEXT,F_EMOTICON); //? Icon ?? + fChannelText->AppendURL("XML Feed Link",archive->GetDataString(CHANNEL_URL) .String(),F_TEXT); + fChannelText->Append("\n",C_TEXT,C_TEXT,F_TEXT); + + fChannelText->Append("\n",C_TEXT,C_TEXT,F_TEXT); + fChannelText->ScrollTo(0,0); + + +} + +void +MainWindow::SetFullscreen(bool fullscreen){ + + BRect wrect(Bounds()); + if (!fullscreen) { + fullscreenitem->SetMarked(false); + wrect = podderrect; + SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_MOVABLE)); + } + else { + fullscreenitem->SetMarked(true); + BScreen screen; + podderrect = Frame(); + wrect = screen.Frame(); + //BRect frect(Bounds()); + SetFlags(Flags() | B_NOT_RESIZABLE | B_NOT_MOVABLE); + } + + MoveTo(wrect.left, wrect.top); + ResizeTo(wrect.Width(), wrect.Height()); + + BRect frect(Bounds()); + dxsplit->SetBarPosition(BPoint(frect.Width()/2.0f-170, frect.Height()/2)); +} + +void +MainWindow::SetToolbarVisible(bool visible){ + + BPoint point(0,42); + if(!visible) { + notoolbar->SetMarked(false); + view->ScrollTo(point); + split->ResizeBy(point.x,point.y); + dxsplit->SetBarPosition(dxsplit->GetBarPosition()+=point); + + if(!itemsView->IsHidden()) + itemsView->Hide(); + if(!channelView->IsHidden()) + channelView->Hide(); + + } else { + + + notoolbar->SetMarked(true); + view->ScrollTo(BPoint(0,0)); + split->ResizeBy(point.x,-point.y); + dxsplit->SetBarPosition(dxsplit->GetBarPosition()-=point); + + if(itemsView->IsHidden()) + itemsView->Show(); + if(channelView->IsHidden()) + channelView->Show(); + } + + +} + diff --git a/sources-experimental/MainWindow.h b/sources-experimental/MainWindow.h new file mode 100644 index 0000000..aeb0bfa --- /dev/null +++ b/sources-experimental/MainWindow.h @@ -0,0 +1,169 @@ +#ifndef MainWindow_H +#define MainWindow_H + +#include +#include +#include +#include +#include +#include +//#include +#include "StackedView.h" +#include + + +#include "SubscriptionListView.h" +#include "DownloadListView.h" +#include "EpisodeListView.h" +#include "EpisodeListItem.h" + +#include "BPAlert.h" + +class SubscriptionListItem; +class SplitPane; +class RunView; + +#define ARCHIVE_PARSE 'pars' +#define CHECK_ALL 'chal' + +class MemoryArchive; +class MainController; +class DownloadListItem; +class SectionSelector; +class GroupItem; +class OPMLTree; + +class MainWindow: public BWindow +{ + + + + public: + MainWindow(); + void init(MainController* controller); + + void MessageReceived(BMessage* message); + bool QuitRequested(); + + + void AddGroup(GroupItem*,bool expanded); + BString GroupOf(SubscriptionListItem* row); + + + void AddEpisodeListItem(EpisodeListItem* ep); + + void ClearEpisodeListView(); + + void AddSubscription(SubscriptionListItem* row,GroupItem* grp); + + void ScrollToSubscripion(SubscriptionListItem* row); + + void RefreshSubscriptionLists(); + void RefreshSubscription(SubscriptionListItem* row); + + void RemoveSubscription(SubscriptionListItem* row); + + EpisodeListView* GetEpisodeListView(); + EpisodeListItem* GetSelectedEpisode(EpisodeListItem* prev = NULL); //indipendentemente dalla view su cui è posto! + + + void RefreshEpisode(EpisodeListItem* row); + + void ShowDescription(MemoryArchive* archive); + + void SetController(MainController* c){ fController = c;} + + SubscriptionListItem* GetSelectedSubscription(); + + GroupItem* GetSelectedGroup(); + bool GetScreenGroupRect(GroupItem *row, BRect *outRect); + + void RemoveGroup(GroupItem*); + + int32 CountSubscriptionOfGroup(GroupItem*); + + SubscriptionListItem* GetSubscriptionOfGroup(int32,GroupItem*); + + + DownloadListItem* GetSelectedDownload(); + + int32 IndexOfSubscription(SubscriptionListItem* item); + + void SetSortingSubscriptions(bool value); + + + void SelectSubscription(int i); + void SelectSubscription(SubscriptionListItem* elv); + + void SelectedSubscription(SubscriptionListItem* elv, int32 bottons = -1); + + void SelectGroup(GroupItem*, int32 bottons = -1); + //void SelectEpisode(EpisodeListView* view, EpisodeListItem* item); + + + void AddDownload(DownloadListItem*); + void RemoveDownload(DownloadListItem*); + + + + void SaveSetting(BMessage* data); + void LoadSetting(BMessage* data); + private: + float CreateMenuBar(); + BView* CreateItemInfoView(); + BView* CreateChannelInfoView(); + + void ShowItemDescription(MemoryArchive* archive); + void ShowChannelDescription(MemoryArchive* archive); + + + void SetFullscreen(bool); + void SetToolbarVisible(bool); + + + void AddDirectoryItem(BMenu*,const char *name,const char* url,char shortcut); + + void RecursiveParseOpml(OPMLTree* branch); + + + MainController* fController; + + BMenuItem* notoolbar; + BMenuItem* fullscreenitem; + BMenu* setworkspace; + BMenu* ChannelSize; + + BMenu* channels; + BMenu* items; + BMenu* groups; + + BView* channelView; //toolbar + BView* itemsView; //toolbar + + + + SubscriptionListView *sx_list; + DownloadListView *down_list; + + BBox *view; //the main view. + + StackedView *fStack; + EpisodeListView *theStack; + + RunView *fItemText; + RunView *fChannelText; + + SplitPane *split,*dxsplit; + + BPopUpMenu* fChannelMenu; + BPopUpMenu* fItemMenu; + BPopUpMenu* fDownloadMenu; + BPopUpMenu* fGroupMenu; + + SectionSelector* fSelector; + + BRect podderrect; + +}; + +#endif diff --git a/sources-experimental/MemoryArchive.cpp b/sources-experimental/MemoryArchive.cpp new file mode 100644 index 0000000..5540889 --- /dev/null +++ b/sources-experimental/MemoryArchive.cpp @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#include "MemoryArchive.h" +#include + + + +MemoryArchive & MemoryArchive::operator=(const MemoryArchive &msg){ + this->fData = msg.fData; + return *this; +} + +void +MemoryArchive::SetKey(ItemProperty key,void* data,ssize_t numBytes) { + + BString superkey("key_"); + superkey << key; + + if(fData.HasData(superkey.String(),B_ANY_TYPE)) + fData.ReplaceData(superkey.String(),B_ANY_TYPE,data,numBytes); + else + fData.AddData(superkey.String(),B_ANY_TYPE,data,numBytes); +} + +void +MemoryArchive::SetKeyString(ItemProperty key,const char* data){ + size_t len = strlen(data); + char copy[ len + 1]; + + strncpy(copy,data,len); + copy[len] = '\0'; + SetKey(key,(void*)copy, len+1); +} + +void +MemoryArchive::SetKeyInt32(ItemProperty key,int32 data){ + SetKey(key,(void*)&data,sizeof(int32)); +} + +ssize_t +MemoryArchive::GetData(ItemProperty key,const void** data){ + BString superkey("key_"); + superkey << key; + ssize_t numBytes = 0; + fData.FindData(superkey.String(),B_ANY_TYPE,0,data,&numBytes); + + return numBytes; +} + +BString +MemoryArchive::GetDataString(ItemProperty key){ + + void* data=NULL; + ssize_t ret = GetData(key,(const void**)&data); + + if(ret>0) + { + BString str((const char*)data,ret); + //if(data) free(data); + return str; + } + else + return NULL; + + + } + +int32 +MemoryArchive::GetDataInt32(ItemProperty key){ + + void* data = NULL; + ssize_t ret = GetData(key,(const void**)&data); + + if(ret == sizeof(int32) ) + { + int32 num = *((int32*)data); + //if(data) free(data); + return num; + } + else + return 0; + + + } + +int32 +MemoryArchive::CountData(){ + return fData.CountNames(B_ANY_TYPE); +} + +void +MemoryArchive::KeyModified(int32 key, void* data, ssize_t numBytes){ + SetKey((ItemProperty)key,data,numBytes); +} + +void +MemoryArchive::FillListener(Notifier* fListener){ +#ifdef ZETA + //now update all my info! (is always true?) + void *cookie = NULL; + char *name; + uint32 type=0; + int32 count = 0; + + while (fData.GetNextName(&cookie, (const char**)&name,NULL,NULL) == B_OK) { + + void* data = NULL; + ssize_t numBytes; + if(fData.FindData(name,B_ANY_TYPE,0,(const void**)&data,&numBytes)==B_OK) + { + //FIX MANCA SSIZE_T! (unmangling the name..) + BString uname(name); + uname.RemoveAll("key_"); + int32 key = atol(uname.String()); + + fListener->SetKey((ItemProperty)key,data,numBytes); + //if(data && numBytes>0)free(data); + } + } +#else + //now update all my info! (is always true?) + //void *cookie = NULL; + char *name; + uint32 type=0; + int32 count = fData.CountNames(B_ANY_TYPE); + + for(int i=0;iSetKey((ItemProperty)key,data,numBytes); + //if(data && numBytes>0)free(data); + } + } +#endif +} + +void +MemoryArchive::MakeEmpty(){ + fData.MakeEmpty(); +} +//-- + diff --git a/sources-experimental/MemoryArchive.h b/sources-experimental/MemoryArchive.h new file mode 100644 index 0000000..fec7198 --- /dev/null +++ b/sources-experimental/MemoryArchive.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef _MemoryArchive_H_ +#define _MemoryArchive_H_ + +#include "Archive.h" +#include "Notifier.h" +#include + +class MemoryArchive : public Archive { + + public: + + virtual ~MemoryArchive(){} + + MemoryArchive &operator=(const MemoryArchive &msg); + + // from Store + void SetKey(ItemProperty key,void* data,ssize_t size); + void SetKeyString(ItemProperty key,const char* data); + void SetKeyInt32(ItemProperty key,int32 data); + + + //from Retriver + ssize_t GetData(ItemProperty key,const void** data); + int32 CountData(); + BString GetDataString(ItemProperty key); + int32 GetDataInt32(ItemProperty key); + + //utility function.. (MOVE?) + void FillListener(Notifier*); + + //from ElementListener + void KeyModified(int32 key, void* data, ssize_t numBytes); + + + void MakeEmpty(); + + private: + + BMessage fData; + +}; +#endif + +//.. diff --git a/sources-experimental/MyColumnTypes.cpp b/sources-experimental/MyColumnTypes.cpp new file mode 100644 index 0000000..43fb48b --- /dev/null +++ b/sources-experimental/MyColumnTypes.cpp @@ -0,0 +1,208 @@ +#include "MyColumnTypes.h" +#include "ColumnTypes.h" +#include +#include + +#include "Utils.h" + +#define kTEXT_MARGIN 8 + +//===================================================================== + +BPositiveIntegerColumn::BPositiveIntegerColumn(const char* title, float width, float minWidth, + float maxWidth, alignment align) + :BTitledColumn(title, width, minWidth, maxWidth, align) +{ + SetWantsEvents(true); +} + + +//-------------------------------------------------------------------- + +void BPositiveIntegerColumn::DrawField(BField *field, BRect rect, BView* parent) +{ + char formatted[256]; + float width = rect.Width() - (2 * kTEXT_MARGIN); + BString string; + + int value=(int)((BIntegerField*)field)->Value(); + + if(value<=0) return; + + sprintf(formatted, "%d", value ); + + string = formatted; + parent->TruncateString(&string, B_TRUNCATE_MIDDLE, width + 2); + DrawString(string.String(), parent, rect); +} + + +//-------------------------------------------------------------------- + +int BPositiveIntegerColumn::CompareFields(BField *field1, BField *field2) +{ + return (((BIntegerField*)field1)->Value() - ((BIntegerField*)field2)->Value()); +} + + + + + void + BPositiveSizeColumn::MouseMoved(BColumnListView *parent, BRow *row, BField *field, + BRect field_rect, BPoint point, uint32 buttons, int32 code, const BMessage *msg ){ + + + } + + + +//-------------------------------------------------------------------- + +BPositiveSizeColumn::BPositiveSizeColumn (const char* title, + float width, + float minWidth, + float maxWidth, + alignment align): + BSizeColumn(title,width,minWidth,maxWidth,align){} + +void +BPositiveSizeColumn::DrawField(BField* field, + BRect rect, + BView* parent) +{ + off_t value=(int)((BSizeField*)field)->Size(); + if(value<=0) return; + BSizeColumn::DrawField(field,rect,parent); +} + +//-------------------------------------------------------------------- + +BPositiveDateColumn::BPositiveDateColumn (const char* title, + float width, + float minWidth, + float maxWidth, + alignment align ): + BDateColumn(title,width,minWidth,maxWidth,align){} + +void +BPositiveDateColumn::DrawField(BField* field, + BRect rect, + BView* parent) +{ + time_t value=(int)((BDateField*)field)->UnixTime(); + if(value<=0) return; + BDateColumn::DrawField(field,rect,parent); +} + + +//-------------------------------------------------------------------- + +BPositiveGraphColumn ::BPositiveGraphColumn(const char* name, + float width, + float minWidth, + float maxWidth, + alignment align): + BIntegerColumn(name,width,minWidth,maxWidth,align) +{ + fBar=LoadIcon("fullbar.png"); + fBack=LoadIcon("graybar.png"); +} + +void +BPositiveGraphColumn ::DrawField(BField* field, + BRect rect, + BView* parent) +{ + int number=(int)((BIntegerField*)field)->Value(); + if(number<=0) return; + + parent->PushState(); + + if (number > 100) + number = 100; + else if (number < 0) + number = 0; + + BRect graphRect(rect); + graphRect.top += 2; + graphRect.bottom = graphRect.top + 11; + graphRect.right = graphRect.left + 99; + + parent->DrawBitmap(fBack,graphRect); //BPoint(rect.right,rect.top)); + + + if (number > 0) { + BRect sourceRect(fBar->Bounds()); + sourceRect.right = sourceRect.left + number; + + BRect destRect(graphRect); + destRect.right = destRect.left + number; + parent->DrawBitmap(fBar,sourceRect,destRect); //sourceRect,destRect); + } + + char numstr[256]; + sprintf(numstr, "%d%%", number); + + float width = be_plain_font->StringWidth(numstr); + parent->MovePenTo(rect.left + rect.Width() / 2 - width / 2, rect.bottom - FontHeight()); + parent->DrawString(numstr); + + + //BGraphColumn::DrawField(field,rect,parent); + parent->PopState(); +} + +BMyBitmapColumn::BMyBitmapColumn (const char* title, + float width, + float minWidth, + float maxWidth, + alignment align): + BTitledColumn(title, width, minWidth, maxWidth, align) + {} + +int BMyBitmapColumn::CompareFields(BField *field1, BField *field2){ + return (((BBitmapField*)field1)->Bitmap() - ((BBitmapField*)field2)->Bitmap()); +} + +void +BMyBitmapColumn::DrawField(BField* field, + BRect rect, + BView* parent){ + + + parent->PushState(); + + BBitmapField *bitmapField = static_cast(field); + const BBitmap *bitmap = bitmapField->Bitmap(); + + if (bitmap != NULL) + { + float x = 0.0; + float y; + BRect r = bitmap->Bounds(); + + y = rect.top; //rect.top + ((rect.Height() - r.Height()) / 2); + + /*switch (Alignment()) + { + case B_ALIGN_LEFT: + x = rect.left + kTEXT_MARGIN; + break; + + case B_ALIGN_CENTER: + x = rect.left + ((rect.Width() - r.Width()) / 2); + break; + + case B_ALIGN_RIGHT: + x = rect.right - kTEXT_MARGIN - r.Width(); + break; + }*/ + x = rect.left; + parent->SetDrawingMode(B_OP_ALPHA); + parent->DrawBitmap(bitmap, BPoint(x,y)); + parent->SetDrawingMode(B_OP_OVER); + } + parent->PopState(); + } + + diff --git a/sources-experimental/MyColumnTypes.h b/sources-experimental/MyColumnTypes.h new file mode 100644 index 0000000..544cd1d --- /dev/null +++ b/sources-experimental/MyColumnTypes.h @@ -0,0 +1,99 @@ +#ifndef _MyColumnType_H +#define _MyColumnType_H + +#include "ColumnListView.h" +#include "ColumnTypes.h" +#include +#include +#include + + +//-------------------------------------------------------------------- +// DrawString only if the value is positive. + +class BPositiveIntegerColumn : public BTitledColumn +{ + public: + BPositiveIntegerColumn (const char* title, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + void DrawField (BField* field, + BRect rect, + BView* parent); + int CompareFields (BField* field1, + BField* field2); + + + +}; + +class BPositiveSizeColumn : public BSizeColumn +{ + public: + BPositiveSizeColumn (const char* title, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + void DrawField (BField* field, + BRect rect, + BView* parent); + + //test code: + void MouseMoved(BColumnListView *parent, BRow *row, BField *field,BRect field_rect, BPoint point, uint32 buttons, int32 code, const BMessage *msg = NULL); + +}; + +class BPositiveDateColumn : public BDateColumn +{ + public: + BPositiveDateColumn (const char* title, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + void DrawField (BField* field, + BRect rect, + BView* parent); +}; + +class BPositiveGraphColumn : public BIntegerColumn +{ + public: + BPositiveGraphColumn(const char* name, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + void DrawField (BField* field, + BRect rect, + BView* parent); + + private: + BBitmap* fBar; + BBitmap* fBack; +}; + + +class BMyBitmapColumn : public BTitledColumn +{ + public: + BMyBitmapColumn (const char* title, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + void DrawField (BField* field, + BRect rect, + BView* parent); + + int CompareFields(BField* field1, + BField* field2); + +}; + + +#endif + diff --git a/sources-experimental/NodeWalker.cpp b/sources-experimental/NodeWalker.cpp new file mode 100644 index 0000000..ab9db90 --- /dev/null +++ b/sources-experimental/NodeWalker.cpp @@ -0,0 +1,695 @@ +/* +Open Tracker License + +Terms and Conditions + +Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice applies to all licensees +and shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Be Incorporated shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from Be Incorporated. + +Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks +of Be Incorporated in the United States and other countries. Other brand product +names are registered trademarks or trademarks of their respective holders. +All rights reserved. +*/ + +#include +#include +#include +#include +#include + +#include "NodeWalker.h" + + + +TWalker::~TWalker() +{ +} + +// all the following calls are pure viruals, should not get called +status_t +TWalker::GetNextEntry(BEntry *, bool ) +{ + TRESPASS(); + return B_ERROR; +} + +status_t +TWalker::GetNextRef(entry_ref *) +{ + TRESPASS(); + return B_ERROR; +} + +int32 +TWalker::GetNextDirents(struct dirent *, size_t, int32) +{ + TRESPASS(); + return 0; +} + + +status_t +TWalker::Rewind() +{ + TRESPASS(); + return B_ERROR; +} + +int32 +TWalker::CountEntries() +{ + TRESPASS(); + return -1; +} + + +TNodeWalker::TNodeWalker(bool includeTopDirectory) + : fDirs(20), + fTopIndex(-1), + fTopDir(0), + fIncludeTopDir(includeTopDirectory), + fOriginalIncludeTopDir(includeTopDirectory), + fJustFile(0), + fOriginalJustFile(0) +{ +} + + +TNodeWalker::TNodeWalker(const char *path, bool includeTopDirectory) + : fDirs(20), + fTopIndex(-1), + fTopDir(0), + fIncludeTopDir(includeTopDirectory), + fOriginalIncludeTopDir(includeTopDirectory), + fJustFile(0), + fOriginalDirCopy(path), + fOriginalJustFile(0) +{ + if (fOriginalDirCopy.InitCheck() != B_OK) { + // not a directory, set up walking a single file + fJustFile = new BEntry(path); + if (fJustFile->InitCheck() != B_OK) { + delete fJustFile; + fJustFile = NULL; + } + fOriginalJustFile = fJustFile; + } else { + fTopDir = new BDirectory(fOriginalDirCopy); + fTopIndex++; + fDirs.AddItem(fTopDir); + } +} + + +TNodeWalker::TNodeWalker(const entry_ref *ref, bool includeTopDirectory) + : fDirs(20), + fTopIndex(-1), + fTopDir(0), + fIncludeTopDir(includeTopDirectory), + fOriginalIncludeTopDir(includeTopDirectory), + fJustFile(0), + fOriginalDirCopy(ref), + fOriginalJustFile(0) +{ + if (fOriginalDirCopy.InitCheck() != B_OK) { + // not a directory, set up walking a single file + fJustFile = new BEntry(ref); + if (fJustFile->InitCheck() != B_OK) { + delete fJustFile; + fJustFile = NULL; + } + fOriginalJustFile = fJustFile; + } else { + fTopDir = new BDirectory(fOriginalDirCopy); + fTopIndex++; + fDirs.AddItem(fTopDir); + } +} + + +TNodeWalker::TNodeWalker(const BDirectory *dir, bool includeTopDirectory) + : fDirs(20), + fTopIndex(-1), + fTopDir(0), + fIncludeTopDir(includeTopDirectory), + fOriginalIncludeTopDir(includeTopDirectory), + fJustFile(0), + fOriginalDirCopy(*dir), + fOriginalJustFile(0) +{ + fTopDir = new BDirectory(*dir); + fTopIndex++; + fDirs.AddItem(fTopDir); +} + + +TNodeWalker::TNodeWalker() + : fDirs(20), + fTopIndex(-1), + fTopDir(0), + fIncludeTopDir(false), + fOriginalIncludeTopDir(false), + fJustFile(0), + fOriginalJustFile(0) +{ +} + +TNodeWalker::TNodeWalker(const char *path) + : fDirs(20), + fTopIndex(-1), + fTopDir(0), + fIncludeTopDir(false), + fOriginalIncludeTopDir(false), + fJustFile(0), + fOriginalDirCopy(path), + fOriginalJustFile(0) +{ + if (fOriginalDirCopy.InitCheck() != B_OK) { + // not a directory, set up walking a single file + fJustFile = new BEntry(path); + if (fJustFile->InitCheck() != B_OK) { + delete fJustFile; + fJustFile = NULL; + } + fOriginalJustFile = fJustFile; + } else { + fTopDir = new BDirectory(fOriginalDirCopy); + fTopIndex++; + fDirs.AddItem(fTopDir); + } +} + +TNodeWalker::TNodeWalker(const entry_ref *ref) + : fDirs(20), + fTopIndex(-1), + fTopDir(0), + fIncludeTopDir(false), + fOriginalIncludeTopDir(false), + fJustFile(0), + fOriginalDirCopy(ref), + fOriginalJustFile(0) +{ + if (fOriginalDirCopy.InitCheck() != B_OK) { + // not a directory, set up walking a single file + fJustFile = new BEntry(ref); + if (fJustFile->InitCheck() != B_OK) { + delete fJustFile; + fJustFile = NULL; + } + fOriginalJustFile = fJustFile; + } else { + fTopDir = new BDirectory(fOriginalDirCopy); + fTopIndex++; + fDirs.AddItem(fTopDir); + } +} + +TNodeWalker::TNodeWalker(const BDirectory *dir) + : fDirs(20), + fTopIndex(-1), + fTopDir(0), + fIncludeTopDir(false), + fOriginalIncludeTopDir(false), + fJustFile(0), + fOriginalDirCopy(*dir), + fOriginalJustFile(0) +{ + fTopDir = new BDirectory(*dir); + fTopIndex++; + fDirs.AddItem(fTopDir); +} + +TNodeWalker::~TNodeWalker() +{ + delete fOriginalJustFile; + + for (;;) { + BDirectory *directory = fDirs.RemoveItemAt(fTopIndex--); + if (directory == NULL) + break; + delete directory; + } +} + +status_t +TNodeWalker::PopDirCommon() +{ + ASSERT(fTopIndex >= 0); + + // done with the old dir, pop it + fDirs.RemoveItemAt(fTopIndex); + fTopIndex--; + delete fTopDir; + fTopDir = NULL; + + if (fTopIndex == -1) + // done + return B_ENTRY_NOT_FOUND; + + // point to the new top dir + fTopDir = fDirs.ItemAt(fTopIndex); + + return B_OK; +} + +void +TNodeWalker::PushDirCommon(const entry_ref *ref) +{ + fTopDir = new BDirectory(ref); + // OK to ignore error here. Will + // catch at next call to GetNextEntry + fTopIndex++; + fDirs.AddItem(fTopDir); +} + +status_t +TNodeWalker::GetNextEntry(BEntry *entry, bool traverse) +{ + if (fJustFile) { + *entry = *fJustFile; + fJustFile = 0; + return B_OK; + } + + if (!fTopDir) + // done + return B_ENTRY_NOT_FOUND; + + // If requested to include the top directory, return that first. + if (fIncludeTopDir) { + fIncludeTopDir = false; + return fTopDir->GetEntry(entry); + } + + // Get the next entry. + status_t err = fTopDir->GetNextEntry(entry, traverse); + + if (err != B_OK) { + err = PopDirCommon(); + if (err != B_OK) + return err; + return GetNextEntry(entry, traverse); + } + // See if this entry is a directory. If it is then push it onto the + // stack + entry_ref ref; + err = entry->GetRef(&ref); + + if (err == B_OK && fTopDir->Contains(ref.name, B_DIRECTORY_NODE)) + PushDirCommon(&ref); + + return err; +} + +status_t +TNodeWalker::GetNextRef(entry_ref *ref) +{ + if (fJustFile) { + fJustFile->GetRef(ref); + fJustFile = 0; + return B_OK; + } + + if (!fTopDir) + // done + return B_ENTRY_NOT_FOUND; + + // If requested to include the top directory, return that first. + if (fIncludeTopDir) { + fIncludeTopDir = false; + BEntry entry; + status_t err = fTopDir->GetEntry(&entry); + if (err == B_OK) + err = entry.GetRef(ref); + return err; + } + + // Get the next entry. + status_t err = fTopDir->GetNextRef(ref); + if (err != B_OK) { + err = PopDirCommon(); + if (err != B_OK) + return err; + return GetNextRef(ref); + } + // See if this entry is a directory. If it is then push it onto the + // stack + + if (fTopDir->Contains(ref->name, B_DIRECTORY_NODE)) + PushDirCommon(ref); + + return B_OK; +} + +static int32 +build_dirent(const BEntry *source, struct dirent *ent, + size_t size, int32 count) +{ + entry_ref ref; + source->GetRef(&ref); + + size_t recordLength = strlen(ref.name) + sizeof(dirent); + if (recordLength > size || count <= 0) + // can't fit in buffer, bail + return 0; + + // info about this node + ent->d_reclen = static_cast(recordLength); + strcpy(ent->d_name, ref.name); + ent->d_dev = ref.device; + ent->d_ino = ref.directory; + + // info about the parent + BEntry parent; + source->GetParent(&parent); + if (parent.InitCheck() == B_OK) { + entry_ref parentRef; + parent.GetRef(&parentRef); + ent->d_pdev = parentRef.device; + ent->d_pino = parentRef.directory; + } else { + ent->d_pdev = 0; + ent->d_pino = 0; + } + + return 1; +} + +int32 +TNodeWalker::GetNextDirents(struct dirent *ent, size_t size, int32 count) +{ + if (fJustFile) { + if (!count) + return 0; + + // simulate GetNextDirents by building a single dirent structure + int32 result = build_dirent(fJustFile, ent, size, count); + fJustFile = 0; + return result; + } + + if (!fTopDir) + // done + return 0; + + // If requested to include the top directory, return that first. + if (fIncludeTopDir) { + fIncludeTopDir = false; + BEntry entry; + if (fTopDir->GetEntry(&entry) < B_OK) + return 0; + + return build_dirent(fJustFile, ent, size, count); + } + + // Get the next entry. + int32 result = fTopDir->GetNextDirents(ent, size, count); + + if (!result) { + status_t err = PopDirCommon(); + if (err != B_OK) + return 0; + + return GetNextDirents(ent, size, count); + } + + // push any directories in the returned entries onto the stack + for (int32 i = 0; i < result; i++) { + if (fTopDir->Contains(ent->d_name, B_DIRECTORY_NODE)) { + entry_ref ref(ent->d_dev, ent->d_ino, ent->d_name); + PushDirCommon(&ref); + } + ent = (dirent *)((char *)ent + ent->d_reclen); + } + + return result; +} + +status_t +TNodeWalker::Rewind() +{ + if (fOriginalJustFile) { + // single file mode, rewind by pointing to the original file + fJustFile = fOriginalJustFile; + return B_OK; + } + + // pop all the directories and point to the initial one + for (;;) { + BDirectory *directory = fDirs.RemoveItemAt(fTopIndex--); + if (!directory) + break; + delete directory; + } + + fTopDir = new BDirectory(fOriginalDirCopy); + fTopIndex = 0; + fIncludeTopDir = fOriginalIncludeTopDir; + fDirs.AddItem(fTopDir); + // rewind the directory + return fTopDir->Rewind(); +} + +int32 +TNodeWalker::CountEntries() +{ + // should not be calling this + TRESPASS(); + return -1; +} + +TVolWalker::TVolWalker(bool knowsAttributes, bool writable, bool includeTopDirectory) + : TNodeWalker(includeTopDirectory), + fKnowsAttr(knowsAttributes), + fWritable(writable) +{ + + /* + Get things initialized. Find first volume, or find the first volume + that supports attributes. + */ + NextVolume(); +} + +TVolWalker::~TVolWalker() +{ +} + +status_t +TVolWalker::NextVolume() +{ + status_t err; + + // The stack of directoies should be empty. + ASSERT(fTopIndex == -1); + ASSERT(fTopDir == NULL); + + do { + err = fVolRoster.GetNextVolume(&fVol); + if (err != B_OK) + break; + } while ((fKnowsAttr && !fVol.KnowsAttr()) || (fWritable && fVol.IsReadOnly())); + + if (err == B_OK) { + // Get the root directory to get things started. There's always + // a root directory for a volume. So if there is an error then it + // means that something is really bad, like the system is out of + // memory. In that case don't worry about truying to skip to the + // next volume. + fTopDir = new BDirectory(); + err = fVol.GetRootDirectory(fTopDir); + fIncludeTopDir = fOriginalIncludeTopDir; + fTopIndex = 0; + fDirs.AddItem(fTopDir); + } + + return err; +} + +status_t +TVolWalker::GetNextEntry(BEntry *entry, bool traverse) +{ + if (!fTopDir) + return B_ENTRY_NOT_FOUND; + + // Get the next entry. + status_t err = _inherited::GetNextEntry(entry, traverse); + + while (err != B_OK) { + // We're done with the current volume. Go to the next one + err = NextVolume(); + if (err != B_OK) + break; + err = GetNextEntry(entry, traverse); + } + + return err; +} + +status_t +TVolWalker::GetNextRef(entry_ref *ref) +{ + if (!fTopDir) + return B_ENTRY_NOT_FOUND; + + // Get the next ref. + status_t err = _inherited::GetNextRef(ref); + + while (err != B_OK) { + // We're done with the current volume. Go to the next one + err = NextVolume(); + if (err != B_OK) + break; + err = GetNextRef(ref); + } + + return err; +} + +int32 +TVolWalker::GetNextDirents(struct dirent *ent, size_t size, int32 count) +{ + if (!fTopDir) + return B_ENTRY_NOT_FOUND; + + // Get the next dirent. + status_t err = _inherited::GetNextDirents(ent, size, count); + + while (err != B_OK) { + // We're done with the current volume. Go to the next one + err = NextVolume(); + if (err != B_OK) + break; + err = GetNextDirents(ent, size, count); + } + + return err; +} + +status_t +TVolWalker::Rewind() +{ + fVolRoster.Rewind(); + return NextVolume(); +} + +TQueryWalker::TQueryWalker(const char *predicate) + : TWalker(), fQuery(), fVolRoster(), fVol() +{ + fPredicate = strdup(predicate); + NextVolume(); +} + +TQueryWalker::~TQueryWalker() +{ + free((char*) fPredicate); + fPredicate = NULL; +} + +status_t +TQueryWalker::GetNextEntry(BEntry *entry, bool traverse) +{ + status_t err; + + do { + err = fQuery.GetNextEntry(entry, traverse); + if (err == B_ENTRY_NOT_FOUND) { + if (NextVolume() != B_OK) + break; + } + } while (err == B_ENTRY_NOT_FOUND); + + return err; +} + +status_t +TQueryWalker::GetNextRef(entry_ref *ref) +{ + status_t err; + + for (;;) { + err = fQuery.GetNextRef(ref); + if (err != B_ENTRY_NOT_FOUND) + break; + + err = NextVolume(); + if (err != B_OK) + break; + } + + return err; +} + +int32 +TQueryWalker::GetNextDirents(struct dirent *ent, size_t size, int32 count) +{ + int32 result; + + for (;;) { + result = fQuery.GetNextDirents(ent, size, count); + if (result != 0) + return result; + + if (NextVolume() != B_OK) + return 0; + } + + return result; +} + +status_t +TQueryWalker::NextVolume() +{ + status_t err; + do { + err = fVolRoster.GetNextVolume(&fVol); + if (err) + break; + } while (!fVol.KnowsQuery()); + + + if (err == B_OK) { + err = fQuery.Clear(); + err = fQuery.SetVolume(&fVol); + err = fQuery.SetPredicate(fPredicate); + err = fQuery.Fetch(); + } + + return err; +} + +int32 +TQueryWalker::CountEntries() +{ + // should not be calling this + TRESPASS(); + return -1; +} + +status_t +TQueryWalker::Rewind() +{ + fVolRoster.Rewind(); + return NextVolume(); +} diff --git a/sources-experimental/NodeWalker.h b/sources-experimental/NodeWalker.h new file mode 100644 index 0000000..71aeb9b --- /dev/null +++ b/sources-experimental/NodeWalker.h @@ -0,0 +1,143 @@ +#ifndef WALKER_H +#define WALKER_H + +#ifndef _BE_BUILD_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "ObjectList.h" + + + +class TWalker : public BEntryList { + // adds a virtual destructor that is severely missing in BEntryList + // BEntryList should never be used polymorphically because of that + +public: + virtual ~TWalker(); + + virtual status_t GetNextEntry(BEntry *, bool traverse = false) = 0; + virtual status_t GetNextRef(entry_ref *) = 0; + virtual int32 GetNextDirents(struct dirent *, size_t, + int32 count = INT_MAX) = 0; + virtual status_t Rewind() = 0; + virtual int32 CountEntries() = 0; +}; + +class TNodeWalker : public TWalker { +// TNodeWalker supports iterating a single volume, starting from a specified +// entry; if passed a non-directory entry it returns just that one entry +public: + TNodeWalker(bool includeTopDirectory); + TNodeWalker(const char *path, bool includeTopDirectory); + TNodeWalker(const entry_ref *ref, bool includeTopDirectory); + TNodeWalker(const BDirectory *dir, bool includeTopDirectory); + virtual ~TNodeWalker(); + + // Backwards compatibility with Tracker compiled for R5 (remove when this + // gets integrated into the official release). + TNodeWalker(); + TNodeWalker(const char *path); + TNodeWalker(const entry_ref *ref); + TNodeWalker(const BDirectory *dir); + + virtual status_t GetNextEntry(BEntry *, bool traverse = false); + virtual status_t GetNextRef(entry_ref *); + virtual int32 GetNextDirents(struct dirent *, size_t, + int32 count = INT_MAX); + virtual status_t Rewind(); + +protected: + status_t PopDirCommon(); + void PushDirCommon(const entry_ref *); + +private: + virtual int32 CountEntries(); + // don't know how to do that, have just a fake stub here + +protected: + BObjectList fDirs; + int32 fTopIndex; + BDirectory *fTopDir; + bool fIncludeTopDir; + bool fOriginalIncludeTopDir; + +private: + BEntry *fJustFile; + BDirectory fOriginalDirCopy; + BEntry *fOriginalJustFile; + // keep around to support Rewind +}; + +class TVolWalker : public TNodeWalker { +// TNodeWalker supports iterating over all the mounted volumes; +// non-attribute and read-only volumes may optionaly be filtered out +public: + TVolWalker(bool knows_attr = true, bool writable = true, + bool includeTopDirectory = true); + virtual ~TVolWalker(); + + virtual status_t GetNextEntry(BEntry *, bool traverse = false); + virtual status_t GetNextRef(entry_ref *); + virtual int32 GetNextDirents(struct dirent *, size_t, + int32 count = INT_MAX); + virtual status_t Rewind(); + + virtual status_t NextVolume(); + // skips to the next volume + // Note: it would be cool to return const BVolume * + // that way a subclass could implement a volume filter - + // it would just override, call inherited for as long as there + // are volumes and it does not like them + // we would have to give up the status_t then, which might be + // ok + +private: + BVolumeRoster fVolRoster; + BVolume fVol; + bool fKnowsAttr; + bool fWritable; + + typedef TNodeWalker _inherited; +}; + +class TQueryWalker : public TWalker { +public: + TQueryWalker(const char *predicate); + virtual ~TQueryWalker(); + + // Does an in-fix walk of all entries + virtual status_t GetNextEntry(BEntry *, bool traverse = false); + virtual status_t GetNextRef(entry_ref *); + virtual int32 GetNextDirents(struct dirent *, size_t, + int32 count = INT_MAX); + + virtual status_t NextVolume(); + // skips to the next volume + virtual status_t Rewind(); + +private: + virtual int32 CountEntries(); + // can't count + + BQuery fQuery; + BVolumeRoster fVolRoster; + BVolume fVol; + bigtime_t fTime; + const char *fPredicate; + + typedef TQueryWalker _inherited; +}; + + + +#endif // WALKER_H + + diff --git a/sources-experimental/Notifier.cpp b/sources-experimental/Notifier.cpp new file mode 100644 index 0000000..df39664 --- /dev/null +++ b/sources-experimental/Notifier.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#include "Notifier.h" +#include + + +Notifier::Notifier() {} +Notifier::~Notifier(){} + + +void +Notifier::SetKey(ItemProperty key,void* data,ssize_t numBytes) { + NotifyListener(key,data,numBytes); +} + +void +Notifier::SetKeyString(ItemProperty key,const char* data){ + + size_t len = strlen(data); + char copy[ len + 1]; + strncpy(copy,data,len); + copy[len] = '\0'; + SetKey(key,(void*)copy, len+1); + //SetKey(key,(void*)data,strlen(data)); + +} + +void +Notifier::SetKeyInt32(ItemProperty key,int32 data){ + SetKey(key,(void*)&data,sizeof(int32)); +} + +void +Notifier::AddElementListener(ElementListener* list){ + fListeners.AddItem((void*)list); +} + +void +Notifier::RemoveElementListener(ElementListener* list){ + fListeners.RemoveItem((void*)list); +} + + +void +Notifier::NotifyListener(ItemProperty key,void* data,ssize_t size) +{ + ElementListener* fListener=NULL; + for(int l=0; lKeyModified(key,data,size); + } +} + +//-- diff --git a/sources-experimental/Notifier.h b/sources-experimental/Notifier.h new file mode 100644 index 0000000..1874e11 --- /dev/null +++ b/sources-experimental/Notifier.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef Notifier_H_ +#define Notifier_H_ + +#include + +#include "ElementListener.h" +#include "ItemProperty.h" + +class Notifier +{ + +public: + Notifier(); + virtual ~Notifier(); + + + void AddElementListener(ElementListener*); + void RemoveElementListener(ElementListener*); + + + + virtual void SetKey(ItemProperty key,void* data,ssize_t size); + void SetKeyString(ItemProperty key,const char* data); + void SetKeyInt32(ItemProperty key,int32 data); + + void NotifyListener(ItemProperty key,void* data,ssize_t size); + + private: + BList fListeners; + +}; +#endif + +//-- diff --git a/sources-experimental/OPMLParser.cpp b/sources-experimental/OPMLParser.cpp new file mode 100644 index 0000000..53169fe --- /dev/null +++ b/sources-experimental/OPMLParser.cpp @@ -0,0 +1,240 @@ +#include "OPMLParser.h" +#include "curl/curl.h" + +#include "Logger.h" + + +OPMLTree* +OPMLParser::Parse(BString filename){ + + + OPMLTree* list=NULL; + + xmlParserCtxtPtr ctxt = xmlNewParserCtxt(); + xmlDocPtr doc = xmlCtxtReadFile(ctxt, filename.String(), NULL, XML_PARSE_RECOVER); + xmlXPathContextPtr pathCtxt = xmlXPathNewContext(doc); + + //testing code! + xmlXPathObjectPtr itemNode = xmlXPathEvalExpression((const xmlChar *)"/opml/head/title", pathCtxt); + if (itemNode == NULL) { + xmlFreeParserCtxt(ctxt); + xmlXPathFreeContext(pathCtxt); + xmlXPathFreeObject(itemNode); + return NULL; + }; + //only one channel per rss file! + if(itemNode->nodesetval == NULL || itemNode->nodesetval->nodeNr !=1){ + xmlFreeParserCtxt(ctxt); + xmlXPathFreeContext(pathCtxt); + xmlXPathFreeObject(itemNode); + //LOG("OPMLParser", liDebug ,"No title in opml file.."); + return NULL; + }; + + //LOG("OPMLParser", liDebug ,"OPML title: %s",XML_GET_CONTENT(itemNode->nodesetval->nodeTab[0]->children)); + BString opml_name((const char*)XML_GET_CONTENT(itemNode->nodesetval->nodeTab[0]->children)); + + + + if (pathCtxt != NULL) { + xmlXPathObjectPtr itemNode = xmlXPathEvalExpression((const xmlChar *)"/opml/body/outline", pathCtxt); + if (itemNode == NULL) { + xmlFreeParserCtxt(ctxt); + xmlXPathFreeContext(pathCtxt); + xmlXPathFreeObject(itemNode); + return NULL; + }; + + + + xmlNodeSetPtr items = itemNode->nodesetval; + + if (items == NULL || items->nodeNr < 1 ) { + xmlFreeParserCtxt(ctxt); + xmlXPathFreeContext(pathCtxt); + xmlXPathFreeObject(itemNode); + return NULL; + }; + + + //the root + list = new OPMLTree; + list->description = opml_name; + list->foglie = new OPMLList(items->nodeNr); + + for (int32 i = 0; i < items->nodeNr; i++) { + ParseOutline(list, items->nodeTab[i]); + } + + xmlXPathFreeObject(itemNode); + }; + + xmlFreeParserCtxt(ctxt); + xmlXPathFreeContext(pathCtxt); + + return list; +} + +int +OPMLParser::ParseOutlineFolder(OPMLTree* root,xmlNodePtr node) +{ + return 0; +} + +int +OPMLParser::ParseOutline(OPMLTree* aroot,xmlNodePtr node){ + + xmlNode *cur_node = NULL; + cur_node = node; + { + + if (cur_node->type == XML_ELEMENT_NODE) + { + BString bname((const char*)cur_node->name); + + if(bname.ICompare("outline") == 0){ + + OPMLTree* subtree = new OPMLTree; + aroot->foglie->AddItem(subtree); + + subtree->foglie = NULL; + + //guardiamo le properties: + xmlAttr *attr = cur_node->properties; + xmlAttr *cur_attr = NULL; + + for (cur_attr = attr; cur_attr; cur_attr = cur_attr->next) { + BString battr((const char*)cur_attr->name); + if(battr.ICompare("text") == 0) { + xmlNodePtr node = cur_attr->children; + BString imageURL ; + imageURL << (const char*)node->content; + subtree->description.SetTo(imageURL); + } + else + if(battr.ICompare("xmlUrl") == 0 || battr.ICompare("url") == 0) { + xmlNodePtr node = cur_attr->children; + BString imageURL ; + imageURL << (const char*)node->content; + subtree->link.SetTo(imageURL); + } + + } //for attributes + + + +// printf("--> Name %s\n", subtree->description.String()); + if (cur_node->children) + { + subtree->foglie = new OPMLList(10); + // printf("--> childs!\n"); + + xmlNode *cur_child = NULL; + for (cur_child = cur_node->children; cur_child; cur_child = cur_child->next) + { + ParseOutline(subtree, cur_child); + } +// printf("--> End Name %s -- %ld\n", subtree->description.String(), subtree->foglie->CountItems()); + // + } + } + } + } + return 0; +} +/* +int +OPMLParser::ParseOutline(OPMLTree* aroot,xmlNodePtr node){ + + xmlNode *cur_node = NULL; + + for (cur_node = node; cur_node; cur_node = cur_node->next) { + + if (cur_node->type == XML_ELEMENT_NODE) + { + printf("-->DEBUG %s\n", (const char*)cur_node->name); + BString bname((const char*)cur_node->name); + + if(bname.ICompare("outline") == 0){ + if(aroot->foglie == NULL) aroot->foglie = new OPMLList(10); + + //LOG("OPMLParser", liDebug ,"New CHILD for [%s]",aroot->description.String()); + + OPMLTree* tree = new OPMLTree; + tree->foglie = NULL; + aroot->foglie->AddItem(tree); + + //guardiamo le properties: + xmlAttr *attr = cur_node->properties; + xmlAttr *cur_attr = NULL; + + for (cur_attr = attr; cur_attr; cur_attr = cur_attr->next) { + BString battr((const char*)cur_attr->name); + if(battr.ICompare("text") == 0) { + xmlNodePtr node = cur_attr->children; + BString imageURL ; + imageURL << (const char*)node->content; + tree->description.SetTo(imageURL); + + //LOG("OPMLParser", liDebug ,"\ttext: %s",tree->description.String()); + } + else + if(battr.ICompare("xmlUrl") == 0 || battr.ICompare("url") == 0) { + xmlNodePtr node = cur_attr->children; + BString imageURL ; + imageURL << (const char*)node->content; + tree->link.SetTo(imageURL); + + //LOG("OPMLParser", liDebug ,"\tlink: %s",tree->link.String()); + } + + } //for attributes + + // ok se non ho 'link' proseguo ricorsivamente altrimenti se ho un link + // significa che sono ad una foglia.. + //if(tree->link != "") return 0; + + + if (cur_node->children) + ParseOutline(tree, cur_node->children); + + + } + + } + } + return 0; +} +*/ +void +OPMLParser::PrintToStream(OPMLTree* tree,int tab) +{ + for(int i=0;idescription.String()); + + if(tree->foglie) + { + for(int i=0;ifoglie->CountItems();i++) + PrintToStream(tree->foglie->ItemAt(i),tab+1); + } +} + +void +OPMLParser::DeleteOPMLTree(OPMLTree* tree){ + + if(tree->foglie) + { + for(int i=0;ifoglie->CountItems();i++) + DeleteOPMLTree(tree->foglie->ItemAt(i)); + + tree->foglie->MakeEmpty(); + delete tree->foglie; + + } + + delete tree; + +} + diff --git a/sources-experimental/OPMLParser.h b/sources-experimental/OPMLParser.h new file mode 100644 index 0000000..890e07b --- /dev/null +++ b/sources-experimental/OPMLParser.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef OPMLParser_H_ +#define OPMLParser_H_ + +#include +#include + +#include "libxml/tree.h" +#include "libxml/xpath.h" +#include "libxml/xpathInternals.h" +#include "libxml/parserInternals.h" +#include "libxml/debugXML.h" + +struct OPMLTree; + +typedef BObjectList OPMLList; + +struct OPMLTree { + BString description; + BString link; + OPMLList *foglie; +}; + + + +class OPMLParser +{ + + public: + OPMLTree* Parse(BString filename); + + void DeleteOPMLTree(OPMLTree*); //recursive delete + + void PrintToStream(OPMLTree*,int tab); + private: + int ParseOutline(OPMLTree* root,xmlNodePtr node); + int ParseOutlineFolder(OPMLTree* root,xmlNodePtr node); + +}; +#endif diff --git a/sources-experimental/PercentageView.cpp b/sources-experimental/PercentageView.cpp new file mode 100644 index 0000000..67a3819 --- /dev/null +++ b/sources-experimental/PercentageView.cpp @@ -0,0 +1,75 @@ + #include "PercentageView.h" + #include + #include "Utils.h" + + BBitmap* empty = NULL ; + BBitmap* bar1 = NULL ; + BBitmap* bar2 = NULL ; + + +PercentageView::PercentageView(BRect rect):BView(rect,"percentageView",B_FOLLOW_NONE,B_WILL_DRAW){ + + if(!empty) + empty = LoadIcon("graybar.png"); + if(!bar1) + bar1 = LoadIcon("fullbar1.png"); + if(!bar2) + bar2 = LoadIcon("fullbar2.png"); + + bar = bar1; + + fPercentage = 0; +} + +void +PercentageView::AttachedToWindow(){ + if(Parent()) + SetViewColor(Parent()->ViewColor()); +} + +void +PercentageView::SetPercentage(int32 percentage){ + + if(percentage<0) percentage=0; + if(percentage>100) percentage=100; + + fPercentage=percentage; + + if(bar == bar1) + bar = bar2; + else + bar = bar1; + + Invalidate(); +} + +void +PercentageView::ResizeToPreferred(){ + + ResizeTo(99,11); + +} + +void +PercentageView::Draw(BRect) +{ + + SetDrawingMode( B_OP_ALPHA ); + + BRect graphRect(Bounds()); + graphRect.right = graphRect.left+99; + //graphRect.top +=2; + graphRect.bottom = graphRect.top + 11; + + if(empty) DrawBitmap(empty,graphRect); //BPoint(rect.right,rect.top)); + + if(fPercentage >0) { + + BRect sourceRect(bar->Bounds()); + sourceRect.right = sourceRect.left + fPercentage; + + BRect destRect(graphRect); + destRect.right = destRect.left + fPercentage; + if(bar) DrawBitmap(bar,sourceRect,destRect); //sourceRect,destRect); + } +} diff --git a/sources-experimental/PercentageView.h b/sources-experimental/PercentageView.h new file mode 100644 index 0000000..62d212e --- /dev/null +++ b/sources-experimental/PercentageView.h @@ -0,0 +1,29 @@ +#ifndef PercentageView_H_ +#define PercentageView_H_ + +#include + +class BBitmap; + +class PercentageView : public BView { + + public: + PercentageView(BRect); + + void SetPercentage(int32); + + int32 GetPercentage(); + + void Draw(BRect rect); + + void AttachedToWindow(); + void ResizeToPreferred(); + + private: + int32 fPercentage; + BBitmap* bar ; + +}; + +#endif +//-- diff --git a/sources-experimental/PercentageWindow.cpp b/sources-experimental/PercentageWindow.cpp new file mode 100644 index 0000000..abef0a9 --- /dev/null +++ b/sources-experimental/PercentageWindow.cpp @@ -0,0 +1,96 @@ +#include "PercentageWindow.h" + +#include "StripeView.h" +#include "BPAlert.h" +#include "PercentageView.h" + +#include +#include + +#define DEFAULT_RECT BRect(0, 0, 310, 75) + +static const int kTextIconOffsetSpace = 30; + +PercentageWindow::PercentageWindow(const char* title,const char* text,BBitmap* icon) : BWindow(DEFAULT_RECT, title, B_MODAL_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE){ + + // Set up the "_master_" view + + StripeView* masterView = new StripeView(Bounds()); + AddChild(masterView); + masterView->SetBitmap(icon); + + kTextIconOffset = 0; + + if(masterView->Bitmap()) + kTextIconOffset = masterView->Bitmap()->Bounds().right + kTextIconOffsetSpace; + + + //ok, un String + //il percentage (a 0) con testo percentuale + float maxW; + + BStringView* string=new BStringView(BRect(kTextIconOffset,6,0,0),"_text",text); + masterView->AddChild(string); + string->ResizeToPreferred(); + maxW=string->Frame().right + 6; + + BRect rect(string->Frame()); + + rect.top=string->Frame().bottom+6; + + pw=new PercentageView(rect); + masterView->AddChild(pw); + pw->ResizeToPreferred(); + + rect=pw->Frame(); + rect.left=rect.right+6; + + + perc=new BStringView(rect,"_percentage","100%"); + masterView->AddChild(perc); + perc->ResizeToPreferred(); + if(perc->Frame().right + 6 > maxW) + maxW=perc->Frame().right + 6; + + perc->SetText("0%"); + + maxW +=kTextIconOffsetSpace; + + //if(maxW>Bounds().right) + ResizeTo(maxW,Bounds().bottom); + + SetLook(B_FLOATING_WINDOW_LOOK); + + MoveTo(BPAlert::AlertPosition(Frame().Width(), Frame().Height())); +} + +void +PercentageWindow::SetPercentage(int p){ + + + BString text; + text << p << "%"; + + if(Lock()){ + perc->SetText(text.String()); + pw->SetPercentage(p); + Unlock(); + } + +} + +bool +PercentageWindow::QuitRequested(){ + if(fLooper) + BMessenger(fLooper).SendMessage(fMsg); + + return true; +} + + +void +PercentageWindow::Go(BLooper* lop,int32 msg){ + fLooper = lop; + fMsg=msg; + Show(); +} diff --git a/sources-experimental/PercentageWindow.h b/sources-experimental/PercentageWindow.h new file mode 100644 index 0000000..91400f6 --- /dev/null +++ b/sources-experimental/PercentageWindow.h @@ -0,0 +1,29 @@ +#ifndef _PercentageWindow_H_ +#define _PercentageWindow_H_ + +#include +#include +#include +#include + +class BStringView; + class PercentageView; + +class PercentageWindow : public BWindow { + + public: + PercentageWindow(const char* title,const char* text,BBitmap* icon=NULL); + void Go(BLooper* lop=NULL,int32 msg=0); + void SetPercentage(int perc); + bool QuitRequested(); + + private: + BLooper* fLooper; + int32 fMsg; + int kTextIconOffset; + BStringView* perc; + PercentageView* pw; + +}; + +#endif diff --git a/sources-experimental/QueueActions.cpp b/sources-experimental/QueueActions.cpp new file mode 100644 index 0000000..2a524ad --- /dev/null +++ b/sources-experimental/QueueActions.cpp @@ -0,0 +1,153 @@ +#include "QueueActions.h" + +#include + +#include + +#define CHKLOCK if(!IsLocked()) debugger("\nQueueActions must me locked!\n"); + +QueueActions::QueueActions(const char* name){ + BString n(name); + n << "'s enemy"; + + + fID = spawn_thread(QueueActions::ManageTheQueue,n.String(),B_NORMAL_PRIORITY,this); + printf("Thread ready [%s] %ld\n",n.String(),fID); + + fLock = create_sem(1,name); + fLocked = false; + fCurrentAction = NULL; +} + +QueueActions::~QueueActions(){ + if(Lock()){ + suspend_thread(fID); + exit_thread(fID); + delete_sem(fLock); + } +} + + +bool +QueueActions::Lock(){ + status_t value = acquire_sem(fLock) ; + if(value==B_NO_ERROR){ + fLocked = true; + } + return (value == B_NO_ERROR); +} + +void +QueueActions::Unlock(){ + fLocked = false; + release_sem(fLock); +} + +void +QueueActions::AddAction(Action* a){ + + //FIX! + //esiste già un azione con lo stesso ID??? + + if(Lock()){ + printf("adding %ld - Action name %s\n",fID,a->GetDescription().String()); + fList.AddItem(a); + if(fList.CountItems() == 1) //Auto-start thread + resume_thread(fID); + + Unlock(); + } +} + +Action* +QueueActions::CurrentAction(){ + CHKLOCK; + return fCurrentAction; +} + +void +QueueActions::SetCurrentAction(Action* action){ + CHKLOCK; + fCurrentAction = action; +} + +int32 +QueueActions::CountActions(){ + CHKLOCK; + return fList.CountItems(); +} + +Action* +QueueActions::ActionAt(int32 pos){ + CHKLOCK; + fList.ItemAt(pos); +} + +void +QueueActions::RemoveActionAt(int32 pos){ + CHKLOCK; + fList.RemoveItemAt(pos); +} + +bool +QueueActions::IsLocked(){ + return fLocked; +} + + +int32 +QueueActions::ManageTheQueue(void* data) { + + QueueActions *qa=(QueueActions*)data; + + printf("Thread started %ld\n",qa->fID); + + while(true){ + + Action *last=NULL; + + if(qa->Lock()) { + + printf("Thread executing PID %ld Count %ld\n",qa->fID,qa->fList.CountItems()); + if(qa->fList.CountItems()>0){ + // remove and delete the action. + last=qa->fList.ItemAt(0); + qa->fList.RemoveItemAt(0); + qa->SetCurrentAction(last); + + } else { + + last=NULL; + qa->SetCurrentAction(last); + } + + qa->Unlock(); + } + + if(last) + { + // pop the action + qa->ActionReadyToPerform(last); + // perform the action + BMessage err; + status_t status = last->Perform(&err); + // do post-perform! + + qa->ActionPerformed(last,status,&err); + + if(qa->Lock()){ + qa->SetCurrentAction(NULL); + delete last; + qa->Unlock(); + } + + } + else { + + printf("Thread suspend PID %ld Count %ld\n",qa->fID,qa->fList.CountItems()); + suspend_thread(qa->fID); + } + + } //while + +} diff --git a/sources-experimental/QueueActions.h b/sources-experimental/QueueActions.h new file mode 100644 index 0000000..2472ec9 --- /dev/null +++ b/sources-experimental/QueueActions.h @@ -0,0 +1,54 @@ +#ifndef QueueActions_H_ +#define QueueActions_H_ + +#include + +#define QA_ADD_ACTION 'qaaa' + +#include "Action.h" +#include + +#include + +class QueueActions { + +public: + + QueueActions(const char* name); + virtual ~QueueActions(); + + void AddAction(Action* ); + + //BEFORE CALLING CurrentAction, you MUST Lock() the Queue! + Action* CurrentAction(); + int32 CountActions(); + Action* ActionAt(int32 pos); + void RemoveActionAt(int32 pos); + + + bool Lock(); + void Unlock(); + bool IsLocked(); + + protected: + + static int32 ManageTheQueue(void*); + + virtual void ActionReadyToPerform(Action*) = 0; + virtual void ActionPerformed(Action*,status_t,BMessage*) = 0; + + + + private: + + + + void SetCurrentAction(Action*); + + thread_id fID; + sem_id fLock; + BObjectList fList; + Action* fCurrentAction; + bool fLocked; +}; +#endif diff --git a/sources-experimental/QueueFileDownload.cpp b/sources-experimental/QueueFileDownload.cpp new file mode 100644 index 0000000..a504db1 --- /dev/null +++ b/sources-experimental/QueueFileDownload.cpp @@ -0,0 +1,40 @@ +#include "QueueFileDownload.h" +#include "ActionDownload.h" +#include "Messenger.h" + +void +QueueFileDownload::ActionReadyToPerform(Action* action) +{ + ActionAsync* ad=dynamic_cast(action); + if(!ad) return; + + ad->SetTargetAndWhat(fLooper,fMsg); + +} + +void +QueueFileDownload::ActionPerformed(Action* action,status_t state,BMessage* msg) +{ + + //ActionAsync* ad=dynamic_cast(action); + //if(!ad) return; + + BMessage notify(*msg); + notify.what = fMsg; + + if(fLooper) + BMessenger(fLooper).SendMessage(¬ify); + + return; +} + +void +QueueFileDownload::SuppressAction(Action* action) { + ActionDownload* ad=dynamic_cast(action); + if(!ad) return; + + ad->SetShouldStop(true); +} + +//-- + diff --git a/sources-experimental/QueueFileDownload.h b/sources-experimental/QueueFileDownload.h new file mode 100644 index 0000000..84be4f2 --- /dev/null +++ b/sources-experimental/QueueFileDownload.h @@ -0,0 +1,27 @@ +#ifndef QueueFileDownload_H_ +#define QueueFileDownload_H_ + +#include "QueueMultiActions.h" +#include + + +class QueueFileDownload : public QueueMultiActions { + +public: + + QueueFileDownload(const char* name,int howMany,BLooper* target,uint32 msg):QueueMultiActions(name,howMany){ + fMsg=msg; + fLooper=target; + }; + + + protected: + void ActionPerformed(Action*,status_t,BMessage*); + void ActionReadyToPerform(Action*); + void SuppressAction(Action*); + + private: + BLooper* fLooper; + uint32 fMsg; +}; +#endif diff --git a/sources-experimental/QueueMultiActions.cpp b/sources-experimental/QueueMultiActions.cpp new file mode 100644 index 0000000..208934a --- /dev/null +++ b/sources-experimental/QueueMultiActions.cpp @@ -0,0 +1,238 @@ +#include "QueueMultiActions.h" + +#include +#include + + +#define CHKLOCK if(!IsLocked()) debugger("\nQueueMultiActions must me locked!\n"); + +QueueMultiActions::QueueMultiActions(const char* name,int count){ + + fCount = count; + if(count > MAX_MULTI) + debugger("wrong number of multi download settings"); + + for(int j=0;jqa=this; + tok->index=i; + fID[i] = spawn_thread(QueueMultiActions::ManageTheQueue,n.String(),B_NORMAL_PRIORITY,tok); + printf("Thread ready [%s] %ld\n",n.String(),fID[i]); + + } + + + + fLock = create_sem(1,name); + fLocked = false; + +} + +QueueMultiActions::~QueueMultiActions(){ + if(Lock()){ + + for(int i=0;iMAX_MULTI) { + Unlock(); + return; + } + + if(fProposedCount > fCount){ + + for(int i=fCount;iqa=this; + tok->index=i; + fID[i] = spawn_thread(QueueMultiActions::ManageTheQueue,n.String(),B_NORMAL_PRIORITY,tok); + printf("Thread ready [%s] %ld\n",n.String(),fID[i]); + } + } + } + else + { + //uhm what to do? + for(int i=fProposedCount;iGetDescription().String()); + fList.AddItem(a); + if(fList.CountItems() <= fCount) //Auto-start thread + { + for(int i=0;iqa; + int index = tok->index; + + //printf("Thread started %ld\n",qa->fID[index]); + + while(true){ + + Action *last=NULL; + + if(qa->Lock()) { + + // printf("Thread executing PID %ld Count %ld\n",qa->fID[index],qa->fList.CountItems()); + if(qa->fList.CountItems()>0){ + // remove and delete the action. + last=qa->fList.ItemAt(0); + qa->fList.RemoveItemAt(0); + qa->SetCurrentAction(last,index); + + } else { + + last=NULL; + qa->SetCurrentAction(last,index); + } + + qa->Unlock(); + } + + if(last) + { + // pop the action + qa->ActionReadyToPerform(last); + // perform the action + BMessage err; + status_t status = last->Perform(&err); + // do post-perform! + + qa->ActionPerformed(last,status,&err); + + if(qa->Lock()){ + qa->SetCurrentAction(NULL,index); + delete last; + qa->Unlock(); + } + + } else { + + //printf("Thread suspend PID %ld Count %ld\n",qa->fID[index],qa->fList.CountItems()); + suspend_thread(qa->fID[index]); + } + + //Check my life? + if(qa->Lock()){ + if( index >= qa->fCount){ + qa->KIllThread(index); + qa->Unlock(); + // printf("Thread died PID %ld\n",qa->fID[index]); + return 0; //bye-bye world! + } + qa->Unlock(); + } + + } //while + +} diff --git a/sources-experimental/QueueMultiActions.h b/sources-experimental/QueueMultiActions.h new file mode 100644 index 0000000..399b95a --- /dev/null +++ b/sources-experimental/QueueMultiActions.h @@ -0,0 +1,67 @@ +#ifndef QueueMultiActions_H_ +#define QueueMultiActions_H_ + +#include +#include +#include + + +#include "Action.h" + +#define MAX_MULTI 5 + +class QueueMultiActions { + +public: + + QueueMultiActions(const char* name, int count); + virtual ~QueueMultiActions(); + + void AddAction(Action* ); + + //BEFORE CALLING CurrentAction, you MUST Lock() the Queue! + Action* CurrentAction(int index); + + int32 CountActions(); + int CountThreads() { return fCount; } + + Action* ActionAt(int32 pos); + void RemoveActionAt(int32 pos); + + + void SetDownloadCount(int count); + + + bool Lock(); + void Unlock(); + bool IsLocked(); + + protected: + + static int32 ManageTheQueue(void*); + + virtual void ActionReadyToPerform(Action*) = 0; + virtual void ActionPerformed(Action*,status_t,BMessage*) = 0; + virtual void SuppressAction(Action*) = 0; + + + private: + struct token + { + int index; + QueueMultiActions* qa; + }; + + + void SetCurrentAction(Action*,int index); + void KIllThread(int id); + + Action* fCurrentAction[MAX_MULTI]; + thread_id fID[MAX_MULTI]; + sem_id fLock; + BObjectList fList; + bool fLocked; + int fCount; + BString fName; +}; +#endif diff --git a/sources-experimental/R5Locale.cpp b/sources-experimental/R5Locale.cpp new file mode 100644 index 0000000..67a6f77 --- /dev/null +++ b/sources-experimental/R5Locale.cpp @@ -0,0 +1,26 @@ +#include "R5Locale.h" +#include "BePodder_R5.h" +#include "Message.h" + +#define ADD(KEY,VALUE) language->AddString(KEY,VALUE); + +BMessage *language=NULL; + +void +init(){ + language=new BMessage(); + for(int i=0;iFindString(key,&data)==B_OK){ + return data; + } + + return key; +} \ No newline at end of file diff --git a/sources-experimental/RVActionBP.h b/sources-experimental/RVActionBP.h new file mode 100644 index 0000000..f82b6fe --- /dev/null +++ b/sources-experimental/RVActionBP.h @@ -0,0 +1,29 @@ +#ifndef _RVActionBP_h_ +#define _RVActionBP_h_ + +#include "RVAction.h" +#include "IActionManagerBP.h" + +extern IActionManagerBP action_manager; + +#include + +class RVActionBP : public RVAction +{ + public: + + virtual ~RVActionBP(){}; + + virtual status_t Perform(BString param){ + int pos = atoi(param.String()); + if(pos>0) + action_manager.FireAction(pos); + return B_OK; + } + virtual BString GetDescription(){ + return "RVActionBP"; + } + +}; + +#endif diff --git a/sources-experimental/RVActionBPOpenURL.h b/sources-experimental/RVActionBPOpenURL.h new file mode 100644 index 0000000..9a9b7d2 --- /dev/null +++ b/sources-experimental/RVActionBPOpenURL.h @@ -0,0 +1,28 @@ +#ifndef _RVActionBPOpenURL_h_ +#define _RVActionBPOpenURL_h_ + +#include "RVAction.h" +#include "MainController.h" +#include + +class RVActionBPOpenURL : public RVAction +{ + public: + + RVActionBPOpenURL(MainController* controller){ fController=controller;}; + virtual ~RVActionBPOpenURL(){ }; + + virtual status_t Perform(BString param){ + fController->OpenURL(param); + return B_OK; + } + virtual BString GetDescription(){ + return "RVActionBPOpenURL"; + } + + private: + MainController* fController; + +}; + +#endif diff --git a/sources-experimental/Retriver.h b/sources-experimental/Retriver.h new file mode 100644 index 0000000..1476963 --- /dev/null +++ b/sources-experimental/Retriver.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef _Retriver_H_ +#define _Retriver_H_ + +#include "ItemProperty.h" +#include + +class Retriver { + + public: + + virtual ssize_t GetData(ItemProperty key,const void** data) = 0; + virtual int32 CountData()= 0; + virtual BString GetDataString(ItemProperty key)= 0; + virtual int32 GetDataInt32(ItemProperty key)= 0; + +}; + +#endif + +//.. diff --git a/sources-experimental/RssChannel.cpp b/sources-experimental/RssChannel.cpp new file mode 100644 index 0000000..b0d3fa7 --- /dev/null +++ b/sources-experimental/RssChannel.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#include "RssChannel.h" +RssChannel::RssChannel(){ + SetKeyInt32(CHANNEL_NEWITEMS,0); +} + +//-- diff --git a/sources-experimental/RssChannel.h b/sources-experimental/RssChannel.h new file mode 100644 index 0000000..3de0b15 --- /dev/null +++ b/sources-experimental/RssChannel.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef _RssChannel_H_ +#define _RssChannel_H_ + +#include "Notifier.h" +#include "FileStatus.h" + +class RssChannel : public Notifier { + + public: + RssChannel(); + void SetTitle(const char* data) { SetKeyString(CHANNEL_TITLE,data); }; + void SetURL(const char* data) { SetKeyString(CHANNEL_URL ,data); }; + void SetFileStatus(FileStatus fs){ SetKeyInt32(CHANNEL_RSS_FILE_STATUS,(int32)fs); } + +}; +#endif diff --git a/sources-experimental/RssItem.cpp b/sources-experimental/RssItem.cpp new file mode 100644 index 0000000..37afec6 --- /dev/null +++ b/sources-experimental/RssItem.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#include "RssItem.h" +#include + +#include "FileStatus.h" +#include +//#include "curl/curl.h" + +//#include "MemoryArchive.h" + +RssItem::RssItem(){ + SetKeyInt32(ITEM_ENCLOSURE_FILE_STATUS,0); +} +void +RssItem::SetKey(ItemProperty key,void* data,ssize_t size){ + + switch(key){ + case ITEM_ENCLOSURE_FILE_STATUS: + fStatus = *((FileStatus*)data); + break; + case ITEM_GUID: + fGuid.SetTo((const char*)data,size); + break; + case ITEM_ENCLOSURE_URL: + fEnclosureLink.SetTo((const char*)data,size); + break; + case ITEM_ENCLOSURE_LOCALPATH: + fEnclosurePath.SetTo((const char*)data,size); + break; + case ITEM_ENCLOSURE_TYPE: + fType.SetTo((const char*)data, size); + break; + default:break; + } + Notifier::SetKey(key,data,size); +} +//.-. diff --git a/sources-experimental/RssItem.h b/sources-experimental/RssItem.h new file mode 100644 index 0000000..cebabd8 --- /dev/null +++ b/sources-experimental/RssItem.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef _RssItem_H_ +#define _RssItem_H_ + +#include "Notifier.h" +#include "FileStatus.h" + + +class RssItem : public Notifier { + public: + RssItem(); + + //from Notifier + void SetKey(ItemProperty key,void* data,ssize_t size); + + //mine: + void SetTitle(const char* data) { SetKeyString(ITEM_TITLE,data); }; + void SetAuthor(const char* data) { SetKeyString(ITEM_AUTHOR,data); }; + + void SetGuid(const char* data) { SetKeyString(ITEM_GUID,data); fGuid.SetTo(data); } + void SetFileStatus(FileStatus fs){ SetKeyInt32(ITEM_ENCLOSURE_FILE_STATUS,(int32)fs); fStatus = fs; } + void SetFilePercentage(int32 per){ SetKeyInt32(ITEM_ENCLOSURE_FILE_PERCENTAGE,(int32)per); } + void SetDownloadSpeed(float speed){ SetKey(ITEM_ENCLOSURE_DOWNLOAD_SPEED,(void*)&speed,sizeof(float)); } + + //which are the essential? + //the idea: crate a 'minimal' Store! and use GetData..(); + + BString Guid() { return fGuid; } + BString EnclosureLink() { return fEnclosureLink; } + BString EnclosureLocalPath() { return fEnclosurePath; } + BString FileType() { return fType; } + + FileStatus GetFileStatus(){ return fStatus; }; + + private: + BString fGuid; + BString fEnclosureLink; + BString fEnclosurePath; + BString fType; + FileStatus fStatus; +}; +#endif diff --git a/sources-experimental/SectionSelector.cpp b/sources-experimental/SectionSelector.cpp new file mode 100644 index 0000000..7bf86fc --- /dev/null +++ b/sources-experimental/SectionSelector.cpp @@ -0,0 +1,243 @@ +#include "SectionSelector.h" +#include "Utils.h" + +#define CURVE 2 + +#define NUM_PART 4 +#define PART_SIZE 100. + +#define BORDER 0 +#define TABSIZE 20 +#define W 41 +#define TAB_SPACE 3 +#define TOP_START 0 +#define BOTTOM_SPACE 3 + +#define kTEXT_MARGIN 8 + +const rgb_color back = ui_color(B_PANEL_BACKGROUND_COLOR); //{ 255,255,255,255}; +const rgb_color line = { 255, 255, 255, 255}; +const rgb_color sel = { 242,227, 0,255}; + +class SmartSelector : public BView { + + public: + SmartSelector(BRect rect,BBitmap* icon,SectionSelector* boss,int id):BView(rect,"",B_FOLLOW_NONE,B_WILL_DRAW){ + fPressed = false; + fIcon=icon; + fBoss = boss; + fId = id; + SetViewColor(B_TRANSPARENT_COLOR); + } + + void Draw(BRect r){ + + if(fPressed) + SetHighColor(sel); + else + SetHighColor(line); + + BRect rect(Bounds()); + //rect.InsetBy(1,1); + FillRect(rect); + + if(fIcon){ + SetDrawingMode(B_OP_ALPHA); + DrawBitmap(fIcon); + } + } + + void SetPressed(bool value){ + fPressed = value; + Invalidate(); + } + + void MouseUp(BPoint p){ + + if(!fPressed){ + fBoss->Select(fId); + fBoss->Invoke(); + } + + } + + private: + bool fPressed; + BBitmap* fIcon; + SectionSelector* fBoss; + int fId; + +}; + + + +SectionSelector::SectionSelector(BRect r,BMessage* msg):BControl(r,"","",msg,B_FOLLOW_ALL_SIDES,B_WILL_DRAW){ + + fSelected = -1; + width = r.right; + //sel = tint_color(back,B_DARKEN_4_TINT); + //SetViewColor(B_TRANSPARENT_COLOR); + count=0; +} + + +void +SectionSelector::AddSection(const char* iconName,BView* view,const char* tooltip){ + if(count < MAX_ITEM){ + Section *sec=new Section; + + sec->view = view; + + float prevPos = count * (W+TAB_SPACE); + + float width = W; + + BRect rect = BRect(prevPos, + TOP_START, + prevPos + W - 1, + TOP_START + TABSIZE - 1); + + + sec->tab = new SmartSelector(rect,LoadIcon(iconName),this,count); + #ifdef ZETA + sec->tab->SetToolTipText(tooltip); + #endif + + AddChild(sec->tab); + + + fStack[count++]=sec; + + BRect b(Bounds()); + + view->MoveTo(BORDER,TABSIZE + BORDER + BOTTOM_SPACE); + + AddChild(view); + view->ResizeTo(b.right - 2*BORDER,b.bottom- 2*BORDER - TABSIZE - BOTTOM_SPACE); + + view->Hide(); + } +} + + +void +SectionSelector::Draw(BRect r){ + + //if( ! r.Intersects( BRect(0,0,Bounds().right,TABSIZE) ) return; + + //BControl::Draw(r); + //for(int i=0;i= MAX_ITEM) return; + + BRect r(fStack[i]->rect); + //SetHighColor(back); + //FillRect(r); + + + if(i==fSelected){ + SetHighColor(sel); + } + else + { + SetHighColor(line); + } + + BRect newR(0,0,W - 2 ,TABSIZE - 2); + newR.OffsetTo(r.left + GAP_TAB + TAB_SPACE + 1,r.top + TOP_START + 1); + FillRect(newR); + + + + + //SetHighColor(line); + //DrawString(fStack[i]->name.String(),this,r); + if(fStack[i]->icon){ + SetDrawingMode(B_OP_ALPHA); + DrawBitmap(fStack[i]->icon,BPoint(r.left + GAP_TAB + TAB_SPACE ,r.top + TOP_START)); + } +} + +*/ + +void +SectionSelector::Select(int index){ + + if(index == fSelected) return; + + int oldsel=fSelected; + + fSelected =index; + + if(oldsel>=0) { + fStack[oldsel]->view->Hide(); + ((SmartSelector*)fStack[oldsel]->tab)->SetPressed(false); + } + + fStack[index]->view->Show(); + ((SmartSelector*)fStack[index]->tab)->SetPressed(true); + + +} +/*void +SectionSelector::MouseUp(BPoint p){ + + + for(int i=0;irect.Contains(p)) + { + if(i != fSelected){ + Select(i); + Invoke(); + } + return; + } + + } +} + +*/ + + +void +SectionSelector::DrawString(const char* string, BView* parent, BRect rect) +{ + float width = rect.Width() - (2 * kTEXT_MARGIN); + float y; + BFont font; + font_height finfo; + + GetFont(&font); + font.GetHeight(&finfo); + + y = rect.top + ((rect.Height() - (finfo.ascent + finfo.descent + finfo.leading)) / 2) + + (finfo.ascent + finfo.descent) - 2; + +/* switch (Alignment()) + { + case B_ALIGN_LEFT: + parent->MovePenTo(rect.left + kTEXT_MARGIN, y); + break; + + case B_ALIGN_CENTER:*/ + parent->MovePenTo(rect.left + kTEXT_MARGIN + ((width - font.StringWidth(string)) / 2), y); + /* break; + + case B_ALIGN_RIGHT: + parent->MovePenTo(rect.right - kTEXT_MARGIN - font.StringWidth(string), y); + break; + }*/ + parent->DrawString(string); +} + +//.. diff --git a/sources-experimental/SectionSelector.h b/sources-experimental/SectionSelector.h new file mode 100644 index 0000000..d1e0c97 --- /dev/null +++ b/sources-experimental/SectionSelector.h @@ -0,0 +1,47 @@ +#include + +#define MAX_ITEM 5 + +class SectionSelector : public BControl +{ + public: + SectionSelector(BRect,BMessage* msg); + + void Draw(BRect); + // void MouseUp(BPoint); + + void AddSection(const char* iconName,BView* tabView,const char* tooltip); + + void Select(int index); + + + int Selected(){ return fSelected; }; + + protected: + + const char* NameOf(int index); + + private: + + struct Section { + + //BRect rect; + //BBitmap* icon; + BView* view; + BView* tab; + }; + + void DrawString(const char* string, BView* parent, BRect rect); + void DrawPart(int index); + + // BRect RectFor(int i); + + int fSelected; + float width; + int count; + + Section* fStack[MAX_ITEM]; + +}; + +//-- diff --git a/sources-experimental/SettingsWindow.cpp b/sources-experimental/SettingsWindow.cpp new file mode 100644 index 0000000..164ed97 --- /dev/null +++ b/sources-experimental/SettingsWindow.cpp @@ -0,0 +1,176 @@ +#include "SettingsWindow.h" +#include "SettingsTextView.h" + +#include +#include +#include "BPLocale.h" +#include +#include +#include +#include +#include "PBox.h" +#include + + + +SettingsWindow::SettingsWindow(BMessage* setting,BHandler* handler,int32 applyMsg) : + BWindow(BRect(250,100,750,350),_T("Preferences"), B_FLOATING_WINDOW_LOOK,B_MODAL_APP_WINDOW_FEEL,B_NOT_RESIZABLE| B_NOT_ZOOMABLE|B_ASYNCHRONOUS_CONTROLS) +{ + fApplyWhatMsg = applyMsg; + fSetting = setting; + fHandler = handler; + fSelected = NULL; + + rgb_color bgcolor = ui_color(B_PANEL_BACKGROUND_COLOR); + + BBox *bgbox=new BBox(Bounds(),"back",B_FOLLOW_ALL,B_WILL_DRAW,B_PLAIN_BORDER); + AddChild(bgbox); + + BRect rect, arect, brect ; + + rect = Bounds(); + rect.InsetBy(5, 5); + rect.bottom -= 50; + + bgView=new BView(BRect(rect),NULL, B_FOLLOW_ALL, B_WILL_DRAW); + bgView->SetViewColor(bgcolor); //255,0,0); + bgbox->AddChild(bgView); + + arect = rect; + arect.right = arect.left + 100; + arect.bottom = rect.bottom - 10; + slist=new BListView(arect,"preferences_list",B_SINGLE_SELECTION_LIST,B_FOLLOW_ALL,B_WILL_DRAW); + + slist->SetSelectionMessage(new BMessage('list')); + BScrollView *scroll=new BScrollView("scrolling", slist, B_FOLLOW_ALL, 0, false, false); + bgView->AddChild(scroll); + slist->Select(0); + slist->MakeFocus(true); + + brect=Bounds(); + brect.InsetBy(5, 5); + brect.top = rect.bottom + 10; + + BView *bottomView=new BView(brect,NULL, B_FOLLOW_BOTTOM, B_WILL_DRAW); + bottomView->SetViewColor(bgcolor); + bgbox->AddChild(bottomView); + + // eliminare bottone close ---------------- + + BFont font(be_plain_font); + arect = bottomView->Bounds(); + arect.InsetBy(10, 10); + arect.top = arect.bottom - 20; + arect.left = arect.right - font.StringWidth(_T("Cancel")) - 30; + BButton *apply = new BButton(arect, "", _T("Save"), new BMessage('apla')); + bottomView->AddChild(apply); + + + + arect.right = arect.left - 20; + arect.top = arect.bottom - 20; + arect.left = arect.right - font.StringWidth(_T("Save")) - 30; + + BButton *close = new BButton(arect, "", _T("Cancel"), new BMessage(B_QUIT_REQUESTED)); + bottomView->AddChild(close); + + + dxrect = bgView->Bounds(); + + trect = dxrect; + trect.InsetBy(0,5); + trect.left += 5; + trect.right -= 123; + trect.top += 1; + trect.bottom -= 135; + + dxrect.top += 2; + dxrect.bottom -= 2; + dxrect.left += 115; + dxrect.right -= 2; + + + + + MoveTo(BAlert::AlertPosition(Bounds().Width(),Bounds().Height())); +} + + + + + +void +SettingsWindow::Select(int i){ + + if(fSelected) + fSelected->Hide(); + + + BBox* newb=fBoxList.ItemAt(i); + + if(newb){ + newb->Show(); + fSelected=newb; + } + else + fSelected = NULL; + + if(slist->CurrentSelection()!=i) + slist->Select(i); +} + +void +SettingsWindow::AddBox(const char* name, BBox* box){ + box->ResizeTo(dxrect.Width(),dxrect.Height()); + box->MoveTo(dxrect.left,dxrect.top); + slist->AddItem(new BStringItem(name)); + bgView->AddChild(box); + box->Hide(); + fBoxList.AddItem(box); +} + + +bool +SettingsWindow::QuitRequested(){ + return true; +} + + +void +SettingsWindow::SaveSettings(){ + for(int i=0;i(fBoxList.ItemAt(i)); + + if(pb) + { + BMessage data; + pb->GetData(&data); + //data.PrintToStream(); + GetSetting()->RemoveData(pb->GetSettingsName()); + GetSetting()->AddMessage(pb->GetSettingsName(),&data); + } + } +} + +void +SettingsWindow::MessageReceived(BMessage *mess){ + switch(mess->what) { + + case 'list': + Select(mess->FindInt32("index")); + break; + + case 'apla': + SaveSettings(); + if(fHandler) + BMessenger(fHandler).SendMessage(fApplyWhatMsg); + Quit(); + break; + default: + BWindow::MessageReceived(mess); + break; + } +} + + + diff --git a/sources-experimental/SettingsWindow.h b/sources-experimental/SettingsWindow.h new file mode 100644 index 0000000..a7357f5 --- /dev/null +++ b/sources-experimental/SettingsWindow.h @@ -0,0 +1,53 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define APPLY_SETTINGS 'apse' + + +class SettingsWindow: public BWindow +{ + + + + + public: + SettingsWindow(BMessage*,BHandler*,int32); + + virtual void MessageReceived(BMessage*); + virtual bool QuitRequested(); + + BMessage* GetSetting(){ return fSetting; } + + protected: + + + void Select(int i); + void AddBox(const char*,BBox*); + + private: + + void SaveSettings(); + + BListView *slist; + BView *bgView; + BView *dxview; + + BObjectList fBoxList; + BBox* fSelected; + BRect dxrect,trect; + + BMessage* fSetting; + BHandler* fHandler; + int32 fApplyWhatMsg; + }; diff --git a/sources-experimental/SplitPane.cpp b/sources-experimental/SplitPane.cpp new file mode 100644 index 0000000..a7bb37d --- /dev/null +++ b/sources-experimental/SplitPane.cpp @@ -0,0 +1,747 @@ +/******************************************************* +* SplitPane© +* +* SplitPane is a usefull UI component. It alows the +* use to ajust two view Horizontaly or Vertacly so +* that they are a desired size. This type of Pane +* shows up most comonly in Mail/News Readers. +* +* @author YNOP (ynop@acm.org) +* @version beta +* @date Dec. 10 1999 +* +* (note: modified by jaf@lcsaudio.com 6/20/00) +* +*******************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SplitPane.h" +#include "Cursors.h" +#include + +BCursor* h_arrow=NULL; +BCursor* v_arrow=NULL; + +#include "ImageButton.h" + +#define MIRROR 'mirr' +#define ROTATE 'rott' + +#include "Utils.h" + +//const pattern test = {(255,0,0,255,0,0,255,0)}; +/******************************************************* +* Setup the main view. Add in all the niffty components +* we have made and get things rolling +*******************************************************/ +SplitPane::SplitPane(BRect frame, BView *one, BView *two,uint32 Mode):BView(frame, "", Mode,B_WILL_DRAW|B_FRAME_EVENTS){ + BRect b = Bounds(); + + PaneOne = one; + PaneTwo = two; + + prevSize.Set(0.0f,0.0f); // used for resizing when resizeOne(X|Y) is true --jaf + resizeOneX = resizeOneY = false; + align = B_VERTICAL; // Most people use it this way + pos.Set(b.Width()/2.0f, b.Height()/2.0f); // Center is a good start place + thickness.Set(10.0f,10.0f); + jump.Set(1.0f,1.0f); // 1 makes a smother slide + VOneDetachable = false; + VTwoDetachable = false; + pad.Set(3.0f,3.0f); + MinSizeOne.Set(0,0); + MinSizeTwo.Set(0,0); + poslocked = false; // free movement + alignlocked = false; // free alignment + Draggin = false; + attached = false; + swapPanes = false; + + WinOne = NULL; + WinTwo = NULL; + + + AddChild(one); + AddChild(two); + + rotateH = LoadIcon("rotateH"); + mirrorH = LoadIcon("mirrorH"); + rotateV = LoadIcon("rotateV"); + mirrorV = LoadIcon("mirrorV"); + + AddChild(rotate = new ImageButton(BRect(0,0,8,8), "",new BMessage(ROTATE), NULL, NULL,NULL)); + AddChild(mirror = new ImageButton(BRect(5,5,14,14), "",new BMessage(MIRROR), NULL, NULL,NULL)); + + rotate->DrawbackgroundColor(false); + mirror->DrawbackgroundColor(false); + + if(!h_arrow) + h_arrow = new BCursor(c_h_resize_cursor); + if(!v_arrow) + v_arrow = new BCursor(c_v_resize_cursor); +} + +/******************************************************* +* When ready grap the parents color and refreash. +*******************************************************/ +void SplitPane::AttachedToWindow(){ + BView::AttachedToWindow(); + rotate->SetTarget(this); + mirror->SetTarget(this); + attached = true; + Update(); +} + +/******************************************************* +* If we are being resized. Fix the stuff we need to fix +*******************************************************/ +void SplitPane::FrameResized(float w, float h){ +// if bar is on the left side follow left +// else if it is on the right side follow the right +// Need to implements smart follow still + BView::FrameResized(w,h); + Update(); + Invalidate(); +} + +/******************************************************* +* The main draw stuff here. basicly just the slider +*******************************************************/ +void SplitPane::Draw(BRect /*f*/){ + + SetHighColor(160,160,160); + + if(align == B_VERTICAL){ + SetHighColor(255,255,255); + FillRect(BRect(pos.x+thickness.x/2,Bounds().top+pad.x+1,pos.x+thickness.x/2,Bounds().bottom-pad.x-1)) ;// 145 + + SetHighColor(145,145,145); + FillRect(BRect(pos.x+thickness.x/2-1,Bounds().top+pad.x+1,pos.x+thickness.x/2-1,Bounds().bottom-pad.x-1)); // 96 + }else{ + SetHighColor(255,255,255);// SetHighColor(145,145,145); + FillRect(BRect(Bounds().left+pad.y+1,pos.y+thickness.y/2,Bounds().right-pad.y-1,pos.y+thickness.y/2)) ;// 145 + + SetHighColor(145,145,145); //SetHighColor(96,96,96); + FillRect(BRect(Bounds().left+pad.y+1,pos.y+thickness.y/2-1,Bounds().right-pad.y-1,pos.y+thickness.y/2-1)); // 96 + } +} + +/******************************************************* +* Keeps Modes for both panles uptodate and acctually +* is the func that sets the location of the slider +*******************************************************/ +void SplitPane::Update(){ + Window()->Lock(); + + BView * p1 = swapPanes ? PaneTwo : PaneOne; + BView * p2 = swapPanes ? PaneOne : PaneTwo; + + const BPoint & ms1 = swapPanes ? MinSizeTwo : MinSizeOne; + const BPoint & ms2 = swapPanes ? MinSizeOne : MinSizeTwo; + + if(align == B_VERTICAL){ + if ((resizeOneX)&&(prevSize.x > 0)) pos.x += Bounds().Width()-prevSize.x; + p1->SetResizingMode((resizeOneX ? B_FOLLOW_LEFT_RIGHT : B_FOLLOW_LEFT)|B_FOLLOW_TOP_BOTTOM); + p2->SetResizingMode((resizeOneX ? B_FOLLOW_RIGHT : B_FOLLOW_LEFT_RIGHT)|B_FOLLOW_TOP_BOTTOM); + if(pos.x > (Bounds().Width()-thickness.x-ms2.x)){ + if(!poslocked){ + pos.x = Bounds().Width()-thickness.x-ms2.x; + } + } + if(pos.x < ms1.x){ + if(!poslocked){ + pos.x = ms1.x; + } + } + }else{ + if ((resizeOneY)&&(prevSize.y > 0)) pos.y += Bounds().Height()-prevSize.y; + p1->SetResizingMode((resizeOneY ? B_FOLLOW_TOP_BOTTOM : B_FOLLOW_TOP) | B_FOLLOW_LEFT_RIGHT); + p2->SetResizingMode((resizeOneY ? B_FOLLOW_BOTTOM : B_FOLLOW_TOP_BOTTOM) | B_FOLLOW_LEFT_RIGHT); + if(pos.y > (Bounds().Height()-thickness.y-ms2.y)){ + if(!poslocked){ + pos.y = Bounds().Height()-thickness.y-ms2.y; + } + } + if(pos.y < ms1.y){ + if(!poslocked){ + pos.y = ms1.y; + } + } + } + + // store our new size so we can do a diff next time we're called + prevSize = BPoint(Bounds().Width(), Bounds().Height()); + + if(p1){ + if(!WinOne){ + if(align == B_VERTICAL){ + p1->MoveTo(pad.x,Bounds().top+pad.x); + p1->ResizeTo(pos.x-pad.x, Bounds().Height()-pad.x-pad.x); // widht x height + }else{ + p1->MoveTo(pad.y,Bounds().top+pad.y); + p1->ResizeTo(Bounds().Width()-pad.y-pad.y, pos.y-pad.y-pad.y); // widht x height + } + } + } + if(p2){ + if(!WinTwo){ + if(align == B_VERTICAL){ + p2->MoveTo(pos.x+thickness.x,Bounds().top+pad.x); + p2->ResizeTo(Bounds().Width()-(pos.x+thickness.x)-pad.x, Bounds().Height()-pad.x-pad.x); + }else{ + p2->MoveTo(Bounds().left+pad.y,pos.y+thickness.y); + p2->ResizeTo(Bounds().Width()-pad.y-pad.y, Bounds().Height()-pos.y-pad.y-thickness.y); + } + } + } + + //vertical-case! + if(align == B_VERTICAL){ + rotate->MoveTo(pos.x + 1 , Bounds().top + pad.x + 1); + mirror->MoveTo(pos.x + 1 , Bounds().top + pad.x + 16); + rotate->SetBitmap(rotateV); + mirror->SetBitmap(mirrorV); + }else{ + rotate->MoveTo(Bounds().right-pad.y - 10, pos.y + 1); + mirror->MoveTo(Bounds().right-pad.y - 25, pos.y + 1); + rotate->SetBitmap(rotateH); + mirror->SetBitmap(mirrorH); + } + + Window()->Unlock(); +} + +/******************************************************* +* Hook for when we click. This takes care of all the +* little stuff - Like where is the mouse and what is +* going on. +*******************************************************/ +void SplitPane::MouseDown(BPoint where){ + Window()->Lock(); + BMessage *currentMsg = Window()->CurrentMessage(); + if (currentMsg->what == B_MOUSE_DOWN) { + uint32 buttons = 0; + currentMsg->FindInt32("buttons", (int32 *)&buttons); + uint32 modifiers = 0; + currentMsg->FindInt32("modifiers", (int32 *)&modifiers); + uint32 clicks = 0; + currentMsg->FindInt32("clicks",(int32*)&clicks); + + if (buttons & B_TERTIARY_MOUSE_BUTTON) { + swapPanes = !swapPanes; + Update(); + Invalidate(); + } + else if (buttons & B_SECONDARY_MOUSE_BUTTON){ + if(!alignlocked){ + switch(align){ + case B_VERTICAL: + align = B_HORIZONTAL; + break; + case B_HORIZONTAL: + align = B_VERTICAL; + break; + } + Update(); + Invalidate(); + } + } + else if ((buttons & B_PRIMARY_MOUSE_BUTTON) && (!Draggin) && (IsInDraggerBounds(where))) { + if(!poslocked){ + Draggin= true; // this is so we can drag + here = where; + } + SetMouseEventMask(B_POINTER_EVENTS,B_LOCK_WINDOW_FOCUS); + } + } + Window()->Unlock(); +} + +bool SplitPane::IsInDraggerBounds(BPoint pt) const +{ + BView * p1 = swapPanes ? PaneTwo : PaneOne; + BView * p2 = swapPanes ? PaneOne : PaneTwo; + + // this block should go in FrameResized .. think about it + return (align == B_VERTICAL) + ? ((pt.x > p1->Frame().right)&&(pt.x < p2->Frame().left)) + : ((pt.y > p1->Frame().bottom)&&(pt.y < p2->Frame().top)); +} + +/******************************************************* +* If we unclick then stop dragging or whatever it is +* we are doing +*******************************************************/ +void SplitPane::MouseUp(BPoint /*where*/){ + Draggin = false; // stop following mouse +} + +/******************************************************* +* If the mouse moves while we dragg. Then follow it +* Also Invalidate so we update the views +*******************************************************/ +void SplitPane::MouseMoved(BPoint where,uint32 transition,const BMessage */*m*/){ + const BPoint & ms1 = swapPanes ? MinSizeTwo : MinSizeOne; + const BPoint & ms2 = swapPanes ? MinSizeOne : MinSizeTwo; + + + + if(Draggin){ + + float minVal; + switch(align){ + case B_HORIZONTAL: + SetViewCursor (h_arrow); + pos.y = (where.y)-(thickness.y/2); + minVal = ms1.y; + break; + case B_VERTICAL: + SetViewCursor (v_arrow); + pos.x = (where.x)-(thickness.x/2); + minVal = ms1.x; + break; + } + + /* + // This code figures out which jump we are closest + // to and if needed we "snap" to that. + int c = Bounds().IntegerWidth() / pos; + Jump * c ... hmmm this is not right at all + */ + + switch(align){ + case B_HORIZONTAL: + if (pos.y < ms1.y) pos.y = ms1.y; + break; + case B_VERTICAL: + if (pos.x < ms1.x) pos.x = ms1.x; + break; + } + + if(align == B_VERTICAL){ + if(pos.x > (Bounds().Width() - thickness.x - ms2.x)){ + pos.x = (Bounds().Width() - thickness.x - ms2.x + 1); + } + }else{ + if(pos.y > (Bounds().Height() - thickness.y - ms2.y)){ + pos.y = (Bounds().Height() - thickness.y - ms2.y + 1); + } + } + + Update(); + + Invalidate(); + } + else{ + switch ( transition ) + { + case B_ENTERED_VIEW: + case B_INSIDE_VIEW: + switch(align){ + case B_HORIZONTAL: + SetViewCursor (h_arrow); + break; + case B_VERTICAL: + SetViewCursor (v_arrow); + break; + } + + break; + case B_EXITED_VIEW: + SetViewCursor (B_CURSOR_SYSTEM_DEFAULT); + break; + } + +} +} + +/******************************************************* +* If you already have a view One, but want to change +* if for some odd reason. This should work. +*******************************************************/ +void SplitPane::AddChildOne(BView *v){ + RemoveChild(PaneOne); + PaneOne = v; + AddChild(PaneOne); +} + +/******************************************************* +* If you already have a view Two, and want to put +* another view there, this is what to use. +*******************************************************/ +void SplitPane::AddChildTwo(BView *v){ + RemoveChild(PaneTwo); + PaneTwo = v; + AddChild(PaneTwo); +} + +/******************************************************* +* Sets is we are horizontal or Vertical. We use the +* standard B_HORIZONTAL and B_VERTICAL flags for this +*******************************************************/ +void SplitPane::SetAlignment(uint a){ + align = a; + if(attached){ + Update(); + } + Invalidate(); +} + +/******************************************************* +* Returns wheather the slider is horizontal or vertical +*******************************************************/ +uint SplitPane::GetAlignment() const { + return align; +} + +/******************************************************* +* Sets whether to swap the positions of our panes. +*******************************************************/ +void SplitPane::SetSwapped(bool sp){ + swapPanes = sp; + if(attached){ + Update(); + } + Invalidate(); +} + +/******************************************************* +* Returns wheather the child panes are swapped. +*******************************************************/ +bool SplitPane::GetSwapped() const { + return swapPanes; +} + +/******************************************************* +* Sets the location of the bar. (we do no bounds +* checking for you so if its off the window thats +* your problem) +*******************************************************/ +void SplitPane::SetBarPosition(BPoint p){ + pos = p; + if(attached){ + Update(); + } + Invalidate(); +} + +/******************************************************* +* Returns about where the bar is ... +*******************************************************/ +BPoint SplitPane::GetBarPosition() const { + return pos; +} + +/******************************************************* +* Sets how thick the bar should be. +*******************************************************/ +void SplitPane::SetBarThickness(BPoint t){ + thickness = t; + if(attached){ + Update(); + } + Invalidate(); +} + +/******************************************************* +* Retuns to us the thickness of the slider bar +*******************************************************/ +BPoint SplitPane::GetBarThickness() const { + return thickness; +} + +/******************************************************* +* Sets the amount of jump the bar has when it is +* moved. This can also be though of as snap. The bar +* will start at 0 and jump(snap) to everry J pixels. +*******************************************************/ +void SplitPane::SetJump(BPoint j){ + jump = j; + if(attached){ + Update(); + } +} + +/******************************************************* +* Lets you know what the jump is .. see SetJump +*******************************************************/ +BPoint SplitPane::GetJump() const { + return jump; +} + +/******************************************************* +* Do we have a View One or is it NULL +*******************************************************/ +bool SplitPane::HasViewOne() const { + if(PaneOne) return true; + return false; +} + +/******************************************************* +* Do we have a View Two .. or is it NULL too +*******************************************************/ +bool SplitPane::HasViewTwo() const { + if(PaneTwo) return true; + return false; +} + +/******************************************************* +* Sets wheather View one is detachable from the +* slider view and from the app. This will creat a +* window that is detached (floating) from the app. +*******************************************************/ +void SplitPane::SetViewOneDetachable(bool b){ + VOneDetachable = b; +} + +/******************************************************* +* Sets view tow detachable or not +*******************************************************/ +void SplitPane::SetViewTwoDetachable(bool b){ + VTwoDetachable = b; +} + +/******************************************************* +* Returns whether the view is detachable +*******************************************************/ +bool SplitPane::IsViewOneDetachable() const { + return VOneDetachable; +} + +/******************************************************* +* Returns if this view is detachable +*******************************************************/ +bool SplitPane::IsViewTwoDetachable() const { + return VTwoDetachable; +} + +/******************************************************* +* Tells the view if the user is alowed to open the +* configuration window for the slider. +*******************************************************/ +void SplitPane::SetEditable(bool /*b*/){ + //ADD CODE HERE YNOP +} + +/******************************************************* +* Tells use if the split pane is user editable +*******************************************************/ +bool SplitPane::IsEditable() const { + return true; //ADD SOME MORE CODE HERE +} + +/******************************************************* +* Sets the inset that the view has. +*******************************************************/ +void SplitPane::SetViewInsetBy(BPoint p){ + pad = p; + if(attached){ + Update(); + } + Invalidate(); +} + +/******************************************************* +* Returns to use the padding around the views +*******************************************************/ +BPoint SplitPane::GetViewInsetBy() const { + return pad; +} + +/******************************************************* +* This sets the minimum size that View one can be. +* if the user trys to go past this .. we just stop +* By default the minimum size is set to 0 (zero) so +* the user can put the slider anywhere. +*******************************************************/ +void SplitPane::SetMinSizeOne(const BPoint & p){ + MinSizeOne = p; +} + +/******************************************************* +* Gives us the minimum size that one can be. +*******************************************************/ +BPoint SplitPane::GetMinSizeOne() const { + return MinSizeOne; +} + +/******************************************************* +* This sets the Minimum size that the second view +* can be. +*******************************************************/ +void SplitPane::SetMinSizeTwo(const BPoint & p){ + MinSizeTwo = p; +} + +/******************************************************* +* Lets us know what that minimum size is. +*******************************************************/ +BPoint SplitPane::GetMinSizeTwo() const { + return MinSizeTwo; +} + +/******************************************************* +* Locks the bar from being moved by the User. The +* system can still move the bar (via SetBarPosition) +*******************************************************/ +void SplitPane::SetBarLocked(bool b){ + poslocked = b; +} + +/******************************************************* +* Returns to use if the bar is in a locked state or +* not. +*******************************************************/ +bool SplitPane::IsBarLocked() const { + return poslocked; +} + +/******************************************************* +* Locks the alignment of the bar. The user can no +* longer toggle between Horizontal and Vertical +* Slider bar. Again you can still progomaticly set +* the position how ever you want. +*******************************************************/ +void SplitPane::SetBarAlignmentLocked(bool b){ + alignlocked = b; +} + +/******************************************************* +* Lets us know about the lock state of the bar +*******************************************************/ +bool SplitPane::IsBarAlignmentLocked() const { + return alignlocked; +} + +/******************************************************* +* Locks the alignment of the bar. The user can no +* longer toggle between Horizontal and Vertical +* Slider bar. Again you can still progomaticly set +* the position how ever you want. +*******************************************************/ +void SplitPane::SetResizeViewOne(bool x, bool y){ + resizeOneX = x; + resizeOneY = y; + if(attached){ + Update(); + } + Invalidate(); +} + +/******************************************************* +* Lets us know about the lock state of the bar +*******************************************************/ +void SplitPane::GetResizeViewOne(bool & rx, bool & ry) const { + rx = resizeOneX; + ry = resizeOneY; +} + + +/******************************************************* +* Gets the Total state of the bar, alignment, size, +* position and many other things that are required +* to fully capture the state of the SplitPane. +* We pack all of this into a cute little BMessage +* so that it is esally expandable and can be saved +* off easyaly too. The SplitPane System does not +* however save the state for you. Your program must +* grab the state and save it in its config file. +*******************************************************/ +void SplitPane::GetState(BMessage & state) const { + state.AddBool("onedetachable",VOneDetachable); + state.AddBool("twodetachable",VTwoDetachable); + state.AddInt32("align",align); + state.AddPoint("pos",pos); + state.AddPoint("thick",thickness); + state.AddPoint("jump",jump); + state.AddPoint("pad",pad); + state.AddPoint("minsizeone",MinSizeOne); + state.AddPoint("minsizetwo",MinSizeTwo); + state.AddBool("poslock",poslocked); + state.AddBool("alignlock",alignlocked); + state.AddBool("resizeonex", resizeOneX); + state.AddBool("resizeoney", resizeOneY); + state.AddBool("swap", swapPanes); +} + +/******************************************************* +* Sets the state of the SplitPane from a BMessage +* like the one recived from GetState(). +* This is one of three ways the user can rebuild the +* state of the SplitPane. The second is to simply +* send the SplitPane the state message, it is the +* same as calling SetState but it ashyncronouse. +* The third way is to use all the Get/Set methouds +* for each element of the SplitPane, this way is +* long and boarding. I suggest you just send the +* View a message :) +*******************************************************/ +void SplitPane::SetState(BMessage *state){ + BPoint pt; + int32 i; + + if(state->FindBool("onedetachable",&VOneDetachable) != B_NO_ERROR) VOneDetachable = false; + if(state->FindBool("towdetachable",&VTwoDetachable) != B_NO_ERROR) VTwoDetachable = false; + if(state->FindInt32("align",&i) == B_NO_ERROR) align = i; + if(state->FindPoint("pos",&pt) == B_NO_ERROR) pos = pt; + if(state->FindPoint("thick",&pt) == B_NO_ERROR) thickness = pt; + if(state->FindPoint("jump",&pt) == B_NO_ERROR) jump = pt; + if(state->FindPoint("pad",&pt) == B_NO_ERROR) pad = pt; + if(state->FindBool("poslock",&poslocked) != B_NO_ERROR) poslocked = false; + if(state->FindBool("alignlock",&alignlocked) != B_NO_ERROR) alignlocked = false; + if(state->FindBool("resizeonex",&resizeOneX) != B_NO_ERROR) resizeOneX = false; + if(state->FindBool("resizeoney",&resizeOneY) != B_NO_ERROR) resizeOneY = false; + if(state->FindBool("swap",&swapPanes) != B_NO_ERROR) swapPanes = false; + + if (attached) { + Update(); + Invalidate(); + } +} + +/******************************************************* +* Ok, hmm what does this do. NOT MUCH. if we get a +* STATE message then lets set the state. This is here +* to provide a asyncronuse way of seting the state and +* also to make life easyer. +*******************************************************/ +void SplitPane::MessageReceived(BMessage *msg){ + switch(msg->what){ + case SPLITPANE_STATE: + SetState(msg); + break; + case MIRROR: + { + swapPanes = !swapPanes; + Update(); + Invalidate(); + } + break; + case ROTATE: + { + if(!alignlocked){ + switch(align){ + case B_VERTICAL: + align = B_HORIZONTAL; + break; + case B_HORIZONTAL: + align = B_VERTICAL; + break; + } + Update(); + Invalidate(); + } + } + break; + default: + BView::MessageReceived(msg); + break; + } +} diff --git a/sources-experimental/SplitPane.h b/sources-experimental/SplitPane.h new file mode 100644 index 0000000..a89b459 --- /dev/null +++ b/sources-experimental/SplitPane.h @@ -0,0 +1,137 @@ +/******************************************************* +* SplitPane© +* +* SplitPane is a usefull UI component. It alows the +* use to ajust two view Horizontaly or Vertacly so +* that they are a desired size. This type of Pane +* shows up most comonly in Mail/News Readers. +* +* @author YNOP (ynop@acm.org) +* @version beta +* @date Dec. 10 1999 +*******************************************************/ +#ifndef _SPLIT_PANE_VIEW_H +#define _SPLIT_PANE_VIEW_H + +#include +#include +#include + + +class ImageButton; + +#define SPLITPANE_STATE 'spst' + +/* jaf: All BPoint arguments represent the value to use when in + * B_VERTICAL alignment followed by the value to use when in + * B_HORIZONTAL alignment. + */ +class SplitPane : public BView { + public: + SplitPane(BRect,BView*,BView*,uint32); + + void AddChildOne(BView*); + void AddChildTwo(BView*); + + void SetAlignment(uint); + uint GetAlignment() const; + + void SetSwapped(bool); + bool GetSwapped() const; + + void SetBarPosition(BPoint pos); + BPoint GetBarPosition() const; + + void SetBarThickness(BPoint); + BPoint GetBarThickness() const; + + void SetJump(BPoint); + BPoint GetJump() const; + + bool HasViewOne() const; + bool HasViewTwo() const; + + void SetViewOneDetachable(bool); + void SetViewTwoDetachable(bool); + + bool IsViewOneDetachable() const; + bool IsViewTwoDetachable() const; + + void SetEditable(bool); + bool IsEditable() const; + + void SetViewInsetBy(BPoint); + BPoint GetViewInsetBy() const; + + void SetMinSizeOne(const BPoint & size); + BPoint GetMinSizeOne() const; + + void SetMinSizeTwo(const BPoint & size); + BPoint GetMinSizeTwo() const; + + void GetState(BMessage & writeTo) const; + void SetBarLocked(bool); + + bool IsBarLocked() const; + void SetBarAlignmentLocked(bool); + + bool IsBarAlignmentLocked() const; + void SetState(BMessage*); + + void SetResizeViewOne(bool whileInVertAlign, bool whileInHorizAlign); + void GetResizeViewOne(bool & returnWhileInVertAlign, bool & returnWhileInHorizAlign) const; + + virtual void Draw(BRect); + virtual void AttachedToWindow(); + virtual void FrameResized(float,float); + virtual void MouseDown(BPoint); + virtual void MouseUp(BPoint); + virtual void MouseMoved(BPoint,uint32,const BMessage*); + virtual void MessageReceived(BMessage*); + + private: + bool IsInDraggerBounds(BPoint pt) const; + void Update(); + + BView *PaneOne; + BView *PaneTwo; + + ImageButton* rotate; + ImageButton* mirror; + + BBitmap* rotateH; + BBitmap* mirrorH; + BBitmap* rotateV; + BBitmap* mirrorV; + + //State info + bool VOneDetachable; + bool VTwoDetachable; + uint align; + BPoint pos; + BPoint thickness; + BPoint jump; + BPoint pad; + BPoint MinSizeOne; + BPoint MinSizeTwo; + bool poslocked; + bool alignlocked; + bool resizeOneX; // added by jaf; determines which child view gets + bool resizeOneY; // resized when SplitPane view is resized + bool swapPanes; + + //end State info + + bool Draggin; + BPoint here; + bool attached; + BPoint prevSize; + + BWindow *WinOne; + BWindow *WinTwo; + +// BWindow *ConfigWindow; +}; + + +#endif diff --git a/sources-experimental/StackedView.cpp b/sources-experimental/StackedView.cpp new file mode 100644 index 0000000..3d1b9a2 --- /dev/null +++ b/sources-experimental/StackedView.cpp @@ -0,0 +1,63 @@ + #include "StackedView.h" + +StackedView::StackedView(BRect _frame,const char* _name, + uint32 _resize, + uint32 _flags): + BView(_frame,_name,_resize,_flags){ + fSelected = NULL; +} + +uint32 +StackedView::AddView(BView* _view){ + fStackedViewList.AddItem(_view); + + _view->MoveTo(0,0); + _view->ResizeTo(Bounds().Width(),Bounds().Height()); + + AddChild(_view); + if(fSelected!=NULL) _view->Hide(); + else fSelected = _view; + return 0; +} + +BView* +StackedView::RemoveView(BView& _view){ + fStackedViewList.RemoveItem(&_view); + return NULL; +} + +uint32 +StackedView::CountViews() const { + return fStackedViewList.CountItems(); +} + +void +StackedView::SetSelectedIndex(uint32 _index){ + BView* at=fStackedViewList.ItemAt(_index); + if(fSelected) fSelected->Hide(); + if(at) at->Show(); + fSelected = at; + + +} + +void +StackedView::AttachedToWindow(){ + + if(Parent()) + SetViewColor(Parent()->ViewColor()); + for(int i=0;iMoveTo(0,0); + at->ResizeTo(Bounds().Width(),Bounds().Height()); + } + +} + +void +StackedView::SetSelectedView(BView& _view){ + int32 index = fStackedViewList.IndexOf(&_view); + if(index >=0) + SetSelectedIndex(index); +} + diff --git a/sources-experimental/StackedView.h b/sources-experimental/StackedView.h new file mode 100644 index 0000000..9fe39c9 --- /dev/null +++ b/sources-experimental/StackedView.h @@ -0,0 +1,57 @@ +#ifndef _StackedView_h_ +#define _StackedView_h_ + +#include "ObjectList.h" +#include + +class StackedView : public BView +{ + public: + + StackedView(BRect _frame, + const char* _name, + uint32 _resize, + uint32 _flags); + //virtual ~StackedView(); + + uint32 CountViews() const; + //uint32 IndexOf(const BView& _view) const; + //bool HasView(const BView& _view) const; + + //BView& EditViewAt(uint32 _index); + //const BView& ViewAt(uint32 _index) const; + + uint32 AddView(BView* _view); + //uint32 InsertView(BView* _view, uint32 _index); + + //BView* RemoveView(uint32 _index); + BView* RemoveView(BView& _view); + + //BView* ReplaceView(uint32 _index, BView* _view); + + void SetSelectedIndex(uint32 _index); + void SetSelectedView(BView& _view); + + //uint32 GetSelectedIndex() const; + BView* GetSelectedView() { return fSelected; } + + //bool GetAutoResize() const; + //void SetAutoResize(bool _autoResize); + + //bool DoesLazyAttach() const; + //void SetLazyAttach(bool _lazy); + + virtual void AttachedToWindow(); + //virtual void SelectionChanged(uint32 _index); + + private: + // status_t IndexFor(const BView& _view, uint32& _index) const; + // void CheckBounds(uint32 _index) const; + + private: + + BObjectList fStackedViewList; + BView* fSelected; +}; +#endif +//-- diff --git a/sources-experimental/Store.h b/sources-experimental/Store.h new file mode 100644 index 0000000..b7f0fdd --- /dev/null +++ b/sources-experimental/Store.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef _Store_H_ +#define _Store_H_ + +#include "ItemProperty.h" +#include + +class Store { + + public: + + virtual void SetKey(ItemProperty key,void* data,ssize_t size) = 0; + + virtual void SetKeyString(ItemProperty key,const char* data) = 0; + virtual void SetKeyInt32(ItemProperty key,int32 data) = 0; + +}; + +#endif + +//.. diff --git a/sources-experimental/StripeView.cpp b/sources-experimental/StripeView.cpp new file mode 100644 index 0000000..d8b19a3 --- /dev/null +++ b/sources-experimental/StripeView.cpp @@ -0,0 +1,55 @@ +#include "StripeView.h" + +static const int kIconStripeWidth = 30; + +StripeView::StripeView(BRect frame) + : BView(frame, "StripeView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW), + fIconBitmap(NULL) +{ + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); +} + + +StripeView::StripeView(BMessage* archive) + : BView(archive), + fIconBitmap(NULL) +{ +} + + +StripeView::~StripeView(){} + + +StripeView* +StripeView::Instantiate(BMessage* archive) +{ + if (!validate_instantiation(archive, "StripeView")) + return NULL; + + return new StripeView(archive); +} + + +status_t +StripeView::Archive(BMessage* archive, bool deep) +{ + return BView::Archive(archive, deep); +} + + +void +StripeView::Draw(BRect updateRect) +{ + // Here's the fun stuff + if (fIconBitmap) { + BRect StripeRect = Bounds(); + StripeRect.right = kIconStripeWidth; + SetHighColor(tint_color(ViewColor(), B_DARKEN_1_TINT)); + FillRect(StripeRect); + + + SetDrawingMode(B_OP_ALPHA); + DrawBitmapAsync(fIconBitmap, BPoint(18, 6)); + SetDrawingMode(B_OP_COPY); + } +} diff --git a/sources-experimental/StripeView.h b/sources-experimental/StripeView.h new file mode 100644 index 0000000..6f7e050 --- /dev/null +++ b/sources-experimental/StripeView.h @@ -0,0 +1,29 @@ +#ifndef _StripeView_H_ +#define _StripeView_H_ + +#include + +class StripeView : public BView { + public: + StripeView(BRect frame); + StripeView(BMessage* archive); + ~StripeView(); + + static StripeView* Instantiate(BMessage* archive); + status_t Archive(BMessage* archive, bool deep = true); + + virtual void Draw(BRect updateRect); + + // These functions (or something analogous) are missing from libbe.so's + // dump. I can only assume that the bitmap is a public var in the + // original implementation -- or BPAlert is a friend of StripeView. + // Neither one is necessary, since I can just add these. + void SetBitmap(BBitmap* Icon) { fIconBitmap = Icon; } + BBitmap* Bitmap() { return fIconBitmap; } + + private: + BBitmap* fIconBitmap; +}; + +#endif +//- diff --git a/sources-experimental/SubscriptionColumn.cpp b/sources-experimental/SubscriptionColumn.cpp new file mode 100644 index 0000000..adddb5e --- /dev/null +++ b/sources-experimental/SubscriptionColumn.cpp @@ -0,0 +1,321 @@ +#include "SubscriptionColumn.h" +#include "BPLocale.h" +#include +#include +#include +#include "Colors.h" + +#ifdef ZETA + #include +#endif + +#define kTEXT_MARGIN 8 + +SubscriptionColumn::SubscriptionColumn(const char* title, float width, float minWidth, + float maxWidth, uint32 trunc, alignment align) + :BStringColumn(title, width, minWidth, maxWidth, align), + fTruncate(trunc) +{ + SetWantsEvents(true); + lastDest = NULL; +} + +//-------------------------------------------------------------------- + +void SubscriptionColumn::DrawField(BField* _field, BRect rect, BView* parent){ + + SubscriptionField* field = dynamic_cast(_field); + + if(field){ + + switch(field->Size()){ + case BIG: + DrawBigField(field,rect,parent); + break; + case SMALL: + DrawSmallField(field,rect,parent); + break; + } + } + else + BStringColumn::DrawField(_field,rect,parent); + +} + +void +SubscriptionColumn::DrawSmallField(SubscriptionField* field, BRect rect, BView* parent) +{ + parent->PushState(); + rect.left += kTEXT_MARGIN; + + float width = rect.Width() - (2 * kTEXT_MARGIN); + + BString out_string(field->String()); + + + + + if( field->GetNewCount() >0) + out_string << " (" << field->GetNewCount() << ")"; + else + out_string << " "; //really don't like maybe we should find a better solution? to avoid the (1) bug + + if (width != field->Width() || out_string.Compare(field->String()) !=0 ) + { + parent->TruncateString(&out_string, fTruncate, width + 2); + field->SetClippedString(out_string.String()); + field->SetWidth(width); + } + + SetFileStatusColor(field->GetFileStatus(),parent); + + DrawString(field->ClippedString(), parent, rect); + parent->PopState(); +} + +void +SubscriptionColumn::DrawBigField(SubscriptionField* field, BRect rect, BView* parent) +{ + //SubscriptionField* field = static_cast(_field); + + const BBitmap *bitmap = field->GetBitmap(); + + parent->PushState(); + + if (bitmap != NULL) + { + float x = 0.0; + float y; + BRect r = bitmap->Bounds(); + + y = rect.top + ((rect.Height() - r.Height()) / 2) - 1; + + switch (Alignment()) + { + case B_ALIGN_LEFT: + x = rect.left ; // + kTEXT_MARGIN; + break; + + case B_ALIGN_CENTER: + x = rect.left + ((rect.Width() - r.Width()) / 2); + break; + + case B_ALIGN_RIGHT: + x = rect.right - kTEXT_MARGIN - r.Width(); + break; + } + parent->SetDrawingMode(B_OP_ALPHA); + parent->DrawBitmap(bitmap, BPoint(x, y)); + parent->SetDrawingMode(B_OP_OVER); + } + + rect.left += 45.0; //55.0; + + float width = rect.Width() - (2 * kTEXT_MARGIN); + + if (width != field->Width()) + { + BString out_string(field->String()); + + parent->TruncateString(&out_string, fTruncate, width + 2); + field->SetClippedString(out_string.String()); + field->SetWidth(width); + } + + float hei=rect.Height() /2.0; + hei -= 3; + rect.top +=3; + + rect.bottom = rect.top + hei; //+ 30; //19 + DrawString(field->ClippedString(), parent, rect); + + //debug: parent->StrokeRect(rect); + rect.top = rect.bottom; + rect.bottom = rect.top + hei; //19; //19 + parent->SetHighColor(0,0,0); //(125,125,125) + + DrawString("", parent, rect); + //debug: parent->StrokeRect(rect); + + if(field->GetNewCount()>0) + { + + BString tot; + + if(field->GetNewCount()==1) + tot << _T("1 new item"); + else { + #ifdef ZETA + tot << _TPS("%d new items").Replace("%d",BFormatter("%d", field->GetNewCount())); + #else + tot << field->GetNewCount() << " new items"; + #endif + } + tot << " "; + parent->DrawString(tot.String()); + } + + DrawStatus(field->GetFileStatus(),parent,field->GetFilePercentage()); + + parent->PopState(); +} + +void +SubscriptionColumn::DrawStatus(FileStatus status,BView* parent,int32 perc){ + + SetFileStatusColor(status,parent); + + switch(status){ + + case ERROR: + parent->DrawString(_T("error")); + break; + case NOT_DOWNLOADED: + parent->DrawString(_T("not down")); + break; + case ENQUEQUED: + parent->DrawString(_T("enquequed")); + break; + case DOWNLOADING: + parent->DrawString(_T("downloading")); + if(perc>=0 && perc<=100){ + BString sp(" "); + sp << perc << "%"; + parent->DrawString(sp.String()); + } + break; + case DOWNLOADED: + break; + case STOPPED: + break; + case CONNECTING: + parent->DrawString(_T("connecting")); + break; + case NOT_FOUND: + parent->DrawString(_T("not found")); + break; + case CANT_CONNECT: + parent->DrawString(_T("can't connect")); + break; + case BAD_FORMAT: + parent->DrawString(_T("invalid format")); + break; + default: + break; + } + + + +} + +void +SubscriptionColumn::SetFileStatusColor(FileStatus status,BView* parent){ + switch(status){ + + case ERROR: + parent->SetHighColor(230,0,0); + // parent->SetLowColor(125,0,0); + + break; + case NOT_DOWNLOADED: + + break; + case ENQUEQUED: + parent->SetHighColor(20,20,220); + break; + case DOWNLOADING: + parent->SetHighColor(0,99,12); //(0,255,0) + //parent->SetLowColor(0,49,12); //(0.125.0) + + break; + case DOWNLOADED: + + break; + case STOPPED: + + break; + case CONNECTING: + parent->SetHighColor(83,118,75); //57,93,0); + //parent->SetLowColor(57,93,0); //(0.125.0) + + break; + case NOT_FOUND: + parent->SetHighColor(230,0,0); + // parent->SetLowColor(125,0,0); + + break; + case CANT_CONNECT: + parent->SetHighColor(230,0,0); + // parent->SetLowColor(125,0,0); + + break; + case BAD_FORMAT: + parent->SetHighColor(230,0,0); + // parent->SetLowColor(125,0,0); + + break; + default: + break; + } +// parent->SetLowColor(parent->HighColor()); +} + +//-------------------------------------------------------------------- + +int SubscriptionColumn::CompareFields(BField* field1, BField* field2) { + int32 index1 = ((PositionableField*)field1)->GetPreferredPosition(); + int32 index2 = ((PositionableField*)field2)->GetPreferredPosition(); + return ( index1 - index2 ); +} + + +//-------------------------------------------------------------------- + +bool SubscriptionColumn::AcceptsField(const BField *field) const { + return static_cast(dynamic_cast(field)); +} + + +void +SubscriptionColumn::MouseMoved(BColumnListView *parent, BRow *row, BField *field, + BRect field_rect, BPoint point, uint32 buttons, int32 code){ + + if(parent && parent->Window()){ + BMessage* msg = parent->Window()->CurrentMessage(); + int32 what; + if(msg && msg->FindInt32("_msg_data_",&what)==B_OK) { + + + + BRect re; + BRow* dest=parent->RowAt(point); + parent->GetRowRect(dest,&re); + + /* + casi possibili di update vecchio + a) !=NULL + b) != nuovo + c) == nuovo E !contine + */ + + if(lastDest && ( ( lastDest != dest ) || ( dest && lastDest == dest && !re.Contains(point) ) )) + parent->UpdateRow(lastDest); + + + if(dest && dest != row && re.Contains(point) && lastDest != dest ){ + parent->ScrollView()->PushState(); + parent->ScrollView()->SetHighColor(White); + parent->ScrollView()->SetHighColor(200,0,0,125); + parent->ScrollView()->SetDrawingMode(B_OP_ALPHA); + parent->ScrollView()->FillRect(re); + parent->ScrollView()->PopState(); + } + + if(re.Contains(point)) + lastDest=dest; + else + lastDest = NULL; + } + } +} + diff --git a/sources-experimental/SubscriptionColumn.h b/sources-experimental/SubscriptionColumn.h new file mode 100644 index 0000000..58fea08 --- /dev/null +++ b/sources-experimental/SubscriptionColumn.h @@ -0,0 +1,114 @@ +#ifndef SubscriptionColumn_H +#define SubscriptionColumn_H + +#include "ColumnTypes.h" +#include "FileStatus.h" + +enum SubscriptionSize { + BIG, + SMALL + }; + + +class PositionableField : public BStringField { + + public: + + PositionableField(const char* txt):BStringField(txt){ + SetPreferredPosition(-1); + SetSize(SMALL); + }; + + void SetSize(SubscriptionSize size) { fSize=size; } + SubscriptionSize Size(){ return fSize;} + + void SetPreferredPosition(int c) { fPosition=c;} + int GetPreferredPosition() { return fPosition; } + + + + private: + + int fPosition; + SubscriptionSize fSize; + +}; + +class SubscriptionField : public PositionableField { + + public: + + SubscriptionField(const char* txt,int32):PositionableField(txt){ + SetNewCount(0); + SetBitmapPointer(NULL); + fMyBitmap =NULL; + fPercentage = 0; + SetFileStatus(DOWNLOADED); + SetSize(BIG); + }; + + + void SetBitmapPointer(BBitmap* bit){ fBitmap=bit; } + void SetBitmapPersonal(BBitmap* bit){ + if(fMyBitmap) delete fMyBitmap; + fMyBitmap=bit; + SetBitmapPointer(bit); + } + + FileStatus GetFileStatus(){ return fStatus;}; + void SetFileStatus(FileStatus status){ fStatus = status; }; + void SetFilePercentage(int perc){ fPercentage = perc; } + int32 GetFilePercentage(){ return fPercentage; } + + void SetNewCount(int32 count){ fNewCount=count;} + void AddNewCount(int32 add){ fNewCount +=add; } + int32 GetNewCount(){ return fNewCount; } + + BBitmap* GetBitmap() { return fBitmap; } + private: + BBitmap* fBitmap; + BBitmap* fMyBitmap; + FileStatus fStatus; + int32 fNewCount; + int32 fPercentage; + //int fPosition; + //SubscriptionSize fSize; + +}; + +class SubscriptionColumn : public BStringColumn { + + public: + SubscriptionColumn (const char *title, + float width, + float maxWidth, + float minWidth, + uint32 truncate, + alignment align = B_ALIGN_LEFT); + void DrawField (BField* field, + BRect rect, + BView* parent); + void DrawBigField (SubscriptionField* field, + BRect rect, + BView* parent); + void DrawSmallField (SubscriptionField* field, + BRect rect, + BView* parent); + + virtual int CompareFields (BField* field1, + BField* field2); + bool AcceptsField (const BField* field) const; + + + void DrawStatus(FileStatus status,BView* parent,int32 perc); + void SetFileStatusColor(FileStatus status,BView* parent); + + + void MouseMoved(BColumnListView *parent, BRow *row, BField *field, + BRect field_rect, BPoint point, uint32 buttons, int32 code); + + private: + uint32 fTruncate; + BRow* lastDest; +}; +#endif diff --git a/sources-experimental/SubscriptionListItem.cpp b/sources-experimental/SubscriptionListItem.cpp new file mode 100644 index 0000000..d263901 --- /dev/null +++ b/sources-experimental/SubscriptionListItem.cpp @@ -0,0 +1,324 @@ +#include "SubscriptionListItem.h" +#include "ItemProperty.h" + +#include "ColumnListView.h" +#include "ColumnTypes.h" +//#include +#include +#include "BPLocale.h" +#include "Utils.h" +#include +#include "malloc.h" + +#include + +#define ALTEZZA_BIG 48 +#define ALTEZZA_SMALL 16 +#define DIMESIONE_ICONA 46 + +BBitmap* fGenericSubIcon=NULL; + +SubscriptionListItem::SubscriptionListItem(entry_ref ref):BRow(ALTEZZA_BIG) +{ + if(!fGenericSubIcon) + fGenericSubIcon= LoadIcon("file-46.png"); + + fWeb.SetTo(""); + + field = new SubscriptionField("",123); + field->SetBitmapPointer(fGenericSubIcon); + SetField( field, 0 ); + + fChannel.AddElementListener(this); + + SetIsNew(false); + + extraSetting = columnsState = NULL; + + fRef=ref; + + fStatusFilter = FILTER_NONE; +} + + +void +SubscriptionListItem::SetSize(SubscriptionSize size){ + + switch(size){ + case BIG: + SetHeight(ALTEZZA_BIG); + break; + case SMALL: + SetHeight(ALTEZZA_SMALL); + break; + }; + field->SetSize(size); +// printf("SubscriptionListItem SET TITLE %s\n",field->String()); +} + + +bool +SubscriptionListItem::HasOwnImage(){ + + if(field->GetBitmap()==fGenericSubIcon) + return false; + + return true; +} + +void +SubscriptionListItem::KeyModified(int32 key, void* data,ssize_t) { + + switch(key) + { + case CHANNEL_TITLE: +// printf("SubscriptionListItem SET TITLE %s\n",(const char*)data); + field->SetString((const char*)data); +// printf("SubscriptionListItem SET TITLE %s\n",field->String()); + break; + + case CHANNEL_URL: + fUrl.SetTo((const char*)data); + break; + + case CHANNEL_WEBLINK: + fWeb.SetTo((const char*)data); + break; + + case CHANNEL_NEWITEMS: + { + int32 c = *((int32*)data); + field->AddNewCount(c); + } + break; + + case CHANNEL_RSS_FILE_STATUS: + { + int32 c = *((int32*)data); + field->SetFileStatus((FileStatus)c); + } + break; + case CHANNEL_IMAGE_DATA: + { + BBitmap* icon = (BBitmap*)data; + if(!icon) return; //safety + //here resizing please! + //quale è il lato + lungo? + + BBitmap* nicon; + float h = icon->Bounds().Height(); + float w =icon->Bounds().Width(); + + if( h == w ) + nicon = rescale_bitmap(icon,DIMESIONE_ICONA,DIMESIONE_ICONA); + else + { + if(h>w) + { + float diff = w/h; + nicon = rescale_bitmap(icon,DIMESIONE_ICONA*diff,DIMESIONE_ICONA); + } + else + { + float diff = h/w; + nicon = rescale_bitmap(icon,DIMESIONE_ICONA,DIMESIONE_ICONA*diff); + } + + } + + field->SetBitmapPersonal(nicon); + } + break; + + default: + break; + }; +} + + +SubscriptionListItem::~SubscriptionListItem(){ + //nothing to do here? +} + + +BBitmap* +SubscriptionListItem::rescale_bitmap( BBitmap * original, int32 width, int32 height ) +{ + + float starting_width = original->Bounds().Width()+1; + float starting_height = original->Bounds().Height()+1; + + float new_width = width; //round(starting_width * new_settings->width_coefficient); + float new_height = height; //round(starting_height * new_settings->height_coefficient); + + // Create a new bitmap here and copy it applying scaling. + // But first create an intermediate bitmap for scaling in one direction only. + // Remember that the returned bitmap must accept views + // First scale the width. + // If the new size is the same as old return the original + if ((new_width == starting_width) && (new_height == starting_height)) + return new BBitmap(original); + + + + BBitmap *intermediate_bitmap; + if (new_width != starting_width) { + intermediate_bitmap = new BBitmap(BRect(0,0,new_width-1,starting_height-1),B_RGB_32_BIT); + if (intermediate_bitmap->IsValid() == FALSE) + #ifdef ZETA + throw bad_alloc(); + #else + return NULL; + #endif + uint32 *target_bits = (uint32*)intermediate_bitmap->Bits(); + int32 target_bpr = intermediate_bitmap->BytesPerRow()/4; + uint32 *source_bits = (uint32*)original->Bits(); + int32 source_bpr = original->BytesPerRow()/4; + int32 bottom = (int32)original->Bounds().bottom; + float diff = (starting_width)/(new_width); + float accumulation = 0; + + + if (diff<1) { + // Enlarge in x direction. + for (int32 y=0;y<=bottom;y++) { + accumulation = 0; + for (int32 x=0;x1) { + // Make smaller in x direction. + diff = (starting_width-1)/new_width; // Why this line??? + for (int32 y=0;y<=bottom;y++) { + accumulation = 0; + for (int32 x=0;xIsValid() == FALSE) + #ifdef ZETA + throw bad_alloc(); + #else + return NULL; + #endif + uint32 *target_bits = (uint32*)new_bitmap->Bits(); + int32 target_bpr = new_bitmap->BytesPerRow()/4; + uint32 *source_bits = (uint32*)intermediate_bitmap->Bits(); + int32 source_bpr = intermediate_bitmap->BytesPerRow()/4; + int32 bottom = (int32)new_bitmap->Bounds().bottom; + float diff = (starting_height-1)/(new_height); + float accumulation = 0; + if (diff<1) { + // Make larger in y direction. + for (int32 y=0;y<=bottom;y++) { + for (int32 x=0;x1) { + // Make smaller in y direction. + diff = (starting_height-1)/new_height; + accumulation = 0; + for (int32 y=0;y<=bottom;y++) { + for (int32 x=0;xSetHighColor(0,0,0); + parent->FillRoundRect(BRect(_rect.left + 6, _rect.top + 6,_rect.left + 9,_rect.top + 9),1,1); + } +} + diff --git a/sources-experimental/SubscriptionListItem.h b/sources-experimental/SubscriptionListItem.h new file mode 100644 index 0000000..6d514e8 --- /dev/null +++ b/sources-experimental/SubscriptionListItem.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef _SubscriptionListItem_H +#define _SubscriptionListItem_H + +#include "ColumnListView.h" +#include "ColumnTypes.h" + +#include "ElementListener.h" + +#include "SubscriptionColumn.h" + +#include "RssChannel.h" + +#include + + +class SubscriptionListItem : public BRow, public ElementListener +{ + public: + + + SubscriptionListItem(entry_ref fRef); + ~SubscriptionListItem(); + + BString GetURL(){ return fUrl;} + BString GetWeblink(){ return fWeb;} + void SetFileStatus(FileStatus c){field->SetFileStatus(c);} + FileStatus GetFileStatus(){return field->GetFileStatus();} + + BString GetTitle(){return field->String();} + void KeyModified(int32 key, void* data,ssize_t); + + void SetNewCount(int32 count){ field->SetNewCount(count);} + void AddNewCount(int32 add){ field->AddNewCount(add);} + int32 GetNewCount(){ return field->GetNewCount(); } + + void SetPreferredPosition(int32 index){ + field->SetPreferredPosition(index); + } + + void SetFilePercentage(int32 per){ field->SetFilePercentage(per);} + + void SetSize(SubscriptionSize size); + + bool HasOwnImage(); + + //don't like this: + RssChannel fChannel; + + void DrawBackground(BRect _rect,BView* _target_view,bool _is_selected,bool _is_focus ); + + bool IsNew(){ return isNew; } + void SetIsNew(bool set){ isNew = set; } + + entry_ref fRef; + + entry_ref lastSelected; //<---- ? remove and add as list. + + BMessage* extraSetting; //TODO: per channel setttings + BMessage* columnsState; //columns states + //TODO: list of selected entry_ref. + + enum StatusFilter { + FILTER_NONE = 0, + FILTER_NEW = 1, + FILTER_DOWNLOADED = 2 + }; + + + StatusFilter fStatusFilter; //maybe can become an attribute? + + private: + + BBitmap* rescale_bitmap( BBitmap * src, int32 width, int32 height ); + SubscriptionField* field; + BString fUrl; //? + BString fWeb; + + inline uint32 mix_2_pixels_fixed(uint32 p1,uint32 p2,uint32 c) + { + uint32 inv_c = 32768 - c; + + return ((((((p1 >> 24) &0xFF) * c + ((p2 >> 24)&0xFF) * inv_c)>>15)<<24) & 0xFF000000) | + ((((((p1 >> 16)&0xFF) * c + ((p2 >> 16)&0xFF) * inv_c)>>15)<<16) & 0x00FF0000) | + ((((((p1 >> 8)&0xFF) * c + ((p2 >> 8)&0xFF) * inv_c)>>15)<<8) & 0x0000FF00) | + (((((p1&0xFF) * c + (p2&0xFF) * inv_c)>>15)) & 0x000000FF); + } + + bool isNew; + + + }; + +#endif diff --git a/sources-experimental/SubscriptionListView.cpp b/sources-experimental/SubscriptionListView.cpp new file mode 100644 index 0000000..ce1dc5b --- /dev/null +++ b/sources-experimental/SubscriptionListView.cpp @@ -0,0 +1,276 @@ +#include "SubscriptionListView.h" +#include "SubscriptionListItem.h" + +#include "BPLocale.h" +#include +#include "Utils.h" +#include "GroupItem.h" +#include "Colors.h" + +#include + +#include + +#define DROP_CHANNEL 'drch' +#define DROP_GROUP 'drgr' + +SubscriptionListView::SubscriptionListView(BRect r): +BColumnListView(r,"SubscriptionListView",B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW|B_FRAME_EVENTS|B_NAVIGABLE,B_FANCY_BORDER,true) +{ + + podcast=new SubscriptionColumn(_T("Subscriptions"),200,36,300,B_TRUNCATE_MIDDLE,B_ALIGN_LEFT); + AddColumn(podcast,0); + SetColumnFlags(B_ALLOW_COLUMN_RESIZE ); + SetSelectionMode(B_SINGLE_SELECTION_LIST); + const rgb_color x = {238,185,0,255}; //244,203,63 244,190,23 + SetColor(B_COLOR_SELECTION,x);//! + + SetColor(B_COLOR_BACKGROUND,White); + + SetColor(B_COLOR_ROW_DIVIDER,BeBackgroundGrey); + + + CurrentSelection(0); + + BMessage* selected=new BMessage(CHANNEL_SELECTED); + selected->AddInt32("buttons",0); + SetSelectionMessage(selected); + + + SetSortColumn(podcast,true,true); + SetSortingEnabled(false); + fItemSize = BIG; +} + +void +SubscriptionListView::FrameResized(float w,float h){ + BColumnListView::FrameResized(w,h); + podcast->SetWidth(w-35); + GetTitleView()->Invalidate(); + Refresh(); +} + +void +SubscriptionListView::SelectionChanged(){ + uint32 buttons; + + BMessage *msg = Window()->CurrentMessage(); + + if(msg) + msg->FindInt32("buttons", (int32 *)&buttons); + + SelectionMessage()->ReplaceInt32("buttons",buttons); + + BColumnListView::SelectionChanged(); +} + +void +SubscriptionListView::MessageDropped(BMessage* msg, BPoint point){ + + if(msg->what==DROP_CHANNEL) DroppedSubscription(msg,point); + else + if(msg->what==DROP_GROUP) DroppedGroup(msg,point); + + +} + +void +SubscriptionListView::DroppedSubscription(BMessage* msg, BPoint point){ + + int32 from=msg->FindInt32("from"); + int32 parentFrom=msg->FindInt32("parent"); + + BRow * frow= NULL; + + if(parentFrom!=-1){ + BRow* parent= RowAt(parentFrom); + if(!parent) return; //some error occured. + frow=RowAt(from,parent); + } + else + frow=RowAt(from); + + BRow *row=RowAt(point); + + if(!frow || frow==row) return; + + SubscriptionListItem* sitem=dynamic_cast(row); + + if(row && sitem) { + int32 to = IndexOf(row); //this is a position relative to the parent. + + //printf("Move from %ld to %ld\n",from,to); + BRow* parent=NULL; + FindParent(row,&parent,NULL); + RemoveRow(frow); + AddRow(frow,to,parent); + DeselectAll(); + } + else + if(row){ //dropped to a group + RemoveRow(frow); + AddRow(frow,row); + DeselectAll(); + } + else + if(!row){ //dropped outside any other channel == add at the bottom. + RemoveRow(frow); + AddRow(frow,CountRows(),NULL); + } + + AddToSelection(frow); +} + + +void +SubscriptionListView::DroppedGroup(BMessage* msg, BPoint point) +{ + int32 from=msg->FindInt32("from"); + int32 parentFrom=msg->FindInt32("parent"); + + BRow* frow= NULL; + + if(parentFrom!=-1){ + BRow* parent= RowAt(parentFrom); + if(!parent) return; //some error occured. + frow=RowAt(from,parent); + } + else + frow=RowAt(from); + + + BRow *row=RowAt(point); + if(!row) return; + + GroupItem* gitem=dynamic_cast(row); + if(gitem) + { + printf("Dropped, we should move the dropped into the group '%s'\n", "fix", gitem->GroupName().String() ); + RemoveRow(frow); + AddRow(frow,row); + DeselectAll(); + } +} + + +bool +SubscriptionListView::InitiateDrag(BPoint p, bool ) +{ + + + BMessage *msg = Window()->CurrentMessage(); + if(msg->FindInt32("buttons") == B_SECONDARY_MOUSE_BUTTON) return false; + + BRow *item=CurrentSelection(NULL); + if(!item) return false; + + SubscriptionListItem* sitem=dynamic_cast(item); + if(sitem) { + BMessage re(DROP_CHANNEL); + re.AddInt32("from",IndexOf(item)); + //are we in a group? + BRow* parent=NULL; + FindParent(item,&parent,NULL); + if(parent) + re.AddInt32("parent",IndexOf(parent)); + else + re.AddInt32("parent",-1); + + #ifdef ZETA + BBitmap *bit=new BBitmap(*( ((SubscriptionField*)item->GetField(0))->GetBitmap() )); + #else + BBitmap *bit=new BBitmap( ((SubscriptionField*)item->GetField(0))->GetBitmap() ); + #endif + DragMessage(&re,bit,B_OP_ALPHA,BPoint(bit->Bounds().Width()/2,bit->Bounds().Height()/2),this); + + return true; + } + + GroupItem* gitem=dynamic_cast(item); + if(gitem) { + BMessage re(DROP_GROUP); + re.AddInt32("from",IndexOf(item)); + BRect r(0,0,20,20); + r.OffsetTo(p.x,p.y); + DragMessage(&re,r,this); + + return true; + } + + return false; +} + +SubscriptionSize +SubscriptionListView::ItemSize(){ + return fItemSize; +} + +void +SubscriptionListView::SetItemSize(SubscriptionSize size){ + + //I hope we are locked! + //change the size of every BRow + + if( fItemSize == size ) return; + + fItemSize = size; + + BRow* selected = CurrentSelection(); + + DeselectAll(); + + ChangeSize(NULL); + + + AddToSelection(selected); + + //redraw all! + Refresh(); +} + +void +SubscriptionListView::ChangeSize(BRow* parent){ + + int32 tot = CountRows(parent); + for(int i=0;i(RowAt(0,parent)); + if(item) { + RemoveRow(item); + AddRow(item,tot,parent); + } + GroupItem* grp=dynamic_cast(RowAt(0,parent)); + if(grp) ChangeSize(grp); + } +} + +void +SubscriptionListView::AddRow(BRow* row, BRow *par){ + + SubscriptionListItem* item=dynamic_cast(row); + if(item) + item->SetSize(fItemSize); + BColumnListView::AddRow(row,par); + +} + +void +SubscriptionListView::AddGroup(GroupItem* group){ + AddRow((BRow*)group,(BRow*)NULL); +} + + + +void +SubscriptionListView::AddRow(BRow* row, int32 index, BRow *par){ + + SubscriptionListItem* item=dynamic_cast(row); + if(item) + item->SetSize(fItemSize); + BColumnListView::AddRow(row,index,par); +} + + +void +SubscriptionListView::MouseMoved(BPoint point,uint32 transit,const BMessage* message){ +} + diff --git a/sources-experimental/SubscriptionListView.h b/sources-experimental/SubscriptionListView.h new file mode 100644 index 0000000..765d6f3 --- /dev/null +++ b/sources-experimental/SubscriptionListView.h @@ -0,0 +1,48 @@ +#ifndef _SubscriptionListView_H_ +#define _SubscriptionListView_H_ + +#include "ColumnListView.h" +#include "SubscriptionColumn.h" + +#define CHANNEL_SELECTED 'invo' + +class GroupItem; + +class SubscriptionListView : public BColumnListView +{ + public: + SubscriptionListView(BRect r); + void FrameResized(float w ,float h); + void SelectionChanged(); + bool InitiateDrag(BPoint point, bool wasSelected); + void MessageDropped(BMessage*, BPoint point); + + void AddRow(BRow*, BRow *parent = 0); + void AddRow(BRow*, int32 index, BRow *parent = 0); + + void AddGroup(GroupItem* ); + //TODO: void AddGroup(GroupItem* group, GroupItem* parent); + + + void SetItemSize(SubscriptionSize size); //BIG or SMALL + SubscriptionSize ItemSize(); + + //Better drag support + + virtual void MouseMoved(BPoint point,uint32 transit,const BMessage* message); + + + + private: + + void ChangeSize(BRow* parent); + void DroppedSubscription(BMessage*, BPoint point); + void DroppedGroup(BMessage*, BPoint point); + + BColumn* podcast; + SubscriptionSize fItemSize; +}; + +#endif + +//. diff --git a/sources-experimental/TextControlFloater.cpp b/sources-experimental/TextControlFloater.cpp new file mode 100644 index 0000000..c8552e0 --- /dev/null +++ b/sources-experimental/TextControlFloater.cpp @@ -0,0 +1,157 @@ +// TextControlFloater.cpp + +#include "TextControlFloater.h" + +#include +#include + + + +// ---------------------------------------------------------------- // + +class MomentaryTextControl : + public BTextControl { + typedef BTextControl _inherited; + +public: + MomentaryTextControl( + BRect frame, + const char* name, + const char* label, + const char* text, + BMessage* message, + uint32 resizingMode=B_FOLLOW_LEFT|B_FOLLOW_TOP, + uint32 flags=B_WILL_DRAW|B_NAVIGABLE) : + BTextControl(frame, name, label, text, message, resizingMode, flags) { + + SetEventMask(B_POINTER_EVENTS|B_KEYBOARD_EVENTS); + } + +public: + virtual void AllAttached() { + TextView()->SelectAll(); + + // size parent to fit me + Window()->ResizeTo(Bounds().Width(),Bounds().Height()-1); + + Window()->Show(); + } + + virtual void MouseDown( + BPoint point) { + + if(Bounds().Contains(point)) + _inherited::MouseDown(point); + + Invoke(); +// // +++++ shouldn't an out-of-bounds click send the changed value? +// BMessenger(Window()).SendMessage(B_QUIT_REQUESTED); + } + + virtual void KeyDown( + const char* bytes, + int32 numBytes) { + + if(numBytes == 1 && *bytes == B_ESCAPE) { + BWindow* w = Window(); // +++++ maui/2 workaround + BMessenger(w).SendMessage(B_QUIT_REQUESTED); + return; + } + } +}; + +// ---------------------------------------------------------------- // + +// ---------------------------------------------------------------- // +// dtor/ctors +// ---------------------------------------------------------------- // + +TextControlFloater::~TextControlFloater() { + if(m_cancelMessage) + delete m_cancelMessage; +} + +TextControlFloater::TextControlFloater( + BRect frame, + alignment align, + const BFont* font, + const char* text, + const BMessenger& target, + BMessage* message, + BMessage* cancelMessage) : + BWindow( + frame, //.InsetBySelf(-3.0,-3.0), // expand frame to counteract control border + "TextControlFloater", + B_NO_BORDER_WINDOW_LOOK, + B_FLOATING_APP_WINDOW_FEEL, + 0), + m_target(target), + m_message(message), + m_cancelMessage(cancelMessage), + m_sentUpdate(false) { + + m_control = new MomentaryTextControl( + Bounds(), + "textControl", + 0, + text, + message, + B_FOLLOW_NONE); + + Run(); + Lock(); + + m_control->TextView()->SetFontAndColor(font); + m_control->TextView()->SetAlignment(align); + m_control->SetDivider(-3.0); + + m_control->SetViewColor(B_TRANSPARENT_COLOR); + m_control->TextView()->SelectAll(); + AddChild(m_control); + m_control->MakeFocus(); + + Unlock(); +} + +// ---------------------------------------------------------------- // +// BWindow +// ---------------------------------------------------------------- // + +void TextControlFloater::WindowActivated( + bool activated) { + + if(!activated) + // +++++ will the message get sent first? + Quit(); +} + +// ---------------------------------------------------------------- // +// BHandler +// ---------------------------------------------------------------- // + +void TextControlFloater::MessageReceived( + BMessage* message) { + + if(message->what == m_message->what) { + // done; relay message to final target + message->AddString("_value", m_control->TextView()->Text()); + m_target.SendMessage(message); + m_sentUpdate = true; + Quit(); + return; + } + + switch(message->what) { + default: + _inherited::MessageReceived(message); + } +} + +bool TextControlFloater::QuitRequested() { + if(!m_sentUpdate && m_cancelMessage) + m_target.SendMessage(m_cancelMessage); + + return true; +} + +// END -- TextControlFloater.cpp -- diff --git a/sources-experimental/TextControlFloater.h b/sources-experimental/TextControlFloater.h new file mode 100644 index 0000000..851de11 --- /dev/null +++ b/sources-experimental/TextControlFloater.h @@ -0,0 +1,64 @@ +// TextControlFloater.h +// * PURPOSE +// Display an editable text field in a simple pop-up window +// (which must automatically close when the user hits 'enter' +// or the window loses focus). +// * TO DO +++++ +// escape key -> cancel +// +// * HISTORY +// e.moon 23aug99 Begun + +#ifndef __TextControlFloater_H__ +#define __TextControlFloater_H__ + +#include +#include + +class BTextControl; +class BFont; + +//#include "cortex_defs.h" + + +class TextControlFloater : + public BWindow { + typedef BWindow _inherited; + +public: // dtor/ctors + virtual ~TextControlFloater(); + + TextControlFloater( + BRect frame, + alignment align, + const BFont* font, + const char* text, + const BMessenger& target, + BMessage* message, + BMessage* cancelMessage=0); + +public: // BWindow + virtual void WindowActivated( + bool activated); + + virtual bool QuitRequested(); + +public: // BHandler + virtual void MessageReceived( + BMessage* message); + +private: + BTextControl* m_control; + + BMessenger m_target; + const BMessage* m_message; + BMessage* m_cancelMessage; + + // true if a message has been sent indicating the + // user modified the text + bool m_sentUpdate; +}; + + +#endif /*__TextControlFloater_H__*/ + diff --git a/sources-experimental/TheApp.cpp b/sources-experimental/TheApp.cpp new file mode 100644 index 0000000..a372994 --- /dev/null +++ b/sources-experimental/TheApp.cpp @@ -0,0 +1,483 @@ +#include "TheApp.h" +#include "FilePanel.h" + +#include +#include + +#include "owner.h" +#include "Logger.h" + +#include +#include +#include +#include +#include "BPLocale.h" + + +#include "BPAlert.h" +#include "Utils.h" +#include "RVAction.h" + +#include "Setting.h" +#include "BPSettingsWindow.h" +//#include "LicenceInfo.h" +#include "MainModel.h" +#include "HelpViewer.h" +#include "AttributeMap.h" +#include "InterfaceDefs.h" + + +#include "IActionManagerBP.h" +#include "ActionHTTPContent.h" +#include +#include "DownloadManager.h" + +extern DownloadManager* download_manager; + + +#define UPDATE_INFO 'updt' +#define CHECK_UPDATE 'ckup' + +MainWindow* main_window; +IActionManagerBP action_manager; +Setting podder_settings("BePodder.conf"); +//LicenceInfo linfo("BePodder.key"); + + +TheApp::TheApp(const char * signature) : + BApplication(signature) +{ + //load settings from disk: + podder_settings.Retrive(); + + InstallMimeTypes(); + + MainModel *fModel = new MainModel(); + main_window=new MainWindow(); + fController = new MainController(main_window,fModel); + + action_manager.init(fController,main_window); + + main_window->init(fController); +} + +void +TheApp::ReadyToRun(){ + +// linfo.LoadFromFile(); + + ApplySettings(); + ApplyWindowSettings(); + + main_window->Show(); + snooze(200000); + +// BMessage grp; +// if( podder_settings.FindMessage(SETTINGS_GROUPS,&grp) == B_OK) +// if(main_window->Lock()){ +// fController->LoadGroupSetting(&grp); +// main_window->Unlock(); +// } + + + this->PostMessage(ARCHIVE_PARSE); + + + +// we disabledupdates? + + BMessage msg; + bool val = true; + if( podder_settings.FindMessage(SETTINGS_UPDATES,&msg) == B_OK) { + if(msg.FindBool("check_updates",&val) != B_OK) val= true; + } + + if(val) + ChekUpdate(); + + + + + return; +} + +void +TheApp::ChekUpdate() { + + /************ + + CHECKING UPDATE IS DISABLED. + + ********/ + + return; + + //uhm check for update? + printf("Checking for updates..\n"); + ActionHTTPContent* update=new ActionHTTPContent("http://www.funkyideasoft.com/latest.nfo"); + update->SetTargetAndWhat(this,UPDATE_INFO); + download_manager->SingleThreadAction(update); +} + +void +TheApp::AboutRequested(){ + + BString text("\nBePodder"); + text <<"\n\nDevelopers:\n\tAndrea Anzani [xeD]\n\tGiuseppe Gargaro [Beck]\n\nGraphic:\n\tzuMi\n\n\n"; + text << "Version : " << VERSION_NAME << " " << VERSION_ID << "\n"; + + BPAlert* about = new BPAlert("about", text.String() ,_T("Close!"),NULL,NULL,B_WIDTH_AS_USUAL,LoadIcon("logo-64.png")); + about->Go(); +} + +bool +TheApp::QuitRequested(){ + + + if(main_window->Lock()){ + + fController->QuitRequested(); + + BMessage data; + main_window->SaveSetting(&data); + podder_settings.RemoveData(SETTINGS_MAINWINDOW); + podder_settings.AddMessage(SETTINGS_MAINWINDOW,&data); + + main_window->Quit(); + } + podder_settings.Store(); + return true; +} + +void +TheApp::ArgvReceived(int32 argc, char **argv){ + + // debugger("ARGV"); + + if(argc<2) return; + + main_window->Activate(); + + BMessage msg('addu'); + msg.AddString("url",argv[1]); + BMessenger(main_window).SendMessage(&msg); +} + + +void +TheApp::MessageReceived(BMessage* msg){ + + //B_ARGV_RECEIVED + + switch(msg->what){ + + case CHECK_UPDATE: + ChekUpdate(); + break; + case UPDATE_INFO: + { + BString rel; + if(msg->FindString("content",&rel)==B_OK && rel != "" && rel.Compare(VERSION_ID) != 0) + { + //FIX da tradurre! + BString text("A new release of this application is available!\n\n Your version : "); + text << VERSION_ID << "\n\n" << "Latest available version : " << rel ; + text << "\n\nGo to our web site and download the latest version!\n" ; + + BPAlert *alert = new BPAlert("BePodder",text.String(),_T("Web Site"),_T("Close"),NULL,B_WIDTH_AS_USUAL, LoadIcon("logo-64.png")); + if(alert->Go()==0) + fController->OpenURL("http://www.funkyideasoft.com/downloads.html"); + } + } + break; + case PERFORM_ACTION: + action_manager.Perform(msg); + break; + case ARCHIVE_PARSE: + { + //show the alert + BPAlert *alert = new BPAlert("BePodder",_TT("alert3"),NULL,NULL,NULL,B_WIDTH_AS_USUAL, LoadIcon("enqueued-32.png")); + alert->Go(NULL); + + + fController->ParseArchive(); + + main_window->SelectSubscription(0); + //close the alert + alert->PostMessage(B_QUIT_REQUESTED); + + } + break; + case APPLY_SETTINGS: + ApplySettings(); + break; + case 'lic2': + { + + BPAlert* about = new BPAlert("Sorry", _T("Shareware application!\n\nPlease support us!\n\nBuy a software licence!\nMore info on our website\n"),_T("Web Site"),_T("Close"),NULL,B_WIDTH_AS_USUAL,LoadIcon("logo-64.png")); + if(about->Go()==0){ + fController->OpenURL("http://www.funkyideasoft.com/bepodder.html"); + } + + } + break; + case HELPVIEWER_OPEN_URL: + { + BString url; + if(msg->FindString("url",&url)==B_OK){ + if(fController) + fController->OpenURL(url); + } + } + break; + default: + BApplication::MessageReceived(msg); + break; + } +} + +void +TheApp::ApplySettings(){ + + BMessage msg; + + msg.MakeEmpty(); + if( podder_settings.FindMessage(SETTINGS_DOWNLOAD,&msg) == B_OK) + fController->LoadSettings(SETTINGS_DOWNLOAD,&msg); + + msg.MakeEmpty(); + if( podder_settings.FindMessage(SETTINGS_PROXY,&msg) == B_OK) + fController->LoadSettings(SETTINGS_PROXY,&msg); + + + msg.MakeEmpty(); + if( podder_settings.FindMessage(SETTINGS_FILETYPE,&msg) == B_OK) + fController->LoadSettings(SETTINGS_FILETYPE,&msg); + + + msg.MakeEmpty(); + if( podder_settings.FindMessage(SETTINGS_CHANNELS,&msg) == B_OK) + fController->LoadSettings(SETTINGS_CHANNELS,&msg); +} + +void +TheApp::ApplyWindowSettings(){ + + BMessage msg; + if( podder_settings.FindMessage(SETTINGS_MAINWINDOW,&msg) == B_OK) + if(main_window->Lock()){ + main_window->LoadSetting(&msg); + main_window->Unlock(); + } +} + + +void +TheApp::InstallMimeTypes(){ + + BMimeType channel(MIME_CHANNEL); + + if (channel.IsInstalled()) { + BMessage info; + BString revision; + if( channel.GetAttrInfo(&info) == B_OK && info.FindString("revision",&revision)==B_OK && revision.ICompare("1.2")==0) + return; + + + channel.Delete(); + } + + printf("Installing Channel MimeType..\n"); + + channel.SetShortDescription("BePodder Channel"); + + BMessage achannel; + + achannel.AddString("attr:name","bp:title"); + achannel.AddString("attr:public_name","Title"); + achannel.AddInt32("attr:type",B_STRING_TYPE); + achannel.AddInt32("attr:width",30); + achannel.AddInt32("attr:alignment",B_ALIGN_LEFT); + achannel.AddBool("attr:extra",false); + achannel.AddBool("attr:viewable",true); + achannel.AddBool("attr:editable",false); + + achannel.AddString("attr:name","bp:link"); + achannel.AddString("attr:public_name","Feed Link"); + achannel.AddInt32("attr:type",B_STRING_TYPE); + achannel.AddInt32("attr:width",30); + achannel.AddInt32("attr:alignment",B_ALIGN_LEFT); + achannel.AddBool("attr:extra",false); + achannel.AddBool("attr:viewable",true); + achannel.AddBool("attr:editable",false); + + achannel.AddString("attr:name","bp:category"); + achannel.AddString("attr:public_name","Category"); + achannel.AddInt32("attr:type",B_STRING_TYPE); + achannel.AddInt32("attr:width",30); + achannel.AddInt32("attr:alignment",B_ALIGN_LEFT); + achannel.AddBool("attr:extra",false); + achannel.AddBool("attr:viewable",true); + achannel.AddBool("attr:editable",false); + + achannel.AddString("attr:name","bp:weblink"); + achannel.AddString("attr:public_name","Website"); + achannel.AddInt32("attr:type",B_STRING_TYPE); + achannel.AddInt32("attr:width",30); + achannel.AddInt32("attr:alignment",B_ALIGN_LEFT); + achannel.AddBool("attr:extra",false); + achannel.AddBool("attr:viewable",true); + achannel.AddBool("attr:editable",false); + +// achannel.AddString("revision","1.2"); + + channel.SetAttrInfo(&achannel); + + if(channel.Install()!=B_OK) + printf("Error Installing!\n"); + + + BMimeType item(MIME_ITEM); + + if (item.IsInstalled()) { + BMessage info; + BString revision; + if( item.GetAttrInfo(&info) == B_OK && info.FindString("revision",&revision)==B_OK && revision.ICompare("1.2")==0) + return; + + item.Delete(); + } + + printf("Installing Item MimeType..\n"); + + item.SetShortDescription("BePodder Episode"); + + + BMessage aitem; + + aitem.AddString("attr:name","bp:item_title"); + aitem.AddString("attr:public_name","Title"); + aitem.AddInt32("attr:type",B_STRING_TYPE); + aitem.AddInt32("attr:width",30); + aitem.AddInt32("attr:alignment",B_ALIGN_LEFT); + aitem.AddBool("attr:extra",false); + aitem.AddBool("attr:viewable",true); + aitem.AddBool("attr:editable",false); + + aitem.AddString("attr:name","bp:item_pubdate"); + aitem.AddString("attr:public_name","Published"); + aitem.AddInt32("attr:type",B_TIME_TYPE); + aitem.AddInt32("attr:width",30); + aitem.AddInt32("attr:alignment",B_ALIGN_LEFT); + aitem.AddBool("attr:extra",false); + aitem.AddBool("attr:viewable",true); + aitem.AddBool("attr:editable",false); + + aitem.AddString("attr:name","bp:item_guid"); + aitem.AddString("attr:public_name","Guid"); + aitem.AddInt32("attr:type",B_STRING_TYPE); + aitem.AddInt32("attr:width",30); + aitem.AddInt32("attr:alignment",B_ALIGN_LEFT); + aitem.AddBool("attr:extra",false); + aitem.AddBool("attr:viewable",true); + aitem.AddBool("attr:editable",false); + + aitem.AddString("attr:name","bp:enclosure_size"); + aitem.AddString("attr:public_name","Enclosure Size"); + aitem.AddInt32("attr:type",B_OFF_T_TYPE); + aitem.AddInt32("attr:width",30); + aitem.AddInt32("attr:alignment",B_ALIGN_RIGHT); + aitem.AddBool("attr:extra",false); + aitem.AddBool("attr:viewable",true); + aitem.AddBool("attr:editable",false); + + aitem.AddString("attr:name","bp:item_status"); + aitem.AddString("attr:public_name","Status"); + aitem.AddInt32("attr:type",B_INT32_TYPE); + aitem.AddInt32("attr:width",30); + aitem.AddInt32("attr:alignment",B_ALIGN_CENTER); + aitem.AddBool("attr:extra",false); + aitem.AddBool("attr:viewable",true); + aitem.AddBool("attr:editable",false); + + aitem.AddString("attr:name","bp:enclosure_url"); + aitem.AddString("attr:public_name","Enclosure URL"); + aitem.AddInt32("attr:type",B_STRING_TYPE); + aitem.AddInt32("attr:width",30); + aitem.AddInt32("attr:alignment",B_ALIGN_LEFT); + aitem.AddBool("attr:extra",false); + aitem.AddBool("attr:viewable",true); + aitem.AddBool("attr:editable",false); + + aitem.AddString("attr:name","bp:enclosure_path"); + aitem.AddString("attr:public_name","Enclosure Path"); + aitem.AddInt32("attr:type",B_STRING_TYPE); + aitem.AddInt32("attr:width",30); + aitem.AddInt32("attr:alignment",B_ALIGN_LEFT); + aitem.AddBool("attr:extra",false); + aitem.AddBool("attr:viewable",true); + aitem.AddBool("attr:editable",false); + + aitem.AddString("attr:name","bp:item_link"); + aitem.AddString("attr:public_name","Link"); + aitem.AddInt32("attr:type",B_STRING_TYPE); + aitem.AddInt32("attr:width",30); + aitem.AddInt32("attr:alignment",B_ALIGN_LEFT); + aitem.AddBool("attr:extra",false); + aitem.AddBool("attr:viewable",true); + aitem.AddBool("attr:editable",false); + + aitem.AddString("attr:name","bp:category"); + aitem.AddString("attr:public_name","Category"); + aitem.AddInt32("attr:type",B_STRING_TYPE); + aitem.AddInt32("attr:width",30); + aitem.AddInt32("attr:alignment",B_ALIGN_LEFT); + aitem.AddBool("attr:extra",false); + aitem.AddBool("attr:viewable",true); + aitem.AddBool("attr:editable",false); + + aitem.AddString("attr:name","bp:item_keywords"); + aitem.AddString("attr:public_name","Keywords"); + aitem.AddInt32("attr:type",B_STRING_TYPE); + aitem.AddInt32("attr:width",30); + aitem.AddInt32("attr:alignment",B_ALIGN_LEFT); + aitem.AddBool("attr:extra",false); + aitem.AddBool("attr:viewable",true); + aitem.AddBool("attr:editable",false); + + aitem.AddString("attr:name","bp:enclosure_type"); + aitem.AddString("attr:public_name","Enclosure Type"); + aitem.AddInt32("attr:type",B_STRING_TYPE); + aitem.AddInt32("attr:width",30); + aitem.AddInt32("attr:alignment",B_ALIGN_LEFT); + aitem.AddBool("attr:extra",false); + aitem.AddBool("attr:viewable",true); + aitem.AddBool("attr:editable",false); + +// aitem.AddString("revision","1.2"); + + item.SetAttrInfo(&aitem); + if(item.Install()!=B_OK) + printf("Error Installing!\n"); + + BMimeType ch(MIME_ARCHIVED_CHANNEL); + + if (ch.IsInstalled()) { + BMessage info; + BString revision; + if( ch.GetAttrInfo(&info) == B_OK && info.FindString("revision",&revision)==B_OK && revision.ICompare("1.2")==0) + return; + ch.Delete(); + } + + printf("Installing Archived Channel MimeType..\n"); + + ch.SetShortDescription("BePodder Archived Channel"); + + BMessage ach; +// ach.AddString("revision","1.2"); + + ch.SetAttrInfo(&ach); + if(ch.Install()!=B_OK) + printf("Error Installing!\n"); +} diff --git a/sources-experimental/TheApp.h b/sources-experimental/TheApp.h new file mode 100644 index 0000000..2c7bae6 --- /dev/null +++ b/sources-experimental/TheApp.h @@ -0,0 +1,31 @@ +#include + +#include "MainWindow.h" +#include "MainController.h" + +class TheApp : public BApplication { + +public: + TheApp(const char * signature); + + void MessageReceived(BMessage*); + void ArgvReceived(int32 argc, char **argv) ; + + void AboutRequested(); + void ReadyToRun(); + bool QuitRequested(); + + void ChekUpdate(); + +private: + + void InstallMimeTypes(); + + + void ApplySettings(); + void ApplyWindowSettings(); + + MainController* fController; + + +}; diff --git a/sources-experimental/TitleTextRender.cpp b/sources-experimental/TitleTextRender.cpp new file mode 100644 index 0000000..0ff589e --- /dev/null +++ b/sources-experimental/TitleTextRender.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#include "TitleTextRender.h" + + +TitleTextRender::TitleTextRender(){ + fFont = *be_bold_font; + +}; + +TitleTextRender::TitleTextRender(BFont font){ + fFont = font; + +}; + +TitleTextRender::~TitleTextRender(){ +} + +void +TitleTextRender::Render(BView *target,const char* txt,int16 num,BPoint pos,BRect r){ + target->SetFont(&fFont); + target->DrawString(txt,num,pos); + target->StrokeLine(pos + BPoint(0,1) , pos + BPoint(fFont.StringWidth(txt),1),B_MIXED_COLORS); +} + +void +TitleTextRender::GetHeight(font_height *height){ + fFont.GetHeight(height); + height->ascent += 5; + height->descent +=5; +} + +void +TitleTextRender::GetEscapements(const char charArray[], int32 numChars,float escapementArray[]){ + fFont.GetEscapements(charArray,numChars,escapementArray); +} + +float +TitleTextRender::Size(float maxwidth){ + return fFont.Size(); +} diff --git a/sources-experimental/TitleTextRender.h b/sources-experimental/TitleTextRender.h new file mode 100644 index 0000000..ad7030e --- /dev/null +++ b/sources-experimental/TitleTextRender.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + + +#ifndef _TitleTextRender_H_ +#define _TitleTextRender_H_ + +#include +#include +#include "TextRender.h" + +class TitleTextRender : public TextRender +{ + public: + TitleTextRender(); + TitleTextRender(BFont font); + virtual ~TitleTextRender(); + + void Render(BView *target,const char*,int16 num,BPoint pos,BRect r); + void GetHeight(font_height *height); + void GetEscapements(const char charArray[], int32 numChars,float escapementArray[]); + float Size(float maxwidth); + + // + + private: + BFont fFont; +}; +#endif diff --git a/sources-experimental/XMLChannelExtractor.cpp b/sources-experimental/XMLChannelExtractor.cpp new file mode 100644 index 0000000..d2d583d --- /dev/null +++ b/sources-experimental/XMLChannelExtractor.cpp @@ -0,0 +1,286 @@ +#include "XMLChannelExtractor.h" + +#include "libxml/tree.h" +#include "libxml/xpath.h" +#include "libxml/xpathInternals.h" +#include "libxml/parserInternals.h" +#include "libxml/debugXML.h" + +#include "RssItem.h" + +#include "curl/curl.h" + +#include "MemoryArchive.h" + +//#define CHANNEL_QUERY "/rss/channel" +#define CHANNEL_QUERY "//*[local-name()='channel']" + +#define FEED_QUERY "//*[local-name()='feed']" + +//#define ITEM_QUERY "/rss/channel/item" +//#define ITEM_QUERY "//*[local-name()='item']" +//#define ENTRY_QUERY "//*[local-name()='entry']" + + +#define START_QUERY "//*[local-name()='" +#define END_QUERY "']" + +BList* +XMLChannelExtractor::Parse(BString filename){ + + BList* list=NULL; + + xmlParserCtxtPtr ctxt = xmlNewParserCtxt(); + xmlDocPtr doc = xmlCtxtReadFile(ctxt, filename.String(), NULL, XML_PARSE_RECOVER|XML_PARSE_NOBLANKS|XML_PARSE_NOCDATA); + xmlXPathContextPtr pathCtxt = xmlXPathNewContext(doc); + + BString elementType("item"); + + //testing code! + { + xmlXPathObjectPtr itemNode = xmlXPathEvalExpression((const xmlChar *)CHANNEL_QUERY, pathCtxt); + if (itemNode == NULL) { + xmlFreeParserCtxt(ctxt); + xmlXPathFreeContext(pathCtxt); + xmlXPathFreeObject(itemNode); + return NULL; + }; + //only one channel per rss file! + if(itemNode->nodesetval == NULL || itemNode->nodesetval->nodeNr !=1){ + //we can try to search for a 'feed' + xmlXPathFreeObject(itemNode); + itemNode = xmlXPathEvalExpression((const xmlChar *)FEED_QUERY, pathCtxt); + if (itemNode == NULL) { + xmlFreeParserCtxt(ctxt); + xmlXPathFreeContext(pathCtxt); + xmlXPathFreeObject(itemNode); + return NULL; + }; + if(itemNode->nodesetval == NULL || itemNode->nodesetval->nodeNr !=1){ + xmlFreeParserCtxt(ctxt); + xmlXPathFreeContext(pathCtxt); + xmlXPathFreeObject(itemNode); + return NULL; + } + elementType.SetTo("entry"); + + }; + + ParseChannel(itemNode->nodesetval->nodeTab[0]->children,elementType); + + /* + Testing code. + + */ + + //parsing the channel's attributes.. + + + + } + + BString elementQuery(START_QUERY); + elementQuery << elementType << END_QUERY; + + if (pathCtxt != NULL) { + xmlXPathObjectPtr itemNode = xmlXPathEvalExpression((const xmlChar *)elementQuery.String(), pathCtxt); + if (itemNode == NULL) { + xmlFreeParserCtxt(ctxt); + xmlXPathFreeContext(pathCtxt); + xmlXPathFreeObject(itemNode); + return NULL; + }; + + xmlNodeSetPtr items = itemNode->nodesetval; + if (items == NULL) { + xmlFreeParserCtxt(ctxt); + xmlXPathFreeContext(pathCtxt); + xmlXPathFreeObject(itemNode); + return NULL; + }; + + + + list=new BList(items->nodeNr); + + for (int32 i = 0; i < items->nodeNr; i++) { + + MemoryArchive *ma=new MemoryArchive(); + + RssItem rss; + rss.AddElementListener(ma); + + fItemExtractor.SetNotifier(&rss); + fItemExtractor.Parse(items->nodeTab[i]->children); + + rss.SetFileStatus(NEW); + + + if( rss.Guid() != "" ) + list->AddItem((void*)ma); + else + if( rss.EnclosureLink() != "") { + rss.SetGuid(rss.EnclosureLink().String()); + list->AddItem((void*)ma); + } + else + if( ma->GetDataString(ITEM_LINK) !=""){ + rss.SetGuid(ma->GetDataString(ITEM_LINK).String()); + list->AddItem((void*)ma); + } + else + if(ma->GetDataString(ITEM_PUBDATE) !=""){ + rss.SetGuid(ma->GetDataString(ITEM_PUBDATE) .String()); + list->AddItem((void*)ma,0); + } + else + { + rss.RemoveElementListener(ma); + delete ma; //! + ma = NULL; + } + + //post process fixes: + + if(ma) { + if(ma->GetDataString(ITEM_PUBDATE) =="") { + //if no data, add the now date! + time_t when = real_time_clock() - i; + ma->SetKey(ITEM_PUBDATE,(void*)&when,(ssize_t)sizeof(time_t)); + } + if(ma->GetDataString(ITEM_LINK) == ma->GetDataString(ITEM_ENCLOSURE_URL)){ + ma->SetKeyString(ITEM_LINK,""); + } + if(ma->GetDataString(ITEM_TITLE) == "" && ma->GetDataString(ITEM_ENCLOSURE_LOCALPATH) != ""){ + ma->SetKeyString(ITEM_TITLE,ma->GetDataString(ITEM_ENCLOSURE_LOCALPATH).String()); + } + if(ma->GetDataString(ITEM_DESCRIPTION) == "" && ma->GetDataString(ITEM_SUMMARY) != ""){ + ma->SetKeyString(ITEM_DESCRIPTION,ma->GetDataString(ITEM_SUMMARY).String()); + } + } + + rss.RemoveElementListener(ma); + } + xmlXPathFreeObject(itemNode); + }; + + xmlFreeParserCtxt(ctxt); + xmlXPathFreeContext(pathCtxt); + + return list; +} + + +int +XMLChannelExtractor::ParseChannel(xmlNodePtr node,BString leaf){ + + xmlNode *cur_node = NULL; + BString currentCategory(""); + + for (cur_node = node; cur_node; cur_node = cur_node->next) { + if (cur_node->type == XML_ELEMENT_NODE) { + + // printf("ParseChannel type: Element, name: %s %s\n", cur_node->name,cur_node->content); + + BString bname((const char*)cur_node->name); + + if (cur_node->children && (cur_node->children->type == XML_TEXT_NODE || cur_node->children->type == XML_CDATA_SECTION_NODE) ) { + + //text element.. + if(bname.ICompare("title") == 0){ + BString title((const char*)cur_node->children->content); + title.RemoveAll("\n"); + NotifyString(CHANNEL_TITLE,title.String()); + } + else + if(bname.ICompare("link") == 0){ + NotifyString(CHANNEL_WEBLINK,(const char*)cur_node->children->content); + } + + else if(bname.ICompare("description") == 0 && cur_node->children != NULL){ + NotifyString(CHANNEL_DESCRIPTION,(const char*)cur_node->children->content); + } + + /* + else if(bname.ICompare("link") == 0){ + NotifyString(,(const char*)cur_node->children->content); + } + else if(bname.ICompare("pubDate") == 0){ + time_t when = curl_getdate((const char*)cur_node->children->content,NULL); + NotifyNotifier(,(void*)&when,sizeof(time_t)); + } + */ + } + + //non text element like only attributes or sub-elemnt(not handled) + { + if(bname.ICompare("image") == 0) + { + _parseImage(cur_node); + }//end - image + else + if(bname.ICompare("category") == 0){ + + BString cat =XMLItemExtractor::_parseCategory(cur_node); + if(cat != "") + currentCategory << " " << cat; //NotifyNotifier(CHANNEL_CATEGORY,(void*)cat.String(),cat.Length()); + } + else + if(bname.ICompare(leaf) == 0) + goto finished; + + } + + } + } + + finished: + if(currentCategory != "") + NotifyNotifier(CHANNEL_CATEGORY,(void*)currentCategory.String(),currentCategory.Length()); + return 0; +} + +void +XMLChannelExtractor::_parseImage(xmlNode* cur_node){ + + xmlAttr *attr = cur_node->properties; + + xmlAttr *cur_attr = NULL; + for (cur_attr = attr; cur_attr; cur_attr = cur_attr->next) { + + BString battr((const char*)cur_attr->name); + + if(battr.ICompare("href") == 0) + { + xmlNodePtr node = cur_attr->children; + //if(node) printf("value %s \n",node->content); + + BString imageURL ; + imageURL << (const char*)node->content; + + NotifyNotifier(CHANNEL_IMAGE_URL,(void*)imageURL.String(),imageURL.Length()); + return; + + } + } //end of for. + + + xmlNode *sub_node = NULL; + if(!cur_node->children) return; + + for (sub_node = cur_node->children; sub_node; sub_node = sub_node->next) { + BString sub_name((const char*)sub_node->name); + if(sub_name.ICompare("url") == 0 ){ + if (sub_node->children && sub_node->children->type == XML_TEXT_NODE){ + //save the url! + BString imageURL ; + imageURL << (const char*)sub_node->children->content; + NotifyNotifier(CHANNEL_IMAGE_URL,(void*)imageURL.String(),imageURL.Length()); + return; + } + } + }// end sub_image! +} + + + diff --git a/sources-experimental/XMLChannelExtractor.h b/sources-experimental/XMLChannelExtractor.h new file mode 100644 index 0000000..482a7d0 --- /dev/null +++ b/sources-experimental/XMLChannelExtractor.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef XMLChannelExtractor_H_ +#define XMLChannelExtractor_H_ + +#include "Extractor.h" +#include "XMLItemExtractor.h" + + +class MemoryArchive; + +class XMLChannelExtractor : public Extractor +{ + + public: + BList* Parse(BString filename); + + private: + XMLItemExtractor fItemExtractor; + int ParseChannel(xmlNodePtr node,BString leaf); + void _parseImage(xmlNodePtr node); +}; +#endif diff --git a/sources-experimental/XMLItemExtractor.cpp b/sources-experimental/XMLItemExtractor.cpp new file mode 100644 index 0000000..9ddf6dd --- /dev/null +++ b/sources-experimental/XMLItemExtractor.cpp @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + + +#include "XMLItemExtractor.h" +#include "curl/curl.h" +#include "FileStatus.h" + + +int +XMLItemExtractor::Parse(xmlNodePtr node){ + + xmlNode *cur_node = NULL; + BString currentCategory(""); + + for (cur_node = node; cur_node; cur_node = cur_node->next) { + if (cur_node->type == XML_ELEMENT_NODE) { + //printf("node type: Element, name: %s %s\n", cur_node->name,cur_node->content); + + BString bname((const char*)cur_node->name); + + if (cur_node->children && (cur_node->children->type == XML_TEXT_NODE || cur_node->children->type == XML_CDATA_SECTION_NODE) ) { + + //text elemnt. + if(bname.ICompare("title") == 0){ + NotifyString(ITEM_TITLE,(const char*)xmlNodeGetContent(cur_node->children)); + } + else if(bname.ICompare("guid") == 0){ + NotifyString(ITEM_GUID,(const char*)cur_node->children->content); + } + else if(bname.ICompare("id") == 0){ //ATOM 0.3 support... + NotifyString(ITEM_GUID,(const char*)cur_node->children->content); + } + else if(bname.ICompare("link") == 0){ + NotifyString(ITEM_LINK,(const char*)cur_node->children->content); + } + else if(bname.ICompare("pubDate") == 0){ + time_t when = curl_getdate((const char*)cur_node->children->content,NULL); + if(when < 0){ + //? not rfc822 ?? + } + NotifyNotifier(ITEM_PUBDATE,(void*)&when,sizeof(time_t)); + } + else if(bname.ICompare("keywords") == 0){ + NotifyString(ITEM_KEYWORDS,(const char*)cur_node->children->content); + } + } + + + if(bname.ICompare("description") == 0 && cur_node->children != NULL){ + NotifyString(ITEM_DESCRIPTION,(const char*)cur_node->children->content); + } + else + if(bname.ICompare("summary") == 0 && cur_node->children != NULL){ + NotifyString(ITEM_SUMMARY,(const char*)cur_node->children->content); + } + + + { + //non text elemnt like only attributes or sub-elemnt(not handled) + if(bname.ICompare("enclosure") == 0){ + + // managing the enclosure: + // FIX + NotifyInt32(ITEM_ENCLOSURE_FILE_STATUS,NOT_DOWNLOADED); + xmlAttr *attr = cur_node->properties; + + + + xmlAttr *cur_attr = NULL; + for (cur_attr = attr; cur_attr; cur_attr = cur_attr->next) { + + BString battr((const char*)cur_attr->name); + //printf("attr url (%ld): %s\n",i,attr->name ); + + if(battr.ICompare("url") == 0){ + xmlNodePtr node = cur_attr->children; + //if(node) printf("value %s \n",node->content); + + BString imageURL ; //= GetNodeContents(node); + imageURL << (const char*)node->content; + imageURL.RemoveAll("\n"); + + BString leaf(imageURL.String()); + int32 last_pos = leaf.FindLast("/"); + + leaf.Remove(0,last_pos+1); + + //printf("outut name: [%s]\n",leaf.String()); + + NotifyNotifier(ITEM_ENCLOSURE_URL,(void*)imageURL.String(),imageURL.Length()); + NotifyNotifier(ITEM_ENCLOSURE_LOCALPATH,(void*)leaf.String(),leaf.Length()); + //fs = 0; + //NotifyNotifier(ITEM_ENCLOSURE_FILE_STATUS,&fs,sizeof(FileStatus)); + + } + else if(battr.ICompare("length") == 0){ + xmlNodePtr node = cur_attr->children; + if(node) { + //printf("size %s \n",node->content); + off_t size = atoll((const char*)node->content); + NotifyNotifier(ITEM_ENCLOSURE_LENGTH,(void*)&size,sizeof(off_t)); + } + + } + else if(battr.ICompare("type") == 0){ + xmlNodePtr node = cur_attr->children; + if(node) { + //printf("type %s \n",node->content); + NotifyString(ITEM_ENCLOSURE_TYPE,(const char*)node->content); + } + } + + } + } + else + if(bname.ICompare("category") == 0){ + BString cat =XMLItemExtractor::_parseCategory(cur_node); + if(cat != "") + currentCategory << " " << cat; + } + + continue; + } + } + } + + if(currentCategory != "") + NotifyNotifier(CHANNEL_CATEGORY,(void*)currentCategory.String(),currentCategory.Length()); + + return 0; +} + + + +BString +XMLItemExtractor::_parseCategory(xmlNode* cur_node){ + + /* + + + + */ + + //debugger("category!"); + + BString categoryString; + + categoryString = _extractCategoryText(cur_node); //TOP LEVEL CATEGORY + + if(categoryString == "") return NULL; //safety (should never happen) + + + + xmlNode *sub_node = NULL; + if(!cur_node->children) return categoryString; + + for (sub_node = cur_node->children; sub_node; sub_node = sub_node->next) { + BString sub_name((const char*)sub_node->name); + if(sub_name.ICompare("category") == 0 ){ + BString sub_category = _extractCategoryText(sub_node); + if(sub_category != ""){ + categoryString << " "; + categoryString << sub_category; + } + } + } + + //add to the archive + return categoryString; + //NotifyNotifier(CHANNEL_CATEGORY,(void*)categoryString.String(),categoryString.Length()); +} + + +BString +XMLItemExtractor::_extractCategoryText(xmlNodePtr cur_node){ + + xmlAttr *attr = cur_node->properties; + + xmlAttr *cur_attr = NULL; + for (cur_attr = attr; cur_attr; cur_attr = cur_attr->next) { + + BString battr((const char*)cur_attr->name); + + if(battr.ICompare("text") == 0) + { + xmlNodePtr node = cur_attr->children; + + BString category ; + category << (const char*)node->content; + + return category; + + } + } //end of for. + + return NULL; +} + diff --git a/sources-experimental/XMLItemExtractor.h b/sources-experimental/XMLItemExtractor.h new file mode 100644 index 0000000..63ecb51 --- /dev/null +++ b/sources-experimental/XMLItemExtractor.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2005 by Andrea Anzani + * oxygenum@tiscali.it + * +*/ + +#ifndef XMLItemExtractor_H_ +#define XMLItemExtractor_H_ + +#include "Extractor.h" + +#include "libxml/tree.h" +#include "libxml/xpath.h" +#include "libxml/xpathInternals.h" +#include "libxml/parserInternals.h" +#include "libxml/debugXML.h" + + +class XMLItemExtractor : public Extractor +{ + + public: + + int Parse(xmlNodePtr node); + + + //general purpose: + + static BString _parseCategory(xmlNodePtr node); + static BString _extractCategoryText(xmlNodePtr node); + +}; +#endif diff --git a/sources-experimental/htmlparse.cpp b/sources-experimental/htmlparse.cpp new file mode 100644 index 0000000..f8a77a4 --- /dev/null +++ b/sources-experimental/htmlparse.cpp @@ -0,0 +1,216 @@ +#include +#include +#include + +#include +#include "htmlparse.h" + +void encode_html( BString &msg ) { + // BStrings are slow and sucky, but this is real easy + msg.ReplaceAll("&","&"); + msg.ReplaceAll("\"","""); + msg.ReplaceAll("<","<"); + msg.ReplaceAll(">",">"); + + msg.ReplaceAll("[b]",""); + msg.ReplaceAll("[/b]",""); + msg.ReplaceAll("[i]",""); + msg.ReplaceAll("[/i]",""); + + msg.Prepend(""); + msg.Append(""); +} + +int +parse_html_2( char * msg, int size, char** to, int* tosize ){ + + return 0; +} + + +int parse_html( char * msg , int size ) +{ + + //-- pre parser --// + BString preparser(msg); +// preparser.ReplaceAll("\n"," "); + preparser.ReplaceAll("\r"," "); + preparser.ReplaceAll("\t"," "); + preparser.ReplaceAll("à","à"); //should be illegal! + preparser.ReplaceAll("è","è"); //should be illegal! + preparser.ReplaceAll(" "," "); //should be illegal! + preparser.ReplaceAll("&","&"); + preparser.ReplaceAll(""","\""); + preparser.ReplaceAll(">",">"); + preparser.ReplaceAll("<","<"); + preparser.ReplaceAll("'","'"); + preparser.CopyInto(msg,0,preparser.Length()); + size = preparser.Length(); + //------------------// + + if(msg[size]!='\0') msg[size]='\0'; + + bool is_in_tag = false; + bool is_newline = true; + bool is_last_space = false; + int copy_pos = 0; + + char * copy = new char[size + 1]; + + memset(copy,'\0',size + 1); + + + for ( int i=0; msg[i]; i++ ) + { + switch ( msg[i] ) + { + case ' ': + if(!is_newline && !is_last_space) { + copy[copy_pos++] = msg[i]; + is_last_space=true; + } + + break; + + case '\n': + is_newline = true; + is_last_space=false; + copy[copy_pos++] = ' '; + break; + case '<': + is_last_space=false; + is_in_tag = true; + /*for (int j = i+1; msg[j]; j++) { + if (isspace(msg[j])) continue; + else if (tolower(msg[j]) == 'a') { + copy[copy_pos++] = '['; + copy[copy_pos++] = ' '; + for (; msg[j] && msg[j] != '='; j++); j++; + for (; msg[j] && isspace(msg[j]); j++); + if (msg[j] == '\"') j++; + for (; msg[j] && !isspace(msg[j]) && msg[j] != '\"'; j++) + copy[copy_pos++] = msg[j]; + copy[copy_pos++] = ' '; + copy[copy_pos++] = ']'; + copy[copy_pos++] = ' '; + } else break; + } + */ + //while( + is_newline = false; + break; + case '>': + is_in_tag = false; + is_newline = false; + is_last_space=false; + break; + case '&': + is_newline = false; + is_last_space=false; + if (strncmp(""",&msg[i],6) == 0) { + copy[copy_pos++] = '\"'; + i += 5; + break; + } + if (strncmp("<",&msg[i],4) == 0) { + copy[copy_pos++] = '<'; + i += 3; + break; + } + if (strncmp(">",&msg[i],4) == 0) { + copy[copy_pos++] = '>'; + i += 3; + break; + } + if (strncmp("&",&msg[i],5) == 0) { + copy[copy_pos++] = '&'; + i += 4; + break; + } + if (strncmp("&#",&msg[i],2) == 0) { + + + + //test code: + + unsigned n = 0, nb, j; + char bytes[6], b0; + + /* properties of UTF-8 chars >= a given value */ + static struct { unsigned minval; int len; char byte0; } + utf8prop[] = { + { 1<<26, 6, 0xfc }, + { 1<<21, 5, 0xf8 }, + { 1<<16, 4, 0xf0 }, + { 1<<11, 3, 0xe0 }, + { 1<<7, 2, 0xc0 }, + { 0, 1, } + }; + + char* buf=msg; + + i += 2; + n = 0; + if (buf[i] == 'x' || buf[i] == 'X') { + for (i++; buf[i] != ';'; i++) { + const char *hex = "0123456789abcdef", + *hex2 = "0123456789ABCDEF"; + char *s; + int c; + if ((s = strchr(hex, buf[i]))) + c = s - hex; + else if ((s = strchr(hex2, buf[i]))) + c = s - hex2; + else + goto invalid; + + n = (n << 4) | c; + } + } + else while (isdigit(buf[i])) + n = n*10+(buf[i++] - '0'); + if (!n || n > 1<<31 || buf[i] != ';') { + invalid: + //fprintf(stderr, "bad input sequence\n"); + break; + } + /* utf-8 encoding starts here */ + if (n < 0x80) { + copy[copy_pos++] = n; + break; + } + for (j = 0; n < utf8prop[j].minval; j++) + ; + nb = utf8prop[j].len; + b0 = utf8prop[j].byte0; + + for (j = nb; j; j--) { + bytes[j-1] = (n & 0x3f) | 0x80; + n >>= 6; + } + bytes[0] |= b0; + + for (j = 0; j < nb; j++) + copy[copy_pos++] = bytes[j]; + + break; + } + default: + is_newline = false; + is_last_space=false; + if ( !is_in_tag ) + { + copy[copy_pos++] = msg[i]; + } + } + } + + copy[copy_pos] = '\0'; + + + strncpy(msg, copy,copy_pos); + + + delete copy; + return copy_pos; +} diff --git a/sources-experimental/htmlparse.h b/sources-experimental/htmlparse.h new file mode 100644 index 0000000..cb55019 --- /dev/null +++ b/sources-experimental/htmlparse.h @@ -0,0 +1,12 @@ +#ifndef IMKIT_HTML_PARSE_H +#define IMKIT_HTML_PARSE_H + +#include + +int parse_html( char * msg, int size ); + +int parse_html_2( char * msg, int size, char** to, int* tosize ); + +void encode_html( BString &msg ); + +#endif // IMKIT_HTML_PARSE_H diff --git a/sources-experimental/owner.h b/sources-experimental/owner.h new file mode 100644 index 0000000..6444f73 --- /dev/null +++ b/sources-experimental/owner.h @@ -0,0 +1,3 @@ +#define VERSION_NAME "Appcaster (ALPHA)" +#define VERSION_ID "1.3.0" +#define EMAIL "bepodder.team@gmail.com" diff --git a/xres.output.rsrc b/xres.output.rsrc new file mode 100644 index 0000000000000000000000000000000000000000..d98baac69a79b73927891297e04d3a4e56ccd3f1 GIT binary patch literal 66472 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�BC}bo?)m!f0q{YSK6iUlB%ie#oqvrAlqB5fTzw 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 Beyjih literal 0 HcmV?d00001 diff --git a/gfx/logo2.svg b/gfx/logo2.svg new file mode 100644 index 0000000..423f05c --- /dev/null +++ b/gfx/logo2.svg @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/icons/Application/bebits_logo.gif b/icons/Application/bebits_logo.gif new file mode 100644 index 0000000000000000000000000000000000000000..092b6f4c70072dcee1c9bec114dcf5a0a0f97284 GIT binary patch literal 1473 zcmchW=~L5Z6op^5CZt7!fPx6bh={36qSXOyr$KfX1hg7lXj%b99Smp{9A^wfkQ9&z z3I8$5fh1%lK=@@LZ=rugpE+}8&X;>=j@MoElmT$19)6v>aNQjaugP?jtxTLvB&LLSP)3l$NC3a287FM+hundmZQ zOu6z(g)**c=4Q3ZzYZq7oIP9*Q(w>CZJayN2s4`I9&+a+x$tSHy1ZA-h@bPKfA0?7ZOYnXt2le&*W9ajj4M7m+IZgg5Fl`f3QbbWF-q0mn$_44_} z*#*NKvN($@E@%yEtwF1Yh9w|Gp>pl)3T@Xvv%^=Q+<90}zNHs`tsnpRNe<-{=TP+U z@wm~D>!ZQ+u_N(g==d3If)brDgJmeGx5jL5DQpv!uD9i`$#No7Mr6v}ewVtX$jE6@ z-#Ze&I}&h5b2xn(q-#LB_83bX$eO0yoes?qQ!~XN+dwEY&}&pTYg7q;su;DZ+}8O= z%TizNfU#Y$q+4CwtuE_P-{^tmy$f_6tnEWy_9HC=YVN>7(;(6~h_sF%t)Db)qnh?n zO^-m^KdBp-(h7z1B9VGXtREKZN2c{ciB=@l3Z(imnf{Ah*Dr@sg-)W-O)B(4rG8Ke zhm>%52F|D#Rm&$bs5J(S&VVdQ4;LX^ddB~s^%~RvmTp=07-owi~5Pufy!cb*7yKGU|{W7l~LTmPD;U70SCAJDBGEP6KaOn0vTEZ@;O z4=wuCb@}Y}6+bYhO%w5ECFX0$2g&8uk;&#RrClV_`qsoETxCG#p5`MM8@4lj4Ck>W z#QZhi@A*%>;jQM8SMN_^BcetF2o%b7tTB&)s!3Yp;d$K*YKtR`a`sKe~cYOCxPI&WtR?dnt>&uUVlEJlJ(| zJf9i0HR4KU4%gXu$zMt8 z6`)OU#$!oVxP(D2xJseMJ9Nwi;!Ofx8F?|&ddXZoW}=j{^0cUwZi!z7&+e;2dAS@hdx8&avw4$frH_(x&y-CfvDv4O?b_JM)%wwrQsK4#Vzao%jl8`R>0 zFh`b$*|jKo+iGW4khe`3>$%zLw2TmsuTb|M`){%Y>*yX8VdXJAhZ~jk#d)#0%KhxR z@jVx+!-H7|?VEN>F4({QW?1~kaF;V0C}o_km<0DJ!hSd-;F literal 0 HcmV?d00001 diff --git a/icons/Application/bepodder-logo1.png b/icons/Application/bepodder-logo1.png new file mode 100644 index 0000000000000000000000000000000000000000..470a2399b9772bdbb56f4441b30089aad85d9d03 GIT binary patch literal 4480 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 literal 0 HcmV?d00001 diff --git a/icons/Application/bepodder_bianco.png b/icons/Application/bepodder_bianco.png new file mode 100644 index 0000000000000000000000000000000000000000..6c96246c1aa47f17c0975d86f586920ac6e2ecb2 GIT binary patch literal 2970 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 QO#lD@07*qoM6N<$g88rF;s5{u literal 0 HcmV?d00001 diff --git a/icons/Application/bp_icon.bmp b/icons/Application/bp_icon.bmp new file mode 100644 index 0000000000000000000000000000000000000000..814408a52e60460a069528627c80f5d5058063cd GIT binary patch literal 3126 zcmcJRU2Icj7{}jUm=QmcE=04D7%L`bnrKEy2wpKi67Yfmn#fRNc7q9b8*;&n31dTa zGB%hAa{PS5NA^gTU2ZHJDeHcy-X z^SuA(_rB*jr%m75yW?q+dhNhx8Qv!KZ6GC3cwv3>Q|!$OgxpNM9JQ6d?=GF#P6`r} zZxjK@$oRCsQ|vuT5-o(b7bfI30-*hEBjAqD54nyM2Agv{U>&sw?R&N)n*SHR&_dYE zv-UNY(@s-XW#dCbBieO-b~iJX-U`b5Y4@v{iq8DsMKq!vkaSlTzqdk;t?E}b+hd4q zNQR$Xe+*#ysF@ZWO6BKWmtwxUmHzNTrYoPLRbYczOCi#827i1zk-Ku|rkMNRrQS)} zZpdoXLsV^0Y%uGWa`@jVJLV1FKm*e>Fh!li{}wQW=Ch8WL#gKnAG_=7>S2ESj7q#L z%T!KM_h{BGNKvFRO(y907n#FnLsY(YY3b`q`%~9$Jwok`lv||_Ep+fhB_NQZh$a0D z^X_9V9~Mj0B4 z;f1Wp=e4hM{yYyIJ+6=uE~|PAAe7-J>118z@cE7H%CG%sISJQqa#b5288yYi$`n64 zDEgQEZ3hq#NKtgv6hE@7+892$3Gk8ENT|WMT5Hn6duA6uJEWx$!H&bA1v@@X@@q*x z3Xw_=>pf^eqrMWVHv)e96%zWg#M4mD!q>D*3O)??)M}NK*e3bzQ%O(VJ6b_4`xyR3TB2Bh40 z7uvO6U;($hL;_!x`7i88gu1Geu|VMBA(qCh7x_gi)BXzwM2}t zc0knh>oULxOvK+<9=uY8Nc?Hz#;!6QxpqR1uZ4fCW+^_SgXhJ-1If1pp%r0(4Q5v1 z#ya^$8`FWta=`naC%$iXV$)FfQJIfMuGcBLt6Ff*a1-53hs?(!y{Okn!4)awf>2WP zF}4bu=$d6Za{UCJ0iclj&+G)ecMHM9;E&lZNg*c$V(phES%^pa8dxgg`JA~4E&O#y zSQ>{wiXvN${9F$+T38B5%yt>tceVoXp67_Sc{gq!Kh-a;&O@YhpX6C&n!EG89FIhY zT9HcbdC9$?)Q4J=To_BtBf1yRu4>mTKYat*+q?&G^Jd~{*%uqRlDI!6I;SCWwc}Up ziy}WaB#Q}I`d&1v$ z3m(fS-~Z{wlHrdl2VZ|OK4Zl%KmmiBxee^_M+fm2wBy-gOW6|(HG7?H#|sk6r>X!1 YR{INWsjTcMEo~>HAaSXv2tWq^2acGZv;Y7A literal 0 HcmV?d00001 diff --git a/icons/Application/logo1.svg b/icons/Application/logo1.svg new file mode 100644 index 0000000..9d4fb0a --- /dev/null +++ b/icons/Application/logo1.svg @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/icons/Application/logo2.svg b/icons/Application/logo2.svg new file mode 100644 index 0000000..423f05c --- /dev/null +++ b/icons/Application/logo2.svg @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/icons/Application/podder.hkv b/icons/Application/podder.hkv new file mode 100644 index 0000000000000000000000000000000000000000..68a0c198d2c310bc5ed043af44ee724eac2bbc34 GIT binary patch literal 20033 zcmeHPZD<@t7~X4o`MO@3+FGwwbQLUCXkwElN@y>)+mE2eTxo(RD&)Lua%(TQ$L{tk z6p8xNf+&cVh(9cqwhBV~L&&dIsn%Ah;-7~8QLxbdsGdb7*g$;W+3Zg4W^cV*R*zg~ zVB6W*XJ+TwdFGvWJ}&)c!c+}YO&X1xHW}ujv?3Zx(p0sKXsBaKm)OzSDAF*ZCx%od zV;WszdwZj3--@Q5$QZ+#J_--owm?yvvI#R)P}G)=$MGepM7HoHZSWSzV`^q1-8!TW z4=XynM9gX`dDZ48+FLueG|It&zTNV2K@dc^>d8}4&9qLYL9We^F<-@^&i^^sbvsHM37YP z;)V&SuX9R5CP!MjECx2j;q8f{JQ)~P9t*>3J}*~RfWhDouTM@rDqq}iFKMCTygX5q z7Xzytujc5%7*@x-y*yEr7XzytFVtXP=kx!<%M(R;F|cxYT?Z}B^{?v~$Kch!_RsaN z8o)*1vijH0Z>*GR#TD{P<`2@bH(TUqwYBnrD}vR}Y^c-EN+t+zi8ejFHbU1fT znn<6P)Eif&&y4qr@GS{V`4)wj!`ENCdZc9%`>Vy1882*u>58KK7+5*|)E{29$#AW) z(?2~?lotc59536%d-L){QCb zAukx;!RAaj_gGDL{|$3RC(p#jx5QJxH}oc8snKe~<|3@=X<<;B1%$IEq`V0d|=C@%(9IbMaXNZwS#v7eqO z%8P+5m{)Ia#2+0Nx*YDjJW-Sv16wdJurdDdDs(N}d3mBJF9udQUW`kD^LVCzd7>yU z239#jt}jiV$x6r04iaw*d^O82WBTKK z)SB0u^Jf*beb3g%rO(6Nw6F!X@0f7qo!9)apEo`V!Ft(btgB{*@N>7HHtL0Rt&A1V zLs4D`L)uPZ3*;q4W?Fn27cSh2NS9(C5O276d(B7vcB!oxuZ?e?i=Ap6r-dz$*O+i3 zROe57p(#f`Q@^j4kzZa*IR1%^8ku=e#){{mXnP?HX*-22ke7(dxI#luPyaI!SQDuw zi{VBXqSnNyCX8_mfdGPPA$A=)O^^V$!`f9f+kD+v4O1alw8F?fBSS5J%;e4kkeq;*8dUT^O_ ztf%F!$2ciBfD7(u&qTO_$#lXn8X(p)w|OD#sEZWdhj;eMJ01g2le3ip8zWj~>io=? zZ6BZRh9`N!PJeggz^5nw?uf~Q*S>$~>bh7E8?^?YE8wyk7Ar0Yczrt?9EkVsvLDxK z!^4JRTII&z7319w=jG<1tb%-;lrZdtD0)^)lX_t$XTg50nn@|TYSL{Of(ZzbEaI@3 z#p?k%U};t$Eiv7W{RH=OjGGX(^xu9H;~1=dvL0d=ASFnExa(lyAc9QeRquy&wy zWf;?)kmy*;g2bn`oJ1Y7$xW|{8roJ2Fdv((&5FhT!^qac2 zSAj^=E!sKj(`rT$lZh-=)~QhgNqq(Or}B~;RoErcMNB7choZt71`nu1W-9d8bGdVM zD`P}!m>e2ap-IKG3jf0`gl771l~vX}$i^4n`r^+=a@|h;IwPg&rjoJp!oQL1&ZdWj z`-+L#!sS3|Zh=jA1Xh;<@u`^+A&mM(o3&E!1pBfWM|I)gItZ0y{3O3mZ}4H zKk+WEgDTJgHe#tdaQ6>Za~)KN4lXZF2Wz+vsz3+$cK~ifOIqg>h1(d%;C3zzPn@vx zg}WiOxSzQ7=}4CNP%h_<@jZgT9>pw{{vRFDluPXgc+!I9j}!0W{P{WEC38-4D!7fCF60d2M$c;GbUM_F&1+n{g7fC>^ZhI;aABF!xIjXiEtH0OB_6 AB>(^b literal 0 HcmV?d00001 diff --git a/icons/Application/podder.png b/icons/Application/podder.png new file mode 100644 index 0000000000000000000000000000000000000000..dc2a784a9151f4a0a0c9570ec6c3104537a8975c GIT binary patch literal 4666 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 literal 0 HcmV?d00001 diff --git a/icons/Application/podder.svg b/icons/Application/podder.svg new file mode 100644 index 0000000..181a945 --- /dev/null +++ b/icons/Application/podder.svg @@ -0,0 +1,68 @@ + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/include/curl/curl.h b/include/curl/curl.h new file mode 100644 index 0000000..08bf8fa --- /dev/null +++ b/include/curl/curl.h @@ -0,0 +1,968 @@ +#ifndef __CURL_CURL_H +#define __CURL_CURL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2002, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * $Id: curl.h,v 1.175 2002/11/18 21:58:46 bagder Exp $ + ***************************************************************************/ + +#include +/* The include stuff here is mainly for time_t! */ +#ifdef vms +# include +# include +#else +# include +# ifdef TIME_WITH_SYS_TIME +# include +# include +# else +# ifdef HAVE_SYS_TIME_H +# include +# else +# include +# endif +# endif +#endif /* defined (vms) */ + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* stupid #define trick to preserve functionality with older code, but + making it use our name space for the future */ +#define HttpPost curl_httppost + +struct curl_httppost { + struct curl_httppost *next; /* next entry in the list */ + char *name; /* pointer to allocated name */ + long namelength; /* length of name length */ + char *contents; /* pointer to allocated data contents */ + long contentslength; /* length of contents field */ + + /* CMC: Added support for buffer uploads */ + char *buffer; /* pointer to allocated buffer contents */ + long bufferlength; /* length of buffer field */ + + char *contenttype; /* Content-Type */ + struct curl_slist* contentheader; /* list of extra headers for this form */ + struct curl_httppost *more; /* if one field name has more than one file, this + link should link to following files */ + long flags; /* as defined below */ +#define HTTPPOST_FILENAME (1<<0) /* specified content is a file name */ +#define HTTPPOST_READFILE (1<<1) /* specified content is a file name */ +#define HTTPPOST_PTRNAME (1<<2) /* name is only stored pointer + do not free in formfree */ +#define HTTPPOST_PTRCONTENTS (1<<3) /* contents is only stored pointer + do not free in formfree */ + +/* CMC: Added support for buffer uploads */ +#define HTTPPOST_BUFFER (1<<4) /* upload file from buffer */ +#define HTTPPOST_PTRBUFFER (1<<5) /* upload file from pointer contents */ + + char *showfilename; /* The file name to show. If not set, the actual + file name will be used (if this is a file part) */ +}; + +typedef int (*curl_progress_callback)(void *clientp, + double dltotal, + double dlnow, + double ultotal, + double ulnow); + +#define CURL_MAX_WRITE_SIZE 20480 + +typedef size_t (*curl_write_callback)(char *buffer, + size_t size, + size_t nitems, + void *outstream); + +typedef size_t (*curl_read_callback)(char *buffer, + size_t size, + size_t nitems, + void *instream); + +typedef int (*curl_passwd_callback)(void *clientp, + const char *prompt, + char *buffer, + int buflen); + +/* the kind of data that is passed to information_callback*/ +typedef enum { + CURLINFO_TEXT = 0, + CURLINFO_HEADER_IN, /* 1 */ + CURLINFO_HEADER_OUT, /* 2 */ + CURLINFO_DATA_IN, /* 3 */ + CURLINFO_DATA_OUT, /* 4 */ + CURLINFO_END +} curl_infotype; + +typedef int (*curl_debug_callback) + (CURL *handle, /* the handle/transfer this concerns */ + curl_infotype type, /* what kind of data */ + char *data, /* points to the data */ + size_t size, /* size of the data pointed to */ + void *userp); /* whatever the user please */ + +/* All possible error codes from all sorts of curl functions. Future versions + may return other values, stay prepared. + + Always add new return codes last. Never *EVER* remove any. The return + codes must remain the same! + */ + +typedef enum { + CURLE_OK = 0, + CURLE_UNSUPPORTED_PROTOCOL, /* 1 */ + CURLE_FAILED_INIT, /* 2 */ + CURLE_URL_MALFORMAT, /* 3 */ + CURLE_URL_MALFORMAT_USER, /* 4 */ + CURLE_COULDNT_RESOLVE_PROXY, /* 5 */ + CURLE_COULDNT_RESOLVE_HOST, /* 6 */ + CURLE_COULDNT_CONNECT, /* 7 */ + CURLE_FTP_WEIRD_SERVER_REPLY, /* 8 */ + CURLE_FTP_ACCESS_DENIED, /* 9 */ + CURLE_FTP_USER_PASSWORD_INCORRECT, /* 10 */ + CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */ + CURLE_FTP_WEIRD_USER_REPLY, /* 12 */ + CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */ + CURLE_FTP_WEIRD_227_FORMAT, /* 14 */ + CURLE_FTP_CANT_GET_HOST, /* 15 */ + CURLE_FTP_CANT_RECONNECT, /* 16 */ + CURLE_FTP_COULDNT_SET_BINARY, /* 17 */ + CURLE_PARTIAL_FILE, /* 18 */ + CURLE_FTP_COULDNT_RETR_FILE, /* 19 */ + CURLE_FTP_WRITE_ERROR, /* 20 */ + CURLE_FTP_QUOTE_ERROR, /* 21 */ + CURLE_HTTP_NOT_FOUND, /* 22 */ + CURLE_WRITE_ERROR, /* 23 */ + CURLE_MALFORMAT_USER, /* 24 - user name is illegally specified */ + CURLE_FTP_COULDNT_STOR_FILE, /* 25 - failed FTP upload */ + CURLE_READ_ERROR, /* 26 - could open/read from file */ + CURLE_OUT_OF_MEMORY, /* 27 */ + CURLE_OPERATION_TIMEOUTED, /* 28 - the timeout time was reached */ + CURLE_FTP_COULDNT_SET_ASCII, /* 29 - TYPE A failed */ + CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */ + CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */ + CURLE_FTP_COULDNT_GET_SIZE, /* 32 - the SIZE command failed */ + CURLE_HTTP_RANGE_ERROR, /* 33 - RANGE "command" didn't work */ + CURLE_HTTP_POST_ERROR, /* 34 */ + CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */ + CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */ + CURLE_FILE_COULDNT_READ_FILE, /* 37 */ + CURLE_LDAP_CANNOT_BIND, /* 38 */ + CURLE_LDAP_SEARCH_FAILED, /* 39 */ + CURLE_LIBRARY_NOT_FOUND, /* 40 */ + CURLE_FUNCTION_NOT_FOUND, /* 41 */ + CURLE_ABORTED_BY_CALLBACK, /* 42 */ + CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */ + CURLE_BAD_CALLING_ORDER, /* 44 */ + CURLE_HTTP_PORT_FAILED, /* 45 - HTTP Interface operation failed */ + CURLE_BAD_PASSWORD_ENTERED, /* 46 - my_getpass() returns fail */ + CURLE_TOO_MANY_REDIRECTS , /* 47 - catch endless re-direct loops */ + CURLE_UNKNOWN_TELNET_OPTION, /* 48 - User specified an unknown option */ + CURLE_TELNET_OPTION_SYNTAX , /* 49 - Malformed telnet option */ + CURLE_OBSOLETE, /* 50 - removed after 7.7.3 */ + CURLE_SSL_PEER_CERTIFICATE, /* 51 - peer's certificate wasn't ok */ + CURLE_GOT_NOTHING, /* 52 - when this is a specific error */ + CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */ + CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as + default */ + CURLE_SEND_ERROR, /* 55 - failed sending network data */ + CURLE_RECV_ERROR, /* 56 - failure in receiving network data */ + CURLE_SHARE_IN_USE, /* 57 - share is in use */ + CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */ + CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */ + CURLE_SSL_CACERT, /* 60 - problem with the CA cert (path?) */ + CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized transfer encoding */ + + CURL_LAST /* never use! */ +} CURLcode; + +/* Make a spelling correction for the operation timed-out define */ +#define CURLE_OPERATION_TIMEDOUT CURLE_OPERATION_TIMEOUTED + +typedef enum { + CURLPROXY_HTTP = 0, + CURLPROXY_SOCKS4 = 4, + CURLPROXY_SOCKS5 = 5 +} curl_proxytype; + +/* this was the error code 50 in 7.7.3 and a few earlier versions, this + is no longer used by libcurl but is instead #defined here only to not + make programs break */ +#define CURLE_ALREADY_COMPLETE 99999 + +/* This is just to make older programs not break: */ +#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE +#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME + +#define CURL_ERROR_SIZE 256 + +/* long may be 32 or 64 bits, but we should never depend on anything else + but 32 */ +#define CURLOPTTYPE_LONG 0 +#define CURLOPTTYPE_OBJECTPOINT 10000 +#define CURLOPTTYPE_FUNCTIONPOINT 20000 + +/* name is uppercase CURLOPT_, + type is one of the defined CURLOPTTYPE_ + number is unique identifier */ +#ifdef CINIT +#undef CINIT +#endif +/* + * Figure out if we can use the ## operator, which is supported by ISO/ANSI C + * and C++. Some compilers support it without setting __STDC__ or __cplusplus + * so we need to carefully check for them too. We don't use configure-checks + * for these since we want these headers to remain generic and working for all + * platforms. + */ +#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \ + defined(__HP_aCC) || defined(__BORLANDC__) + /* This compiler is believed to have an ISO compatible preprocessor */ +#define CURL_ISOCPP +#else + /* This compiler is believed NOT to have an ISO compatible preprocessor */ +#undef CURL_ISOCPP +#endif + +#ifdef CURL_ISOCPP +#define CINIT(name,type,number) CURLOPT_ ## name = CURLOPTTYPE_ ## type + number +#else +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +#define LONG CURLOPTTYPE_LONG +#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT +#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT +#define CINIT(name,type,number) CURLOPT_/**/name = type + number +#endif + +typedef enum { + CINIT(NOTHING, LONG, 0), /********* the first one is unused ************/ + + /* This is the FILE * or void * the regular output should be written to. */ + CINIT(FILE, OBJECTPOINT, 1), + + /* The full URL to get/put */ + CINIT(URL, OBJECTPOINT, 2), + + /* Port number to connect to, if other than default. Specify the CONF_PORT + flag in the CURLOPT_FLAGS to activate this */ + CINIT(PORT, LONG, 3), + + /* Name of proxy to use. Specify the CONF_PROXY flag in the CURLOPT_FLAGS to + activate this */ + CINIT(PROXY, OBJECTPOINT, 4), + + /* Name and password to use when fetching. Specify the CONF_USERPWD flag in + the CURLOPT_FLAGS to activate this */ + CINIT(USERPWD, OBJECTPOINT, 5), + + /* Name and password to use with Proxy. Specify the CONF_PROXYUSERPWD + flag in the CURLOPT_FLAGS to activate this */ + CINIT(PROXYUSERPWD, OBJECTPOINT, 6), + + /* Range to get, specified as an ASCII string. Specify the CONF_RANGE flag + in the CURLOPT_FLAGS to activate this */ + CINIT(RANGE, OBJECTPOINT, 7), + + /* not used */ + + /* Specified file stream to upload from (use as input): */ + CINIT(INFILE, OBJECTPOINT, 9), + + /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE + * bytes big. If this is not used, error messages go to stderr instead: */ + CINIT(ERRORBUFFER, OBJECTPOINT, 10), + + /* Function that will be called to store the output (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11), + + /* Function that will be called to read the input (instead of fread). The + * parameters will use fread() syntax, make sure to follow them. */ + CINIT(READFUNCTION, FUNCTIONPOINT, 12), + + /* Time-out the read operation after this amount of seconds */ + CINIT(TIMEOUT, LONG, 13), + + /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about + * how large the file being sent really is. That allows better error + * checking and better verifies that the upload was succcessful. -1 means + * unknown size. */ + CINIT(INFILESIZE, LONG, 14), + + /* POST input fields. */ + CINIT(POSTFIELDS, OBJECTPOINT, 15), + + /* Set the referer page (needed by some CGIs) */ + CINIT(REFERER, OBJECTPOINT, 16), + + /* Set the FTP PORT string (interface name, named or numerical IP address) + Use i.e '-' to use default address. */ + CINIT(FTPPORT, OBJECTPOINT, 17), + + /* Set the User-Agent string (examined by some CGIs) */ + CINIT(USERAGENT, OBJECTPOINT, 18), + + /* If the download receives less than "low speed limit" bytes/second + * during "low speed time" seconds, the operations is aborted. + * You could i.e if you have a pretty high speed connection, abort if + * it is less than 2000 bytes/sec during 20 seconds. + */ + + /* Set the "low speed limit" */ + CINIT(LOW_SPEED_LIMIT, LONG , 19), + + /* Set the "low speed time" */ + CINIT(LOW_SPEED_TIME, LONG, 20), + + /* Set the continuation offset */ + CINIT(RESUME_FROM, LONG, 21), + + /* Set cookie in request: */ + CINIT(COOKIE, OBJECTPOINT, 22), + + /* This points to a linked list of headers, struct curl_slist kind */ + CINIT(HTTPHEADER, OBJECTPOINT, 23), + + /* This points to a linked list of post entries, struct HttpPost */ + CINIT(HTTPPOST, OBJECTPOINT, 24), + + /* name of the file keeping your private SSL-certificate */ + CINIT(SSLCERT, OBJECTPOINT, 25), + + /* password for the SSL-private key, keep this for compatibility */ + CINIT(SSLCERTPASSWD, OBJECTPOINT, 26), + /* password for the SSL private key */ + CINIT(SSLKEYPASSWD, OBJECTPOINT, 26), + + /* send TYPE parameter? */ + CINIT(CRLF, LONG, 27), + + /* send linked-list of QUOTE commands */ + CINIT(QUOTE, OBJECTPOINT, 28), + + /* send FILE * or void * to store headers to, if you use a callback it + is simply passed to the callback unmodified */ + CINIT(WRITEHEADER, OBJECTPOINT, 29), + + /* point to a file to read the initial cookies from, also enables + "cookie awareness" */ + CINIT(COOKIEFILE, OBJECTPOINT, 31), + + /* What version to specifly try to use. + See CURL_SSLVERSION defines below. */ + CINIT(SSLVERSION, LONG, 32), + + /* What kind of HTTP time condition to use, see defines */ + CINIT(TIMECONDITION, LONG, 33), + + /* Time to use with the above condition. Specified in number of seconds + since 1 Jan 1970 */ + CINIT(TIMEVALUE, LONG, 34), + + /* HTTP request, for odd commands like DELETE, TRACE and others */ + /* OBSOLETE DEFINE, left for tradition only */ + CINIT(HTTPREQUEST, OBJECTPOINT, 35), + + /* Custom request, for customizing the get command like + HTTP: DELETE, TRACE and others + FTP: to use a different list command + */ + CINIT(CUSTOMREQUEST, OBJECTPOINT, 36), + + /* HTTP request, for odd commands like DELETE, TRACE and others */ + CINIT(STDERR, OBJECTPOINT, 37), + + /* 38 is not used */ + + /* send linked-list of post-transfer QUOTE commands */ + CINIT(POSTQUOTE, OBJECTPOINT, 39), + + /* Pass a pointer to string of the output using full variable-replacement + as described elsewhere. */ + CINIT(WRITEINFO, OBJECTPOINT, 40), + + /* Previous FLAG bits */ + CINIT(VERBOSE, LONG, 41), /* talk a lot */ + CINIT(HEADER, LONG, 42), /* throw the header out too */ + CINIT(NOPROGRESS, LONG, 43), /* shut off the progress meter */ + CINIT(NOBODY, LONG, 44), /* use HEAD to get http document */ + CINIT(FAILONERROR, LONG, 45), /* no output on http error codes >= 300 */ + CINIT(UPLOAD, LONG, 46), /* this is an upload */ + CINIT(POST, LONG, 47), /* HTTP POST method */ + CINIT(FTPLISTONLY, LONG, 48), /* Use NLST when listing ftp dir */ + + CINIT(FTPAPPEND, LONG, 50), /* Append instead of overwrite on upload! */ + + /* Specify whether to read the user+password from the .netrc or the URL. + * This must be one of the CURL_NETRC_* enums below. */ + CINIT(NETRC, LONG, 51), + + CINIT(FOLLOWLOCATION, LONG, 52), /* use Location: Luke! */ + + /* This FTPASCII name is now obsolete, to be removed, use the TRANSFERTEXT + instead. It goes for more protocols than just ftp... */ + CINIT(FTPASCII, LONG, 53), /* use TYPE A for transfer */ + + CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */ + CINIT(PUT, LONG, 54), /* PUT the input file */ + + CINIT(MUTE, LONG, 55), /* OBSOLETE OPTION, removed in 7.8 */ + + /* Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_progress_callback + * prototype defines. */ + CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56), + + /* Data passed to the progress callback */ + CINIT(PROGRESSDATA, OBJECTPOINT, 57), + + /* We want the referer field set automatically when following locations */ + CINIT(AUTOREFERER, LONG, 58), + + /* Port of the proxy, can be set in the proxy string as well with: + "[host]:[port]" */ + CINIT(PROXYPORT, LONG, 59), + + /* size of the POST input data, if strlen() is not good to use */ + CINIT(POSTFIELDSIZE, LONG, 60), + + /* tunnel non-http operations through a HTTP proxy */ + CINIT(HTTPPROXYTUNNEL, LONG, 61), + + /* Set the interface string to use as outgoing network interface */ + CINIT(INTERFACE, OBJECTPOINT, 62), + + /* Set the krb4 security level, this also enables krb4 awareness. This is a + * string, 'clear', 'safe', 'confidential' or 'private'. If the string is + * set but doesn't match one of these, 'private' will be used. */ + CINIT(KRB4LEVEL, OBJECTPOINT, 63), + + /* Set if we should verify the peer in ssl handshake, set 1 to verify. */ + CINIT(SSL_VERIFYPEER, LONG, 64), + + /* The CApath or CAfile used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CINIT(CAINFO, OBJECTPOINT, 65), + + /* Function pointer to replace the internal password prompt */ + CINIT(PASSWDFUNCTION, FUNCTIONPOINT, 66), + + /* Custom pointer that gets passed as first argument to the password + function */ + CINIT(PASSWDDATA, OBJECTPOINT, 67), + + /* Maximum number of http redirects to follow */ + CINIT(MAXREDIRS, LONG, 68), + + /* Pass a pointer to a time_t to get a possible date of the requested + document! Pass a NULL to shut it off. */ + CINIT(FILETIME, OBJECTPOINT, 69), + + /* This points to a linked list of telnet options */ + CINIT(TELNETOPTIONS, OBJECTPOINT, 70), + + /* Max amount of cached alive connections */ + CINIT(MAXCONNECTS, LONG, 71), + + /* What policy to use when closing connections when the cache is filled + up */ + CINIT(CLOSEPOLICY, LONG, 72), + + /* Callback to use when CURLCLOSEPOLICY_CALLBACK is set */ + CINIT(CLOSEFUNCTION, FUNCTIONPOINT, 73), + + /* Set to explicitly use a new connection for the upcoming transfer. + Do not use this unless you're absolutely sure of this, as it makes the + operation slower and is less friendly for the network. */ + CINIT(FRESH_CONNECT, LONG, 74), + + /* Set to explicitly forbid the upcoming transfer's connection to be re-used + when done. Do not use this unless you're absolutely sure of this, as it + makes the operation slower and is less friendly for the network. */ + CINIT(FORBID_REUSE, LONG, 75), + + /* Set to a file name that contains random data for libcurl to use to + seed the random engine when doing SSL connects. */ + CINIT(RANDOM_FILE, OBJECTPOINT, 76), + + /* Set to the Entropy Gathering Daemon socket pathname */ + CINIT(EGDSOCKET, OBJECTPOINT, 77), + + /* Time-out connect operations after this amount of seconds, if connects + are OK within this time, then fine... This only aborts the connect + phase. [Only works on unix-style/SIGALRM operating systems] */ + CINIT(CONNECTTIMEOUT, LONG, 78), + + /* Function that will be called to store headers (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79), + + /* Set this to force the HTTP request to get back to GET. Only really usable + if POST, PUT or a custom request have been used first. + */ + CINIT(HTTPGET, LONG, 80), + + /* Set if we should verify the Common name from the peer certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches the + * provided hostname. */ + CINIT(SSL_VERIFYHOST, LONG, 81), + + /* Specify which file name to write all known cookies in after completed + operation. Set file name to "-" (dash) to make it go to stdout. */ + CINIT(COOKIEJAR, OBJECTPOINT, 82), + + /* Specify which SSL ciphers to use */ + CINIT(SSL_CIPHER_LIST, OBJECTPOINT, 83), + + /* Specify which HTTP version to use! This must be set to one of the + CURL_HTTP_VERSION* enums set below. */ + CINIT(HTTP_VERSION, LONG, 84), + + /* Specificly switch on or off the FTP engine's use of the EPSV command. By + default, that one will always be attempted before the more traditional + PASV command. */ + CINIT(FTP_USE_EPSV, LONG, 85), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */ + CINIT(SSLCERTTYPE, OBJECTPOINT, 86), + + /* name of the file keeping your private SSL-key */ + CINIT(SSLKEY, OBJECTPOINT, 87), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */ + CINIT(SSLKEYTYPE, OBJECTPOINT, 88), + + /* crypto engine for the SSL-sub system */ + CINIT(SSLENGINE, OBJECTPOINT, 89), + + /* set the crypto engine for the SSL-sub system as default + the param has no meaning... + */ + CINIT(SSLENGINE_DEFAULT, LONG, 90), + + /* Non-zero value means to use the global dns cache */ + CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), + + /* DNS cache timeout */ + CINIT(DNS_CACHE_TIMEOUT, LONG, 92), + + /* send linked-list of pre-transfer QUOTE commands (Wesley Laxton)*/ + CINIT(PREQUOTE, OBJECTPOINT, 93), + + /* set the debug function */ + CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94), + + /* set the data for the debug function */ + CINIT(DEBUGDATA, OBJECTPOINT, 95), + + /* mark this as start of a cookie session */ + CINIT(COOKIESESSION, LONG, 96), + + /* The CApath directory used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CINIT(CAPATH, OBJECTPOINT, 97), + + /* Instruct libcurl to use a smaller receive buffer */ + CINIT(BUFFERSIZE, LONG, 98), + + /* Instruct libcurl to not use any signal/alarm handlers, even when using + timeouts. This option is useful for multi-threaded applications. + See libcurl-the-guide for more background information. */ + CINIT(NOSIGNAL, LONG, 99), + + /* Provide a CURLShare for mutexing non-ts data */ + CINIT(SHARE, OBJECTPOINT, 100), + + /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default), + CURLPROXY_SOCKS4 and CURLPROXY_SOCKS5. */ + CINIT(PROXYTYPE, LONG, 101), + + /* Set the Accept-Encoding string. Use this to tell a server you would like + the response to be compressed. */ + CINIT(ENCODING, OBJECTPOINT, 102), + + + CURLOPT_LASTENTRY /* the last unused */ +} CURLoption; + + /* two convenient "aliases" that follow the name scheme better */ +#define CURLOPT_WRITEDATA CURLOPT_FILE +#define CURLOPT_READDATA CURLOPT_INFILE +#define CURLOPT_HEADERDATA CURLOPT_WRITEHEADER + + + /* These enums are for use with the CURLOPT_HTTP_VERSION option. */ +enum { + CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd + like the library to choose the best possible + for us! */ + CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */ + CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */ + + CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */ +}; + + /* These enums are for use with the CURLOPT_NETRC option. */ +enum CURL_NETRC_OPTION { + CURL_NETRC_IGNORED, /* The .netrc will never be read. + * This is the default. */ + CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred + * to one in the .netrc. */ + CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored. + * Unless one is set programmatically, the .netrc + * will be queried. */ + CURL_NETRC_LAST +}; + +enum { + CURL_SSLVERSION_DEFAULT, + CURL_SSLVERSION_TLSv1, + CURL_SSLVERSION_SSLv2, + CURL_SSLVERSION_SSLv3, + + CURL_SSLVERSION_LAST /* never use, keep last */ +}; + + +typedef enum { + CURL_TIMECOND_NONE, + + CURL_TIMECOND_IFMODSINCE, + CURL_TIMECOND_IFUNMODSINCE, + CURL_TIMECOND_LASTMOD, + + CURL_TIMECOND_LAST +} curl_TimeCond; + +/* for backwards compatibility */ +#ifndef TIMECOND_IFMODSINCE +#define TIMECOND_IFMODSINCE CURL_TIMECOND_IFMODSINCE +#endif +#ifndef TIMECOND_IFUNMODSINCE +#define TIMECOND_IFUNMODSINCE CURL_TIMECOND_IFUNMODSINCE +#endif +#ifndef TIMECOND_LASTMOD +#define TIMECOND_LASTMOD CURL_TIMECOND_LASTMOD +#endif + +#ifdef __BEOS__ +#include +#endif + + +/* These functions are in the libcurl, they're here for portable reasons and + they are used by the 'curl' client. They really should be moved to some kind + of "portability library" since it has nothing to do with file transfers and + might be usable to other programs... + + NOTE: they return TRUE if the strings match *case insensitively*. + */ +extern int (curl_strequal)(const char *s1, const char *s2); +extern int (curl_strnequal)(const char *s1, const char *s2, size_t n); +#define strequal(a,b) curl_strequal(a,b) +#define strnequal(a,b,c) curl_strnequal(a,b,c) + +/* DEPRECATED function to build formdata */ +int curl_formparse(char *, struct curl_httppost **, + struct curl_httppost **_post); + +/* name is uppercase CURLFORM_ */ +#ifdef CFINIT +#undef CFINIT +#endif + +#ifdef CURL_ISOCPP +#define CFINIT(name) CURLFORM_ ## name +#else +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +#define CFINIT(name) CURLFORM_/**/name +#endif + +typedef enum { + CFINIT(NOTHING), /********* the first one is unused ************/ + + /* */ + CFINIT(COPYNAME), + CFINIT(PTRNAME), + CFINIT(NAMELENGTH), + CFINIT(COPYCONTENTS), + CFINIT(PTRCONTENTS), + CFINIT(CONTENTSLENGTH), + CFINIT(FILECONTENT), + CFINIT(ARRAY), + CFINIT(OBSOLETE), + CFINIT(FILE), + + CFINIT(BUFFER), + CFINIT(BUFFERPTR), + CFINIT(BUFFERLENGTH), + + CFINIT(CONTENTTYPE), + CFINIT(CONTENTHEADER), + CFINIT(FILENAME), + CFINIT(END), + CFINIT(OBSOLETE2), + + CURLFORM_LASTENTRY /* the last unusued */ +} CURLformoption; + +#undef CFINIT /* done */ + +/* structure to be used as parameter for CURLFORM_ARRAY */ +struct curl_forms { + CURLformoption option; + const char *value; +}; + +/* use this for multipart formpost building */ +/* Returns code for curl_formadd() + * + * Returns: + * CURL_FORMADD_OK on success + * CURL_FORMADD_MEMORY if the FormInfo allocation fails + * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form + * CURL_FORMADD_NULL if a null pointer was given for a char + * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed + * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used + * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) + * CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated + * CURL_FORMADD_MEMORY if some allocation for string copying failed. + * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array + * + ***************************************************************************/ +typedef enum { + CURL_FORMADD_OK, /* first, no error */ + + CURL_FORMADD_MEMORY, + CURL_FORMADD_OPTION_TWICE, + CURL_FORMADD_NULL, + CURL_FORMADD_UNKNOWN_OPTION, + CURL_FORMADD_INCOMPLETE, + CURL_FORMADD_ILLEGAL_ARRAY, + + CURL_FORMADD_LAST /* last */ +} CURLFORMcode; + +CURLFORMcode curl_formadd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + ...); + +/* cleanup a form: */ +void curl_formfree(struct curl_httppost *form); + +/* Unix and Win32 getenv function call, this returns a malloc()'ed string that + MUST be free()ed after usage is complete. */ +char *curl_getenv(const char *variable); + +/* Returns a static ascii string of the libcurl version. */ +char *curl_version(void); + +/* Escape and unescape URL encoding in strings. The functions return a new + * allocated string or NULL if an error occurred. */ +char *curl_escape(const char *string, int length); +char *curl_unescape(const char *string, int length); +/* 20020912 WJM. Provide for a de-allocation in the same translation unit + that did the allocation. Added in libcurl 7.10 */ +void curl_free(void *p); + +/* curl_global_init() should be invoked exactly once for each application that + uses libcurl */ +CURLcode curl_global_init(long flags); + +/* curl_global_cleanup() should be invoked exactly once for each application + that uses libcurl */ +void curl_global_cleanup(void); + +/* This is the version number */ +#define LIBCURL_VERSION "7.10.2" +#define LIBCURL_VERSION_NUM 0x070a02 + +/* linked-list structure for the CURLOPT_QUOTE option (and other) */ +struct curl_slist { + char *data; + struct curl_slist *next; +}; + +struct curl_slist *curl_slist_append(struct curl_slist *, const char *); +void curl_slist_free_all(struct curl_slist *); + +/* + * NAME curl_getdate() + * + * DESCRIPTION + * + * Returns the time, in seconds since 1 Jan 1970 of the time string given in + * the first argument. The time argument in the second parameter is for cases + * where the specified time is relative now, like 'two weeks' or 'tomorrow' + * etc. + */ +time_t curl_getdate(const char *p, const time_t *now); + + +#define CURLINFO_STRING 0x100000 +#define CURLINFO_LONG 0x200000 +#define CURLINFO_DOUBLE 0x300000 +#define CURLINFO_MASK 0x0fffff +#define CURLINFO_TYPEMASK 0xf00000 + +typedef enum { + CURLINFO_NONE, /* first, never use this */ + CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1, + CURLINFO_HTTP_CODE = CURLINFO_LONG + 2, + CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3, + CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4, + CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5, + CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6, + CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7, + CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8, + CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9, + CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10, + CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11, + CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12, + CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13, + CURLINFO_FILETIME = CURLINFO_LONG + 14, + + CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15, + CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16, + + CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17, + + CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18, + + CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19, + CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20, + + /* Fill in new entries here! */ + + CURLINFO_LASTONE = 21 +} CURLINFO; + +/* unfortunately, the easy.h and multi.h include files need options and info + stuff before they can be included! */ +#include "easy.h" /* nothing in curl is fun without the easy stuff */ +#include "multi.h" + +typedef enum { + CURLCLOSEPOLICY_NONE, /* first, never use this */ + + CURLCLOSEPOLICY_OLDEST, + CURLCLOSEPOLICY_LEAST_RECENTLY_USED, + CURLCLOSEPOLICY_LEAST_TRAFFIC, + CURLCLOSEPOLICY_SLOWEST, + CURLCLOSEPOLICY_CALLBACK, + + CURLCLOSEPOLICY_LAST /* last, never use this */ +} curl_closepolicy; + +#define CURL_GLOBAL_SSL (1<<0) +#define CURL_GLOBAL_WIN32 (1<<1) +#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32) +#define CURL_GLOBAL_NOTHING 0 +#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL + + +/***************************************************************************** + * Setup defines, protos etc for the sharing stuff. + */ + +/* Different types of locks that a share can aquire */ +typedef enum { + CURL_LOCK_TYPE_NONE = 0, + CURL_LOCK_TYPE_COOKIE = 1<<0, + CURL_LOCK_TYPE_DNS = 1<<1, + CURL_LOCK_TYPE_SSL_SESSION = 2<<1, + CURL_LOCK_TYPE_CONNECT = 2<<2, + CURL_LOCK_TYPE_LAST +} curl_lock_type; + +typedef void (*curl_lock_function)(CURL *, curl_lock_type, void *); +typedef void (*curl_unlock_function)(CURL *, curl_lock_type, void *); + +typedef struct { + unsigned int specifier; + unsigned int locked; + unsigned int dirty; + + curl_lock_function lockfunc; + curl_unlock_function unlockfunc; + void *clientdata; +} curl_share; + +curl_share *curl_share_init (void); +CURLcode curl_share_setopt (curl_share *, curl_lock_type, int); +CURLcode curl_share_set_lock_function (curl_share *, curl_lock_function); +CURLcode curl_share_set_unlock_function (curl_share *, curl_unlock_function); +CURLcode curl_share_set_lock_data (curl_share *, void *); +CURLcode curl_share_destroy (curl_share *); + +/**************************************************************************** + * Structures for querying information about the curl library at runtime. + */ + +typedef enum { + CURLVERSION_FIRST, + CURLVERSION_LAST /* never actually use this */ +} CURLversion; + +/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by + basicly all programs ever, that want to get version information. It is + meant to be a built-in version number for what kind of struct the caller + expects. If the struct ever changes, we redfine the NOW to another enum + from above. */ +#define CURLVERSION_NOW CURLVERSION_FIRST + +typedef struct { + CURLversion age; /* age of the returned struct */ + const char *version; /* LIBCURL_VERSION */ + unsigned int version_num; /* LIBCURL_VERSION_NUM */ + const char *host; /* OS/host/cpu/machine when configured */ + int features; /* bitmask, see defines below */ + char *ssl_version; /* human readable string */ + long ssl_version_num; /* number */ + const char *libz_version; /* human readable string */ + /* protocols is terminated by an entry with a NULL protoname */ + const char **protocols; +} curl_version_info_data; + +#define CURL_VERSION_IPV6 (1<<0) +#define CURL_VERSION_KERBEROS4 (1<<1) +#define CURL_VERSION_SSL (1<<2) +#define CURL_VERSION_LIBZ (1<<3) + +/* returns a pointer to a static copy of the version info struct */ +curl_version_info_data *curl_version_info(CURLversion); + +#ifdef __cplusplus +} +#endif + +#endif /* __CURL_CURL_H */ diff --git a/include/curl/easy.h b/include/curl/easy.h new file mode 100644 index 0000000..42a2264 --- /dev/null +++ b/include/curl/easy.h @@ -0,0 +1,68 @@ +#ifndef __CURL_EASY_H +#define __CURL_EASY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2002, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * $Id: easy.h,v 1.7 2002/09/03 11:53:00 bagder Exp $ + ***************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +CURL *curl_easy_init(void); +CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...); +CURLcode curl_easy_perform(CURL *curl); +void curl_easy_cleanup(CURL *curl); + +/* + * NAME curl_easy_getinfo() + * + * DESCRIPTION + * + * Request internal information from the curl session with this function. The + * third argument MUST be a pointer to a long, a pointer to a char * or a + * pointer to a double (as the documentation describes elsewhere). The data + * pointed to will be filled in accordingly and can be relied upon only if the + * function returns CURLE_OK. This function is intended to get used *AFTER* a + * performed transfer, all results from this function are undefined until the + * transfer is completed. + */ +CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...); + + +/* + * NAME curl_easy_duphandle() + * + * DESCRIPTION + * + * Creates a new curl session handle with the same options set for the handle + * passed in. Duplicating a handle could only be a matter of cloning data and + * options, internal state info and things like persistant connections cannot + * be transfered. It is useful in multithreaded applications when you can run + * curl_easy_duphandle() for each new thread to avoid a series of identical + * curl_easy_setopt() invokes in every thread. + */ +CURL* curl_easy_duphandle(CURL *curl); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/curl/mprintf.h b/include/curl/mprintf.h new file mode 100644 index 0000000..4017f67 --- /dev/null +++ b/include/curl/mprintf.h @@ -0,0 +1,83 @@ +/************************************************************************* + * + * $Id: mprintf.h,v 1.6 2001/08/15 18:17:14 bagder Exp $ + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND + * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. + * + ************************************************************************* + * + * Preliminary documentation + * + * printf conversions: + * + * conversion ::= '%%' | '%' [position] ( number | float | string ) + * position ::= digits '$' + * number ::= [number-flags] ( 'd' | 'i' | 'o' | 'x' | 'X' | 'u') + * number-flags ::= 'h' | 'l' | 'L' ... + * float ::= [float-flags] ( 'f' | 'e' | 'E' | 'g' | 'G' ) + * string ::= [string-flags] 's' + * string-flags ::= padding | '#' + * digits ::= (digit)+ + * digit ::= 0-9 + * + * c + * p + * n + * + * qualifiers + * + * - : left adjustment + * + : show sign + * SPACE : padding + * # : alterative + * . : precision + * * : width + * 0 : padding / size + * 1-9 : size + * h : short + * l : long + * ll : longlong + * L : long double + * Z : long / longlong + * q : longlong + * + ************************************************************************/ + +#ifndef H_MPRINTF +#define H_MPRINTF + +#include +#include /* needed for FILE */ + +int curl_mprintf(const char *format, ...); +int curl_mfprintf(FILE *fd, const char *format, ...); +int curl_msprintf(char *buffer, const char *format, ...); +int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...); +int curl_mvprintf(const char *format, va_list args); +int curl_mvfprintf(FILE *fd, const char *format, va_list args); +int curl_mvsprintf(char *buffer, const char *format, va_list args); +int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format, va_list args); +char *curl_maprintf(const char *format, ...); +char *curl_mvaprintf(const char *format, va_list args); + +#ifdef _MPRINTF_REPLACE +# define printf curl_mprintf +# define fprintf curl_mfprintf +# define sprintf curl_msprintf +# define snprintf curl_msnprintf +# define vprintf curl_mvprintf +# define vfprintf curl_mvfprintf +# define vsprintf curl_mvsprintf +# define vsnprintf curl_mvsnprintf +# define aprintf curl_maprintf +# define vaprintf curl_mvaprintf +#endif + +#endif /* H_MPRINTF */ diff --git a/include/curl/multi.h b/include/curl/multi.h new file mode 100644 index 0000000..e5b2a72 --- /dev/null +++ b/include/curl/multi.h @@ -0,0 +1,190 @@ +#ifndef __CURL_MULTI_H +#define __CURL_MULTI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2002, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * $Id: multi.h,v 1.4 2002/09/03 11:53:00 bagder Exp $ + ***************************************************************************/ +/* + This is meant to be the "external" header file. Don't give away any + internals here! + + This document presents a mixture of ideas from at least: + - Daniel Stenberg + - Steve Dekorte + - Sterling Hughes + - Ben Greear + + ------------------------------------------- + GOALS + + o Enable a "pull" interface. The application that uses libcurl decides where + and when to ask libcurl to get/send data. + + o Enable multiple simultaneous transfers in the same thread without making it + complicated for the application. + + o Enable the application to select() on its own file descriptors and curl's + file descriptors simultaneous easily. + + Example sources using this interface is here: ../multi/ + +*/ + +#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) +#include +#else +#include +#include +#endif + +#include "curl.h" + +typedef void CURLM; + +typedef enum { + CURLM_CALL_MULTI_PERFORM=-1, /* please call curl_multi_perform() soon */ + CURLM_OK, + CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */ + CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */ + CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */ + CURLM_INTERNAL_ERROR, /* this is a libcurl bug */ + CURLM_LAST +} CURLMcode; + +typedef enum { + CURLMSG_NONE, /* first, not used */ + CURLMSG_DONE, /* This easy handle has completed. 'whatever' points to + the CURLcode of the transfer */ + CURLMSG_LAST /* last, not used */ +} CURLMSG; + +struct CURLMsg { + CURLMSG msg; /* what this message means */ + CURL *easy_handle; /* the handle it concerns */ + union { + void *whatever; /* message-specific data */ + CURLcode result; /* return code for transfer */ + } data; +}; +typedef struct CURLMsg CURLMsg; + +/* + * Name: curl_multi_init() + * + * Desc: inititalize multi-style curl usage + * Returns: a new CURLM handle to use in all 'curl_multi' functions. + */ +CURLM *curl_multi_init(void); + +/* + * Name: curl_multi_add_handle() + * + * Desc: add a standard curl handle to the multi stack + * Returns: CURLMcode type, general multi error code. + */ +CURLMcode curl_multi_add_handle(CURLM *multi_handle, + CURL *curl_handle); + + /* + * Name: curl_multi_remove_handle() + * + * Desc: removes a curl handle from the multi stack again + * Returns: CURLMcode type, general multi error code. + */ +CURLMcode curl_multi_remove_handle(CURLM *multi_handle, + CURL *curl_handle); + + /* + * Name: curl_multi_fdset() + * + * Desc: Ask curl for its fd_set sets. The app can use these to select() or + * poll() on. We want curl_multi_perform() called as soon as one of + * them are ready. + * Returns: CURLMcode type, general multi error code. + */ +CURLMcode curl_multi_fdset(CURLM *multi_handle, + fd_set *read_fd_set, + fd_set *write_fd_set, + fd_set *exc_fd_set, + int *max_fd); + + /* + * Name: curl_multi_perform() + * + * Desc: When the app thinks there's data available for curl it calls this + * function to read/write whatever there is right now. This returns + * as soon as the reads and writes are done. This function does not + * require that there actually is data available for reading or that + * data can be written, it can be called just in case. It returns + * the number of handles that still transfer data in the second + * argument's integer-pointer. + * + * Returns: CURLMcode type, general multi error code. *NOTE* that this only + * returns errors etc regarding the whole multi stack. There might + * still have occurred problems on invidual transfers even when this + * returns OK. + */ +CURLMcode curl_multi_perform(CURLM *multi_handle, + int *running_handles); + + /* + * Name: curl_multi_cleanup() + * + * Desc: Cleans up and removes a whole multi stack. It does not free or + * touch any individual easy handles in any way. We need to define + * in what state those handles will be if this function is called + * in the middle of a transfer. + * Returns: CURLMcode type, general multi error code. + */ +CURLMcode curl_multi_cleanup(CURLM *multi_handle); + +/* + * Name: curl_multi_info_read() + * + * Desc: Ask the multi handle if there's any messages/informationals from + * the individual transfers. Messages include informationals such as + * error code from the transfer or just the fact that a transfer is + * completed. More details on these should be written down as well. + * + * Repeated calls to this function will return a new struct each + * time, until a special "end of msgs" struct is returned as a signal + * that there is no more to get at this point. + * + * The data the returned pointer points to will not survive calling + * curl_multi_cleanup(). + * + * The 'CURLMsg' struct is meant to be very simple and only contain + * very basic informations. If more involved information is wanted, + * we will provide the particular "transfer handle" in that struct + * and that should/could/would be used in subsequent + * curl_easy_getinfo() calls (or similar). The point being that we + * must never expose complex structs to applications, as then we'll + * undoubtably get backwards compatibility problems in the future. + * + * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out + * of structs. It also writes the number of messages left in the + * queue (after this read) in the integer the second argument points + * to. + */ +CURLMsg *curl_multi_info_read(CURLM *multi_handle, + int *msgs_in_queue); + +#endif diff --git a/include/curl/stdcheaders.h b/include/curl/stdcheaders.h new file mode 100644 index 0000000..1b9e9fa --- /dev/null +++ b/include/curl/stdcheaders.h @@ -0,0 +1,36 @@ +#ifndef __STDC_HEADERS_H +#define __STDC_HEADERS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2002, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * $Id: stdcheaders.h,v 1.5 2002/09/03 11:53:00 bagder Exp $ + ***************************************************************************/ + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +size_t fread (void *, size_t, size_t, FILE *); +size_t fwrite (const void *, size_t, size_t, FILE *); + +int strcasecmp(const char *, const char *); +int strncasecmp(const char *, const char *, size_t); + +#endif diff --git a/include/curl/types.h b/include/curl/types.h new file mode 100644 index 0000000..d762de8 --- /dev/null +++ b/include/curl/types.h @@ -0,0 +1,28 @@ +#ifndef __CURL_TYPES_H +#define __CURL_TYPES_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2002, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * $Id: types.h,v 1.5 2002/09/03 11:53:00 bagder Exp $ + ***************************************************************************/ +typedef void CURL; +typedef void CURLconnect; + +#endif /* __CURL_TYPES_H */ diff --git a/include/libclv/ColorTools.h b/include/libclv/ColorTools.h new file mode 100644 index 0000000..ad23154 --- /dev/null +++ b/include/libclv/ColorTools.h @@ -0,0 +1,69 @@ +/******************************************************************************* +/ +/ File: ColorTools.h +/ +/ Description: Additional experimental color manipulation functions. +/ +/ Copyright 2000, Be Incorporated, All Rights Reserved +/ +*******************************************************************************/ + + +#ifndef _COLOR_TOOLS_H +#define _COLOR_TOOLS_H + +#include + +#if B_BEOS_VERSION <= B_BEOS_VERSION_MAUI + +namespace BExperimental { + +// Comparison operators. + +inline bool operator==(const rgb_color c1, const rgb_color c2) +{ + return (*((uint32*)&c1)) == (*((uint32*)&c2)); +} + +inline bool operator!=(const rgb_color c1, const rgb_color c2) +{ + return (*((uint32*)&c1)) != (*((uint32*)&c2)); +} + +// Color creation. +/* +inline rgb_color make_color(uint8 red, uint8 green, uint8 blue, uint8 alpha=255) +{ + rgb_color c; + c.red = red; + c.green = green; + c.blue = blue; + c.alpha = alpha; + return c; +}*/ + +// Mix two colors together, ignoring their relative alpha channels. +// If amount is 0, the result is color1; if 255, the result is color2; +// if another value, it is somewhere in-between. The resulting alpha +// channel is mixed exactly like the other color channels. +rgb_color mix_color(rgb_color color1, rgb_color color2, uint8 amount); + +// Blend two colors together, weighting by their relative alpha channels. +// The resulting color is the same as mix_color(), except that the amount +// used from color1 and color2's color channels is dependent on that color's +// alpha channel. For example, if color1.alpha is 0 and color2.alpha is +// 255, the resulting red, green, and blue values will be the same as those +// in color2, regardless of 'amount'. +rgb_color blend_color(rgb_color color1, rgb_color color2, uint8 amount); + +// Return a color that is the disabled representation of 'color' when drawn +// on a solid color 'background'. +rgb_color disable_color(rgb_color color, rgb_color background); + +} // namespace BExperimental + +using namespace BExperimental; + +#endif + +#endif diff --git a/include/libclv/ColumnListView.h b/include/libclv/ColumnListView.h new file mode 100644 index 0000000..6df9d99 --- /dev/null +++ b/include/libclv/ColumnListView.h @@ -0,0 +1,343 @@ +/******************************************************************************* +/ +/ File: ColumnListView.h +/ +/ Description: Experimental multi-column list view. +/ +/ Copyright 2000+, Be Incorporated, All Rights Reserved +/ +*******************************************************************************/ + + +#ifndef _COLUMN_LIST_VIEW_H +#define _COLUMN_LIST_VIEW_H + +#include +#include +#include +#include +#include + +class BScrollBar; + +namespace BPrivate { + +class OutlineView; +class TitleView; +class BRowContainer; +class RecursiveOutlineIterator; + +} // ns BPrivate + +class BField; +class BRow; +class BColumn; +class BColumnListView; + +enum LatchType { + B_NO_LATCH, + B_OPEN_LATCH, + B_PRESSED_LATCH, + B_CLOSED_LATCH +}; + +typedef enum { + B_ALLOW_COLUMN_NONE = 0, + B_ALLOW_COLUMN_MOVE = 1, + B_ALLOW_COLUMN_RESIZE = 2, + B_ALLOW_COLUMN_POPUP = 4, + B_ALLOW_COLUMN_REMOVE = 8, +} column_flags; + +enum ColumnListViewColor { + B_COLOR_BACKGROUND = 0, + B_COLOR_TEXT = 1, + B_COLOR_ROW_DIVIDER = 2, + B_COLOR_SELECTION = 3, + B_COLOR_SELECTION_TEXT = 4, + B_COLOR_NON_FOCUS_SELECTION = 5, + B_COLOR_EDIT_BACKGROUND = 6, + B_COLOR_EDIT_TEXT = 7, + B_COLOR_HEADER_BACKGROUND = 8, + B_COLOR_HEADER_TEXT = 9, + B_COLOR_SEPARATOR_LINE = 10, + B_COLOR_SEPARATOR_BORDER = 11, + + B_COLOR_TOTAL = 12 +}; + +enum ColumnListViewFont { + B_FONT_ROW = 0, + B_FONT_HEADER = 1, + + B_FONT_TOTAL = 2 +}; + + +// A single row/column intersection in the list. +class BField { +public: + BField(); + virtual ~BField(); +}; + +// A single line in the list. Each line contains a BField object +// for each column in the list, associated by their "logical field" +// index. Hierarchies are formed by adding other BRow objects as +// a parent of a row, using the AddRow() function in BColumnListView(). +class BRow { +public: + BRow(float height = 16.0); + virtual ~BRow(); + virtual bool HasLatch() const; + + int32 CountFields() const; + BField* GetField(int32 logicalFieldIndex); + const BField* GetField(int32 logicalFieldIndex) const; + void SetField(BField* field, int32 logicalFieldIndex); + + float Height() const; + void SetHeight(float h){fHeight=h;}; + bool IsExpanded() const; + + virtual void DrawBackground( + BRect /*_rect*/, + BView* /*_target_view*/, + bool /*_is_selected*/, + bool /*_is_focus */){} +private: + // Blows up into the debugger if the validation fails. + void ValidateFields() const; + void ValidateField(const BField *field, int32 logicalFieldIndex) const; +private: + BList fFields; + BPrivate:: + BRowContainer* fChildList; + bool fIsExpanded; + float fHeight; + BRow* fNextSelected; + BRow* fPrevSelected; + BRow* fParent; +protected: + BColumnListView* fList; +private: + + friend class BColumnListView; + friend class BPrivate::RecursiveOutlineIterator; + friend class BPrivate::OutlineView; +}; + +// Information about a single column in the list. A column knows +// how to display the BField objects that occur at its location in +// each of the list's rows. See ColumnTypes.h for particular +// subclasses of BField and BColumn that handle common data types. +class BColumn +{ +public: + BColumn(float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + virtual ~BColumn(); + + float Width() const; + void SetWidth(float width); + float MinWidth() const; + float MaxWidth() const; + + virtual void DrawTitle(BRect rect, BView *targetView); + virtual void DrawField(BField *field, BRect rect, BView *targetView); + virtual int CompareFields(BField *field1, BField *field2); + + virtual void MouseMoved(BColumnListView *parent, BRow *row, BField *field, + BRect field_rect, BPoint point, uint32 buttons, int32 code); + virtual void MouseDown(BColumnListView *parent, BRow *row, BField *field, + BRect field_rect, BPoint point, uint32 buttons); + virtual void MouseUp(BColumnListView *parent, BRow *row, BField *field); + + virtual void GetColumnName(BString* into) const; + + bool IsVisible() const; + void SetVisible(bool); + + bool WantsEvents() const; + void SetWantsEvents(bool); + + bool ShowHeading() const; + void SetShowHeading(bool); + + alignment Alignment() const; + void SetAlignment(alignment); + + int32 LogicalFieldNum() const; + + /*! + \param field The BField derivative to validate. + + Implement this function on your BColumn derivatives to validate BField derivatives + that your BColumn will be drawing/manipulating. + + This function will be called when BFields are added to the Column, use dynamic_cast<> to + determine if it is of a kind that your BColumn know how ot handle. return false if it is not. + + \note The debugger will be called if you return false from here with information about + what type of BField and BColumn and the logical field index where it occured. + + \note Do not call the inherited version of this, it just returns true; + */ + virtual bool AcceptsField(const BField* field) const; + +private: + float fWidth; + float fMinWidth; + float fMaxWidth; + bool fVisible; + int32 fFieldID; + BColumnListView *fList; + bool fSortAscending; + bool fWantsEvents; + bool fShowHeading; + alignment fAlignment; + + friend class BPrivate::OutlineView; + friend class BColumnListView; + friend class BPrivate::TitleView; +}; + +// The column list view class. +class BColumnListView : public BView, public BInvoker +{ +public: + BColumnListView(BRect rect, + const char *name, + uint32 resizingMode, + uint32 drawFlags, + border_style = B_NO_BORDER, + bool showHorizontalScrollbar = true); + virtual ~BColumnListView(); + + // Interaction + virtual bool InitiateDrag(BPoint, bool wasSelected); + virtual void MessageDropped(BMessage*, BPoint point); + virtual void ExpandOrCollapse(BRow *row, bool expand); + virtual status_t Invoke(BMessage *message = NULL); + virtual void ItemInvoked(); + virtual void SetInvocationMessage(BMessage*); + BMessage* InvocationMessage() const; + uint32 InvocationCommand() const; + BRow* FocusRow() const; + void SetFocusRow(int32 index, bool select=false); + void SetFocusRow(BRow *row, bool select=false); + void SetMouseTrackingEnabled(bool); + + // Selection + list_view_type SelectionMode() const; + void Deselect(BRow *row); + void AddToSelection(BRow *row); + void DeselectAll(); + BRow* CurrentSelection(BRow *lastSelected = 0) const; + virtual void SelectionChanged(); + virtual void SetSelectionMessage(BMessage *); + BMessage* SelectionMessage(); + uint32 SelectionCommand() const; + void SetSelectionMode(list_view_type); // list_view_type is defined in ListView.h. + + // Sorting + void SetSortingEnabled(bool); + bool SortingEnabled() const; + void SetSortColumn(BColumn *column, bool add, bool ascending); + void ClearSortColumns(); + + // The status view is a little area in the lower left hand corner. + void AddStatusView(BView *view); + BView* RemoveStatusView(); + + // Column Manipulation + void AddColumn(BColumn*, int32 logicalFieldIndex); + void MoveColumn(BColumn*, int32 index); + void RemoveColumn(BColumn*); + int32 CountColumns() const; + BColumn* ColumnAt(int32 index) const; + void SetColumnVisible(BColumn*, bool isVisible); + void SetColumnVisible(int32, bool); + bool IsColumnVisible(int32) const; + void SetColumnFlags(column_flags flags); + + // Row manipulation + const BRow* RowAt(int32 index, BRow *parent = 0) const; + BRow* RowAt(int32 index, BRow *parent = 0); + const BRow* RowAt(BPoint) const; + BRow* RowAt(BPoint); + bool GetRowRect(const BRow *row, BRect *outRect) const; + bool FindParent(BRow *row, BRow **outs_parent, bool *out_isVisible) const; + int32 IndexOf(BRow *row); + int32 CountRows(BRow *parent = 0) const; + void AddRow(BRow*, BRow *parent = 0); + void AddRow(BRow*, int32 index, BRow *parent = 0); + + void ScrollTo(const BRow* Row); + + // Does not delete row or children at this time. + // todo: Make delete row and children + void RemoveRow(BRow*); + + void UpdateRow(BRow*); + void Clear(); + + // Appearance (DEPRECATED) + void GetFont(BFont* font) const {BView::GetFont(font);} + virtual void SetFont(const BFont *font, uint32 mask = B_FONT_ALL); + virtual void SetHighColor(rgb_color); + void SetSelectionColor(rgb_color); + void SetBackgroundColor(rgb_color); + void SetEditColor(rgb_color); + const rgb_color SelectionColor() const; + const rgb_color BackgroundColor() const; + const rgb_color EditColor() const; + + // Appearance (NEW STYLE) + void SetColor(ColumnListViewColor color_num, rgb_color color); + void SetFont(ColumnListViewFont font_num, const BFont* font, uint32 mask = B_FONT_ALL); + rgb_color Color(ColumnListViewColor color_num) const; + void GetFont(ColumnListViewFont font_num, BFont* font) const; + + BPoint SuggestTextPosition(const BRow* row, const BColumn* column=NULL) const; + + void SetLatchWidth(float width); + float LatchWidth() const; + virtual void DrawLatch(BView*, BRect, LatchType, BRow*); + virtual void MakeFocus(bool isfocus = true); + void SaveState(BMessage *msg); + void LoadState(BMessage *msg); + + BView* ScrollView() const { return (BView *)fOutlineView; } + void SetEditMode(bool state); + void Refresh(); + BView* GetScrollView(){ return (BView*)fOutlineView;} + BView* GetTitleView(){ return (BView*)fTitleView;} +protected: + virtual void MessageReceived(BMessage *message); + virtual void KeyDown(const char *bytes, int32 numBytes); + virtual void AttachedToWindow(); + virtual void WindowActivated(bool active); + virtual void Draw(BRect); + + + + +private: + rgb_color fColorList[B_COLOR_TOTAL]; + BPrivate::TitleView* fTitleView; + BPrivate::OutlineView* fOutlineView; + BList fColumns; + BScrollBar* fHorizontalScrollBar; + BScrollBar* fVerticalScrollBar; + BList fSortColumns; + BView* fStatusView; + BMessage* fSelectionMessage; + bool fSortingEnabled; + float fLatchWidth; + border_style fBorderStyle; +}; + +#endif diff --git a/include/libclv/ColumnTypes.h b/include/libclv/ColumnTypes.h new file mode 100644 index 0000000..9a02beb --- /dev/null +++ b/include/libclv/ColumnTypes.h @@ -0,0 +1,254 @@ +/******************************************************************************* +/ +/ File: ColumnTypes.h +/ +/ Description: Experimental classes that implement particular column/field +/ data types for use in BColumnListView. +/ +/ Copyright 2000+, Be Incorporated, All Rights Reserved +/ +*******************************************************************************/ + + +#ifndef _COLUMN_TYPES_H +#define _COLUMN_TYPES_H + +#include "ColumnListView.h" +#include +#include +#include + + +//===================================================================== +// Common base-class: a column that draws a standard title at its top. + +class BTitledColumn : public BColumn +{ + public: + BTitledColumn (const char *title, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + virtual void DrawTitle (BRect rect, + BView* parent); + virtual void GetColumnName (BString* into) const; + + void DrawString (const char*, + BView*, + BRect); + void SetTitle (const char* title); + void Title (BString* forTitle) const; // sets the BString arg to be the title + float FontHeight () const; + + private: + float fFontHeight; + BString fTitle; +}; + + +//===================================================================== +// Field and column classes for strings. + +class BStringField : public BField +{ + public: + BStringField (const char* string); + + void SetString (const char* string); + const char* String () const; + void SetClippedString (const char* string); + const char* ClippedString (); + void SetWidth (float); + float Width (); + + private: + float fWidth; + BString fString; + BString fClippedString; +}; + + +//-------------------------------------------------------------------- + +class BStringColumn : public BTitledColumn +{ + public: + BStringColumn (const char *title, + float width, + float maxWidth, + float minWidth, + uint32 truncate, + alignment align = B_ALIGN_LEFT); + virtual void DrawField (BField* field, + BRect rect, + BView* parent); + virtual int CompareFields (BField* field1, + BField* field2); + virtual bool AcceptsField (const BField* field) const; + + private: + uint32 fTruncate; +}; + + +//===================================================================== +// Field and column classes for dates. + +class BDateField : public BField +{ + public: + BDateField (time_t* t); + void SetWidth (float); + float Width (); + void SetClippedString (const char*); + const char* ClippedString (); + time_t Seconds (); + time_t UnixTime (); + + private: + struct tm fTime; + time_t fUnixTime; + time_t fSeconds; + BString fClippedString; + float fWidth; +}; + + +//-------------------------------------------------------------------- + +class BDateColumn : public BTitledColumn +{ + public: + BDateColumn (const char* title, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + virtual void DrawField (BField* field, + BRect rect, + BView* parent); + virtual int CompareFields (BField* field1, + BField* field2); + private: + BString fTitle; +}; + + +//===================================================================== +// Field and column classes for numeric sizes. + +class BSizeField : public BField +{ + public: + BSizeField (off_t size); + void SetSize (off_t); + off_t Size (); + + private: + off_t fSize; +}; + + +//-------------------------------------------------------------------- + +class BSizeColumn : public BTitledColumn +{ + public: + BSizeColumn (const char* title, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + virtual void DrawField (BField* field, + BRect rect, + BView* parent); + virtual int CompareFields (BField* field1, + BField* field2); +}; + + +//===================================================================== +// Field and column classes for integers. + +class BIntegerField : public BField +{ + public: + BIntegerField (int32 number); + void SetValue (int32); + int32 Value (); + + private: + int32 fInteger; +}; + + +//-------------------------------------------------------------------- + +class BIntegerColumn : public BTitledColumn +{ + public: + BIntegerColumn (const char* title, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + virtual void DrawField (BField* field, + BRect rect, + BView* parent); + virtual int CompareFields (BField* field1, + BField* field2); +}; + + +//===================================================================== +// Field and column classes for bitmaps + +class BBitmapField : public BField +{ + public: + BBitmapField (BBitmap* bitmap); + const BBitmap* Bitmap (); + void SetBitmap (BBitmap* bitmap); + + private: + BBitmap* fBitmap; +}; + + +//-------------------------------------------------------------------- + +class BBitmapColumn : public BTitledColumn +{ + public: + BBitmapColumn (const char* title, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + virtual void DrawField (BField*field, + BRect rect, + BView* parent); + virtual int CompareFields (BField* field1, BField* field2); + virtual bool AcceptsField (const BField* field) const; +}; + + +//===================================================================== +// Column to display BIntegerField objects as a graph. + +class GraphColumn : public BIntegerColumn +{ + public: + GraphColumn (const char* name, + float width, + float minWidth, + float maxWidth, + alignment align = B_ALIGN_LEFT); + virtual void DrawField (BField*field, + BRect rect, + BView* parent); +}; + +#endif + diff --git a/include/libfish/HelpViewer.h b/include/libfish/HelpViewer.h new file mode 100644 index 0000000..2776013 --- /dev/null +++ b/include/libfish/HelpViewer.h @@ -0,0 +1,60 @@ +#ifndef HelpViewer_H_ +#define HelpViewer_H_ + +#include + +//#include "KeyMap.h" +#include +#include "libxml/tree.h" +#include "libxml/xpath.h" +#include "libxml/xpathInternals.h" +#include "libxml/parserInternals.h" +#include "libxml/debugXML.h" + +class HDoc; + +#define HELPVIEWER_OPEN_URL 'opur' +#define HELPVIEWER_GOTO 'goto' + +class HelpViewer : public BView { + + public: + HelpViewer(BRect r); + virtual ~HelpViewer(); + + void LoadFile(const char* file); + void ParsePage(xmlNodePtr node); + + void SetPage(uint); + int CountPage(); + + void SetForeColor(rgb_color c); + void SetBackColor(rgb_color c); + + void SetOpenUrlHandler(BHandler* hand); + void SetGotoHandler(BHandler* hand); + + void MessageReceived(BMessage* msg); + void SearchSetPage(BString id); + + void AttachedToWindow(); + + private: + + + void RecalcScrollbar(); + void findAttribute(xmlNodePtr node,BMessage*); + + + + //KeyMap fPages; + BObjectList fPages; + int16 Selected; + + rgb_color foreColor; + rgb_color backColor; + BHandler *fGotoHand; + +}; +#endif +// -- diff --git a/include/libfunky/Colors.h b/include/libfunky/Colors.h new file mode 100644 index 0000000..42a582f --- /dev/null +++ b/include/libfunky/Colors.h @@ -0,0 +1,53 @@ +//Useful until be gets around to making these sorts of things +//globals akin to be_plain_font, etc. + + +#ifndef _SGB_COLORS_H_ +#define _SGB_COLORS_H_ + + +//****************************************************************************************************** +//**** SYSTEM HEADER FILES +//****************************************************************************************************** +#include + + +//****************************************************************************************************** +//**** CONSTANT DEFINITIONS +//****************************************************************************************************** +//Be standard UI colors +const rgb_color BeBackgroundGrey = {216,216,216, 255}; +const rgb_color BeInactiveControlGrey = {240,240,240, 255}; +const rgb_color BeFocusBlue = {0, 0, 229, 255}; +const rgb_color BeHighlight = {255,255,255, 255}; +const rgb_color BeShadow = {152,152,152, 255}; +const rgb_color BeDarkShadow = {108,108,108, 255}; +const rgb_color BeLightShadow = {194,194,194, 255}; +const rgb_color BeButtonGrey = {232,232,232, 255}; +const rgb_color BeInactiveGrey = {127,127,127, 255}; +const rgb_color BeListSelectGrey = {178,178,178, 255}; +const rgb_color BeTitleBarYellow = {255,203,0, 255}; + +//Other colors +const rgb_color Black = {0, 0, 0, 255}; +const rgb_color White = {255,255,255, 255}; +const rgb_color Red = {255,0, 0, 255}; +const rgb_color Green = {0, 167,0, 255}; +const rgb_color LightGreen = {90, 240,90, 255}; +const rgb_color Blue = {49, 61, 225, 255}; +const rgb_color LightBlue = {64, 162,255, 255}; +const rgb_color Purple = {144,64, 221, 255}; +const rgb_color LightPurple = {166,74, 255, 255}; +const rgb_color Lavender = {193,122,255, 255}; +const rgb_color Yellow = {255,203,0, 255}; +const rgb_color Orange = {255,163,0, 255}; +const rgb_color Flesh = {255,231,186, 255}; +const rgb_color Tan = {208,182,121, 255}; +const rgb_color Brown = {154,110,45, 255}; +const rgb_color Grey = {200,200,200, 255}; +const rgb_color LightMetallicBlue = {143,166,240, 255}; +const rgb_color MedMetallicBlue = {75, 96, 154, 255}; +const rgb_color DarkMetallicBlue = {78, 89, 126, 255}; + + +#endif diff --git a/include/libfunky/ImageCache.h b/include/libfunky/ImageCache.h new file mode 100644 index 0000000..47c28d1 --- /dev/null +++ b/include/libfunky/ImageCache.h @@ -0,0 +1,52 @@ +#ifndef ImageCache_H +#define ImageCache_H + + /** + * ImageCache. + * @author Andrea Anzani. + */ + +class BBitmap; + +#include +#include +#include "KeyMap.h" + +class ImageCache +{ + +protected: // Constructor/Destructor + + ImageCache(); + + ~ImageCache(); + +public: // Operations + + /** Returns the image corresponding to the which constant */ + static BBitmap * GetImage( BString which ,BString name); + + + static void AddImage(BString name,BBitmap* which); + static void DeleteImage(BString name); + + /** Frees the singleton instance of the cache; + Call this when app quits + */ + static void Release(); + +private: + + static BBitmap * LoadImage( const char *resourceName,const char *); + // Class Data + + static ImageCache * m_instance; + +private: // Instance Data + + + KeyMap m_bitmaps; + +}; + +#endif /* __C_ImageCache_H__ */ diff --git a/include/libfunky/KeyMap.h b/include/libfunky/KeyMap.h new file mode 100644 index 0000000..0406536 --- /dev/null +++ b/include/libfunky/KeyMap.h @@ -0,0 +1,207 @@ +#ifndef __Keymap_h__ +#define __Keymap_h__ + +#include +#include + +using namespace std; + +template +class KeyMap +{ +public: + + bool AddItem( T1 const & key, T2 const & value); + bool RemoveItemFor( T1 const & key); + + T2 ValueFor(T1 key,bool* found = NULL); + T2 ValueAt(int32 position); + + T1 KeyAt(int32 position); + void RemoveItemAt(int32 position); + + uint32 CountItems(); + + void PrintToStream(); + bool MakeEmpty(); + bool IsEmpty(); + +private: + + bool getValue( T1 const & key, T2 *value); //returns value + bool getIndex( T2 const & value, T1 *key ); //returns key + + bool getFirst( T1 *key, T2 *value ); + bool getNext( T1 *key, T2 *value ); + + typename std::map::iterator begin(); + typename std::map::iterator end(); + + std::map m_Map; + typename std::map::iterator m_pPos; +}; + +template +bool KeyMap::AddItem( T1 const & key, T2 const & value) +{ + + std::pair::iterator,bool> result = m_Map.insert( make_pair(key, value) ); + if (!result.second) { + return false; + } + + return true; +} + +template +bool KeyMap::RemoveItemFor( T1 const & key ) +{ + m_Map.erase( key ); + return true; +} + +template +bool KeyMap::IsEmpty() +{ + return m_Map.empty(); +} + + +template +bool KeyMap::MakeEmpty() +{ + m_Map.clear(); + return true; +} + + + +template +bool KeyMap::getIndex( T2 const & value, T1 *key ) +{ + //do something with all elements having a certain value + typename std::map::iterator pos; + for (pos = m_Map.begin(); pos != m_Map.end(); ++pos) { + if (pos->second == value) { + *key = (pos->first); + return true; + } + } + return false; +} + +template +bool KeyMap::getFirst( T1 *key, T2 *value ) +{ + if (m_Map.empty() ) { + return false; + } + //do something with all elements having a certain value + typename std::map::iterator pos; + m_pPos= m_Map.begin(); + *key = m_pPos->first; + *value= m_pPos->second; + return true; +} + +template +bool KeyMap::getNext( T1 *key, T2 *value ) +{ + if ( m_Map.empty() ) { + return false; + } + if ( ++m_pPos == m_Map.end() ) { + return false; + } + *key = m_pPos->first; + *value= m_pPos->second; + return true; +} + +template +bool KeyMap::getValue(T1 const & key, T2 *value) +{ + typename std::map::iterator pos; + pos = m_Map.find(key); + if (m_Map.end() != pos) { + *value = pos->second; + return true; + } + return false; +} + +template +T2 KeyMap::ValueFor(T1 key, bool* found) +{ + T2 pointer; + if (found) + { + *found = getValue(key, &pointer); + return ((*found) ? pointer : NULL); + } + bool f = getValue(key, &pointer); + return (f ? pointer : NULL); +} + +template +T2 KeyMap::ValueAt(int32 position) +{ + typename std::map::iterator i = begin(); + std::advance(i, position); + if(i == end()) + return NULL; + else + return i->second; +} + +template +T1 KeyMap::KeyAt(int32 position) +{ + typename std::map::iterator i = begin(); + std::advance(i, position); + if(i == end()) + return NULL; + else + return i->first; +} + +template +void KeyMap::RemoveItemAt(int32 position) +{ + typename std::map::iterator i = begin(); + std::advance(i, position); + RemoveItemFor(i->first); +} + + +template +uint32 KeyMap::CountItems() +{ + return m_Map.size(); +} + +template +void KeyMap::PrintToStream() +{ + typename std::map::iterator pos; + cout << std::endl << " -- KeyMap::PrintToStream --" << std::endl; + for (pos = m_Map.begin(); pos != m_Map.end(); ++pos) { + cout << pos->first <<" : " << pos->second << std::endl; + } +} + +template +typename std::map::iterator KeyMap::begin() +{ + m_pPos = m_Map.begin(); + return m_pPos; +} + +template +typename std::map::iterator KeyMap::end() +{ + m_pPos = m_Map.end(); + return m_pPos; +} + +#endif // __Keymap_h__ diff --git a/include/libfunky/ObjectList.h b/include/libfunky/ObjectList.h new file mode 100644 index 0000000..bfa1832 --- /dev/null +++ b/include/libfunky/ObjectList.h @@ -0,0 +1,866 @@ +/* +Open Tracker License + +Terms and Conditions + +Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice applies to all licensees +and shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Be Incorporated shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from Be Incorporated. + +Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks +of Be Incorporated in the United States and other countries. Other brand product +names are registered trademarks or trademarks of their respective holders. +All rights reserved. +*/ + +/**************************************************************************** +** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ** +** ** +** DANGER, WILL ROBINSON! ** +** ** +** The interfaces contained here are part of BeOS's ** +** ** +** >> PRIVATE NOT FOR PUBLIC USE << ** +** ** +** implementation. ** +** ** +** These interfaces WILL CHANGE in future releases. ** +** If you use them, your app WILL BREAK at some future time. ** +** ** +** (And yes, this does mean that binaries built from OpenTracker will not ** +** be compatible with some future releases of the OS. When that happens, ** +** we will provide an updated version of this file to keep compatibility.) ** +** ** +** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ** +****************************************************************************/ + +// +// ObjectList is a wrapper around BList that adds type safety, +// optional object ownership, search, insert operations, etc. +// + +#ifndef __OBJECT_LIST__ +#define __OBJECT_LIST__ + +#ifndef _BE_H +#include +#endif + +#include + + +template class BObjectList; + +template +struct UnaryPredicate { + + virtual int operator()(const T *) const + // virtual could be avoided here if FindBinaryInsertionIndex, + // etc. were member template functions + { return 0; } + +private: + static int _unary_predicate_glue(const void *item, void *context); + +friend class BObjectList; +}; + +template +int +UnaryPredicate::_unary_predicate_glue(const void *item, void *context) +{ + return ((UnaryPredicate *)context)->operator()((const T *)item); +} + + +class _PointerList_ : public BList { +public: + _PointerList_(const _PointerList_ &list); + _PointerList_(int32 itemsPerBlock = 20, bool owning = false); + ~_PointerList_(); + + typedef void *(* GenericEachFunction)(void *, void *); + typedef int (* GenericCompareFunction)(const void *, const void *); + typedef int (* GenericCompareFunctionWithState)(const void *, const void *, + void *); + typedef int (* UnaryPredicateGlue)(const void *, void *); + + void *EachElement(GenericEachFunction, void *); + void SortItems(GenericCompareFunction); + void SortItems(GenericCompareFunctionWithState, void *state); + void HSortItems(GenericCompareFunction); + void HSortItems(GenericCompareFunctionWithState, void *state); + + void *BinarySearch(const void *, GenericCompareFunction) const; + void *BinarySearch(const void *, GenericCompareFunctionWithState, void *state) const; + + int32 BinarySearchIndex(const void *, GenericCompareFunction) const; + int32 BinarySearchIndex(const void *, GenericCompareFunctionWithState, void *state) const; + int32 BinarySearchIndexByPredicate(const void *, UnaryPredicateGlue) const; + + bool Owning() const; + bool ReplaceItem(int32, void *); + +protected: + bool owning; + +}; + +template +class BObjectList : private _PointerList_ { +public: + + // iteration and sorting + typedef T *(* EachFunction)(T *, void *); + typedef const T *(* ConstEachFunction)(const T *, void *); + typedef int (* CompareFunction)(const T *, const T *); + typedef int (* CompareFunctionWithState)(const T *, const T *, void *state); + + BObjectList(int32 itemsPerBlock = 20, bool owning = false); + BObjectList(const BObjectList &list); + // clones list; if list is owning, makes copies of all + // the items + + virtual ~BObjectList(); + + BObjectList &operator=(const BObjectList &list); + // clones list; if list is owning, makes copies of all + // the items + + // adding and removing + // ToDo: + // change Add calls to return const item + bool AddItem(T *); + bool AddItem(T *, int32); + bool AddList(BObjectList *); + bool AddList(BObjectList *, int32); + + bool RemoveItem(T *, bool deleteIfOwning = true); + // if owning, deletes the removed item + T *RemoveItemAt(int32); + // returns the removed item + + void MakeEmpty(bool deleteIfOwning = true); + + // item access + T *ItemAt(int32) const; + + bool ReplaceItem(int32 index, T *); + // if list is owning, deletes the item at first + T *SwapWithItem(int32 index, T *newItem); + // same as ReplaceItem, except does not delete old item at , + // returns it instead + + T *FirstItem() const; + T *LastItem() const; + + // misc. getters + int32 IndexOf(const T *) const; + bool HasItem(const T *) const; + bool IsEmpty() const; + int32 CountItems() const; + + T *EachElement(EachFunction, void *); + const T *EachElement(ConstEachFunction, void *) const; + + void SortItems(CompareFunction); + void SortItems(CompareFunctionWithState, void *state); + void HSortItems(CompareFunction); + void HSortItems(CompareFunctionWithState, void *state); + + // linear search, returns first item that matches predicate + const T *FindIf(const UnaryPredicate &) const; + T *FindIf(const UnaryPredicate &); + + // list must be sorted with CompareFunction for these to work + T *BinarySearch(const T &, CompareFunction) const; + T *BinarySearch(const T &, CompareFunctionWithState, void *state) const; + + template + T *BinarySearchByKey(const Key &key, int (*compare)(const Key *, const T *)) + const; + + template + T *BinarySearchByKey(const Key &key, + int (*compare)(const Key *, const T *, void *), void *state) const; + + int32 BinarySearchIndex(const T &item, CompareFunction compare) const; + int32 BinarySearchIndex(const T &item, CompareFunctionWithState compare, + void *state) const; + + template + int32 BinarySearchIndexByKey(const Key &key, + int (*compare)(const Key *, const T *)) const; + + // Binary insertion - list must be sorted with CompareFunction for + // these to work + + // simple insert + bool BinaryInsert(T *, CompareFunction); + bool BinaryInsert(T *, CompareFunctionWithState, void *state); + bool BinaryInsert(T *, const UnaryPredicate &); + + // unique insert, returns false if item already in list + bool BinaryInsertUnique(T *, CompareFunction); + bool BinaryInsertUnique(T *, CompareFunctionWithState, void *state); + bool BinaryInsertUnique(T *, const UnaryPredicate &); + + // insert a copy of the item, returns new inserted item + T *BinaryInsertCopy(const T ©This, CompareFunction); + T *BinaryInsertCopy(const T ©This, CompareFunctionWithState, void *state); + + // insert a copy of the item if not in list already + // returns new inserted item or existing item in case of a conflict + T *BinaryInsertCopyUnique(const T ©This, CompareFunction); + T *BinaryInsertCopyUnique(const T ©This, CompareFunctionWithState, void *state); + + int32 FindBinaryInsertionIndex(const UnaryPredicate &, bool *alreadyInList = 0) const; + // returns either the index into which a new item should be inserted + // or index of an existing item that matches the predicate + + // deprecated API, will go away + BList *AsBList() + { return this; } + const BList *AsBList() const + { return this; } +private: + void SetItem(int32, T *); +}; + +template +Result +WhileEachListItem(BObjectList *list, Result (Item::*func)(Param1), Param1 p1) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (list->ItemAt(index)->*func)(p1)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (*func)(Item *, Param1), Param1 p1) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (*func)(list->ItemAt(index), p1)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (Item::*func)(Param1, Param2), + Param1 p1, Param2 p2) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (list->ItemAt(index)->*func)(p1, p2)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (*func)(Item *, Param1, Param2), + Param1 p1, Param2 p2) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (*func)(list->ItemAt(index), p1, p2)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (*func)(Item *, Param1, Param2, + Param3, Param4), Param1 p1, Param2 p2, Param3 p3, Param4 p4) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (*func)(list->ItemAt(index), p1, p2, p3, p4)) != 0) + break; + + return result; +} + +template +void +EachListItemIgnoreResult(BObjectList *list, Result (Item::*func)()) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (list->ItemAt(index)->*func)(); +} + +template +void +EachListItem(BObjectList *list, void (*func)(Item *, Param1), Param1 p1) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1); +} + +template +void +EachListItem(BObjectList *list, void (Item::*func)(Param1, Param2), + Param1 p1, Param2 p2) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (list->ItemAt(index)->*func)(p1, p2); +} + +template +void +EachListItem(BObjectList *list, void (*func)(Item *,Param1, Param2), + Param1 p1, Param2 p2) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1, p2); +} + +template +void +EachListItem(BObjectList *list, void (*func)(Item *,Param1, Param2, + Param3), Param1 p1, Param2 p2, Param3 p3) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1, p2, p3); +} + + +template +void +EachListItem(BObjectList *list, void (*func)(Item *,Param1, Param2, + Param3, Param4), Param1 p1, Param2 p2, Param3 p3, Param4 p4) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1, p2, p3, p4); +} + +// inline code + +inline bool +_PointerList_::Owning() const +{ + return owning; +} + +template +BObjectList::BObjectList(int32 itemsPerBlock, bool owning) + : _PointerList_(itemsPerBlock, owning) +{ +} + +template +BObjectList::BObjectList(const BObjectList &list) + : _PointerList_(list) +{ + owning = list.owning; + if (owning) { + // make our own copies in an owning list + int32 count = list.CountItems(); + for (int32 index = 0; index < count; index++) { + T *item = list.ItemAt(index); + if (item) + item = new T(*item); + SetItem(index, item); + } + } +} + +template +BObjectList::~BObjectList() +{ + if (Owning()) + // have to nuke elements first + MakeEmpty(); +} + +template +BObjectList & +BObjectList::operator=(const BObjectList &list) +{ + owning = list.owning; + BObjectList &result = (BObjectList &)_PointerList_::operator=(list); + if (owning) { + // make our own copies in an owning list + int32 count = list.CountItems(); + for (int32 index = 0; index < count; index++) { + T *item = list.ItemAt(index); + if (item) + item = new T(*item); + SetItem(index, item); + } + } + return result; +} + +template +bool +BObjectList::AddItem(T *item) +{ + // need to cast to void * to make T work for const pointers + return _PointerList_::AddItem((void *)item); +} + +template +bool +BObjectList::AddItem(T *item, int32 atIndex) +{ + return _PointerList_::AddItem((void *)item, atIndex); +} + +template +bool +BObjectList::AddList(BObjectList *newItems) +{ + return _PointerList_::AddList(newItems); +} + +template +bool +BObjectList::AddList(BObjectList *newItems, int32 atIndex) +{ + return _PointerList_::AddList(newItems, atIndex); +} + + +template +bool +BObjectList::RemoveItem(T *item, bool deleteIfOwning) +{ + bool result = _PointerList_::RemoveItem((void *)item); + + if (result && Owning() && deleteIfOwning) + delete item; + + return result; +} + +template +T * +BObjectList::RemoveItemAt(int32 index) +{ + return (T *)_PointerList_::RemoveItem(index); +} + +template +inline T * +BObjectList::ItemAt(int32 index) const +{ + return (T *)_PointerList_::ItemAt(index); +} + +template +bool +BObjectList::ReplaceItem(int32 index, T *item) +{ + if (owning) + delete ItemAt(index); + return _PointerList_::ReplaceItem(index, (void *)item); +} + +template +T * +BObjectList::SwapWithItem(int32 index, T *newItem) +{ + T *result = ItemAt(index); + _PointerList_::ReplaceItem(index, (void *)newItem); + return result; +} + +template +void +BObjectList::SetItem(int32 index, T *newItem) +{ + _PointerList_::ReplaceItem(index, (void *)newItem); +} + +template +int32 +BObjectList::IndexOf(const T *item) const +{ + return _PointerList_::IndexOf((void *)item); +} + +template +T * +BObjectList::FirstItem() const +{ + return (T *)_PointerList_::FirstItem(); +} + +template +T * +BObjectList::LastItem() const +{ + return (T *)_PointerList_::LastItem(); +} + +template +bool +BObjectList::HasItem(const T *item) const +{ + return _PointerList_::HasItem((void *)item); +} + +template +bool +BObjectList::IsEmpty() const +{ + return _PointerList_::IsEmpty(); +} + +template +int32 +BObjectList::CountItems() const +{ + return _PointerList_::CountItems(); +} + +template +void +BObjectList::MakeEmpty(bool deleteIfOwning) +{ + if (owning && deleteIfOwning) { + int32 count = CountItems(); + for (int32 index = 0; index < count; index++) + delete ItemAt(index); + } + _PointerList_::MakeEmpty(); +} + +template +T * +BObjectList::EachElement(EachFunction func, void *params) +{ + return (T *)_PointerList_::EachElement((GenericEachFunction)func, params); +} + + +template +const T * +BObjectList::EachElement(ConstEachFunction func, void *params) const +{ + return (const T *) + const_cast *>(this)->_PointerList_::EachElement( + (GenericEachFunction)func, params); +} + +template +const T * +BObjectList::FindIf(const UnaryPredicate &predicate) const +{ + int32 count = CountItems(); + for (int32 index = 0; index < count; index++) + if (predicate.operator()(ItemAt(index)) == 0) + return ItemAt(index); + return 0; +} + +template +T * +BObjectList::FindIf(const UnaryPredicate &predicate) +{ + int32 count = CountItems(); + for (int32 index = 0; index < count; index++) + if (predicate.operator()(ItemAt(index)) == 0) + return ItemAt(index); + return 0; +} + + +template +void +BObjectList::SortItems(CompareFunction function) +{ + _PointerList_::SortItems((GenericCompareFunction)function); +} + +template +void +BObjectList::SortItems(CompareFunctionWithState function, void *state) +{ + _PointerList_::SortItems((GenericCompareFunctionWithState)function, state); +} + +template +void +BObjectList::HSortItems(CompareFunction function) +{ + _PointerList_::HSortItems((GenericCompareFunction)function); +} + +template +void +BObjectList::HSortItems(CompareFunctionWithState function, void *state) +{ + _PointerList_::HSortItems((GenericCompareFunctionWithState)function, state); +} + +template +T * +BObjectList::BinarySearch(const T &key, CompareFunction func) const +{ + return (T*)_PointerList_::BinarySearch(&key, + (GenericCompareFunction)func); +} + +template +T * +BObjectList::BinarySearch(const T &key, CompareFunctionWithState func, void *state) const +{ + return (T*)_PointerList_::BinarySearch(&key, + (GenericCompareFunctionWithState)func, state); +} + + +template +template +T * +BObjectList::BinarySearchByKey(const Key &key, + int (*compare)(const Key *, const T *)) const +{ + return (T*)_PointerList_::BinarySearch(&key, + (GenericCompareFunction)compare); +} + + +template +template +T * +BObjectList::BinarySearchByKey(const Key &key, + int (*compare)(const Key *, const T *, void *), void *state) const +{ + return (T*)_PointerList_::BinarySearch(&key, + (GenericCompareFunctionWithState)compare, state); +} + + +template +int32 +BObjectList::BinarySearchIndex(const T &item, CompareFunction compare) const +{ + return _PointerList_::BinarySearchIndex(&item, + (GenericCompareFunction)compare); +} + + +template +int32 +BObjectList::BinarySearchIndex(const T &item, + CompareFunctionWithState compare, void *state) const +{ + return _PointerList_::BinarySearchIndex(&item, + (GenericCompareFunctionWithState)compare, state); +} + + +template +template +int32 +BObjectList::BinarySearchIndexByKey(const Key &key, + int (*compare)(const Key *, const T *)) const +{ + return _PointerList_::BinarySearchIndex(&key, + (GenericCompareFunction)compare); +} + + +template +bool +BObjectList::BinaryInsert(T *item, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunction)func); + if (index >= 0) { + // already in list, add after existing + return AddItem(item, index + 1); + } + + return AddItem(item, -index - 1); +} + +template +bool +BObjectList::BinaryInsert(T *item, CompareFunctionWithState func, void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunctionWithState)func, state); + if (index >= 0) { + // already in list, add after existing + return AddItem(item, index + 1); + } + + return AddItem(item, -index - 1); +} + +template +bool +BObjectList::BinaryInsertUnique(T *item, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunction)func); + if (index >= 0) + return false; + + return AddItem(item, -index - 1); +} + +template +bool +BObjectList::BinaryInsertUnique(T *item, CompareFunctionWithState func, void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunctionWithState)func, state); + if (index >= 0) + return false; + + return AddItem(item, -index - 1); +} + + +template +T * +BObjectList::BinaryInsertCopy(const T ©This, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunction)func); + + if (index >= 0) + index++; + else + index = -index - 1; + + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +T * +BObjectList::BinaryInsertCopy(const T ©This, CompareFunctionWithState func, void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunctionWithState)func, state); + + if (index >= 0) + index++; + else + index = -index - 1; + + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +T * +BObjectList::BinaryInsertCopyUnique(const T ©This, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunction)func); + if (index >= 0) + return ItemAt(index); + + index = -index - 1; + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +T * +BObjectList::BinaryInsertCopyUnique(const T ©This, CompareFunctionWithState func, + void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunctionWithState)func, state); + if (index >= 0) + return ItemAt(index); + + index = -index - 1; + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +int32 +BObjectList::FindBinaryInsertionIndex(const UnaryPredicate &pred, bool *alreadyInList) + const +{ + int32 index = _PointerList_::BinarySearchIndexByPredicate(&pred, + (UnaryPredicateGlue)&UnaryPredicate::_unary_predicate_glue); + + if (alreadyInList) + *alreadyInList = index >= 0; + + if (index < 0) + index = -index - 1; + + return index; +} + +template +bool +BObjectList::BinaryInsert(T *item, const UnaryPredicate &pred) +{ + return AddItem(item, FindBinaryInsertionIndex(pred)); +} + +template +bool +BObjectList::BinaryInsertUnique(T *item, const UnaryPredicate &pred) +{ + bool alreadyInList; + int32 index = FindBinaryInsertionIndex(pred, &alreadyInList); + if (alreadyInList) + return false; + + AddItem(item, index); + return true; +} + +#endif /* __OBJECT_LIST__ */ diff --git a/include/libfunky/PBox.h b/include/libfunky/PBox.h new file mode 100644 index 0000000..b5710db --- /dev/null +++ b/include/libfunky/PBox.h @@ -0,0 +1,59 @@ +#ifndef PBox_H +#define PBox_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ObjectList.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +class BBox; +class BButton; + +class PBox : public BBox { + enum { + LISTCHANGED, + SAVE, + REVERT + }; + + public: + + PBox(BRect rect,BMessage fTemplate, BMessage fData,const char* settings_name); + + void AttachedToWindow(); + virtual void MessageReceived(BMessage *msg); + + void GetData(BMessage* data); + + const char* GetSettingsName(){ return fSName.String();} + private: + + float BuildGUI(BMessage viewTemplate, BMessage settings,BView *view); + + BView *fView; + + BView* fPrefView; + + BMessage fTemplate; + BMessage fData; + float fFontHeight; + BString fSName; + +}; + +#endif diff --git a/include/libfunky/Setting.h b/include/libfunky/Setting.h new file mode 100644 index 0000000..2debf94 --- /dev/null +++ b/include/libfunky/Setting.h @@ -0,0 +1,24 @@ +#ifndef Setting_H_ +#define Setting_H_ + +#include +#include + +class Setting : public BMessage { + + public: + + Setting(const char* name); + + void Store(); + void Retrive(); + + BString SettingPath(); + + private: + BString filename; +}; + +#endif + +//.. diff --git a/include/libfunky/SettingsTextView.h b/include/libfunky/SettingsTextView.h new file mode 100644 index 0000000..d16b54b --- /dev/null +++ b/include/libfunky/SettingsTextView.h @@ -0,0 +1,25 @@ +#ifndef SettingsTextView_H_ +#define SettingsTextView_H_ + +#include +#include +#include + + +class SettingsTextView : public BView +{ + public: + SettingsTextView(BRect frame, char *name, BString testo); + void AttachedToWindow(); + void Draw(BRect updateRect); + void SetText(const char*text){fText.SetTo(text);}; + BString Text(){ return fText; } + private: + BString fText; + + + + +}; + +#endif diff --git a/include/libfunky/Utils.h b/include/libfunky/Utils.h new file mode 100644 index 0000000..e8fbac0 --- /dev/null +++ b/include/libfunky/Utils.h @@ -0,0 +1,39 @@ +#ifndef _Utils_H_ +#define _Utils_H_ + +#include +#include +#include +#include + + +BString GetAppRelativePath(); +BString GetAppFilename(); +bool CheckMIME(BString mime,BNode* node); + +BBitmap* LoadIcon(const char* name); +void AddIcon(const char* name,BBitmap*); + + + +status_t ReadAttributeData(BNode* node,const char *name, char **buffer, int32 *size); + +status_t ReadAttributeString(BNode* node,const char *name, char **buffer, int32 *size); +BString ReadAttributeString(BNode* node,const char *name); + +status_t ReadAttributeInt32(BNode* node,const char *name, int32 *dest); +int32 ReadAttributeInt32(BNode* node,const char *name); + +status_t WriteAttributeInt32(BNode* node,const char *name, int32 dest); +status_t WriteAttributeString(BNode* node,const char *name, const char* string); + +status_t WriteAttributeMessage(BNode* node,const char* name,BMessage*); +status_t ReadAttributeMessage(BNode* node,const char* name,BMessage*); + +BString ReadableSize(off_t bytes); +BString ReadableSpeed(float speed); + +void BPDrawString(const char* string, BView* parent, BRect rect,alignment ali,float kTextMargin = 0.0); + + +#endif diff --git a/include/libxml/DOCBparser.h b/include/libxml/DOCBparser.h new file mode 100644 index 0000000..461d4ee --- /dev/null +++ b/include/libxml/DOCBparser.h @@ -0,0 +1,96 @@ +/* + * Summary: old DocBook SGML parser + * Description: interface for a DocBook SGML non-verifying parser + * This code is DEPRECATED, and should not be used anymore. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __DOCB_PARSER_H__ +#define __DOCB_PARSER_H__ +#include + +#ifdef LIBXML_DOCB_ENABLED + +#include +#include + +#ifndef IN_LIBXML +#ifdef __GNUC__ +#warning "The DOCBparser module has been deprecated in libxml2-2.6.0" +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Most of the back-end structures from XML and SGML are shared. + */ +typedef xmlParserCtxt docbParserCtxt; +typedef xmlParserCtxtPtr docbParserCtxtPtr; +typedef xmlSAXHandler docbSAXHandler; +typedef xmlSAXHandlerPtr docbSAXHandlerPtr; +typedef xmlParserInput docbParserInput; +typedef xmlParserInputPtr docbParserInputPtr; +typedef xmlDocPtr docbDocPtr; + +/* + * There is only few public functions. + */ +XMLPUBFUN int XMLCALL + docbEncodeEntities(unsigned char *out, + int *outlen, + const unsigned char *in, + int *inlen, int quoteChar); + +XMLPUBFUN docbDocPtr XMLCALL + docbSAXParseDoc (xmlChar *cur, + const char *encoding, + docbSAXHandlerPtr sax, + void *userData); +XMLPUBFUN docbDocPtr XMLCALL + docbParseDoc (xmlChar *cur, + const char *encoding); +XMLPUBFUN docbDocPtr XMLCALL + docbSAXParseFile (const char *filename, + const char *encoding, + docbSAXHandlerPtr sax, + void *userData); +XMLPUBFUN docbDocPtr XMLCALL + docbParseFile (const char *filename, + const char *encoding); + +/** + * Interfaces for the Push mode. + */ +XMLPUBFUN void XMLCALL + docbFreeParserCtxt (docbParserCtxtPtr ctxt); +XMLPUBFUN docbParserCtxtPtr XMLCALL + docbCreatePushParserCtxt(docbSAXHandlerPtr sax, + void *user_data, + const char *chunk, + int size, + const char *filename, + xmlCharEncoding enc); +XMLPUBFUN int XMLCALL + docbParseChunk (docbParserCtxtPtr ctxt, + const char *chunk, + int size, + int terminate); +XMLPUBFUN docbParserCtxtPtr XMLCALL + docbCreateFileParserCtxt(const char *filename, + const char *encoding); +XMLPUBFUN int XMLCALL + docbParseDocument (docbParserCtxtPtr ctxt); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_DOCB_ENABLED */ + +#endif /* __DOCB_PARSER_H__ */ diff --git a/include/libxml/HTMLparser.h b/include/libxml/HTMLparser.h new file mode 100644 index 0000000..2604d86 --- /dev/null +++ b/include/libxml/HTMLparser.h @@ -0,0 +1,298 @@ +/* + * Summary: interface for an HTML 4.0 non-verifying parser + * Description: this module implements an HTML 4.0 non-verifying parser + * with API compatible with the XML parser ones. It should + * be able to parse "real world" HTML, even if severely + * broken from a specification point of view. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __HTML_PARSER_H__ +#define __HTML_PARSER_H__ +#include +#include + +#ifdef LIBXML_HTML_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Most of the back-end structures from XML and HTML are shared. + */ +typedef xmlParserCtxt htmlParserCtxt; +typedef xmlParserCtxtPtr htmlParserCtxtPtr; +typedef xmlParserNodeInfo htmlParserNodeInfo; +typedef xmlSAXHandler htmlSAXHandler; +typedef xmlSAXHandlerPtr htmlSAXHandlerPtr; +typedef xmlParserInput htmlParserInput; +typedef xmlParserInputPtr htmlParserInputPtr; +typedef xmlDocPtr htmlDocPtr; +typedef xmlNodePtr htmlNodePtr; + +/* + * Internal description of an HTML element, representing HTML 4.01 + * and XHTML 1.0 (which share the same structure). + */ +typedef struct _htmlElemDesc htmlElemDesc; +typedef htmlElemDesc *htmlElemDescPtr; +struct _htmlElemDesc { + const char *name; /* The tag name */ + char startTag; /* Whether the start tag can be implied */ + char endTag; /* Whether the end tag can be implied */ + char saveEndTag; /* Whether the end tag should be saved */ + char empty; /* Is this an empty element ? */ + char depr; /* Is this a deprecated element ? */ + char dtd; /* 1: only in Loose DTD, 2: only Frameset one */ + char isinline; /* is this a block 0 or inline 1 element */ + const char *desc; /* the description */ + +/* NRK Jan.2003 + * New fields encapsulating HTML structure + * + * Bugs: + * This is a very limited representation. It fails to tell us when + * an element *requires* subelements (we only have whether they're + * allowed or not), and it doesn't tell us where CDATA and PCDATA + * are allowed. Some element relationships are not fully represented: + * these are flagged with the word MODIFIER + */ + const char** subelts; /* allowed sub-elements of this element */ + const char* defaultsubelt; /* subelement for suggested auto-repair + if necessary or NULL */ + const char** attrs_opt; /* Optional Attributes */ + const char** attrs_depr; /* Additional deprecated attributes */ + const char** attrs_req; /* Required attributes */ +}; + +/* + * Internal description of an HTML entity. + */ +typedef struct _htmlEntityDesc htmlEntityDesc; +typedef htmlEntityDesc *htmlEntityDescPtr; +struct _htmlEntityDesc { + unsigned int value; /* the UNICODE value for the character */ + const char *name; /* The entity name */ + const char *desc; /* the description */ +}; + +/* + * There is only few public functions. + */ +XMLPUBFUN const htmlElemDesc * XMLCALL + htmlTagLookup (const xmlChar *tag); +XMLPUBFUN const htmlEntityDesc * XMLCALL + htmlEntityLookup(const xmlChar *name); +XMLPUBFUN const htmlEntityDesc * XMLCALL + htmlEntityValueLookup(unsigned int value); + +XMLPUBFUN int XMLCALL + htmlIsAutoClosed(htmlDocPtr doc, + htmlNodePtr elem); +XMLPUBFUN int XMLCALL + htmlAutoCloseTag(htmlDocPtr doc, + const xmlChar *name, + htmlNodePtr elem); +XMLPUBFUN const htmlEntityDesc * XMLCALL + htmlParseEntityRef(htmlParserCtxtPtr ctxt, + const xmlChar **str); +XMLPUBFUN int XMLCALL + htmlParseCharRef(htmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + htmlParseElement(htmlParserCtxtPtr ctxt); + +XMLPUBFUN htmlParserCtxtPtr XMLCALL + htmlCreateMemoryParserCtxt(const char *buffer, + int size); + +XMLPUBFUN int XMLCALL + htmlParseDocument(htmlParserCtxtPtr ctxt); +XMLPUBFUN htmlDocPtr XMLCALL + htmlSAXParseDoc (xmlChar *cur, + const char *encoding, + htmlSAXHandlerPtr sax, + void *userData); +XMLPUBFUN htmlDocPtr XMLCALL + htmlParseDoc (xmlChar *cur, + const char *encoding); +XMLPUBFUN htmlDocPtr XMLCALL + htmlSAXParseFile(const char *filename, + const char *encoding, + htmlSAXHandlerPtr sax, + void *userData); +XMLPUBFUN htmlDocPtr XMLCALL + htmlParseFile (const char *filename, + const char *encoding); +XMLPUBFUN int XMLCALL + UTF8ToHtml (unsigned char *out, + int *outlen, + const unsigned char *in, + int *inlen); +XMLPUBFUN int XMLCALL + htmlEncodeEntities(unsigned char *out, + int *outlen, + const unsigned char *in, + int *inlen, int quoteChar); +XMLPUBFUN int XMLCALL + htmlIsScriptAttribute(const xmlChar *name); +XMLPUBFUN int XMLCALL + htmlHandleOmittedElem(int val); + +#ifdef LIBXML_PUSH_ENABLED +/** + * Interfaces for the Push mode. + */ +XMLPUBFUN htmlParserCtxtPtr XMLCALL + htmlCreatePushParserCtxt(htmlSAXHandlerPtr sax, + void *user_data, + const char *chunk, + int size, + const char *filename, + xmlCharEncoding enc); +XMLPUBFUN int XMLCALL + htmlParseChunk (htmlParserCtxtPtr ctxt, + const char *chunk, + int size, + int terminate); +#endif /* LIBXML_PUSH_ENABLED */ + +XMLPUBFUN void XMLCALL + htmlFreeParserCtxt (htmlParserCtxtPtr ctxt); + +/* + * New set of simpler/more flexible APIs + */ +/** + * xmlParserOption: + * + * This is the set of XML parser options that can be passed down + * to the xmlReadDoc() and similar calls. + */ +typedef enum { + HTML_PARSE_NOERROR = 1<<5, /* suppress error reports */ + HTML_PARSE_NOWARNING= 1<<6, /* suppress warning reports */ + HTML_PARSE_PEDANTIC = 1<<7, /* pedantic error reporting */ + HTML_PARSE_NOBLANKS = 1<<8, /* remove blank nodes */ + HTML_PARSE_NONET = 1<<11 /* Forbid network access */ +} htmlParserOption; + +XMLPUBFUN void XMLCALL + htmlCtxtReset (htmlParserCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + htmlCtxtUseOptions (htmlParserCtxtPtr ctxt, + int options); +XMLPUBFUN htmlDocPtr XMLCALL + htmlReadDoc (const xmlChar *cur, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN htmlDocPtr XMLCALL + htmlReadFile (const char *URL, + const char *encoding, + int options); +XMLPUBFUN htmlDocPtr XMLCALL + htmlReadMemory (const char *buffer, + int size, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN htmlDocPtr XMLCALL + htmlReadFd (int fd, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN htmlDocPtr XMLCALL + htmlReadIO (xmlInputReadCallback ioread, + xmlInputCloseCallback ioclose, + void *ioctx, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN htmlDocPtr XMLCALL + htmlCtxtReadDoc (xmlParserCtxtPtr ctxt, + const xmlChar *cur, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN htmlDocPtr XMLCALL + htmlCtxtReadFile (xmlParserCtxtPtr ctxt, + const char *filename, + const char *encoding, + int options); +XMLPUBFUN htmlDocPtr XMLCALL + htmlCtxtReadMemory (xmlParserCtxtPtr ctxt, + const char *buffer, + int size, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN htmlDocPtr XMLCALL + htmlCtxtReadFd (xmlParserCtxtPtr ctxt, + int fd, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN htmlDocPtr XMLCALL + htmlCtxtReadIO (xmlParserCtxtPtr ctxt, + xmlInputReadCallback ioread, + xmlInputCloseCallback ioclose, + void *ioctx, + const char *URL, + const char *encoding, + int options); + +/* NRK/Jan2003: further knowledge of HTML structure + */ +typedef enum { + HTML_NA = 0 , /* something we don't check at all */ + HTML_INVALID = 0x1 , + HTML_DEPRECATED = 0x2 , + HTML_VALID = 0x4 , + HTML_REQUIRED = 0xc /* VALID bit set so ( & HTML_VALID ) is TRUE */ +} htmlStatus ; + +/* Using htmlElemDesc rather than name here, to emphasise the fact + that otherwise there's a lookup overhead +*/ +XMLPUBFUN htmlStatus XMLCALL htmlAttrAllowed(const htmlElemDesc*, const xmlChar*, int) ; +XMLPUBFUN int XMLCALL htmlElementAllowedHere(const htmlElemDesc*, const xmlChar*) ; +XMLPUBFUN htmlStatus XMLCALL htmlElementStatusHere(const htmlElemDesc*, const htmlElemDesc*) ; +XMLPUBFUN htmlStatus XMLCALL htmlNodeStatus(const htmlNodePtr, int) ; +/** + * htmlDefaultSubelement: + * @elt: HTML element + * + * Returns the default subelement for this element + */ +#define htmlDefaultSubelement(elt) elt->defaultsubelt +/** + * htmlElementAllowedHereDesc: + * @parent: HTML parent element + * @elt: HTML element + * + * Checks whether an HTML element description may be a + * direct child of the specified element. + * + * Returns 1 if allowed; 0 otherwise. + */ +#define htmlElementAllowedHereDesc(parent,elt) \ + htmlElementAllowedHere((parent), (elt)->name) +/** + * htmlRequiredAttrs: + * @elt: HTML element + * + * Returns the attributes required for the specified element. + */ +#define htmlRequiredAttrs(elt) (elt)->attrs_req + + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_HTML_ENABLED */ +#endif /* __HTML_PARSER_H__ */ diff --git a/include/libxml/HTMLtree.h b/include/libxml/HTMLtree.h new file mode 100644 index 0000000..50b8544 --- /dev/null +++ b/include/libxml/HTMLtree.h @@ -0,0 +1,142 @@ +/* + * Summary: specific APIs to process HTML tree, especially serialization + * Description: this module implements a few function needed to process + * tree in an HTML specific way. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __HTML_TREE_H__ +#define __HTML_TREE_H__ + +#include +#include +#include +#include + +#ifdef LIBXML_HTML_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * HTML_TEXT_NODE: + * + * Macro. A text node in a HTML document is really implemented + * the same way as a text node in an XML document. + */ +#define HTML_TEXT_NODE XML_TEXT_NODE +/** + * HTML_ENTITY_REF_NODE: + * + * Macro. An entity reference in a HTML document is really implemented + * the same way as an entity reference in an XML document. + */ +#define HTML_ENTITY_REF_NODE XML_ENTITY_REF_NODE +/** + * HTML_COMMENT_NODE: + * + * Macro. A comment in a HTML document is really implemented + * the same way as a comment in an XML document. + */ +#define HTML_COMMENT_NODE XML_COMMENT_NODE +/** + * HTML_PRESERVE_NODE: + * + * Macro. A preserved node in a HTML document is really implemented + * the same way as a CDATA section in an XML document. + */ +#define HTML_PRESERVE_NODE XML_CDATA_SECTION_NODE +/** + * HTML_PI_NODE: + * + * Macro. A processing instruction in a HTML document is really implemented + * the same way as a processing instruction in an XML document. + */ +#define HTML_PI_NODE XML_PI_NODE + +XMLPUBFUN htmlDocPtr XMLCALL + htmlNewDoc (const xmlChar *URI, + const xmlChar *ExternalID); +XMLPUBFUN htmlDocPtr XMLCALL + htmlNewDocNoDtD (const xmlChar *URI, + const xmlChar *ExternalID); +XMLPUBFUN const xmlChar * XMLCALL + htmlGetMetaEncoding (htmlDocPtr doc); +XMLPUBFUN int XMLCALL + htmlSetMetaEncoding (htmlDocPtr doc, + const xmlChar *encoding); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void XMLCALL + htmlDocDumpMemory (xmlDocPtr cur, + xmlChar **mem, + int *size); +XMLPUBFUN int XMLCALL + htmlDocDump (FILE *f, + xmlDocPtr cur); +XMLPUBFUN int XMLCALL + htmlSaveFile (const char *filename, + xmlDocPtr cur); +XMLPUBFUN int XMLCALL + htmlNodeDump (xmlBufferPtr buf, + xmlDocPtr doc, + xmlNodePtr cur); +XMLPUBFUN void XMLCALL + htmlNodeDumpFile (FILE *out, + xmlDocPtr doc, + xmlNodePtr cur); +XMLPUBFUN int XMLCALL + htmlNodeDumpFileFormat (FILE *out, + xmlDocPtr doc, + xmlNodePtr cur, + const char *encoding, + int format); +XMLPUBFUN int XMLCALL + htmlSaveFileEnc (const char *filename, + xmlDocPtr cur, + const char *encoding); +XMLPUBFUN int XMLCALL + htmlSaveFileFormat (const char *filename, + xmlDocPtr cur, + const char *encoding, + int format); + +XMLPUBFUN void XMLCALL + htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, + xmlDocPtr doc, + xmlNodePtr cur, + const char *encoding, + int format); +XMLPUBFUN void XMLCALL + htmlDocContentDumpOutput(xmlOutputBufferPtr buf, + xmlDocPtr cur, + const char *encoding); +XMLPUBFUN void XMLCALL + htmlDocContentDumpFormatOutput(xmlOutputBufferPtr buf, + xmlDocPtr cur, + const char *encoding, + int format); +XMLPUBFUN void XMLCALL + htmlNodeDumpOutput (xmlOutputBufferPtr buf, + xmlDocPtr doc, + xmlNodePtr cur, + const char *encoding); + +#endif /* LIBXML_OUTPUT_ENABLED */ + +XMLPUBFUN int XMLCALL + htmlIsBooleanAttr (const xmlChar *name); + + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_HTML_ENABLED */ + +#endif /* __HTML_TREE_H__ */ + diff --git a/include/libxml/Makefile b/include/libxml/Makefile new file mode 100644 index 0000000..3f780d3 --- /dev/null +++ b/include/libxml/Makefile @@ -0,0 +1,556 @@ +# Makefile.in generated by automake 1.9.2 from Makefile.am. +# include/libxml/Makefile. Generated from Makefile.in by configure. + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + + +srcdir = . +top_srcdir = ../.. + +pkgdatadir = $(datadir)/libxml2 +pkglibdir = $(libdir)/libxml2 +pkgincludedir = $(includedir)/libxml2 +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = /bin/ginstall -c +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = i586-pc-beos +host_triplet = i586-pc-beos +subdir = include/libxml +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/xmlversion.h.in $(xmlinc_HEADERS) +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = xmlversion.h +SOURCES = +DIST_SOURCES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(xmlincdir)" +xmlincHEADERS_INSTALL = $(INSTALL_HEADER) +HEADERS = $(xmlinc_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = ${SHELL} /boot/home/Desktop/libxml2-2.6.20/missing --run aclocal-1.9 +AMDEP_FALSE = # +AMDEP_TRUE = +AMTAR = ${SHELL} /boot/home/Desktop/libxml2-2.6.20/missing --run tar +AR = ar +AS = as +AUTOCONF = ${SHELL} /boot/home/Desktop/libxml2-2.6.20/missing --run autoconf +AUTOHEADER = ${SHELL} /boot/home/Desktop/libxml2-2.6.20/missing --run autoheader +AUTOMAKE = ${SHELL} /boot/home/Desktop/libxml2-2.6.20/missing --run automake-1.9 +AWK = gawk +BASE_THREAD_LIBS = +C14N_OBJ = c14n.c +CATALOG_OBJ = catalog.o +CC = gcc +CCDEPMODE = depmode=gcc +CFLAGS = -g -O2 -pedantic -W -Wformat -Wunused -Wimplicit -Wreturn-type -Wswitch -Wcomment -Wtrigraphs -Wformat -Wchar-subscripts -Wuninitialized -Wparentheses -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline -Wredundant-decls +CPP = gcc -E +CPPFLAGS = +CXX = g++ +CXXCPP = g++ -E +CXXDEPMODE = depmode=gcc +CXXFLAGS = -g -O2 +CYGPATH_W = echo +CYGWIN_EXTRA_LDFLAGS = +CYGWIN_EXTRA_PYTHON_LIBADD = +DEBUG_OBJ = debugXML.o +DEFS = -DHAVE_CONFIG_H +DEPDIR = .deps +DLLTOOL = dlltool +DOCB_OBJ = DOCBparser.o +ECHO = echo +ECHO_C = +ECHO_N = -n +ECHO_T = +EGREP = grep -E +EXEEXT = +F77 = +FFLAGS = +FTP_OBJ = nanoftp.o +HAVE_ISINF = +HAVE_ISNAN = +HTML_DIR = $(datadir)/doc/$(PACKAGE)-$(VERSION)/html +HTML_OBJ = HTMLparser.o HTMLtree.o +HTTP_OBJ = nanohttp.o +ICONV_LIBS = -liconv +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_PROGRAM = ${INSTALL} +INSTALL_SCRIPT = ${INSTALL} +INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s +LDFLAGS = +LIBOBJS = +LIBS = -lsocket +LIBTOOL = $(SHELL) $(top_builddir)/libtool +LIBXML_MAJOR_VERSION = 2 +LIBXML_MICRO_VERSION = 20 +LIBXML_MINOR_VERSION = 6 +LIBXML_VERSION = 2.6.20 +LIBXML_VERSION_EXTRA = +LIBXML_VERSION_INFO = 8:20:6 +LIBXML_VERSION_NUMBER = 20620 +LN_S = ln -s +LTLIBOBJS = +MAKEINFO = ${SHELL} /boot/home/Desktop/libxml2-2.6.20/missing --run makeinfo +MODULE_EXTENSION = .so +MODULE_PLATFORM_LIBS = -ldl +MV = /bin/mv +M_LIBS = +OBJDUMP = objdump +OBJEXT = o +PACKAGE = libxml2 +PACKAGE_BUGREPORT = +PACKAGE_NAME = +PACKAGE_STRING = +PACKAGE_TARNAME = +PACKAGE_VERSION = +PATH_SEPARATOR = : +PERL = /boot/home/config/bin/perl +PYTHON = /bin/python +PYTHON_INCLUDES = +PYTHON_SITE_PACKAGES = /boot/beos/system/lib/python2.4/site-packages +PYTHON_SUBDIR = +PYTHON_TESTS = +PYTHON_VERSION = 2.4 +RANLIB = ranlib +RDL_LIBS = +READER_TEST = Readertests +RELDATE = Mon Jul 11 2005 +RM = /bin/rm +SET_MAKE = +SHELL = /bin/sh +STATIC_BINARIES = +STRIP = strip +TAR = /bin/tar +TEST_C14N = C14Ntests +TEST_CATALOG = Catatests +TEST_DEBUG = Scripttests +TEST_HTML = HTMLtests +TEST_MODULES = ModuleTests +TEST_PATTERN = Patterntests +TEST_PHTML = HTMLPushtests +TEST_PUSH = XMLPushtests +TEST_REGEXPS = Regexptests Automatatests +TEST_SAX = SAXtests +TEST_SCHEMAS = Schemastests Relaxtests +TEST_THREADS = Threadtests +TEST_VALID = Validtests +TEST_VTIME = VTimingtests +TEST_XINCLUDE = XIncludetests +TEST_XPATH = XPathtests +TEST_XPTR = XPtrtests +THREADS_W32 = +THREAD_CFLAGS = -DHAVE_BEOS_THREADS -D_REENTRANT +THREAD_LIBS = -lpthread +U = +VERSION = 2.6.20 +WIN32_EXTRA_LDFLAGS = +WIN32_EXTRA_LIBADD = +WITH_C14N = 1 +WITH_CATALOG = 1 +WITH_DEBUG = 1 +WITH_DOCB = 1 +WITH_FTP = 1 +WITH_HTML = 1 +WITH_HTTP = 1 +WITH_ICONV = 1 +WITH_ISO8859X = 1 +WITH_LEGACY = 1 +WITH_MEM_DEBUG = 0 +WITH_MODULES = 1 +WITH_OUTPUT = 1 +WITH_PATTERN = 1 +WITH_PUSH = 1 +WITH_PYTHON_FALSE = +WITH_PYTHON_TRUE = # +WITH_READER = 1 +WITH_REGEXPS = 1 +WITH_RUN_DEBUG = 0 +WITH_SAX1 = 1 +WITH_SCHEMAS = 1 +WITH_THREADS = 1 +WITH_TREE = 1 +WITH_TRIO = 0 +WITH_TRIO_SOURCES_FALSE = +WITH_TRIO_SOURCES_TRUE = # +WITH_VALID = 1 +WITH_WRITER = 1 +WITH_XINCLUDE = 1 +WITH_XPATH = 1 +WITH_XPTR = 1 +XINCLUDE_OBJ = xinclude.o +XMLLINT = /usr/bin/xmllint +XML_CFLAGS = +XML_INCLUDEDIR = -I${includedir}/libxml2 +XML_LIBDIR = -L${libdir} +XML_LIBS = -lxml2 -lz -lpthread -liconv -lsocket +XML_LIBTOOLLIBS = libxml2.la +XPATH_OBJ = xpath.o +XPTR_OBJ = xpointer.o +XSLTPROC = /usr/bin/xsltproc +Z_CFLAGS = +Z_LIBS = -lz +ac_ct_AR = ar +ac_ct_AS = +ac_ct_CC = gcc +ac_ct_CXX = g++ +ac_ct_DLLTOOL = +ac_ct_F77 = +ac_ct_OBJDUMP = +ac_ct_RANLIB = ranlib +ac_ct_STRIP = strip +am__fastdepCC_FALSE = +am__fastdepCC_TRUE = # +am__fastdepCXX_FALSE = +am__fastdepCXX_TRUE = # +am__include = include +am__leading_dot = . +am__quote = +am__tar = ${AMTAR} chof - "$$tardir" +am__untar = ${AMTAR} xf - +bindir = ${exec_prefix}/bin +build = i586-pc-beos +build_alias = +build_cpu = i586 +build_os = beos +build_vendor = pc +datadir = ${prefix}/share +exec_prefix = ${prefix} +host = i586-pc-beos +host_alias = +host_cpu = i586 +host_os = beos +host_vendor = pc +includedir = ${prefix}/include +infodir = ${prefix}/info +install_sh = /boot/home/Desktop/libxml2-2.6.20/install-sh +libdir = ${exec_prefix}/lib +libexecdir = ${exec_prefix}/libexec +localstatedir = ${prefix}/var +mandir = ${prefix}/man +mkdir_p = mkdir -p -- +oldincludedir = /usr/include +prefix = /usr/local +program_transform_name = s,x,x, +pythondir = $(libdir)/python${PYTHON_VERSION}/site-packages +sbindir = ${exec_prefix}/sbin +sharedstatedir = ${prefix}/com +sysconfdir = ${prefix}/etc +target_alias = +xmlincdir = $(includedir)/libxml2/libxml +xmlinc_HEADERS = \ + SAX.h \ + entities.h \ + encoding.h \ + parser.h \ + parserInternals.h \ + xmlerror.h \ + HTMLparser.h \ + HTMLtree.h \ + debugXML.h \ + tree.h \ + list.h \ + hash.h \ + xpath.h \ + xpathInternals.h \ + xpointer.h \ + xinclude.h \ + xmlIO.h \ + xmlmemory.h \ + nanohttp.h \ + nanoftp.h \ + uri.h \ + valid.h \ + xlink.h \ + xmlversion.h \ + DOCBparser.h \ + catalog.h \ + threads.h \ + globals.h \ + c14n.h \ + xmlautomata.h \ + xmlregexp.h \ + xmlmodule.h \ + xmlschemas.h \ + schemasInternals.h \ + xmlschemastypes.h \ + xmlstring.h \ + xmlunicode.h \ + xmlreader.h \ + relaxng.h \ + dict.h \ + SAX2.h \ + xmlexports.h \ + xmlwriter.h \ + chvalid.h \ + pattern.h \ + xmlsave.h + +EXTRA_DIST = xmlversion.h.in +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/libxml/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu include/libxml/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +xmlversion.h: $(top_builddir)/config.status $(srcdir)/xmlversion.h.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: +install-xmlincHEADERS: $(xmlinc_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(xmlincdir)" || $(mkdir_p) "$(DESTDIR)$(xmlincdir)" + @list='$(xmlinc_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(xmlincHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(xmlincdir)/$$f'"; \ + $(xmlincHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(xmlincdir)/$$f"; \ + done + +uninstall-xmlincHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(xmlinc_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(xmlincdir)/$$f'"; \ + rm -f "$(DESTDIR)$(xmlincdir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(xmlincdir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-libtool \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-xmlincHEADERS + +install-exec-am: + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am uninstall-xmlincHEADERS + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool ctags distclean distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-exec-hook \ + install-info install-info-am install-man install-strip \ + install-xmlincHEADERS installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-info-am \ + uninstall-xmlincHEADERS + + +install-exec-hook: + $(mkinstalldirs) $(DESTDIR)$(xmlincdir) +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/include/libxml/Makefile.am b/include/libxml/Makefile.am new file mode 100644 index 0000000..03f9564 --- /dev/null +++ b/include/libxml/Makefile.am @@ -0,0 +1,56 @@ +## Process this file with automake to produce Makefile.in + +xmlincdir = $(includedir)/libxml2/libxml + +xmlinc_HEADERS = \ + SAX.h \ + entities.h \ + encoding.h \ + parser.h \ + parserInternals.h \ + xmlerror.h \ + HTMLparser.h \ + HTMLtree.h \ + debugXML.h \ + tree.h \ + list.h \ + hash.h \ + xpath.h \ + xpathInternals.h \ + xpointer.h \ + xinclude.h \ + xmlIO.h \ + xmlmemory.h \ + nanohttp.h \ + nanoftp.h \ + uri.h \ + valid.h \ + xlink.h \ + xmlversion.h \ + DOCBparser.h \ + catalog.h \ + threads.h \ + globals.h \ + c14n.h \ + xmlautomata.h \ + xmlregexp.h \ + xmlmodule.h \ + xmlschemas.h \ + schemasInternals.h \ + xmlschemastypes.h \ + xmlstring.h \ + xmlunicode.h \ + xmlreader.h \ + relaxng.h \ + dict.h \ + SAX2.h \ + xmlexports.h \ + xmlwriter.h \ + chvalid.h \ + pattern.h \ + xmlsave.h + +install-exec-hook: + $(mkinstalldirs) $(DESTDIR)$(xmlincdir) + +EXTRA_DIST = xmlversion.h.in diff --git a/include/libxml/Makefile.in b/include/libxml/Makefile.in new file mode 100644 index 0000000..bdcc706 --- /dev/null +++ b/include/libxml/Makefile.in @@ -0,0 +1,556 @@ +# Makefile.in generated by automake 1.9.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = include/libxml +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/xmlversion.h.in $(xmlinc_HEADERS) +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = xmlversion.h +SOURCES = +DIST_SOURCES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(xmlincdir)" +xmlincHEADERS_INSTALL = $(INSTALL_HEADER) +HEADERS = $(xmlinc_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASE_THREAD_LIBS = @BASE_THREAD_LIBS@ +C14N_OBJ = @C14N_OBJ@ +CATALOG_OBJ = @CATALOG_OBJ@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +CYGWIN_EXTRA_LDFLAGS = @CYGWIN_EXTRA_LDFLAGS@ +CYGWIN_EXTRA_PYTHON_LIBADD = @CYGWIN_EXTRA_PYTHON_LIBADD@ +DEBUG_OBJ = @DEBUG_OBJ@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOCB_OBJ = @DOCB_OBJ@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +FTP_OBJ = @FTP_OBJ@ +HAVE_ISINF = @HAVE_ISINF@ +HAVE_ISNAN = @HAVE_ISNAN@ +HTML_DIR = @HTML_DIR@ +HTML_OBJ = @HTML_OBJ@ +HTTP_OBJ = @HTTP_OBJ@ +ICONV_LIBS = @ICONV_LIBS@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBXML_MAJOR_VERSION = @LIBXML_MAJOR_VERSION@ +LIBXML_MICRO_VERSION = @LIBXML_MICRO_VERSION@ +LIBXML_MINOR_VERSION = @LIBXML_MINOR_VERSION@ +LIBXML_VERSION = @LIBXML_VERSION@ +LIBXML_VERSION_EXTRA = @LIBXML_VERSION_EXTRA@ +LIBXML_VERSION_INFO = @LIBXML_VERSION_INFO@ +LIBXML_VERSION_NUMBER = @LIBXML_VERSION_NUMBER@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MODULE_EXTENSION = @MODULE_EXTENSION@ +MODULE_PLATFORM_LIBS = @MODULE_PLATFORM_LIBS@ +MV = @MV@ +M_LIBS = @M_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PYTHON = @PYTHON@ +PYTHON_INCLUDES = @PYTHON_INCLUDES@ +PYTHON_SITE_PACKAGES = @PYTHON_SITE_PACKAGES@ +PYTHON_SUBDIR = @PYTHON_SUBDIR@ +PYTHON_TESTS = @PYTHON_TESTS@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RDL_LIBS = @RDL_LIBS@ +READER_TEST = @READER_TEST@ +RELDATE = @RELDATE@ +RM = @RM@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STATIC_BINARIES = @STATIC_BINARIES@ +STRIP = @STRIP@ +TAR = @TAR@ +TEST_C14N = @TEST_C14N@ +TEST_CATALOG = @TEST_CATALOG@ +TEST_DEBUG = @TEST_DEBUG@ +TEST_HTML = @TEST_HTML@ +TEST_MODULES = @TEST_MODULES@ +TEST_PATTERN = @TEST_PATTERN@ +TEST_PHTML = @TEST_PHTML@ +TEST_PUSH = @TEST_PUSH@ +TEST_REGEXPS = @TEST_REGEXPS@ +TEST_SAX = @TEST_SAX@ +TEST_SCHEMAS = @TEST_SCHEMAS@ +TEST_THREADS = @TEST_THREADS@ +TEST_VALID = @TEST_VALID@ +TEST_VTIME = @TEST_VTIME@ +TEST_XINCLUDE = @TEST_XINCLUDE@ +TEST_XPATH = @TEST_XPATH@ +TEST_XPTR = @TEST_XPTR@ +THREADS_W32 = @THREADS_W32@ +THREAD_CFLAGS = @THREAD_CFLAGS@ +THREAD_LIBS = @THREAD_LIBS@ +U = @U@ +VERSION = @VERSION@ +WIN32_EXTRA_LDFLAGS = @WIN32_EXTRA_LDFLAGS@ +WIN32_EXTRA_LIBADD = @WIN32_EXTRA_LIBADD@ +WITH_C14N = @WITH_C14N@ +WITH_CATALOG = @WITH_CATALOG@ +WITH_DEBUG = @WITH_DEBUG@ +WITH_DOCB = @WITH_DOCB@ +WITH_FTP = @WITH_FTP@ +WITH_HTML = @WITH_HTML@ +WITH_HTTP = @WITH_HTTP@ +WITH_ICONV = @WITH_ICONV@ +WITH_ISO8859X = @WITH_ISO8859X@ +WITH_LEGACY = @WITH_LEGACY@ +WITH_MEM_DEBUG = @WITH_MEM_DEBUG@ +WITH_MODULES = @WITH_MODULES@ +WITH_OUTPUT = @WITH_OUTPUT@ +WITH_PATTERN = @WITH_PATTERN@ +WITH_PUSH = @WITH_PUSH@ +WITH_PYTHON_FALSE = @WITH_PYTHON_FALSE@ +WITH_PYTHON_TRUE = @WITH_PYTHON_TRUE@ +WITH_READER = @WITH_READER@ +WITH_REGEXPS = @WITH_REGEXPS@ +WITH_RUN_DEBUG = @WITH_RUN_DEBUG@ +WITH_SAX1 = @WITH_SAX1@ +WITH_SCHEMAS = @WITH_SCHEMAS@ +WITH_THREADS = @WITH_THREADS@ +WITH_TREE = @WITH_TREE@ +WITH_TRIO = @WITH_TRIO@ +WITH_TRIO_SOURCES_FALSE = @WITH_TRIO_SOURCES_FALSE@ +WITH_TRIO_SOURCES_TRUE = @WITH_TRIO_SOURCES_TRUE@ +WITH_VALID = @WITH_VALID@ +WITH_WRITER = @WITH_WRITER@ +WITH_XINCLUDE = @WITH_XINCLUDE@ +WITH_XPATH = @WITH_XPATH@ +WITH_XPTR = @WITH_XPTR@ +XINCLUDE_OBJ = @XINCLUDE_OBJ@ +XMLLINT = @XMLLINT@ +XML_CFLAGS = @XML_CFLAGS@ +XML_INCLUDEDIR = @XML_INCLUDEDIR@ +XML_LIBDIR = @XML_LIBDIR@ +XML_LIBS = @XML_LIBS@ +XML_LIBTOOLLIBS = @XML_LIBTOOLLIBS@ +XPATH_OBJ = @XPATH_OBJ@ +XPTR_OBJ = @XPTR_OBJ@ +XSLTPROC = @XSLTPROC@ +Z_CFLAGS = @Z_CFLAGS@ +Z_LIBS = @Z_LIBS@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_AS = @ac_ct_AS@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DLLTOOL = @ac_ct_DLLTOOL@ +ac_ct_F77 = @ac_ct_F77@ +ac_ct_OBJDUMP = @ac_ct_OBJDUMP@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +pythondir = @pythondir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +xmlincdir = $(includedir)/libxml2/libxml +xmlinc_HEADERS = \ + SAX.h \ + entities.h \ + encoding.h \ + parser.h \ + parserInternals.h \ + xmlerror.h \ + HTMLparser.h \ + HTMLtree.h \ + debugXML.h \ + tree.h \ + list.h \ + hash.h \ + xpath.h \ + xpathInternals.h \ + xpointer.h \ + xinclude.h \ + xmlIO.h \ + xmlmemory.h \ + nanohttp.h \ + nanoftp.h \ + uri.h \ + valid.h \ + xlink.h \ + xmlversion.h \ + DOCBparser.h \ + catalog.h \ + threads.h \ + globals.h \ + c14n.h \ + xmlautomata.h \ + xmlregexp.h \ + xmlmodule.h \ + xmlschemas.h \ + schemasInternals.h \ + xmlschemastypes.h \ + xmlstring.h \ + xmlunicode.h \ + xmlreader.h \ + relaxng.h \ + dict.h \ + SAX2.h \ + xmlexports.h \ + xmlwriter.h \ + chvalid.h \ + pattern.h \ + xmlsave.h + +EXTRA_DIST = xmlversion.h.in +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/libxml/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu include/libxml/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +xmlversion.h: $(top_builddir)/config.status $(srcdir)/xmlversion.h.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: +install-xmlincHEADERS: $(xmlinc_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(xmlincdir)" || $(mkdir_p) "$(DESTDIR)$(xmlincdir)" + @list='$(xmlinc_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(xmlincHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(xmlincdir)/$$f'"; \ + $(xmlincHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(xmlincdir)/$$f"; \ + done + +uninstall-xmlincHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(xmlinc_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(xmlincdir)/$$f'"; \ + rm -f "$(DESTDIR)$(xmlincdir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(xmlincdir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-libtool \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-xmlincHEADERS + +install-exec-am: + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am uninstall-xmlincHEADERS + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool ctags distclean distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-exec-hook \ + install-info install-info-am install-man install-strip \ + install-xmlincHEADERS installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-info-am \ + uninstall-xmlincHEADERS + + +install-exec-hook: + $(mkinstalldirs) $(DESTDIR)$(xmlincdir) +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/include/libxml/SAX.h b/include/libxml/SAX.h new file mode 100644 index 0000000..0ca161b --- /dev/null +++ b/include/libxml/SAX.h @@ -0,0 +1,173 @@ +/* + * Summary: Old SAX version 1 handler, deprecated + * Description: DEPRECATED set of SAX version 1 interfaces used to + * build the DOM tree. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + + +#ifndef __XML_SAX_H__ +#define __XML_SAX_H__ + +#include +#include +#include +#include +#include + +#ifdef LIBXML_LEGACY_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif +XMLPUBFUN const xmlChar * XMLCALL + getPublicId (void *ctx); +XMLPUBFUN const xmlChar * XMLCALL + getSystemId (void *ctx); +XMLPUBFUN void XMLCALL + setDocumentLocator (void *ctx, + xmlSAXLocatorPtr loc); + +XMLPUBFUN int XMLCALL + getLineNumber (void *ctx); +XMLPUBFUN int XMLCALL + getColumnNumber (void *ctx); + +XMLPUBFUN int XMLCALL + isStandalone (void *ctx); +XMLPUBFUN int XMLCALL + hasInternalSubset (void *ctx); +XMLPUBFUN int XMLCALL + hasExternalSubset (void *ctx); + +XMLPUBFUN void XMLCALL + internalSubset (void *ctx, + const xmlChar *name, + const xmlChar *ExternalID, + const xmlChar *SystemID); +XMLPUBFUN void XMLCALL + externalSubset (void *ctx, + const xmlChar *name, + const xmlChar *ExternalID, + const xmlChar *SystemID); +XMLPUBFUN xmlEntityPtr XMLCALL + getEntity (void *ctx, + const xmlChar *name); +XMLPUBFUN xmlEntityPtr XMLCALL + getParameterEntity (void *ctx, + const xmlChar *name); +XMLPUBFUN xmlParserInputPtr XMLCALL + resolveEntity (void *ctx, + const xmlChar *publicId, + const xmlChar *systemId); + +XMLPUBFUN void XMLCALL + entityDecl (void *ctx, + const xmlChar *name, + int type, + const xmlChar *publicId, + const xmlChar *systemId, + xmlChar *content); +XMLPUBFUN void XMLCALL + attributeDecl (void *ctx, + const xmlChar *elem, + const xmlChar *fullname, + int type, + int def, + const xmlChar *defaultValue, + xmlEnumerationPtr tree); +XMLPUBFUN void XMLCALL + elementDecl (void *ctx, + const xmlChar *name, + int type, + xmlElementContentPtr content); +XMLPUBFUN void XMLCALL + notationDecl (void *ctx, + const xmlChar *name, + const xmlChar *publicId, + const xmlChar *systemId); +XMLPUBFUN void XMLCALL + unparsedEntityDecl (void *ctx, + const xmlChar *name, + const xmlChar *publicId, + const xmlChar *systemId, + const xmlChar *notationName); + +XMLPUBFUN void XMLCALL + startDocument (void *ctx); +XMLPUBFUN void XMLCALL + endDocument (void *ctx); +XMLPUBFUN void XMLCALL + attribute (void *ctx, + const xmlChar *fullname, + const xmlChar *value); +XMLPUBFUN void XMLCALL + startElement (void *ctx, + const xmlChar *fullname, + const xmlChar **atts); +XMLPUBFUN void XMLCALL + endElement (void *ctx, + const xmlChar *name); +XMLPUBFUN void XMLCALL + reference (void *ctx, + const xmlChar *name); +XMLPUBFUN void XMLCALL + characters (void *ctx, + const xmlChar *ch, + int len); +XMLPUBFUN void XMLCALL + ignorableWhitespace (void *ctx, + const xmlChar *ch, + int len); +XMLPUBFUN void XMLCALL + processingInstruction (void *ctx, + const xmlChar *target, + const xmlChar *data); +XMLPUBFUN void XMLCALL + globalNamespace (void *ctx, + const xmlChar *href, + const xmlChar *prefix); +XMLPUBFUN void XMLCALL + setNamespace (void *ctx, + const xmlChar *name); +XMLPUBFUN xmlNsPtr XMLCALL + getNamespace (void *ctx); +XMLPUBFUN int XMLCALL + checkNamespace (void *ctx, + xmlChar *nameSpace); +XMLPUBFUN void XMLCALL + namespaceDecl (void *ctx, + const xmlChar *href, + const xmlChar *prefix); +XMLPUBFUN void XMLCALL + comment (void *ctx, + const xmlChar *value); +XMLPUBFUN void XMLCALL + cdataBlock (void *ctx, + const xmlChar *value, + int len); + +#ifdef LIBXML_SAX1_ENABLED +XMLPUBFUN void XMLCALL + initxmlDefaultSAXHandler (xmlSAXHandlerV1 *hdlr, + int warning); +#ifdef LIBXML_HTML_ENABLED +XMLPUBFUN void XMLCALL + inithtmlDefaultSAXHandler (xmlSAXHandlerV1 *hdlr); +#endif +#ifdef LIBXML_DOCB_ENABLED +XMLPUBFUN void XMLCALL + initdocbDefaultSAXHandler (xmlSAXHandlerV1 *hdlr); +#endif +#endif /* LIBXML_SAX1_ENABLED */ + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_LEGACY_ENABLED */ + +#endif /* __XML_SAX_H__ */ diff --git a/include/libxml/SAX2.h b/include/libxml/SAX2.h new file mode 100644 index 0000000..6626564 --- /dev/null +++ b/include/libxml/SAX2.h @@ -0,0 +1,176 @@ +/* + * Summary: SAX2 parser interface used to build the DOM tree + * Description: those are the default SAX2 interfaces used by + * the library when building DOM tree. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + + +#ifndef __XML_SAX2_H__ +#define __XML_SAX2_H__ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +XMLPUBFUN const xmlChar * XMLCALL + xmlSAX2GetPublicId (void *ctx); +XMLPUBFUN const xmlChar * XMLCALL + xmlSAX2GetSystemId (void *ctx); +XMLPUBFUN void XMLCALL + xmlSAX2SetDocumentLocator (void *ctx, + xmlSAXLocatorPtr loc); + +XMLPUBFUN int XMLCALL + xmlSAX2GetLineNumber (void *ctx); +XMLPUBFUN int XMLCALL + xmlSAX2GetColumnNumber (void *ctx); + +XMLPUBFUN int XMLCALL + xmlSAX2IsStandalone (void *ctx); +XMLPUBFUN int XMLCALL + xmlSAX2HasInternalSubset (void *ctx); +XMLPUBFUN int XMLCALL + xmlSAX2HasExternalSubset (void *ctx); + +XMLPUBFUN void XMLCALL + xmlSAX2InternalSubset (void *ctx, + const xmlChar *name, + const xmlChar *ExternalID, + const xmlChar *SystemID); +XMLPUBFUN void XMLCALL + xmlSAX2ExternalSubset (void *ctx, + const xmlChar *name, + const xmlChar *ExternalID, + const xmlChar *SystemID); +XMLPUBFUN xmlEntityPtr XMLCALL + xmlSAX2GetEntity (void *ctx, + const xmlChar *name); +XMLPUBFUN xmlEntityPtr XMLCALL + xmlSAX2GetParameterEntity (void *ctx, + const xmlChar *name); +XMLPUBFUN xmlParserInputPtr XMLCALL + xmlSAX2ResolveEntity (void *ctx, + const xmlChar *publicId, + const xmlChar *systemId); + +XMLPUBFUN void XMLCALL + xmlSAX2EntityDecl (void *ctx, + const xmlChar *name, + int type, + const xmlChar *publicId, + const xmlChar *systemId, + xmlChar *content); +XMLPUBFUN void XMLCALL + xmlSAX2AttributeDecl (void *ctx, + const xmlChar *elem, + const xmlChar *fullname, + int type, + int def, + const xmlChar *defaultValue, + xmlEnumerationPtr tree); +XMLPUBFUN void XMLCALL + xmlSAX2ElementDecl (void *ctx, + const xmlChar *name, + int type, + xmlElementContentPtr content); +XMLPUBFUN void XMLCALL + xmlSAX2NotationDecl (void *ctx, + const xmlChar *name, + const xmlChar *publicId, + const xmlChar *systemId); +XMLPUBFUN void XMLCALL + xmlSAX2UnparsedEntityDecl (void *ctx, + const xmlChar *name, + const xmlChar *publicId, + const xmlChar *systemId, + const xmlChar *notationName); + +XMLPUBFUN void XMLCALL + xmlSAX2StartDocument (void *ctx); +XMLPUBFUN void XMLCALL + xmlSAX2EndDocument (void *ctx); +#if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) +XMLPUBFUN void XMLCALL + xmlSAX2StartElement (void *ctx, + const xmlChar *fullname, + const xmlChar **atts); +XMLPUBFUN void XMLCALL + xmlSAX2EndElement (void *ctx, + const xmlChar *name); +#endif /* LIBXML_SAX1_ENABLED or LIBXML_HTML_ENABLED */ +XMLPUBFUN void XMLCALL + xmlSAX2StartElementNs (void *ctx, + const xmlChar *localname, + const xmlChar *prefix, + const xmlChar *URI, + int nb_namespaces, + const xmlChar **namespaces, + int nb_attributes, + int nb_defaulted, + const xmlChar **attributes); +XMLPUBFUN void XMLCALL + xmlSAX2EndElementNs (void *ctx, + const xmlChar *localname, + const xmlChar *prefix, + const xmlChar *URI); +XMLPUBFUN void XMLCALL + xmlSAX2Reference (void *ctx, + const xmlChar *name); +XMLPUBFUN void XMLCALL + xmlSAX2Characters (void *ctx, + const xmlChar *ch, + int len); +XMLPUBFUN void XMLCALL + xmlSAX2IgnorableWhitespace (void *ctx, + const xmlChar *ch, + int len); +XMLPUBFUN void XMLCALL + xmlSAX2ProcessingInstruction (void *ctx, + const xmlChar *target, + const xmlChar *data); +XMLPUBFUN void XMLCALL + xmlSAX2Comment (void *ctx, + const xmlChar *value); +XMLPUBFUN void XMLCALL + xmlSAX2CDataBlock (void *ctx, + const xmlChar *value, + int len); + +#ifdef LIBXML_SAX1_ENABLED +XMLPUBFUN int XMLCALL + xmlSAXDefaultVersion (int version); +#endif /* LIBXML_SAX1_ENABLED */ + +XMLPUBFUN int XMLCALL + xmlSAXVersion (xmlSAXHandler *hdlr, + int version); +XMLPUBFUN void XMLCALL + xmlSAX2InitDefaultSAXHandler (xmlSAXHandler *hdlr, + int warning); +#ifdef LIBXML_HTML_ENABLED +XMLPUBFUN void XMLCALL + xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr); +XMLPUBFUN void XMLCALL + htmlDefaultSAXHandlerInit (void); +#endif +#ifdef LIBXML_DOCB_ENABLED +XMLPUBFUN void XMLCALL + xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr); +XMLPUBFUN void XMLCALL + docbDefaultSAXHandlerInit (void); +#endif +XMLPUBFUN void XMLCALL + xmlDefaultSAXHandlerInit (void); +#ifdef __cplusplus +} +#endif +#endif /* __XML_SAX2_H__ */ diff --git a/include/libxml/c14n.h b/include/libxml/c14n.h new file mode 100644 index 0000000..9f4c6c0 --- /dev/null +++ b/include/libxml/c14n.h @@ -0,0 +1,105 @@ +/* + * Summary: Provide Canonical XML and Exclusive XML Canonicalization + * Description: the c14n modules provides a + * + * "Canonical XML" implementation + * http://www.w3.org/TR/xml-c14n + * + * and an + * + * "Exclusive XML Canonicalization" implementation + * http://www.w3.org/TR/xml-exc-c14n + + * Copy: See Copyright for the status of this software. + * + * Author: Aleksey Sanin + */ +#ifndef __XML_C14N_H__ +#define __XML_C14N_H__ +#ifdef LIBXML_C14N_ENABLED +#ifdef LIBXML_OUTPUT_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include +#include + +/* + * XML Canonicazation + * http://www.w3.org/TR/xml-c14n + * + * Exclusive XML Canonicazation + * http://www.w3.org/TR/xml-exc-c14n + * + * Canonical form of an XML document could be created if and only if + * a) default attributes (if any) are added to all nodes + * b) all character and parsed entity references are resolved + * In order to achive this in libxml2 the document MUST be loaded with + * following global setings: + * + * xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS; + * xmlSubstituteEntitiesDefault(1); + * + * or corresponding parser context setting: + * xmlParserCtxtPtr ctxt; + * + * ... + * ctxt->loadsubset = XML_DETECT_IDS | XML_COMPLETE_ATTRS; + * ctxt->replaceEntities = 1; + * ... + */ + + +XMLPUBFUN int XMLCALL + xmlC14NDocSaveTo (xmlDocPtr doc, + xmlNodeSetPtr nodes, + int exclusive, + xmlChar **inclusive_ns_prefixes, + int with_comments, + xmlOutputBufferPtr buf); + +XMLPUBFUN int XMLCALL + xmlC14NDocDumpMemory (xmlDocPtr doc, + xmlNodeSetPtr nodes, + int exclusive, + xmlChar **inclusive_ns_prefixes, + int with_comments, + xmlChar **doc_txt_ptr); + +XMLPUBFUN int XMLCALL + xmlC14NDocSave (xmlDocPtr doc, + xmlNodeSetPtr nodes, + int exclusive, + xmlChar **inclusive_ns_prefixes, + int with_comments, + const char* filename, + int compression); + + +/** + * This is the core C14N function + */ +typedef int (*xmlC14NIsVisibleCallback) (void* user_data, + xmlNodePtr node, + xmlNodePtr parent); + +XMLPUBFUN int XMLCALL + xmlC14NExecute (xmlDocPtr doc, + xmlC14NIsVisibleCallback is_visible_callback, + void* user_data, + int exclusive, + xmlChar **inclusive_ns_prefixes, + int with_comments, + xmlOutputBufferPtr buf); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBXML_OUTPUT_ENABLED */ +#endif /* LIBXML_C14N_ENABLED */ +#endif /* __XML_C14N_H__ */ + diff --git a/include/libxml/catalog.h b/include/libxml/catalog.h new file mode 100644 index 0000000..b444137 --- /dev/null +++ b/include/libxml/catalog.h @@ -0,0 +1,182 @@ +/** + * Summary: interfaces to the Catalog handling system + * Description: the catalog module implements the support for + * XML Catalogs and SGML catalogs + * + * SGML Open Technical Resolution TR9401:1997. + * http://www.jclark.com/sp/catalog.htm + * + * XML Catalogs Working Draft 06 August 2001 + * http://www.oasis-open.org/committees/entity/spec-2001-08-06.html + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_CATALOG_H__ +#define __XML_CATALOG_H__ + +#include + +#include +#include +#include + +#ifdef LIBXML_CATALOG_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * XML_CATALOGS_NAMESPACE: + * + * The namespace for the XML Catalogs elements. + */ +#define XML_CATALOGS_NAMESPACE \ + (const xmlChar *) "urn:oasis:names:tc:entity:xmlns:xml:catalog" +/** + * XML_CATALOG_PI: + * + * The specific XML Catalog Processing Instuction name. + */ +#define XML_CATALOG_PI \ + (const xmlChar *) "oasis-xml-catalog" + +/* + * The API is voluntarily limited to general cataloging. + */ +typedef enum { + XML_CATA_PREFER_NONE = 0, + XML_CATA_PREFER_PUBLIC = 1, + XML_CATA_PREFER_SYSTEM +} xmlCatalogPrefer; + +typedef enum { + XML_CATA_ALLOW_NONE = 0, + XML_CATA_ALLOW_GLOBAL = 1, + XML_CATA_ALLOW_DOCUMENT = 2, + XML_CATA_ALLOW_ALL = 3 +} xmlCatalogAllow; + +typedef struct _xmlCatalog xmlCatalog; +typedef xmlCatalog *xmlCatalogPtr; + +/* + * Operations on a given catalog. + */ +XMLPUBFUN xmlCatalogPtr XMLCALL + xmlNewCatalog (int sgml); +XMLPUBFUN xmlCatalogPtr XMLCALL + xmlLoadACatalog (const char *filename); +XMLPUBFUN xmlCatalogPtr XMLCALL + xmlLoadSGMLSuperCatalog (const char *filename); +XMLPUBFUN int XMLCALL + xmlConvertSGMLCatalog (xmlCatalogPtr catal); +XMLPUBFUN int XMLCALL + xmlACatalogAdd (xmlCatalogPtr catal, + const xmlChar *type, + const xmlChar *orig, + const xmlChar *replace); +XMLPUBFUN int XMLCALL + xmlACatalogRemove (xmlCatalogPtr catal, + const xmlChar *value); +XMLPUBFUN xmlChar * XMLCALL + xmlACatalogResolve (xmlCatalogPtr catal, + const xmlChar *pubID, + const xmlChar *sysID); +XMLPUBFUN xmlChar * XMLCALL + xmlACatalogResolveSystem(xmlCatalogPtr catal, + const xmlChar *sysID); +XMLPUBFUN xmlChar * XMLCALL + xmlACatalogResolvePublic(xmlCatalogPtr catal, + const xmlChar *pubID); +XMLPUBFUN xmlChar * XMLCALL + xmlACatalogResolveURI (xmlCatalogPtr catal, + const xmlChar *URI); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void XMLCALL + xmlACatalogDump (xmlCatalogPtr catal, + FILE *out); +#endif /* LIBXML_OUTPUT_ENABLED */ +XMLPUBFUN void XMLCALL + xmlFreeCatalog (xmlCatalogPtr catal); +XMLPUBFUN int XMLCALL + xmlCatalogIsEmpty (xmlCatalogPtr catal); + +/* + * Global operations. + */ +XMLPUBFUN void XMLCALL + xmlInitializeCatalog (void); +XMLPUBFUN int XMLCALL + xmlLoadCatalog (const char *filename); +XMLPUBFUN void XMLCALL + xmlLoadCatalogs (const char *paths); +XMLPUBFUN void XMLCALL + xmlCatalogCleanup (void); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void XMLCALL + xmlCatalogDump (FILE *out); +#endif /* LIBXML_OUTPUT_ENABLED */ +XMLPUBFUN xmlChar * XMLCALL + xmlCatalogResolve (const xmlChar *pubID, + const xmlChar *sysID); +XMLPUBFUN xmlChar * XMLCALL + xmlCatalogResolveSystem (const xmlChar *sysID); +XMLPUBFUN xmlChar * XMLCALL + xmlCatalogResolvePublic (const xmlChar *pubID); +XMLPUBFUN xmlChar * XMLCALL + xmlCatalogResolveURI (const xmlChar *URI); +XMLPUBFUN int XMLCALL + xmlCatalogAdd (const xmlChar *type, + const xmlChar *orig, + const xmlChar *replace); +XMLPUBFUN int XMLCALL + xmlCatalogRemove (const xmlChar *value); +XMLPUBFUN xmlDocPtr XMLCALL + xmlParseCatalogFile (const char *filename); +XMLPUBFUN int XMLCALL + xmlCatalogConvert (void); + +/* + * Strictly minimal interfaces for per-document catalogs used + * by the parser. + */ +XMLPUBFUN void XMLCALL + xmlCatalogFreeLocal (void *catalogs); +XMLPUBFUN void * XMLCALL + xmlCatalogAddLocal (void *catalogs, + const xmlChar *URL); +XMLPUBFUN xmlChar * XMLCALL + xmlCatalogLocalResolve (void *catalogs, + const xmlChar *pubID, + const xmlChar *sysID); +XMLPUBFUN xmlChar * XMLCALL + xmlCatalogLocalResolveURI(void *catalogs, + const xmlChar *URI); +/* + * Preference settings. + */ +XMLPUBFUN int XMLCALL + xmlCatalogSetDebug (int level); +XMLPUBFUN xmlCatalogPrefer XMLCALL + xmlCatalogSetDefaultPrefer(xmlCatalogPrefer prefer); +XMLPUBFUN void XMLCALL + xmlCatalogSetDefaults (xmlCatalogAllow allow); +XMLPUBFUN xmlCatalogAllow XMLCALL + xmlCatalogGetDefaults (void); + + +/* DEPRECATED interfaces */ +XMLPUBFUN const xmlChar * XMLCALL + xmlCatalogGetSystem (const xmlChar *sysID); +XMLPUBFUN const xmlChar * XMLCALL + xmlCatalogGetPublic (const xmlChar *pubID); + +#ifdef __cplusplus +} +#endif +#endif /* LIBXML_CATALOG_ENABLED */ +#endif /* __XML_CATALOG_H__ */ diff --git a/include/libxml/chvalid.h b/include/libxml/chvalid.h new file mode 100644 index 0000000..6301a91 --- /dev/null +++ b/include/libxml/chvalid.h @@ -0,0 +1,230 @@ +/* + * Summary: Unicode character range checking + * Description: this module exports interfaces for the character + * range validation APIs + * + * This file is automatically generated from the cvs source + * definition files using the genChRanges.py Python script + * + * Generation date: Tue Nov 18 08:14:21 2003 + * Sources: chvalid.def + * Author: William Brack + */ + +#ifndef __XML_CHVALID_H__ +#define __XML_CHVALID_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Define our typedefs and structures + * + */ +typedef struct _xmlChSRange xmlChSRange; +typedef xmlChSRange *xmlChSRangePtr; +struct _xmlChSRange { + unsigned short low; + unsigned short high; +}; + +typedef struct _xmlChLRange xmlChLRange; +typedef xmlChLRange *xmlChLRangePtr; +struct _xmlChLRange { + unsigned int low; + unsigned int high; +}; + +typedef struct _xmlChRangeGroup xmlChRangeGroup; +typedef xmlChRangeGroup *xmlChRangeGroupPtr; +struct _xmlChRangeGroup { + int nbShortRange; + int nbLongRange; + xmlChSRangePtr shortRange; /* points to an array of ranges */ + xmlChLRangePtr longRange; +}; + +/** + * Range checking routine + */ +XMLPUBFUN int XMLCALL + xmlCharInRange(unsigned int val, const xmlChRangeGroupPtr group); + + +/** + * xmlIsBaseChar_ch: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsBaseChar_ch(c) (((0x41 <= (c)) && ((c) <= 0x5a)) || \ + ((0x61 <= (c)) && ((c) <= 0x7a)) || \ + ((0xc0 <= (c)) && ((c) <= 0xd6)) || \ + ((0xd8 <= (c)) && ((c) <= 0xf6)) || \ + (0xf8 <= (c))) + +/** + * xmlIsBaseCharQ: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsBaseCharQ(c) (((c) < 0x100) ? \ + xmlIsBaseChar_ch((c)) : \ + xmlCharInRange((c), &xmlIsBaseCharGroup)) + +XMLPUBVAR xmlChRangeGroup xmlIsBaseCharGroup; + +/** + * xmlIsBlank_ch: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsBlank_ch(c) (((c) == 0x20) || \ + ((0x9 <= (c)) && ((c) <= 0xa)) || \ + ((c) == 0xd)) + +/** + * xmlIsBlankQ: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsBlankQ(c) (((c) < 0x100) ? \ + xmlIsBlank_ch((c)) : 0) + + +/** + * xmlIsChar_ch: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsChar_ch(c) (((0x9 <= (c)) && ((c) <= 0xa)) || \ + ((c) == 0xd) || \ + (0x20 <= (c))) + +/** + * xmlIsCharQ: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsCharQ(c) (((c) < 0x100) ? \ + xmlIsChar_ch((c)) :\ + (((0x100 <= (c)) && ((c) <= 0xd7ff)) || \ + ((0xe000 <= (c)) && ((c) <= 0xfffd)) || \ + ((0x10000 <= (c)) && ((c) <= 0x10ffff)))) + +XMLPUBVAR xmlChRangeGroup xmlIsCharGroup; + +/** + * xmlIsCombiningQ: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsCombiningQ(c) (((c) < 0x100) ? \ + 0 : \ + xmlCharInRange((c), &xmlIsCombiningGroup)) + +XMLPUBVAR xmlChRangeGroup xmlIsCombiningGroup; + +/** + * xmlIsDigit_ch: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsDigit_ch(c) (((0x30 <= (c)) && ((c) <= 0x39))) + +/** + * xmlIsDigitQ: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsDigitQ(c) (((c) < 0x100) ? \ + xmlIsDigit_ch((c)) : \ + xmlCharInRange((c), &xmlIsDigitGroup)) + +XMLPUBVAR xmlChRangeGroup xmlIsDigitGroup; + +/** + * xmlIsExtender_ch: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsExtender_ch(c) (((c) == 0xb7)) + +/** + * xmlIsExtenderQ: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsExtenderQ(c) (((c) < 0x100) ? \ + xmlIsExtender_ch((c)) : \ + xmlCharInRange((c), &xmlIsExtenderGroup)) + +XMLPUBVAR xmlChRangeGroup xmlIsExtenderGroup; + +/** + * xmlIsIdeographicQ: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsIdeographicQ(c) (((c) < 0x100) ? \ + 0 :\ + (((0x4e00 <= (c)) && ((c) <= 0x9fa5)) || \ + ((c) == 0x3007) || \ + ((0x3021 <= (c)) && ((c) <= 0x3029)))) + +XMLPUBVAR xmlChRangeGroup xmlIsIdeographicGroup; +XMLPUBVAR unsigned char xmlIsPubidChar_tab[256]; + +/** + * xmlIsPubidChar_ch: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsPubidChar_ch(c) (xmlIsPubidChar_tab[(c)]) + +/** + * xmlIsPubidCharQ: + * @c: char to validate + * + * Automatically generated by genChRanges.py + */ +#define xmlIsPubidCharQ(c) (((c) < 0x100) ? \ + xmlIsPubidChar_ch((c)) : 0) + +XMLPUBFUN int XMLCALL + xmlIsBaseChar(unsigned int ch); +XMLPUBFUN int XMLCALL + xmlIsBlank(unsigned int ch); +XMLPUBFUN int XMLCALL + xmlIsChar(unsigned int ch); +XMLPUBFUN int XMLCALL + xmlIsCombining(unsigned int ch); +XMLPUBFUN int XMLCALL + xmlIsDigit(unsigned int ch); +XMLPUBFUN int XMLCALL + xmlIsExtender(unsigned int ch); +XMLPUBFUN int XMLCALL + xmlIsIdeographic(unsigned int ch); +XMLPUBFUN int XMLCALL + xmlIsPubidChar(unsigned int ch); + +#ifdef __cplusplus +} +#endif +#endif /* __XML_CHVALID_H__ */ diff --git a/include/libxml/debugXML.h b/include/libxml/debugXML.h new file mode 100644 index 0000000..5a9d20b --- /dev/null +++ b/include/libxml/debugXML.h @@ -0,0 +1,217 @@ +/* + * Summary: Tree debugging APIs + * Description: Interfaces to a set of routines used for debugging the tree + * produced by the XML parser. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __DEBUG_XML__ +#define __DEBUG_XML__ +#include +#include +#include + +#ifdef LIBXML_DEBUG_ENABLED + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The standard Dump routines. + */ +XMLPUBFUN void XMLCALL + xmlDebugDumpString (FILE *output, + const xmlChar *str); +XMLPUBFUN void XMLCALL + xmlDebugDumpAttr (FILE *output, + xmlAttrPtr attr, + int depth); +XMLPUBFUN void XMLCALL + xmlDebugDumpAttrList (FILE *output, + xmlAttrPtr attr, + int depth); +XMLPUBFUN void XMLCALL + xmlDebugDumpOneNode (FILE *output, + xmlNodePtr node, + int depth); +XMLPUBFUN void XMLCALL + xmlDebugDumpNode (FILE *output, + xmlNodePtr node, + int depth); +XMLPUBFUN void XMLCALL + xmlDebugDumpNodeList (FILE *output, + xmlNodePtr node, + int depth); +XMLPUBFUN void XMLCALL + xmlDebugDumpDocumentHead(FILE *output, + xmlDocPtr doc); +XMLPUBFUN void XMLCALL + xmlDebugDumpDocument (FILE *output, + xmlDocPtr doc); +XMLPUBFUN void XMLCALL + xmlDebugDumpDTD (FILE *output, + xmlDtdPtr dtd); +XMLPUBFUN void XMLCALL + xmlDebugDumpEntities (FILE *output, + xmlDocPtr doc); + +/**************************************************************** + * * + * Checking routines * + * * + ****************************************************************/ + +XMLPUBFUN int XMLCALL + xmlDebugCheckDocument (FILE * output, + xmlDocPtr doc); + +/**************************************************************** + * * + * XML shell helpers * + * * + ****************************************************************/ + +XMLPUBFUN void XMLCALL + xmlLsOneNode (FILE *output, xmlNodePtr node); +XMLPUBFUN int XMLCALL + xmlLsCountNode (xmlNodePtr node); + +XMLPUBFUN const char * XMLCALL + xmlBoolToText (int boolval); + +/**************************************************************** + * * + * The XML shell related structures and functions * + * * + ****************************************************************/ + +#ifdef LIBXML_XPATH_ENABLED +/** + * xmlShellReadlineFunc: + * @prompt: a string prompt + * + * This is a generic signature for the XML shell input function. + * + * Returns a string which will be freed by the Shell. + */ +typedef char * (* xmlShellReadlineFunc)(char *prompt); + +/** + * xmlShellCtxt: + * + * A debugging shell context. + * TODO: add the defined function tables. + */ +typedef struct _xmlShellCtxt xmlShellCtxt; +typedef xmlShellCtxt *xmlShellCtxtPtr; +struct _xmlShellCtxt { + char *filename; + xmlDocPtr doc; + xmlNodePtr node; + xmlXPathContextPtr pctxt; + int loaded; + FILE *output; + xmlShellReadlineFunc input; +}; + +/** + * xmlShellCmd: + * @ctxt: a shell context + * @arg: a string argument + * @node: a first node + * @node2: a second node + * + * This is a generic signature for the XML shell functions. + * + * Returns an int, negative returns indicating errors. + */ +typedef int (* xmlShellCmd) (xmlShellCtxtPtr ctxt, + char *arg, + xmlNodePtr node, + xmlNodePtr node2); + +XMLPUBFUN void XMLCALL + xmlShellPrintXPathError (int errorType, + const char *arg); +XMLPUBFUN void XMLCALL + xmlShellPrintXPathResult(xmlXPathObjectPtr list); +XMLPUBFUN int XMLCALL + xmlShellList (xmlShellCtxtPtr ctxt, + char *arg, + xmlNodePtr node, + xmlNodePtr node2); +XMLPUBFUN int XMLCALL + xmlShellBase (xmlShellCtxtPtr ctxt, + char *arg, + xmlNodePtr node, + xmlNodePtr node2); +XMLPUBFUN int XMLCALL + xmlShellDir (xmlShellCtxtPtr ctxt, + char *arg, + xmlNodePtr node, + xmlNodePtr node2); +XMLPUBFUN int XMLCALL + xmlShellLoad (xmlShellCtxtPtr ctxt, + char *filename, + xmlNodePtr node, + xmlNodePtr node2); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void XMLCALL + xmlShellPrintNode (xmlNodePtr node); +XMLPUBFUN int XMLCALL + xmlShellCat (xmlShellCtxtPtr ctxt, + char *arg, + xmlNodePtr node, + xmlNodePtr node2); +XMLPUBFUN int XMLCALL + xmlShellWrite (xmlShellCtxtPtr ctxt, + char *filename, + xmlNodePtr node, + xmlNodePtr node2); +XMLPUBFUN int XMLCALL + xmlShellSave (xmlShellCtxtPtr ctxt, + char *filename, + xmlNodePtr node, + xmlNodePtr node2); +#endif /* LIBXML_OUTPUT_ENABLED */ +#ifdef LIBXML_VALID_ENABLED +XMLPUBFUN int XMLCALL + xmlShellValidate (xmlShellCtxtPtr ctxt, + char *dtd, + xmlNodePtr node, + xmlNodePtr node2); +#endif /* LIBXML_VALID_ENABLED */ +XMLPUBFUN int XMLCALL + xmlShellDu (xmlShellCtxtPtr ctxt, + char *arg, + xmlNodePtr tree, + xmlNodePtr node2); +XMLPUBFUN int XMLCALL + xmlShellPwd (xmlShellCtxtPtr ctxt, + char *buffer, + xmlNodePtr node, + xmlNodePtr node2); + +/* + * The Shell interface. + */ +XMLPUBFUN void XMLCALL + xmlShell (xmlDocPtr doc, + char *filename, + xmlShellReadlineFunc input, + FILE *output); + +#endif /* LIBXML_XPATH_ENABLED */ + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_DEBUG_ENABLED */ +#endif /* __DEBUG_XML__ */ diff --git a/include/libxml/dict.h b/include/libxml/dict.h new file mode 100644 index 0000000..abb8339 --- /dev/null +++ b/include/libxml/dict.h @@ -0,0 +1,69 @@ +/* + * Summary: string dictionnary + * Description: dictionary of reusable strings, just used to avoid allocation + * and freeing operations. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_DICT_H__ +#define __XML_DICT_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The dictionnary. + */ +typedef struct _xmlDict xmlDict; +typedef xmlDict *xmlDictPtr; + +/* + * Constructor and destructor. + */ +XMLPUBFUN xmlDictPtr XMLCALL + xmlDictCreate (void); +XMLPUBFUN xmlDictPtr XMLCALL + xmlDictCreateSub(xmlDictPtr sub); +XMLPUBFUN int XMLCALL + xmlDictReference(xmlDictPtr dict); +XMLPUBFUN void XMLCALL + xmlDictFree (xmlDictPtr dict); + +/* + * Lookup of entry in the dictionnary. + */ +XMLPUBFUN const xmlChar * XMLCALL + xmlDictLookup (xmlDictPtr dict, + const xmlChar *name, + int len); +XMLPUBFUN const xmlChar * XMLCALL + xmlDictExists (xmlDictPtr dict, + const xmlChar *name, + int len); +XMLPUBFUN const xmlChar * XMLCALL + xmlDictQLookup (xmlDictPtr dict, + const xmlChar *prefix, + const xmlChar *name); +XMLPUBFUN int XMLCALL + xmlDictOwns (xmlDictPtr dict, + const xmlChar *str); +XMLPUBFUN int XMLCALL + xmlDictSize (xmlDictPtr dict); + +/* + * Cleanup function + */ +XMLPUBFUN void XMLCALL + xmlDictCleanup (void); + +#ifdef __cplusplus +} +#endif +#endif /* ! __XML_DICT_H__ */ diff --git a/include/libxml/encoding.h b/include/libxml/encoding.h new file mode 100644 index 0000000..c74b25f --- /dev/null +++ b/include/libxml/encoding.h @@ -0,0 +1,226 @@ +/* + * Summary: interface for the encoding conversion functions + * Description: interface for the encoding conversion functions needed for + * XML basic encoding and iconv() support. + * + * Related specs are + * rfc2044 (UTF-8 and UTF-16) F. Yergeau Alis Technologies + * [ISO-10646] UTF-8 and UTF-16 in Annexes + * [ISO-8859-1] ISO Latin-1 characters codes. + * [UNICODE] The Unicode Consortium, "The Unicode Standard -- + * Worldwide Character Encoding -- Version 1.0", Addison- + * Wesley, Volume 1, 1991, Volume 2, 1992. UTF-8 is + * described in Unicode Technical Report #4. + * [US-ASCII] Coded Character Set--7-bit American Standard Code for + * Information Interchange, ANSI X3.4-1986. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_CHAR_ENCODING_H__ +#define __XML_CHAR_ENCODING_H__ + +#include + +#ifdef LIBXML_ICONV_ENABLED +#include +#endif +#ifdef __cplusplus +extern "C" { +#endif + +/* + * xmlCharEncoding: + * + * Predefined values for some standard encodings. + * Libxml does not do beforehand translation on UTF8 and ISOLatinX. + * It also supports ASCII, ISO-8859-1, and UTF16 (LE and BE) by default. + * + * Anything else would have to be translated to UTF8 before being + * given to the parser itself. The BOM for UTF16 and the encoding + * declaration are looked at and a converter is looked for at that + * point. If not found the parser stops here as asked by the XML REC. A + * converter can be registered by the user using xmlRegisterCharEncodingHandler + * but the current form doesn't allow stateful transcoding (a serious + * problem agreed !). If iconv has been found it will be used + * automatically and allow stateful transcoding, the simplest is then + * to be sure to enable iconv and to provide iconv libs for the encoding + * support needed. + * + * Note that the generic "UTF-16" is not a predefined value. Instead, only + * the specific UTF-16LE and UTF-16BE are present. + */ +typedef enum { + XML_CHAR_ENCODING_ERROR= -1, /* No char encoding detected */ + XML_CHAR_ENCODING_NONE= 0, /* No char encoding detected */ + XML_CHAR_ENCODING_UTF8= 1, /* UTF-8 */ + XML_CHAR_ENCODING_UTF16LE= 2, /* UTF-16 little endian */ + XML_CHAR_ENCODING_UTF16BE= 3, /* UTF-16 big endian */ + XML_CHAR_ENCODING_UCS4LE= 4, /* UCS-4 little endian */ + XML_CHAR_ENCODING_UCS4BE= 5, /* UCS-4 big endian */ + XML_CHAR_ENCODING_EBCDIC= 6, /* EBCDIC uh! */ + XML_CHAR_ENCODING_UCS4_2143=7, /* UCS-4 unusual ordering */ + XML_CHAR_ENCODING_UCS4_3412=8, /* UCS-4 unusual ordering */ + XML_CHAR_ENCODING_UCS2= 9, /* UCS-2 */ + XML_CHAR_ENCODING_8859_1= 10,/* ISO-8859-1 ISO Latin 1 */ + XML_CHAR_ENCODING_8859_2= 11,/* ISO-8859-2 ISO Latin 2 */ + XML_CHAR_ENCODING_8859_3= 12,/* ISO-8859-3 */ + XML_CHAR_ENCODING_8859_4= 13,/* ISO-8859-4 */ + XML_CHAR_ENCODING_8859_5= 14,/* ISO-8859-5 */ + XML_CHAR_ENCODING_8859_6= 15,/* ISO-8859-6 */ + XML_CHAR_ENCODING_8859_7= 16,/* ISO-8859-7 */ + XML_CHAR_ENCODING_8859_8= 17,/* ISO-8859-8 */ + XML_CHAR_ENCODING_8859_9= 18,/* ISO-8859-9 */ + XML_CHAR_ENCODING_2022_JP= 19,/* ISO-2022-JP */ + XML_CHAR_ENCODING_SHIFT_JIS=20,/* Shift_JIS */ + XML_CHAR_ENCODING_EUC_JP= 21,/* EUC-JP */ + XML_CHAR_ENCODING_ASCII= 22 /* pure ASCII */ +} xmlCharEncoding; + +/** + * xmlCharEncodingInputFunc: + * @out: a pointer to an array of bytes to store the UTF-8 result + * @outlen: the length of @out + * @in: a pointer to an array of chars in the original encoding + * @inlen: the length of @in + * + * Take a block of chars in the original encoding and try to convert + * it to an UTF-8 block of chars out. + * + * Returns the number of bytes written, -1 if lack of space, or -2 + * if the transcoding failed. + * The value of @inlen after return is the number of octets consumed + * if the return value is positive, else unpredictiable. + * The value of @outlen after return is the number of octets consumed. + */ +typedef int (* xmlCharEncodingInputFunc)(unsigned char *out, int *outlen, + const unsigned char *in, int *inlen); + + +/** + * xmlCharEncodingOutputFunc: + * @out: a pointer to an array of bytes to store the result + * @outlen: the length of @out + * @in: a pointer to an array of UTF-8 chars + * @inlen: the length of @in + * + * Take a block of UTF-8 chars in and try to convert it to another + * encoding. + * Note: a first call designed to produce heading info is called with + * in = NULL. If stateful this should also initialize the encoder state. + * + * Returns the number of bytes written, -1 if lack of space, or -2 + * if the transcoding failed. + * The value of @inlen after return is the number of octets consumed + * if the return value is positive, else unpredictiable. + * The value of @outlen after return is the number of octets produced. + */ +typedef int (* xmlCharEncodingOutputFunc)(unsigned char *out, int *outlen, + const unsigned char *in, int *inlen); + + +/* + * Block defining the handlers for non UTF-8 encodings. + * If iconv is supported, there are two extra fields. + */ + +typedef struct _xmlCharEncodingHandler xmlCharEncodingHandler; +typedef xmlCharEncodingHandler *xmlCharEncodingHandlerPtr; +struct _xmlCharEncodingHandler { + char *name; + xmlCharEncodingInputFunc input; + xmlCharEncodingOutputFunc output; +#ifdef LIBXML_ICONV_ENABLED + iconv_t iconv_in; + iconv_t iconv_out; +#endif /* LIBXML_ICONV_ENABLED */ +}; + +#ifdef __cplusplus +} +#endif +#include +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Interfaces for encoding handlers. + */ +XMLPUBFUN void XMLCALL + xmlInitCharEncodingHandlers (void); +XMLPUBFUN void XMLCALL + xmlCleanupCharEncodingHandlers (void); +XMLPUBFUN void XMLCALL + xmlRegisterCharEncodingHandler (xmlCharEncodingHandlerPtr handler); +XMLPUBFUN xmlCharEncodingHandlerPtr XMLCALL + xmlGetCharEncodingHandler (xmlCharEncoding enc); +XMLPUBFUN xmlCharEncodingHandlerPtr XMLCALL + xmlFindCharEncodingHandler (const char *name); +XMLPUBFUN xmlCharEncodingHandlerPtr XMLCALL + xmlNewCharEncodingHandler (const char *name, + xmlCharEncodingInputFunc input, + xmlCharEncodingOutputFunc output); + +/* + * Interfaces for encoding names and aliases. + */ +XMLPUBFUN int XMLCALL + xmlAddEncodingAlias (const char *name, + const char *alias); +XMLPUBFUN int XMLCALL + xmlDelEncodingAlias (const char *alias); +XMLPUBFUN const char * XMLCALL + xmlGetEncodingAlias (const char *alias); +XMLPUBFUN void XMLCALL + xmlCleanupEncodingAliases (void); +XMLPUBFUN xmlCharEncoding XMLCALL + xmlParseCharEncoding (const char *name); +XMLPUBFUN const char * XMLCALL + xmlGetCharEncodingName (xmlCharEncoding enc); + +/* + * Interfaces directly used by the parsers. + */ +XMLPUBFUN xmlCharEncoding XMLCALL + xmlDetectCharEncoding (const unsigned char *in, + int len); + +XMLPUBFUN int XMLCALL + xmlCharEncOutFunc (xmlCharEncodingHandler *handler, + xmlBufferPtr out, + xmlBufferPtr in); + +XMLPUBFUN int XMLCALL + xmlCharEncInFunc (xmlCharEncodingHandler *handler, + xmlBufferPtr out, + xmlBufferPtr in); +XMLPUBFUN int XMLCALL + xmlCharEncFirstLine (xmlCharEncodingHandler *handler, + xmlBufferPtr out, + xmlBufferPtr in); +XMLPUBFUN int XMLCALL + xmlCharEncCloseFunc (xmlCharEncodingHandler *handler); + +/* + * Export a few useful functions + */ +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN int XMLCALL + UTF8Toisolat1 (unsigned char *out, + int *outlen, + const unsigned char *in, + int *inlen); +#endif /* LIBXML_OUTPUT_ENABLED */ +XMLPUBFUN int XMLCALL + isolat1ToUTF8 (unsigned char *out, + int *outlen, + const unsigned char *in, + int *inlen); +#ifdef __cplusplus +} +#endif + +#endif /* __XML_CHAR_ENCODING_H__ */ diff --git a/include/libxml/entities.h b/include/libxml/entities.h new file mode 100644 index 0000000..0bb28a0 --- /dev/null +++ b/include/libxml/entities.h @@ -0,0 +1,139 @@ +/* + * Summary: interface for the XML entities handling + * Description: this module provides some of the entity API needed + * for the parser and applications. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_ENTITIES_H__ +#define __XML_ENTITIES_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The different valid entity types. + */ +typedef enum { + XML_INTERNAL_GENERAL_ENTITY = 1, + XML_EXTERNAL_GENERAL_PARSED_ENTITY = 2, + XML_EXTERNAL_GENERAL_UNPARSED_ENTITY = 3, + XML_INTERNAL_PARAMETER_ENTITY = 4, + XML_EXTERNAL_PARAMETER_ENTITY = 5, + XML_INTERNAL_PREDEFINED_ENTITY = 6 +} xmlEntityType; + +/* + * An unit of storage for an entity, contains the string, the value + * and the linkind data needed for the linking in the hash table. + */ + +struct _xmlEntity { + void *_private; /* application data */ + xmlElementType type; /* XML_ENTITY_DECL, must be second ! */ + const xmlChar *name; /* Entity name */ + struct _xmlNode *children; /* First child link */ + struct _xmlNode *last; /* Last child link */ + struct _xmlDtd *parent; /* -> DTD */ + struct _xmlNode *next; /* next sibling link */ + struct _xmlNode *prev; /* previous sibling link */ + struct _xmlDoc *doc; /* the containing document */ + + xmlChar *orig; /* content without ref substitution */ + xmlChar *content; /* content or ndata if unparsed */ + int length; /* the content length */ + xmlEntityType etype; /* The entity type */ + const xmlChar *ExternalID; /* External identifier for PUBLIC */ + const xmlChar *SystemID; /* URI for a SYSTEM or PUBLIC Entity */ + + struct _xmlEntity *nexte; /* unused */ + const xmlChar *URI; /* the full URI as computed */ + int owner; /* does the entity own the childrens */ +}; + +/* + * All entities are stored in an hash table. + * There is 2 separate hash tables for global and parameter entities. + */ + +typedef struct _xmlHashTable xmlEntitiesTable; +typedef xmlEntitiesTable *xmlEntitiesTablePtr; + +/* + * External functions: + */ + +#ifdef LIBXML_LEGACY_ENABLED +XMLPUBFUN void XMLCALL + xmlInitializePredefinedEntities (void); +#endif /* LIBXML_LEGACY_ENABLED */ +XMLPUBFUN xmlEntityPtr XMLCALL + xmlAddDocEntity (xmlDocPtr doc, + const xmlChar *name, + int type, + const xmlChar *ExternalID, + const xmlChar *SystemID, + const xmlChar *content); +XMLPUBFUN xmlEntityPtr XMLCALL + xmlAddDtdEntity (xmlDocPtr doc, + const xmlChar *name, + int type, + const xmlChar *ExternalID, + const xmlChar *SystemID, + const xmlChar *content); +XMLPUBFUN xmlEntityPtr XMLCALL + xmlGetPredefinedEntity (const xmlChar *name); +XMLPUBFUN xmlEntityPtr XMLCALL + xmlGetDocEntity (xmlDocPtr doc, + const xmlChar *name); +XMLPUBFUN xmlEntityPtr XMLCALL + xmlGetDtdEntity (xmlDocPtr doc, + const xmlChar *name); +XMLPUBFUN xmlEntityPtr XMLCALL + xmlGetParameterEntity (xmlDocPtr doc, + const xmlChar *name); +#ifdef LIBXML_LEGACY_ENABLED +XMLPUBFUN const xmlChar * XMLCALL + xmlEncodeEntities (xmlDocPtr doc, + const xmlChar *input); +#endif /* LIBXML_LEGACY_ENABLED */ +XMLPUBFUN xmlChar * XMLCALL + xmlEncodeEntitiesReentrant(xmlDocPtr doc, + const xmlChar *input); +XMLPUBFUN xmlChar * XMLCALL + xmlEncodeSpecialChars (xmlDocPtr doc, + const xmlChar *input); +XMLPUBFUN xmlEntitiesTablePtr XMLCALL + xmlCreateEntitiesTable (void); +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN xmlEntitiesTablePtr XMLCALL + xmlCopyEntitiesTable (xmlEntitiesTablePtr table); +#endif /* LIBXML_TREE_ENABLED */ +XMLPUBFUN void XMLCALL + xmlFreeEntitiesTable (xmlEntitiesTablePtr table); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void XMLCALL + xmlDumpEntitiesTable (xmlBufferPtr buf, + xmlEntitiesTablePtr table); +XMLPUBFUN void XMLCALL + xmlDumpEntityDecl (xmlBufferPtr buf, + xmlEntityPtr ent); +#endif /* LIBXML_OUTPUT_ENABLED */ +#ifdef LIBXML_LEGACY_ENABLED +XMLPUBFUN void XMLCALL + xmlCleanupPredefinedEntities(void); +#endif /* LIBXML_LEGACY_ENABLED */ + + +#ifdef __cplusplus +} +#endif + +# endif /* __XML_ENTITIES_H__ */ diff --git a/include/libxml/globals.h b/include/libxml/globals.h new file mode 100644 index 0000000..1173a8f --- /dev/null +++ b/include/libxml/globals.h @@ -0,0 +1,455 @@ +/* + * Summary: interface for all global variables of the library + * Description: all the global variables and thread handling for + * those variables is handled by this module. + * + * The bottom of this file is automatically generated by build_glob.py + * based on the description file global.data + * + * Copy: See Copyright for the status of this software. + * + * Author: Gary Pennington , Daniel Veillard + */ + +#ifndef __XML_GLOBALS_H +#define __XML_GLOBALS_H + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +XMLPUBFUN void XMLCALL xmlInitGlobals(void); +XMLPUBFUN void XMLCALL xmlCleanupGlobals(void); + +typedef xmlParserInputBufferPtr (*xmlParserInputBufferCreateFilenameFunc) (const char *URI, xmlCharEncoding enc); +typedef xmlOutputBufferPtr (*xmlOutputBufferCreateFilenameFunc) (const char *URI, xmlCharEncodingHandlerPtr encoder, int compression); +XMLPUBFUN xmlParserInputBufferCreateFilenameFunc +XMLCALL xmlParserInputBufferCreateFilenameDefault (xmlParserInputBufferCreateFilenameFunc func); +XMLPUBFUN xmlOutputBufferCreateFilenameFunc +XMLCALL xmlOutputBufferCreateFilenameDefault (xmlOutputBufferCreateFilenameFunc func); + +/* + * Externally global symbols which need to be protected for backwards + * compatibility support. + */ + +#undef docbDefaultSAXHandler +#undef htmlDefaultSAXHandler +#undef oldXMLWDcompatibility +#undef xmlBufferAllocScheme +#undef xmlDefaultBufferSize +#undef xmlDefaultSAXHandler +#undef xmlDefaultSAXLocator +#undef xmlDoValidityCheckingDefaultValue +#undef xmlFree +#undef xmlGenericError +#undef xmlStructuredError +#undef xmlGenericErrorContext +#undef xmlGetWarningsDefaultValue +#undef xmlIndentTreeOutput +#undef xmlTreeIndentString +#undef xmlKeepBlanksDefaultValue +#undef xmlLineNumbersDefaultValue +#undef xmlLoadExtDtdDefaultValue +#undef xmlMalloc +#undef xmlMallocAtomic +#undef xmlMemStrdup +#undef xmlParserDebugEntities +#undef xmlParserVersion +#undef xmlPedanticParserDefaultValue +#undef xmlRealloc +#undef xmlSaveNoEmptyTags +#undef xmlSubstituteEntitiesDefaultValue +#undef xmlRegisterNodeDefaultValue +#undef xmlDeregisterNodeDefaultValue +#undef xmlLastError +#undef xmlParserInputBufferCreateFilenameValue +#undef xmlOutputBufferCreateFilenameValue + +typedef void (*xmlRegisterNodeFunc) (xmlNodePtr node); +typedef void (*xmlDeregisterNodeFunc) (xmlNodePtr node); + +typedef struct _xmlGlobalState xmlGlobalState; +typedef xmlGlobalState *xmlGlobalStatePtr; +struct _xmlGlobalState +{ + const char *xmlParserVersion; + + xmlSAXLocator xmlDefaultSAXLocator; + xmlSAXHandlerV1 xmlDefaultSAXHandler; + xmlSAXHandlerV1 docbDefaultSAXHandler; + xmlSAXHandlerV1 htmlDefaultSAXHandler; + + xmlFreeFunc xmlFree; + xmlMallocFunc xmlMalloc; + xmlStrdupFunc xmlMemStrdup; + xmlReallocFunc xmlRealloc; + + xmlGenericErrorFunc xmlGenericError; + xmlStructuredErrorFunc xmlStructuredError; + void *xmlGenericErrorContext; + + int oldXMLWDcompatibility; + + xmlBufferAllocationScheme xmlBufferAllocScheme; + int xmlDefaultBufferSize; + + int xmlSubstituteEntitiesDefaultValue; + int xmlDoValidityCheckingDefaultValue; + int xmlGetWarningsDefaultValue; + int xmlKeepBlanksDefaultValue; + int xmlLineNumbersDefaultValue; + int xmlLoadExtDtdDefaultValue; + int xmlParserDebugEntities; + int xmlPedanticParserDefaultValue; + + int xmlSaveNoEmptyTags; + int xmlIndentTreeOutput; + const char *xmlTreeIndentString; + + xmlRegisterNodeFunc xmlRegisterNodeDefaultValue; + xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue; + + xmlMallocFunc xmlMallocAtomic; + xmlError xmlLastError; + + xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValue; + xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValue; +}; + +#ifdef __cplusplus +} +#endif +#include +#ifdef __cplusplus +extern "C" { +#endif + +XMLPUBFUN void XMLCALL xmlInitializeGlobalState(xmlGlobalStatePtr gs); + +XMLPUBFUN void XMLCALL xmlThrDefSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler); + +XMLPUBFUN void XMLCALL xmlThrDefSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler); + +XMLPUBFUN xmlRegisterNodeFunc XMLCALL xmlRegisterNodeDefault(xmlRegisterNodeFunc func); +XMLPUBFUN xmlRegisterNodeFunc XMLCALL xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func); +XMLPUBFUN xmlDeregisterNodeFunc XMLCALL xmlDeregisterNodeDefault(xmlDeregisterNodeFunc func); +XMLPUBFUN xmlDeregisterNodeFunc XMLCALL xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func); + +XMLPUBFUN xmlOutputBufferCreateFilenameFunc XMLCALL + xmlThrDefOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func); +XMLPUBFUN xmlParserInputBufferCreateFilenameFunc XMLCALL + xmlThrDefParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func); + +/** DOC_DISABLE */ +/* + * In general the memory allocation entry points are not kept + * thread specific but this can be overridden by LIBXML_THREAD_ALLOC_ENABLED + * - xmlMalloc + * - xmlMallocAtomic + * - xmlRealloc + * - xmlMemStrdup + * - xmlFree + */ + +#ifdef LIBXML_THREAD_ALLOC_ENABLED +#ifdef LIBXML_THREAD_ENABLED +XMLPUBFUN xmlMallocFunc * XMLCALL __xmlMalloc(void); +#define xmlMalloc \ +(*(__xmlMalloc())) +#else +XMLPUBVAR xmlMallocFunc xmlMalloc; +#endif + +#ifdef LIBXML_THREAD_ENABLED +XMLPUBFUN xmlMallocFunc * XMLCALL __xmlMallocAtomic(void); +#define xmlMallocAtomic \ +(*(__xmlMallocAtomic())) +#else +XMLPUBVAR xmlMallocFunc xmlMallocAtomic; +#endif + +#ifdef LIBXML_THREAD_ENABLED +XMLPUBFUN xmlReallocFunc * XMLCALL __xmlRealloc(void); +#define xmlRealloc \ +(*(__xmlRealloc())) +#else +XMLPUBVAR xmlReallocFunc xmlRealloc; +#endif + +#ifdef LIBXML_THREAD_ENABLED +XMLPUBFUN xmlFreeFunc * XMLCALL __xmlFree(void); +#define xmlFree \ +(*(__xmlFree())) +#else +XMLPUBVAR xmlFreeFunc xmlFree; +#endif + +#ifdef LIBXML_THREAD_ENABLED +XMLPUBFUN xmlStrdupFunc * XMLCALL __xmlMemStrdup(void); +#define xmlMemStrdup \ +(*(__xmlMemStrdup())) +#else +XMLPUBVAR xmlStrdupFunc xmlMemStrdup; +#endif + +#else /* !LIBXML_THREAD_ALLOC_ENABLED */ +XMLPUBVAR xmlMallocFunc xmlMalloc; +XMLPUBVAR xmlMallocFunc xmlMallocAtomic; +XMLPUBVAR xmlReallocFunc xmlRealloc; +XMLPUBVAR xmlFreeFunc xmlFree; +XMLPUBVAR xmlStrdupFunc xmlMemStrdup; +#endif /* LIBXML_THREAD_ALLOC_ENABLED */ + +#ifdef LIBXML_DOCB_ENABLED +XMLPUBFUN xmlSAXHandlerV1 * XMLCALL __docbDefaultSAXHandler(void); +#ifdef LIBXML_THREAD_ENABLED +#define docbDefaultSAXHandler \ +(*(__docbDefaultSAXHandler())) +#else +XMLPUBVAR xmlSAXHandlerV1 docbDefaultSAXHandler; +#endif +#endif + +#ifdef LIBXML_HTML_ENABLED +XMLPUBFUN xmlSAXHandlerV1 * XMLCALL __htmlDefaultSAXHandler(void); +#ifdef LIBXML_THREAD_ENABLED +#define htmlDefaultSAXHandler \ +(*(__htmlDefaultSAXHandler())) +#else +XMLPUBVAR xmlSAXHandlerV1 htmlDefaultSAXHandler; +#endif +#endif + +XMLPUBFUN xmlError * XMLCALL __xmlLastError(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlLastError \ +(*(__xmlLastError())) +#else +XMLPUBVAR xmlError xmlLastError; +#endif + +/* + * Everything starting from the line below is + * Automatically generated by build_glob.py. + * Do not modify the previous line. + */ + + +XMLPUBFUN int * XMLCALL __oldXMLWDcompatibility(void); +#ifdef LIBXML_THREAD_ENABLED +#define oldXMLWDcompatibility \ +(*(__oldXMLWDcompatibility())) +#else +XMLPUBVAR int oldXMLWDcompatibility; +#endif + +XMLPUBFUN xmlBufferAllocationScheme * XMLCALL __xmlBufferAllocScheme(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlBufferAllocScheme \ +(*(__xmlBufferAllocScheme())) +#else +XMLPUBVAR xmlBufferAllocationScheme xmlBufferAllocScheme; +#endif +XMLPUBFUN xmlBufferAllocationScheme XMLCALL xmlThrDefBufferAllocScheme(xmlBufferAllocationScheme v); + +XMLPUBFUN int * XMLCALL __xmlDefaultBufferSize(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlDefaultBufferSize \ +(*(__xmlDefaultBufferSize())) +#else +XMLPUBVAR int xmlDefaultBufferSize; +#endif +XMLPUBFUN int XMLCALL xmlThrDefDefaultBufferSize(int v); + +XMLPUBFUN xmlSAXHandlerV1 * XMLCALL __xmlDefaultSAXHandler(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlDefaultSAXHandler \ +(*(__xmlDefaultSAXHandler())) +#else +XMLPUBVAR xmlSAXHandlerV1 xmlDefaultSAXHandler; +#endif + +XMLPUBFUN xmlSAXLocator * XMLCALL __xmlDefaultSAXLocator(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlDefaultSAXLocator \ +(*(__xmlDefaultSAXLocator())) +#else +XMLPUBVAR xmlSAXLocator xmlDefaultSAXLocator; +#endif + +XMLPUBFUN int * XMLCALL __xmlDoValidityCheckingDefaultValue(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlDoValidityCheckingDefaultValue \ +(*(__xmlDoValidityCheckingDefaultValue())) +#else +XMLPUBVAR int xmlDoValidityCheckingDefaultValue; +#endif +XMLPUBFUN int XMLCALL xmlThrDefDoValidityCheckingDefaultValue(int v); + +XMLPUBFUN xmlGenericErrorFunc * XMLCALL __xmlGenericError(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlGenericError \ +(*(__xmlGenericError())) +#else +XMLPUBVAR xmlGenericErrorFunc xmlGenericError; +#endif + +XMLPUBFUN xmlStructuredErrorFunc * XMLCALL __xmlStructuredError(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlStructuredError \ +(*(__xmlStructuredError())) +#else +XMLPUBVAR xmlStructuredErrorFunc xmlStructuredError; +#endif + +XMLPUBFUN void * * XMLCALL __xmlGenericErrorContext(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlGenericErrorContext \ +(*(__xmlGenericErrorContext())) +#else +XMLPUBVAR void * xmlGenericErrorContext; +#endif + +XMLPUBFUN int * XMLCALL __xmlGetWarningsDefaultValue(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlGetWarningsDefaultValue \ +(*(__xmlGetWarningsDefaultValue())) +#else +XMLPUBVAR int xmlGetWarningsDefaultValue; +#endif +XMLPUBFUN int XMLCALL xmlThrDefGetWarningsDefaultValue(int v); + +XMLPUBFUN int * XMLCALL __xmlIndentTreeOutput(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlIndentTreeOutput \ +(*(__xmlIndentTreeOutput())) +#else +XMLPUBVAR int xmlIndentTreeOutput; +#endif +XMLPUBFUN int XMLCALL xmlThrDefIndentTreeOutput(int v); + +XMLPUBFUN const char * * XMLCALL __xmlTreeIndentString(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlTreeIndentString \ +(*(__xmlTreeIndentString())) +#else +XMLPUBVAR const char * xmlTreeIndentString; +#endif +XMLPUBFUN const char * XMLCALL xmlThrDefTreeIndentString(const char * v); + +XMLPUBFUN int * XMLCALL __xmlKeepBlanksDefaultValue(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlKeepBlanksDefaultValue \ +(*(__xmlKeepBlanksDefaultValue())) +#else +XMLPUBVAR int xmlKeepBlanksDefaultValue; +#endif +XMLPUBFUN int XMLCALL xmlThrDefKeepBlanksDefaultValue(int v); + +XMLPUBFUN int * XMLCALL __xmlLineNumbersDefaultValue(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlLineNumbersDefaultValue \ +(*(__xmlLineNumbersDefaultValue())) +#else +XMLPUBVAR int xmlLineNumbersDefaultValue; +#endif +XMLPUBFUN int XMLCALL xmlThrDefLineNumbersDefaultValue(int v); + +XMLPUBFUN int * XMLCALL __xmlLoadExtDtdDefaultValue(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlLoadExtDtdDefaultValue \ +(*(__xmlLoadExtDtdDefaultValue())) +#else +XMLPUBVAR int xmlLoadExtDtdDefaultValue; +#endif +XMLPUBFUN int XMLCALL xmlThrDefLoadExtDtdDefaultValue(int v); + +XMLPUBFUN int * XMLCALL __xmlParserDebugEntities(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlParserDebugEntities \ +(*(__xmlParserDebugEntities())) +#else +XMLPUBVAR int xmlParserDebugEntities; +#endif +XMLPUBFUN int XMLCALL xmlThrDefParserDebugEntities(int v); + +XMLPUBFUN const char * * XMLCALL __xmlParserVersion(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlParserVersion \ +(*(__xmlParserVersion())) +#else +XMLPUBVAR const char * xmlParserVersion; +#endif + +XMLPUBFUN int * XMLCALL __xmlPedanticParserDefaultValue(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlPedanticParserDefaultValue \ +(*(__xmlPedanticParserDefaultValue())) +#else +XMLPUBVAR int xmlPedanticParserDefaultValue; +#endif +XMLPUBFUN int XMLCALL xmlThrDefPedanticParserDefaultValue(int v); + +XMLPUBFUN int * XMLCALL __xmlSaveNoEmptyTags(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlSaveNoEmptyTags \ +(*(__xmlSaveNoEmptyTags())) +#else +XMLPUBVAR int xmlSaveNoEmptyTags; +#endif +XMLPUBFUN int XMLCALL xmlThrDefSaveNoEmptyTags(int v); + +XMLPUBFUN int * XMLCALL __xmlSubstituteEntitiesDefaultValue(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlSubstituteEntitiesDefaultValue \ +(*(__xmlSubstituteEntitiesDefaultValue())) +#else +XMLPUBVAR int xmlSubstituteEntitiesDefaultValue; +#endif +XMLPUBFUN int XMLCALL xmlThrDefSubstituteEntitiesDefaultValue(int v); + +XMLPUBFUN xmlRegisterNodeFunc * XMLCALL __xmlRegisterNodeDefaultValue(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlRegisterNodeDefaultValue \ +(*(__xmlRegisterNodeDefaultValue())) +#else +XMLPUBVAR xmlRegisterNodeFunc xmlRegisterNodeDefaultValue; +#endif + +XMLPUBFUN xmlDeregisterNodeFunc * XMLCALL __xmlDeregisterNodeDefaultValue(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlDeregisterNodeDefaultValue \ +(*(__xmlDeregisterNodeDefaultValue())) +#else +XMLPUBVAR xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue; +#endif + +XMLPUBFUN xmlParserInputBufferCreateFilenameFunc * XMLCALL __xmlParserInputBufferCreateFilenameValue(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlParserInputBufferCreateFilenameValue \ +(*(__xmlParserInputBufferCreateFilenameValue())) +#else +XMLPUBVAR xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValue; +#endif + +XMLPUBFUN xmlOutputBufferCreateFilenameFunc * XMLCALL __xmlOutputBufferCreateFilenameValue(void); +#ifdef LIBXML_THREAD_ENABLED +#define xmlOutputBufferCreateFilenameValue \ +(*(__xmlOutputBufferCreateFilenameValue())) +#else +XMLPUBVAR xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValue; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __XML_GLOBALS_H */ diff --git a/include/libxml/hash.h b/include/libxml/hash.h new file mode 100644 index 0000000..7fe4be7 --- /dev/null +++ b/include/libxml/hash.h @@ -0,0 +1,233 @@ +/* + * Summary: Chained hash tables + * Description: This module implements the hash table support used in + * various places in the library. + * + * Copy: See Copyright for the status of this software. + * + * Author: Bjorn Reese + */ + +#ifndef __XML_HASH_H__ +#define __XML_HASH_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The hash table. + */ +typedef struct _xmlHashTable xmlHashTable; +typedef xmlHashTable *xmlHashTablePtr; + +#ifdef __cplusplus +} +#endif + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Recent version of gcc produce a warning when a function pointer is assigned + * to an object pointer, or vice versa. The following macro is a dirty hack + * to allow suppression of the warning. If your architecture has function + * pointers which are a different size than a void pointer, there may be some + * serious trouble within the library. + */ +/** + * XML_CAST_FPTR: + * @fptr: pointer to a function + * + * Macro to do a casting from an object pointer to a + * function pointer without encountering a warning from + * gcc + * + * #define XML_CAST_FPTR(fptr) (*(void **)(&fptr)) + * This macro violated ISO C aliasing rules (gcc4 on s390 broke) + * so it is disabled now + */ + +#define XML_CAST_FPTR(fptr) fptr + + +/* + * function types: + */ +/** + * xmlHashDeallocator: + * @payload: the data in the hash + * @name: the name associated + * + * Callback to free data from a hash. + */ +typedef void (*xmlHashDeallocator)(void *payload, xmlChar *name); +/** + * xmlHashCopier: + * @payload: the data in the hash + * @name: the name associated + * + * Callback to copy data from a hash. + * + * Returns a copy of the data or NULL in case of error. + */ +typedef void *(*xmlHashCopier)(void *payload, xmlChar *name); +/** + * xmlHashScanner: + * @payload: the data in the hash + * @data: extra scannner data + * @name: the name associated + * + * Callback when scanning data in a hash with the simple scanner. + */ +typedef void (*xmlHashScanner)(void *payload, void *data, xmlChar *name); +/** + * xmlHashScannerFull: + * @payload: the data in the hash + * @data: extra scannner data + * @name: the name associated + * @name2: the second name associated + * @name3: the third name associated + * + * Callback when scanning data in a hash with the full scanner. + */ +typedef void (*xmlHashScannerFull)(void *payload, void *data, + const xmlChar *name, const xmlChar *name2, + const xmlChar *name3); + +/* + * Constructor and destructor. + */ +XMLPUBFUN xmlHashTablePtr XMLCALL + xmlHashCreate (int size); +XMLPUBFUN xmlHashTablePtr XMLCALL + xmlHashCreateDict(int size, + xmlDictPtr dict); +XMLPUBFUN void XMLCALL + xmlHashFree (xmlHashTablePtr table, + xmlHashDeallocator f); + +/* + * Add a new entry to the hash table. + */ +XMLPUBFUN int XMLCALL + xmlHashAddEntry (xmlHashTablePtr table, + const xmlChar *name, + void *userdata); +XMLPUBFUN int XMLCALL + xmlHashUpdateEntry(xmlHashTablePtr table, + const xmlChar *name, + void *userdata, + xmlHashDeallocator f); +XMLPUBFUN int XMLCALL + xmlHashAddEntry2(xmlHashTablePtr table, + const xmlChar *name, + const xmlChar *name2, + void *userdata); +XMLPUBFUN int XMLCALL + xmlHashUpdateEntry2(xmlHashTablePtr table, + const xmlChar *name, + const xmlChar *name2, + void *userdata, + xmlHashDeallocator f); +XMLPUBFUN int XMLCALL + xmlHashAddEntry3(xmlHashTablePtr table, + const xmlChar *name, + const xmlChar *name2, + const xmlChar *name3, + void *userdata); +XMLPUBFUN int XMLCALL + xmlHashUpdateEntry3(xmlHashTablePtr table, + const xmlChar *name, + const xmlChar *name2, + const xmlChar *name3, + void *userdata, + xmlHashDeallocator f); + +/* + * Remove an entry from the hash table. + */ +XMLPUBFUN int XMLCALL + xmlHashRemoveEntry(xmlHashTablePtr table, const xmlChar *name, + xmlHashDeallocator f); +XMLPUBFUN int XMLCALL + xmlHashRemoveEntry2(xmlHashTablePtr table, const xmlChar *name, + const xmlChar *name2, xmlHashDeallocator f); +XMLPUBFUN int XMLCALL + xmlHashRemoveEntry3(xmlHashTablePtr table, const xmlChar *name, + const xmlChar *name2, const xmlChar *name3, + xmlHashDeallocator f); + +/* + * Retrieve the userdata. + */ +XMLPUBFUN void * XMLCALL + xmlHashLookup (xmlHashTablePtr table, + const xmlChar *name); +XMLPUBFUN void * XMLCALL + xmlHashLookup2 (xmlHashTablePtr table, + const xmlChar *name, + const xmlChar *name2); +XMLPUBFUN void * XMLCALL + xmlHashLookup3 (xmlHashTablePtr table, + const xmlChar *name, + const xmlChar *name2, + const xmlChar *name3); +XMLPUBFUN void * XMLCALL + xmlHashQLookup (xmlHashTablePtr table, + const xmlChar *name, + const xmlChar *prefix); +XMLPUBFUN void * XMLCALL + xmlHashQLookup2 (xmlHashTablePtr table, + const xmlChar *name, + const xmlChar *prefix, + const xmlChar *name2, + const xmlChar *prefix2); +XMLPUBFUN void * XMLCALL + xmlHashQLookup3 (xmlHashTablePtr table, + const xmlChar *name, + const xmlChar *prefix, + const xmlChar *name2, + const xmlChar *prefix2, + const xmlChar *name3, + const xmlChar *prefix3); + +/* + * Helpers. + */ +XMLPUBFUN xmlHashTablePtr XMLCALL + xmlHashCopy (xmlHashTablePtr table, + xmlHashCopier f); +XMLPUBFUN int XMLCALL + xmlHashSize (xmlHashTablePtr table); +XMLPUBFUN void XMLCALL + xmlHashScan (xmlHashTablePtr table, + xmlHashScanner f, + void *data); +XMLPUBFUN void XMLCALL + xmlHashScan3 (xmlHashTablePtr table, + const xmlChar *name, + const xmlChar *name2, + const xmlChar *name3, + xmlHashScanner f, + void *data); +XMLPUBFUN void XMLCALL + xmlHashScanFull (xmlHashTablePtr table, + xmlHashScannerFull f, + void *data); +XMLPUBFUN void XMLCALL + xmlHashScanFull3(xmlHashTablePtr table, + const xmlChar *name, + const xmlChar *name2, + const xmlChar *name3, + xmlHashScannerFull f, + void *data); +#ifdef __cplusplus +} +#endif +#endif /* ! __XML_HASH_H__ */ diff --git a/include/libxml/list.h b/include/libxml/list.h new file mode 100644 index 0000000..1d83482 --- /dev/null +++ b/include/libxml/list.h @@ -0,0 +1,137 @@ +/* + * Summary: lists interfaces + * Description: this module implement the list support used in + * various place in the library. + * + * Copy: See Copyright for the status of this software. + * + * Author: Gary Pennington + */ + +#ifndef __XML_LINK_INCLUDE__ +#define __XML_LINK_INCLUDE__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _xmlLink xmlLink; +typedef xmlLink *xmlLinkPtr; + +typedef struct _xmlList xmlList; +typedef xmlList *xmlListPtr; + +/** + * xmlListDeallocator: + * @lk: the data to deallocate + * + * Callback function used to free data from a list. + */ +typedef void (*xmlListDeallocator) (xmlLinkPtr lk); +/** + * xmlListDataCompare: + * @data0: the first data + * @data1: the second data + * + * Callback function used to compare 2 data. + * + * Returns 0 is equality, -1 or 1 otherwise depending on the ordering. + */ +typedef int (*xmlListDataCompare) (const void *data0, const void *data1); +/** + * xmlListWalker: + * @data: the data found in the list + * @user: extra user provided data to the walker + * + * Callback function used when walking a list with xmlListWalk(). + * + * Returns 0 to stop walking the list, 1 otherwise. + */ +typedef int (*xmlListWalker) (const void *data, const void *user); + +/* Creation/Deletion */ +XMLPUBFUN xmlListPtr XMLCALL + xmlListCreate (xmlListDeallocator deallocator, + xmlListDataCompare compare); +XMLPUBFUN void XMLCALL + xmlListDelete (xmlListPtr l); + +/* Basic Operators */ +XMLPUBFUN void * XMLCALL + xmlListSearch (xmlListPtr l, + void *data); +XMLPUBFUN void * XMLCALL + xmlListReverseSearch (xmlListPtr l, + void *data); +XMLPUBFUN int XMLCALL + xmlListInsert (xmlListPtr l, + void *data) ; +XMLPUBFUN int XMLCALL + xmlListAppend (xmlListPtr l, + void *data) ; +XMLPUBFUN int XMLCALL + xmlListRemoveFirst (xmlListPtr l, + void *data); +XMLPUBFUN int XMLCALL + xmlListRemoveLast (xmlListPtr l, + void *data); +XMLPUBFUN int XMLCALL + xmlListRemoveAll (xmlListPtr l, + void *data); +XMLPUBFUN void XMLCALL + xmlListClear (xmlListPtr l); +XMLPUBFUN int XMLCALL + xmlListEmpty (xmlListPtr l); +XMLPUBFUN xmlLinkPtr XMLCALL + xmlListFront (xmlListPtr l); +XMLPUBFUN xmlLinkPtr XMLCALL + xmlListEnd (xmlListPtr l); +XMLPUBFUN int XMLCALL + xmlListSize (xmlListPtr l); + +XMLPUBFUN void XMLCALL + xmlListPopFront (xmlListPtr l); +XMLPUBFUN void XMLCALL + xmlListPopBack (xmlListPtr l); +XMLPUBFUN int XMLCALL + xmlListPushFront (xmlListPtr l, + void *data); +XMLPUBFUN int XMLCALL + xmlListPushBack (xmlListPtr l, + void *data); + +/* Advanced Operators */ +XMLPUBFUN void XMLCALL + xmlListReverse (xmlListPtr l); +XMLPUBFUN void XMLCALL + xmlListSort (xmlListPtr l); +XMLPUBFUN void XMLCALL + xmlListWalk (xmlListPtr l, + xmlListWalker walker, + const void *user); +XMLPUBFUN void XMLCALL + xmlListReverseWalk (xmlListPtr l, + xmlListWalker walker, + const void *user); +XMLPUBFUN void XMLCALL + xmlListMerge (xmlListPtr l1, + xmlListPtr l2); +XMLPUBFUN xmlListPtr XMLCALL + xmlListDup (const xmlListPtr old); +XMLPUBFUN int XMLCALL + xmlListCopy (xmlListPtr cur, + const xmlListPtr old); +/* Link operators */ +XMLPUBFUN void * XMLCALL + xmlLinkGetData (xmlLinkPtr lk); + +/* xmlListUnique() */ +/* xmlListSwap */ + +#ifdef __cplusplus +} +#endif + +#endif /* __XML_LINK_INCLUDE__ */ diff --git a/include/libxml/nanoftp.h b/include/libxml/nanoftp.h new file mode 100644 index 0000000..e3c28a0 --- /dev/null +++ b/include/libxml/nanoftp.h @@ -0,0 +1,143 @@ +/* + * Summary: minimal FTP implementation + * Description: minimal FTP implementation allowing to fetch resources + * like external subset. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __NANO_FTP_H__ +#define __NANO_FTP_H__ + +#include + +#ifdef LIBXML_FTP_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * ftpListCallback: + * @userData: user provided data for the callback + * @filename: the file name (including "->" when links are shown) + * @attrib: the attribute string + * @owner: the owner string + * @group: the group string + * @size: the file size + * @links: the link count + * @year: the year + * @month: the month + * @day: the day + * @hour: the hour + * @minute: the minute + * + * A callback for the xmlNanoFTPList command. + * Note that only one of year and day:minute are specified. + */ +typedef void (*ftpListCallback) (void *userData, + const char *filename, const char *attrib, + const char *owner, const char *group, + unsigned long size, int links, int year, + const char *month, int day, int hour, + int minute); +/** + * ftpDataCallback: + * @userData: the user provided context + * @data: the data received + * @len: its size in bytes + * + * A callback for the xmlNanoFTPGet command. + */ +typedef void (*ftpDataCallback) (void *userData, + const char *data, + int len); + +/* + * Init + */ +XMLPUBFUN void XMLCALL + xmlNanoFTPInit (void); +XMLPUBFUN void XMLCALL + xmlNanoFTPCleanup (void); + +/* + * Creating/freeing contexts. + */ +XMLPUBFUN void * XMLCALL + xmlNanoFTPNewCtxt (const char *URL); +XMLPUBFUN void XMLCALL + xmlNanoFTPFreeCtxt (void * ctx); +XMLPUBFUN void * XMLCALL + xmlNanoFTPConnectTo (const char *server, + int port); +/* + * Opening/closing session connections. + */ +XMLPUBFUN void * XMLCALL + xmlNanoFTPOpen (const char *URL); +XMLPUBFUN int XMLCALL + xmlNanoFTPConnect (void *ctx); +XMLPUBFUN int XMLCALL + xmlNanoFTPClose (void *ctx); +XMLPUBFUN int XMLCALL + xmlNanoFTPQuit (void *ctx); +XMLPUBFUN void XMLCALL + xmlNanoFTPScanProxy (const char *URL); +XMLPUBFUN void XMLCALL + xmlNanoFTPProxy (const char *host, + int port, + const char *user, + const char *passwd, + int type); +XMLPUBFUN int XMLCALL + xmlNanoFTPUpdateURL (void *ctx, + const char *URL); + +/* + * Rather internal commands. + */ +XMLPUBFUN int XMLCALL + xmlNanoFTPGetResponse (void *ctx); +XMLPUBFUN int XMLCALL + xmlNanoFTPCheckResponse (void *ctx); + +/* + * CD/DIR/GET handlers. + */ +XMLPUBFUN int XMLCALL + xmlNanoFTPCwd (void *ctx, + const char *directory); +XMLPUBFUN int XMLCALL + xmlNanoFTPDele (void *ctx, + const char *file); + +XMLPUBFUN int XMLCALL + xmlNanoFTPGetConnection (void *ctx); +XMLPUBFUN int XMLCALL + xmlNanoFTPCloseConnection(void *ctx); +XMLPUBFUN int XMLCALL + xmlNanoFTPList (void *ctx, + ftpListCallback callback, + void *userData, + const char *filename); +XMLPUBFUN int XMLCALL + xmlNanoFTPGetSocket (void *ctx, + const char *filename); +XMLPUBFUN int XMLCALL + xmlNanoFTPGet (void *ctx, + ftpDataCallback callback, + void *userData, + const char *filename); +XMLPUBFUN int XMLCALL + xmlNanoFTPRead (void *ctx, + void *dest, + int len); + +#ifdef __cplusplus +} +#endif +#endif /* LIBXML_FTP_ENABLED */ +#endif /* __NANO_FTP_H__ */ diff --git a/include/libxml/nanohttp.h b/include/libxml/nanohttp.h new file mode 100644 index 0000000..1d8ac24 --- /dev/null +++ b/include/libxml/nanohttp.h @@ -0,0 +1,81 @@ +/* + * Summary: minimal HTTP implementation + * Description: minimal HTTP implementation allowing to fetch resources + * like external subset. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __NANO_HTTP_H__ +#define __NANO_HTTP_H__ + +#include + +#ifdef LIBXML_HTTP_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif +XMLPUBFUN void XMLCALL + xmlNanoHTTPInit (void); +XMLPUBFUN void XMLCALL + xmlNanoHTTPCleanup (void); +XMLPUBFUN void XMLCALL + xmlNanoHTTPScanProxy (const char *URL); +XMLPUBFUN int XMLCALL + xmlNanoHTTPFetch (const char *URL, + const char *filename, + char **contentType); +XMLPUBFUN void * XMLCALL + xmlNanoHTTPMethod (const char *URL, + const char *method, + const char *input, + char **contentType, + const char *headers, + int ilen); +XMLPUBFUN void * XMLCALL + xmlNanoHTTPMethodRedir (const char *URL, + const char *method, + const char *input, + char **contentType, + char **redir, + const char *headers, + int ilen); +XMLPUBFUN void * XMLCALL + xmlNanoHTTPOpen (const char *URL, + char **contentType); +XMLPUBFUN void * XMLCALL + xmlNanoHTTPOpenRedir (const char *URL, + char **contentType, + char **redir); +XMLPUBFUN int XMLCALL + xmlNanoHTTPReturnCode (void *ctx); +XMLPUBFUN const char * XMLCALL + xmlNanoHTTPAuthHeader (void *ctx); +XMLPUBFUN const char * XMLCALL + xmlNanoHTTPRedir (void *ctx); +XMLPUBFUN int XMLCALL + xmlNanoHTTPContentLength( void * ctx ); +XMLPUBFUN const char * XMLCALL + xmlNanoHTTPEncoding (void *ctx); +XMLPUBFUN const char * XMLCALL + xmlNanoHTTPMimeType (void *ctx); +XMLPUBFUN int XMLCALL + xmlNanoHTTPRead (void *ctx, + void *dest, + int len); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN int XMLCALL + xmlNanoHTTPSave (void *ctxt, + const char *filename); +#endif /* LIBXML_OUTPUT_ENABLED */ +XMLPUBFUN void XMLCALL + xmlNanoHTTPClose (void *ctx); +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_HTTP_ENABLED */ +#endif /* __NANO_HTTP_H__ */ diff --git a/include/libxml/parser.h b/include/libxml/parser.h new file mode 100644 index 0000000..7203ca3 --- /dev/null +++ b/include/libxml/parser.h @@ -0,0 +1,1169 @@ +/* + * Summary: the core parser module + * Description: Interfaces, constants and types related to the XML parser + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_PARSER_H__ +#define __XML_PARSER_H__ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * XML_DEFAULT_VERSION: + * + * The default version of XML used: 1.0 + */ +#define XML_DEFAULT_VERSION "1.0" + +/** + * xmlParserInput: + * + * An xmlParserInput is an input flow for the XML processor. + * Each entity parsed is associated an xmlParserInput (except the + * few predefined ones). This is the case both for internal entities + * - in which case the flow is already completely in memory - or + * external entities - in which case we use the buf structure for + * progressive reading and I18N conversions to the internal UTF-8 format. + */ + +/** + * xmlParserInputDeallocate: + * @str: the string to deallocate + * + * Callback for freeing some parser input allocations. + */ +typedef void (* xmlParserInputDeallocate)(xmlChar *str); + +struct _xmlParserInput { + /* Input buffer */ + xmlParserInputBufferPtr buf; /* UTF-8 encoded buffer */ + + const char *filename; /* The file analyzed, if any */ + const char *directory; /* the directory/base of the file */ + const xmlChar *base; /* Base of the array to parse */ + const xmlChar *cur; /* Current char being parsed */ + const xmlChar *end; /* end of the array to parse */ + int length; /* length if known */ + int line; /* Current line */ + int col; /* Current column */ + /* + * NOTE: consumed is only tested for equality in the parser code, + * so even if there is an overflow this should not give troubles + * for parsing very large instances. + */ + unsigned long consumed; /* How many xmlChars already consumed */ + xmlParserInputDeallocate free; /* function to deallocate the base */ + const xmlChar *encoding; /* the encoding string for entity */ + const xmlChar *version; /* the version string for entity */ + int standalone; /* Was that entity marked standalone */ + int id; /* an unique identifier for the entity */ +}; + +/** + * xmlParserNodeInfo: + * + * The parser can be asked to collect Node informations, i.e. at what + * place in the file they were detected. + * NOTE: This is off by default and not very well tested. + */ +typedef struct _xmlParserNodeInfo xmlParserNodeInfo; +typedef xmlParserNodeInfo *xmlParserNodeInfoPtr; + +struct _xmlParserNodeInfo { + const struct _xmlNode* node; + /* Position & line # that text that created the node begins & ends on */ + unsigned long begin_pos; + unsigned long begin_line; + unsigned long end_pos; + unsigned long end_line; +}; + +typedef struct _xmlParserNodeInfoSeq xmlParserNodeInfoSeq; +typedef xmlParserNodeInfoSeq *xmlParserNodeInfoSeqPtr; +struct _xmlParserNodeInfoSeq { + unsigned long maximum; + unsigned long length; + xmlParserNodeInfo* buffer; +}; + +/** + * xmlParserInputState: + * + * The parser is now working also as a state based parser. + * The recursive one use the state info for entities processing. + */ +typedef enum { + XML_PARSER_EOF = -1, /* nothing is to be parsed */ + XML_PARSER_START = 0, /* nothing has been parsed */ + XML_PARSER_MISC, /* Misc* before int subset */ + XML_PARSER_PI, /* Within a processing instruction */ + XML_PARSER_DTD, /* within some DTD content */ + XML_PARSER_PROLOG, /* Misc* after internal subset */ + XML_PARSER_COMMENT, /* within a comment */ + XML_PARSER_START_TAG, /* within a start tag */ + XML_PARSER_CONTENT, /* within the content */ + XML_PARSER_CDATA_SECTION, /* within a CDATA section */ + XML_PARSER_END_TAG, /* within a closing tag */ + XML_PARSER_ENTITY_DECL, /* within an entity declaration */ + XML_PARSER_ENTITY_VALUE, /* within an entity value in a decl */ + XML_PARSER_ATTRIBUTE_VALUE, /* within an attribute value */ + XML_PARSER_SYSTEM_LITERAL, /* within a SYSTEM value */ + XML_PARSER_EPILOG, /* the Misc* after the last end tag */ + XML_PARSER_IGNORE, /* within an IGNORED section */ + XML_PARSER_PUBLIC_LITERAL /* within a PUBLIC value */ +} xmlParserInputState; + +/** + * XML_DETECT_IDS: + * + * Bit in the loadsubset context field to tell to do ID/REFs lookups. + * Use it to initialize xmlLoadExtDtdDefaultValue. + */ +#define XML_DETECT_IDS 2 + +/** + * XML_COMPLETE_ATTRS: + * + * Bit in the loadsubset context field to tell to do complete the + * elements attributes lists with the ones defaulted from the DTDs. + * Use it to initialize xmlLoadExtDtdDefaultValue. + */ +#define XML_COMPLETE_ATTRS 4 + +/** + * XML_SKIP_IDS: + * + * Bit in the loadsubset context field to tell to not do ID/REFs registration. + * Used to initialize xmlLoadExtDtdDefaultValue in some special cases. + */ +#define XML_SKIP_IDS 8 + +/** + * xmlParserMode: + * + * A parser can operate in various modes + */ +typedef enum { + XML_PARSE_UNKNOWN = 0, + XML_PARSE_DOM = 1, + XML_PARSE_SAX = 2, + XML_PARSE_PUSH_DOM = 3, + XML_PARSE_PUSH_SAX = 4, + XML_PARSE_READER = 5 +} xmlParserMode; + +/** + * xmlParserCtxt: + * + * The parser context. + * NOTE This doesn't completely define the parser state, the (current ?) + * design of the parser uses recursive function calls since this allow + * and easy mapping from the production rules of the specification + * to the actual code. The drawback is that the actual function call + * also reflect the parser state. However most of the parsing routines + * takes as the only argument the parser context pointer, so migrating + * to a state based parser for progressive parsing shouldn't be too hard. + */ +struct _xmlParserCtxt { + struct _xmlSAXHandler *sax; /* The SAX handler */ + void *userData; /* For SAX interface only, used by DOM build */ + xmlDocPtr myDoc; /* the document being built */ + int wellFormed; /* is the document well formed */ + int replaceEntities; /* shall we replace entities ? */ + const xmlChar *version; /* the XML version string */ + const xmlChar *encoding; /* the declared encoding, if any */ + int standalone; /* standalone document */ + int html; /* an HTML(1)/Docbook(2) document */ + + /* Input stream stack */ + xmlParserInputPtr input; /* Current input stream */ + int inputNr; /* Number of current input streams */ + int inputMax; /* Max number of input streams */ + xmlParserInputPtr *inputTab; /* stack of inputs */ + + /* Node analysis stack only used for DOM building */ + xmlNodePtr node; /* Current parsed Node */ + int nodeNr; /* Depth of the parsing stack */ + int nodeMax; /* Max depth of the parsing stack */ + xmlNodePtr *nodeTab; /* array of nodes */ + + int record_info; /* Whether node info should be kept */ + xmlParserNodeInfoSeq node_seq; /* info about each node parsed */ + + int errNo; /* error code */ + + int hasExternalSubset; /* reference and external subset */ + int hasPErefs; /* the internal subset has PE refs */ + int external; /* are we parsing an external entity */ + + int valid; /* is the document valid */ + int validate; /* shall we try to validate ? */ + xmlValidCtxt vctxt; /* The validity context */ + + xmlParserInputState instate; /* current type of input */ + int token; /* next char look-ahead */ + + char *directory; /* the data directory */ + + /* Node name stack */ + const xmlChar *name; /* Current parsed Node */ + int nameNr; /* Depth of the parsing stack */ + int nameMax; /* Max depth of the parsing stack */ + const xmlChar * *nameTab; /* array of nodes */ + + long nbChars; /* number of xmlChar processed */ + long checkIndex; /* used by progressive parsing lookup */ + int keepBlanks; /* ugly but ... */ + int disableSAX; /* SAX callbacks are disabled */ + int inSubset; /* Parsing is in int 1/ext 2 subset */ + const xmlChar * intSubName; /* name of subset */ + xmlChar * extSubURI; /* URI of external subset */ + xmlChar * extSubSystem; /* SYSTEM ID of external subset */ + + /* xml:space values */ + int * space; /* Should the parser preserve spaces */ + int spaceNr; /* Depth of the parsing stack */ + int spaceMax; /* Max depth of the parsing stack */ + int * spaceTab; /* array of space infos */ + + int depth; /* to prevent entity substitution loops */ + xmlParserInputPtr entity; /* used to check entities boundaries */ + int charset; /* encoding of the in-memory content + actually an xmlCharEncoding */ + int nodelen; /* Those two fields are there to */ + int nodemem; /* Speed up large node parsing */ + int pedantic; /* signal pedantic warnings */ + void *_private; /* For user data, libxml won't touch it */ + + int loadsubset; /* should the external subset be loaded */ + int linenumbers; /* set line number in element content */ + void *catalogs; /* document's own catalog */ + int recovery; /* run in recovery mode */ + int progressive; /* is this a progressive parsing */ + xmlDictPtr dict; /* dictionnary for the parser */ + const xmlChar * *atts; /* array for the attributes callbacks */ + int maxatts; /* the size of the array */ + int docdict; /* use strings from dict to build tree */ + + /* + * pre-interned strings + */ + const xmlChar *str_xml; + const xmlChar *str_xmlns; + const xmlChar *str_xml_ns; + + /* + * Everything below is used only by the new SAX mode + */ + int sax2; /* operating in the new SAX mode */ + int nsNr; /* the number of inherited namespaces */ + int nsMax; /* the size of the arrays */ + const xmlChar * *nsTab; /* the array of prefix/namespace name */ + int *attallocs; /* which attribute were allocated */ + void * *pushTab; /* array of data for push */ + xmlHashTablePtr attsDefault; /* defaulted attributes if any */ + xmlHashTablePtr attsSpecial; /* non-CDATA attributes if any */ + int nsWellFormed; /* is the document XML Nanespace okay */ + int options; /* Extra options */ + + /* + * Those fields are needed only for treaming parsing so far + */ + int dictNames; /* Use dictionary names for the tree */ + int freeElemsNr; /* number of freed element nodes */ + xmlNodePtr freeElems; /* List of freed element nodes */ + int freeAttrsNr; /* number of freed attributes nodes */ + xmlAttrPtr freeAttrs; /* List of freed attributes nodes */ + + /* + * the complete error informations for the last error. + */ + xmlError lastError; + xmlParserMode parseMode; /* the parser mode */ +}; + +/** + * xmlSAXLocator: + * + * A SAX Locator. + */ +struct _xmlSAXLocator { + const xmlChar *(*getPublicId)(void *ctx); + const xmlChar *(*getSystemId)(void *ctx); + int (*getLineNumber)(void *ctx); + int (*getColumnNumber)(void *ctx); +}; + +/** + * xmlSAXHandler: + * + * A SAX handler is bunch of callbacks called by the parser when processing + * of the input generate data or structure informations. + */ + +/** + * resolveEntitySAXFunc: + * @ctx: the user data (XML parser context) + * @publicId: The public ID of the entity + * @systemId: The system ID of the entity + * + * Callback: + * The entity loader, to control the loading of external entities, + * the application can either: + * - override this resolveEntity() callback in the SAX block + * - or better use the xmlSetExternalEntityLoader() function to + * set up it's own entity resolution routine + * + * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour. + */ +typedef xmlParserInputPtr (*resolveEntitySAXFunc) (void *ctx, + const xmlChar *publicId, + const xmlChar *systemId); +/** + * internalSubsetSAXFunc: + * @ctx: the user data (XML parser context) + * @name: the root element name + * @ExternalID: the external ID + * @SystemID: the SYSTEM ID (e.g. filename or URL) + * + * Callback on internal subset declaration. + */ +typedef void (*internalSubsetSAXFunc) (void *ctx, + const xmlChar *name, + const xmlChar *ExternalID, + const xmlChar *SystemID); +/** + * externalSubsetSAXFunc: + * @ctx: the user data (XML parser context) + * @name: the root element name + * @ExternalID: the external ID + * @SystemID: the SYSTEM ID (e.g. filename or URL) + * + * Callback on external subset declaration. + */ +typedef void (*externalSubsetSAXFunc) (void *ctx, + const xmlChar *name, + const xmlChar *ExternalID, + const xmlChar *SystemID); +/** + * getEntitySAXFunc: + * @ctx: the user data (XML parser context) + * @name: The entity name + * + * Get an entity by name. + * + * Returns the xmlEntityPtr if found. + */ +typedef xmlEntityPtr (*getEntitySAXFunc) (void *ctx, + const xmlChar *name); +/** + * getParameterEntitySAXFunc: + * @ctx: the user data (XML parser context) + * @name: The entity name + * + * Get a parameter entity by name. + * + * Returns the xmlEntityPtr if found. + */ +typedef xmlEntityPtr (*getParameterEntitySAXFunc) (void *ctx, + const xmlChar *name); +/** + * entityDeclSAXFunc: + * @ctx: the user data (XML parser context) + * @name: the entity name + * @type: the entity type + * @publicId: The public ID of the entity + * @systemId: The system ID of the entity + * @content: the entity value (without processing). + * + * An entity definition has been parsed. + */ +typedef void (*entityDeclSAXFunc) (void *ctx, + const xmlChar *name, + int type, + const xmlChar *publicId, + const xmlChar *systemId, + xmlChar *content); +/** + * notationDeclSAXFunc: + * @ctx: the user data (XML parser context) + * @name: The name of the notation + * @publicId: The public ID of the entity + * @systemId: The system ID of the entity + * + * What to do when a notation declaration has been parsed. + */ +typedef void (*notationDeclSAXFunc)(void *ctx, + const xmlChar *name, + const xmlChar *publicId, + const xmlChar *systemId); +/** + * attributeDeclSAXFunc: + * @ctx: the user data (XML parser context) + * @elem: the name of the element + * @fullname: the attribute name + * @type: the attribute type + * @def: the type of default value + * @defaultValue: the attribute default value + * @tree: the tree of enumerated value set + * + * An attribute definition has been parsed. + */ +typedef void (*attributeDeclSAXFunc)(void *ctx, + const xmlChar *elem, + const xmlChar *fullname, + int type, + int def, + const xmlChar *defaultValue, + xmlEnumerationPtr tree); +/** + * elementDeclSAXFunc: + * @ctx: the user data (XML parser context) + * @name: the element name + * @type: the element type + * @content: the element value tree + * + * An element definition has been parsed. + */ +typedef void (*elementDeclSAXFunc)(void *ctx, + const xmlChar *name, + int type, + xmlElementContentPtr content); +/** + * unparsedEntityDeclSAXFunc: + * @ctx: the user data (XML parser context) + * @name: The name of the entity + * @publicId: The public ID of the entity + * @systemId: The system ID of the entity + * @notationName: the name of the notation + * + * What to do when an unparsed entity declaration is parsed. + */ +typedef void (*unparsedEntityDeclSAXFunc)(void *ctx, + const xmlChar *name, + const xmlChar *publicId, + const xmlChar *systemId, + const xmlChar *notationName); +/** + * setDocumentLocatorSAXFunc: + * @ctx: the user data (XML parser context) + * @loc: A SAX Locator + * + * Receive the document locator at startup, actually xmlDefaultSAXLocator. + * Everything is available on the context, so this is useless in our case. + */ +typedef void (*setDocumentLocatorSAXFunc) (void *ctx, + xmlSAXLocatorPtr loc); +/** + * startDocumentSAXFunc: + * @ctx: the user data (XML parser context) + * + * Called when the document start being processed. + */ +typedef void (*startDocumentSAXFunc) (void *ctx); +/** + * endDocumentSAXFunc: + * @ctx: the user data (XML parser context) + * + * Called when the document end has been detected. + */ +typedef void (*endDocumentSAXFunc) (void *ctx); +/** + * startElementSAXFunc: + * @ctx: the user data (XML parser context) + * @name: The element name, including namespace prefix + * @atts: An array of name/value attributes pairs, NULL terminated + * + * Called when an opening tag has been processed. + */ +typedef void (*startElementSAXFunc) (void *ctx, + const xmlChar *name, + const xmlChar **atts); +/** + * endElementSAXFunc: + * @ctx: the user data (XML parser context) + * @name: The element name + * + * Called when the end of an element has been detected. + */ +typedef void (*endElementSAXFunc) (void *ctx, + const xmlChar *name); +/** + * attributeSAXFunc: + * @ctx: the user data (XML parser context) + * @name: The attribute name, including namespace prefix + * @value: The attribute value + * + * Handle an attribute that has been read by the parser. + * The default handling is to convert the attribute into an + * DOM subtree and past it in a new xmlAttr element added to + * the element. + */ +typedef void (*attributeSAXFunc) (void *ctx, + const xmlChar *name, + const xmlChar *value); +/** + * referenceSAXFunc: + * @ctx: the user data (XML parser context) + * @name: The entity name + * + * Called when an entity reference is detected. + */ +typedef void (*referenceSAXFunc) (void *ctx, + const xmlChar *name); +/** + * charactersSAXFunc: + * @ctx: the user data (XML parser context) + * @ch: a xmlChar string + * @len: the number of xmlChar + * + * Receiving some chars from the parser. + */ +typedef void (*charactersSAXFunc) (void *ctx, + const xmlChar *ch, + int len); +/** + * ignorableWhitespaceSAXFunc: + * @ctx: the user data (XML parser context) + * @ch: a xmlChar string + * @len: the number of xmlChar + * + * Receiving some ignorable whitespaces from the parser. + * UNUSED: by default the DOM building will use characters. + */ +typedef void (*ignorableWhitespaceSAXFunc) (void *ctx, + const xmlChar *ch, + int len); +/** + * processingInstructionSAXFunc: + * @ctx: the user data (XML parser context) + * @target: the target name + * @data: the PI data's + * + * A processing instruction has been parsed. + */ +typedef void (*processingInstructionSAXFunc) (void *ctx, + const xmlChar *target, + const xmlChar *data); +/** + * commentSAXFunc: + * @ctx: the user data (XML parser context) + * @value: the comment content + * + * A comment has been parsed. + */ +typedef void (*commentSAXFunc) (void *ctx, + const xmlChar *value); +/** + * cdataBlockSAXFunc: + * @ctx: the user data (XML parser context) + * @value: The pcdata content + * @len: the block length + * + * Called when a pcdata block has been parsed. + */ +typedef void (*cdataBlockSAXFunc) ( + void *ctx, + const xmlChar *value, + int len); +/** + * warningSAXFunc: + * @ctx: an XML parser context + * @msg: the message to display/transmit + * @...: extra parameters for the message display + * + * Display and format a warning messages, callback. + */ +typedef void (*warningSAXFunc) (void *ctx, + const char *msg, ...); +/** + * errorSAXFunc: + * @ctx: an XML parser context + * @msg: the message to display/transmit + * @...: extra parameters for the message display + * + * Display and format an error messages, callback. + */ +typedef void (*errorSAXFunc) (void *ctx, + const char *msg, ...); +/** + * fatalErrorSAXFunc: + * @ctx: an XML parser context + * @msg: the message to display/transmit + * @...: extra parameters for the message display + * + * Display and format fatal error messages, callback. + * Note: so far fatalError() SAX callbacks are not used, error() + * get all the callbacks for errors. + */ +typedef void (*fatalErrorSAXFunc) (void *ctx, + const char *msg, ...); +/** + * isStandaloneSAXFunc: + * @ctx: the user data (XML parser context) + * + * Is this document tagged standalone? + * + * Returns 1 if true + */ +typedef int (*isStandaloneSAXFunc) (void *ctx); +/** + * hasInternalSubsetSAXFunc: + * @ctx: the user data (XML parser context) + * + * Does this document has an internal subset. + * + * Returns 1 if true + */ +typedef int (*hasInternalSubsetSAXFunc) (void *ctx); + +/** + * hasExternalSubsetSAXFunc: + * @ctx: the user data (XML parser context) + * + * Does this document has an external subset? + * + * Returns 1 if true + */ +typedef int (*hasExternalSubsetSAXFunc) (void *ctx); + +/************************************************************************ + * * + * The SAX version 2 API extensions * + * * + ************************************************************************/ +/** + * XML_SAX2_MAGIC: + * + * Special constant found in SAX2 blocks initialized fields + */ +#define XML_SAX2_MAGIC 0xDEEDBEAF + +/** + * startElementNsSAX2Func: + * @ctx: the user data (XML parser context) + * @localname: the local name of the element + * @prefix: the element namespace prefix if available + * @URI: the element namespace name if available + * @nb_namespaces: number of namespace definitions on that node + * @namespaces: pointer to the array of prefix/URI pairs namespace definitions + * @nb_attributes: the number of attributes on that node + * @nb_defaulted: the number of defaulted attributes. The defaulted + * ones are at the end of the array + * @attributes: pointer to the array of (localname/prefix/URI/value/end) + * attribute values. + * + * SAX2 callback when an element start has been detected by the parser. + * It provides the namespace informations for the element, as well as + * the new namespace declarations on the element. + */ + +typedef void (*startElementNsSAX2Func) (void *ctx, + const xmlChar *localname, + const xmlChar *prefix, + const xmlChar *URI, + int nb_namespaces, + const xmlChar **namespaces, + int nb_attributes, + int nb_defaulted, + const xmlChar **attributes); + +/** + * endElementNsSAX2Func: + * @ctx: the user data (XML parser context) + * @localname: the local name of the element + * @prefix: the element namespace prefix if available + * @URI: the element namespace name if available + * + * SAX2 callback when an element end has been detected by the parser. + * It provides the namespace informations for the element. + */ + +typedef void (*endElementNsSAX2Func) (void *ctx, + const xmlChar *localname, + const xmlChar *prefix, + const xmlChar *URI); + + +struct _xmlSAXHandler { + internalSubsetSAXFunc internalSubset; + isStandaloneSAXFunc isStandalone; + hasInternalSubsetSAXFunc hasInternalSubset; + hasExternalSubsetSAXFunc hasExternalSubset; + resolveEntitySAXFunc resolveEntity; + getEntitySAXFunc getEntity; + entityDeclSAXFunc entityDecl; + notationDeclSAXFunc notationDecl; + attributeDeclSAXFunc attributeDecl; + elementDeclSAXFunc elementDecl; + unparsedEntityDeclSAXFunc unparsedEntityDecl; + setDocumentLocatorSAXFunc setDocumentLocator; + startDocumentSAXFunc startDocument; + endDocumentSAXFunc endDocument; + startElementSAXFunc startElement; + endElementSAXFunc endElement; + referenceSAXFunc reference; + charactersSAXFunc characters; + ignorableWhitespaceSAXFunc ignorableWhitespace; + processingInstructionSAXFunc processingInstruction; + commentSAXFunc comment; + warningSAXFunc warning; + errorSAXFunc error; + fatalErrorSAXFunc fatalError; /* unused error() get all the errors */ + getParameterEntitySAXFunc getParameterEntity; + cdataBlockSAXFunc cdataBlock; + externalSubsetSAXFunc externalSubset; + unsigned int initialized; + /* The following fields are extensions available only on version 2 */ + void *_private; + startElementNsSAX2Func startElementNs; + endElementNsSAX2Func endElementNs; + xmlStructuredErrorFunc serror; +}; + +/* + * SAX Version 1 + */ +typedef struct _xmlSAXHandlerV1 xmlSAXHandlerV1; +typedef xmlSAXHandlerV1 *xmlSAXHandlerV1Ptr; +struct _xmlSAXHandlerV1 { + internalSubsetSAXFunc internalSubset; + isStandaloneSAXFunc isStandalone; + hasInternalSubsetSAXFunc hasInternalSubset; + hasExternalSubsetSAXFunc hasExternalSubset; + resolveEntitySAXFunc resolveEntity; + getEntitySAXFunc getEntity; + entityDeclSAXFunc entityDecl; + notationDeclSAXFunc notationDecl; + attributeDeclSAXFunc attributeDecl; + elementDeclSAXFunc elementDecl; + unparsedEntityDeclSAXFunc unparsedEntityDecl; + setDocumentLocatorSAXFunc setDocumentLocator; + startDocumentSAXFunc startDocument; + endDocumentSAXFunc endDocument; + startElementSAXFunc startElement; + endElementSAXFunc endElement; + referenceSAXFunc reference; + charactersSAXFunc characters; + ignorableWhitespaceSAXFunc ignorableWhitespace; + processingInstructionSAXFunc processingInstruction; + commentSAXFunc comment; + warningSAXFunc warning; + errorSAXFunc error; + fatalErrorSAXFunc fatalError; /* unused error() get all the errors */ + getParameterEntitySAXFunc getParameterEntity; + cdataBlockSAXFunc cdataBlock; + externalSubsetSAXFunc externalSubset; + unsigned int initialized; +}; + + +/** + * xmlExternalEntityLoader: + * @URL: The System ID of the resource requested + * @ID: The Public ID of the resource requested + * @context: the XML parser context + * + * External entity loaders types. + * + * Returns the entity input parser. + */ +typedef xmlParserInputPtr (*xmlExternalEntityLoader) (const char *URL, + const char *ID, + xmlParserCtxtPtr context); + +#ifdef __cplusplus +} +#endif + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * Init/Cleanup + */ +XMLPUBFUN void XMLCALL + xmlInitParser (void); +XMLPUBFUN void XMLCALL + xmlCleanupParser (void); + +/* + * Input functions + */ +XMLPUBFUN int XMLCALL + xmlParserInputRead (xmlParserInputPtr in, + int len); +XMLPUBFUN int XMLCALL + xmlParserInputGrow (xmlParserInputPtr in, + int len); + +/* + * Basic parsing Interfaces + */ +#ifdef LIBXML_SAX1_ENABLED +XMLPUBFUN xmlDocPtr XMLCALL + xmlParseDoc (const xmlChar *cur); +XMLPUBFUN xmlDocPtr XMLCALL + xmlParseFile (const char *filename); +XMLPUBFUN xmlDocPtr XMLCALL + xmlParseMemory (const char *buffer, + int size); +#endif /* LIBXML_SAX1_ENABLED */ +XMLPUBFUN int XMLCALL + xmlSubstituteEntitiesDefault(int val); +XMLPUBFUN int XMLCALL + xmlKeepBlanksDefault (int val); +XMLPUBFUN void XMLCALL + xmlStopParser (xmlParserCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + xmlPedanticParserDefault(int val); +XMLPUBFUN int XMLCALL + xmlLineNumbersDefault (int val); + +#ifdef LIBXML_SAX1_ENABLED +/* + * Recovery mode + */ +XMLPUBFUN xmlDocPtr XMLCALL + xmlRecoverDoc (xmlChar *cur); +XMLPUBFUN xmlDocPtr XMLCALL + xmlRecoverMemory (const char *buffer, + int size); +XMLPUBFUN xmlDocPtr XMLCALL + xmlRecoverFile (const char *filename); +#endif /* LIBXML_SAX1_ENABLED */ + +/* + * Less common routines and SAX interfaces + */ +XMLPUBFUN int XMLCALL + xmlParseDocument (xmlParserCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + xmlParseExtParsedEnt (xmlParserCtxtPtr ctxt); +#ifdef LIBXML_SAX1_ENABLED +XMLPUBFUN int XMLCALL + xmlSAXUserParseFile (xmlSAXHandlerPtr sax, + void *user_data, + const char *filename); +XMLPUBFUN int XMLCALL + xmlSAXUserParseMemory (xmlSAXHandlerPtr sax, + void *user_data, + const char *buffer, + int size); +XMLPUBFUN xmlDocPtr XMLCALL + xmlSAXParseDoc (xmlSAXHandlerPtr sax, + const xmlChar *cur, + int recovery); +XMLPUBFUN xmlDocPtr XMLCALL + xmlSAXParseMemory (xmlSAXHandlerPtr sax, + const char *buffer, + int size, + int recovery); +XMLPUBFUN xmlDocPtr XMLCALL + xmlSAXParseMemoryWithData (xmlSAXHandlerPtr sax, + const char *buffer, + int size, + int recovery, + void *data); +XMLPUBFUN xmlDocPtr XMLCALL + xmlSAXParseFile (xmlSAXHandlerPtr sax, + const char *filename, + int recovery); +XMLPUBFUN xmlDocPtr XMLCALL + xmlSAXParseFileWithData (xmlSAXHandlerPtr sax, + const char *filename, + int recovery, + void *data); +XMLPUBFUN xmlDocPtr XMLCALL + xmlSAXParseEntity (xmlSAXHandlerPtr sax, + const char *filename); +XMLPUBFUN xmlDocPtr XMLCALL + xmlParseEntity (const char *filename); +#endif /* LIBXML_SAX1_ENABLED */ + +#ifdef LIBXML_VALID_ENABLED +XMLPUBFUN xmlDtdPtr XMLCALL + xmlSAXParseDTD (xmlSAXHandlerPtr sax, + const xmlChar *ExternalID, + const xmlChar *SystemID); +XMLPUBFUN xmlDtdPtr XMLCALL + xmlParseDTD (const xmlChar *ExternalID, + const xmlChar *SystemID); +XMLPUBFUN xmlDtdPtr XMLCALL + xmlIOParseDTD (xmlSAXHandlerPtr sax, + xmlParserInputBufferPtr input, + xmlCharEncoding enc); +#endif /* LIBXML_VALID_ENABLE */ +#ifdef LIBXML_SAX1_ENABLED +XMLPUBFUN int XMLCALL + xmlParseBalancedChunkMemory(xmlDocPtr doc, + xmlSAXHandlerPtr sax, + void *user_data, + int depth, + const xmlChar *string, + xmlNodePtr *lst); +#endif /* LIBXML_SAX1_ENABLED */ +XMLPUBFUN xmlParserErrors XMLCALL + xmlParseInNodeContext (xmlNodePtr node, + const char *data, + int datalen, + int options, + xmlNodePtr *lst); +#ifdef LIBXML_SAX1_ENABLED +XMLPUBFUN int XMLCALL + xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, + xmlSAXHandlerPtr sax, + void *user_data, + int depth, + const xmlChar *string, + xmlNodePtr *lst, + int recover); +XMLPUBFUN int XMLCALL + xmlParseExternalEntity (xmlDocPtr doc, + xmlSAXHandlerPtr sax, + void *user_data, + int depth, + const xmlChar *URL, + const xmlChar *ID, + xmlNodePtr *lst); +#endif /* LIBXML_SAX1_ENABLED */ +XMLPUBFUN int XMLCALL + xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, + const xmlChar *URL, + const xmlChar *ID, + xmlNodePtr *lst); + +/* + * Parser contexts handling. + */ +XMLPUBFUN xmlParserCtxtPtr XMLCALL + xmlNewParserCtxt (void); +XMLPUBFUN int XMLCALL + xmlInitParserCtxt (xmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlClearParserCtxt (xmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlFreeParserCtxt (xmlParserCtxtPtr ctxt); +#ifdef LIBXML_SAX1_ENABLED +XMLPUBFUN void XMLCALL + xmlSetupParserForBuffer (xmlParserCtxtPtr ctxt, + const xmlChar* buffer, + const char *filename); +#endif /* LIBXML_SAX1_ENABLED */ +XMLPUBFUN xmlParserCtxtPtr XMLCALL + xmlCreateDocParserCtxt (const xmlChar *cur); + +#ifdef LIBXML_LEGACY_ENABLED +/* + * Reading/setting optional parsing features. + */ +XMLPUBFUN int XMLCALL + xmlGetFeaturesList (int *len, + const char **result); +XMLPUBFUN int XMLCALL + xmlGetFeature (xmlParserCtxtPtr ctxt, + const char *name, + void *result); +XMLPUBFUN int XMLCALL + xmlSetFeature (xmlParserCtxtPtr ctxt, + const char *name, + void *value); +#endif /* LIBXML_LEGACY_ENABLED */ + +#ifdef LIBXML_PUSH_ENABLED +/* + * Interfaces for the Push mode. + */ +XMLPUBFUN xmlParserCtxtPtr XMLCALL + xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, + void *user_data, + const char *chunk, + int size, + const char *filename); +XMLPUBFUN int XMLCALL + xmlParseChunk (xmlParserCtxtPtr ctxt, + const char *chunk, + int size, + int terminate); +#endif /* LIBXML_PUSH_ENABLED */ + +/* + * Special I/O mode. + */ + +XMLPUBFUN xmlParserCtxtPtr XMLCALL + xmlCreateIOParserCtxt (xmlSAXHandlerPtr sax, + void *user_data, + xmlInputReadCallback ioread, + xmlInputCloseCallback ioclose, + void *ioctx, + xmlCharEncoding enc); + +XMLPUBFUN xmlParserInputPtr XMLCALL + xmlNewIOInputStream (xmlParserCtxtPtr ctxt, + xmlParserInputBufferPtr input, + xmlCharEncoding enc); + +/* + * Node infos. + */ +XMLPUBFUN const xmlParserNodeInfo* XMLCALL + xmlParserFindNodeInfo (const xmlParserCtxtPtr ctxt, + const xmlNodePtr node); +XMLPUBFUN void XMLCALL + xmlInitNodeInfoSeq (xmlParserNodeInfoSeqPtr seq); +XMLPUBFUN void XMLCALL + xmlClearNodeInfoSeq (xmlParserNodeInfoSeqPtr seq); +XMLPUBFUN unsigned long XMLCALL + xmlParserFindNodeInfoIndex(const xmlParserNodeInfoSeqPtr seq, + const xmlNodePtr node); +XMLPUBFUN void XMLCALL + xmlParserAddNodeInfo (xmlParserCtxtPtr ctxt, + const xmlParserNodeInfoPtr info); + +/* + * External entities handling actually implemented in xmlIO. + */ + +XMLPUBFUN void XMLCALL + xmlSetExternalEntityLoader(xmlExternalEntityLoader f); +XMLPUBFUN xmlExternalEntityLoader XMLCALL + xmlGetExternalEntityLoader(void); +XMLPUBFUN xmlParserInputPtr XMLCALL + xmlLoadExternalEntity (const char *URL, + const char *ID, + xmlParserCtxtPtr ctxt); + +/* + * Index lookup, actually implemented in the encoding module + */ +XMLPUBFUN long XMLCALL + xmlByteConsumed (xmlParserCtxtPtr ctxt); + +/* + * New set of simpler/more flexible APIs + */ +/** + * xmlParserOption: + * + * This is the set of XML parser options that can be passed down + * to the xmlReadDoc() and similar calls. + */ +typedef enum { + XML_PARSE_RECOVER = 1<<0, /* recover on errors */ + XML_PARSE_NOENT = 1<<1, /* substitute entities */ + XML_PARSE_DTDLOAD = 1<<2, /* load the external subset */ + XML_PARSE_DTDATTR = 1<<3, /* default DTD attributes */ + XML_PARSE_DTDVALID = 1<<4, /* validate with the DTD */ + XML_PARSE_NOERROR = 1<<5, /* suppress error reports */ + XML_PARSE_NOWARNING = 1<<6, /* suppress warning reports */ + XML_PARSE_PEDANTIC = 1<<7, /* pedantic error reporting */ + XML_PARSE_NOBLANKS = 1<<8, /* remove blank nodes */ + XML_PARSE_SAX1 = 1<<9, /* use the SAX1 interface internally */ + XML_PARSE_XINCLUDE = 1<<10,/* Implement XInclude substitition */ + XML_PARSE_NONET = 1<<11,/* Forbid network access */ + XML_PARSE_NODICT = 1<<12,/* Do not reuse the context dictionnary */ + XML_PARSE_NSCLEAN = 1<<13,/* remove redundant namespaces declarations */ + XML_PARSE_NOCDATA = 1<<14,/* merge CDATA as text nodes */ + XML_PARSE_NOXINCNODE= 1<<15 /* do not generate XINCLUDE START/END nodes */ +} xmlParserOption; + +XMLPUBFUN void XMLCALL + xmlCtxtReset (xmlParserCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + xmlCtxtResetPush (xmlParserCtxtPtr ctxt, + const char *chunk, + int size, + const char *filename, + const char *encoding); +XMLPUBFUN int XMLCALL + xmlCtxtUseOptions (xmlParserCtxtPtr ctxt, + int options); +XMLPUBFUN xmlDocPtr XMLCALL + xmlReadDoc (const xmlChar *cur, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN xmlDocPtr XMLCALL + xmlReadFile (const char *URL, + const char *encoding, + int options); +XMLPUBFUN xmlDocPtr XMLCALL + xmlReadMemory (const char *buffer, + int size, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN xmlDocPtr XMLCALL + xmlReadFd (int fd, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN xmlDocPtr XMLCALL + xmlReadIO (xmlInputReadCallback ioread, + xmlInputCloseCallback ioclose, + void *ioctx, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN xmlDocPtr XMLCALL + xmlCtxtReadDoc (xmlParserCtxtPtr ctxt, + const xmlChar *cur, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN xmlDocPtr XMLCALL + xmlCtxtReadFile (xmlParserCtxtPtr ctxt, + const char *filename, + const char *encoding, + int options); +XMLPUBFUN xmlDocPtr XMLCALL + xmlCtxtReadMemory (xmlParserCtxtPtr ctxt, + const char *buffer, + int size, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN xmlDocPtr XMLCALL + xmlCtxtReadFd (xmlParserCtxtPtr ctxt, + int fd, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN xmlDocPtr XMLCALL + xmlCtxtReadIO (xmlParserCtxtPtr ctxt, + xmlInputReadCallback ioread, + xmlInputCloseCallback ioclose, + void *ioctx, + const char *URL, + const char *encoding, + int options); + +#ifdef __cplusplus +} +#endif +#endif /* __XML_PARSER_H__ */ + diff --git a/include/libxml/parserInternals.h b/include/libxml/parserInternals.h new file mode 100644 index 0000000..7ac0ce6 --- /dev/null +++ b/include/libxml/parserInternals.h @@ -0,0 +1,602 @@ +/* + * Summary: internals routines exported by the parser. + * Description: this module exports a number of internal parsing routines + * they are not really all intended for applications but + * can prove useful doing low level processing. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_PARSER_INTERNALS_H__ +#define __XML_PARSER_INTERNALS_H__ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * xmlParserMaxDepth: + * + * arbitrary depth limit for the XML documents that we allow to + * process. This is not a limitation of the parser but a safety + * boundary feature. + */ +XMLPUBVAR unsigned int xmlParserMaxDepth; + + /** + * XML_MAX_NAMELEN: + * + * Identifiers can be longer, but this will be more costly + * at runtime. + */ +#define XML_MAX_NAMELEN 100 + +/** + * INPUT_CHUNK: + * + * The parser tries to always have that amount of input ready. + * One of the point is providing context when reporting errors. + */ +#define INPUT_CHUNK 250 + +/************************************************************************ + * * + * UNICODE version of the macros. * + * * + ************************************************************************/ +/** + * IS_BYTE_CHAR: + * @c: an byte value (int) + * + * Macro to check the following production in the XML spec: + * + * [2] Char ::= #x9 | #xA | #xD | [#x20...] + * any byte character in the accepted range + */ +#define IS_BYTE_CHAR(c) xmlIsChar_ch(c) + +/** + * IS_CHAR: + * @c: an UNICODE value (int) + * + * Macro to check the following production in the XML spec: + * + * [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] + * | [#x10000-#x10FFFF] + * any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. + */ +#define IS_CHAR(c) xmlIsCharQ(c) + +/** + * IS_CHAR_CH: + * @c: an xmlChar (usually an unsigned char) + * + * Behaves like IS_CHAR on single-byte value + */ +#define IS_CHAR_CH(c) xmlIsChar_ch(c) + +/** + * IS_BLANK: + * @c: an UNICODE value (int) + * + * Macro to check the following production in the XML spec: + * + * [3] S ::= (#x20 | #x9 | #xD | #xA)+ + */ +#define IS_BLANK(c) xmlIsBlankQ(c) + +/** + * IS_BLANK_CH: + * @c: an xmlChar value (normally unsigned char) + * + * Behaviour same as IS_BLANK + */ +#define IS_BLANK_CH(c) xmlIsBlank_ch(c) + +/** + * IS_BASECHAR: + * @c: an UNICODE value (int) + * + * Macro to check the following production in the XML spec: + * + * [85] BaseChar ::= ... long list see REC ... + */ +#define IS_BASECHAR(c) xmlIsBaseCharQ(c) + +/** + * IS_DIGIT: + * @c: an UNICODE value (int) + * + * Macro to check the following production in the XML spec: + * + * [88] Digit ::= ... long list see REC ... + */ +#define IS_DIGIT(c) xmlIsDigitQ(c) + +/** + * IS_DIGIT_CH: + * @c: an xmlChar value (usually an unsigned char) + * + * Behaves like IS_DIGIT but with a single byte argument + */ +#define IS_DIGIT_CH(c) xmlIsDigit_ch(c) + +/** + * IS_COMBINING: + * @c: an UNICODE value (int) + * + * Macro to check the following production in the XML spec: + * + * [87] CombiningChar ::= ... long list see REC ... + */ +#define IS_COMBINING(c) xmlIsCombiningQ(c) + +/** + * IS_COMBINING_CH: + * @c: an xmlChar (usually an unsigned char) + * + * Always false (all combining chars > 0xff) + */ +#define IS_COMBINING_CH(c) 0 + +/** + * IS_EXTENDER: + * @c: an UNICODE value (int) + * + * Macro to check the following production in the XML spec: + * + * + * [89] Extender ::= #x00B7 | #x02D0 | #x02D1 | #x0387 | #x0640 | + * #x0E46 | #x0EC6 | #x3005 | [#x3031-#x3035] | + * [#x309D-#x309E] | [#x30FC-#x30FE] + */ +#define IS_EXTENDER(c) xmlIsExtenderQ(c) + +/** + * IS_EXTENDER_CH: + * @c: an xmlChar value (usually an unsigned char) + * + * Behaves like IS_EXTENDER but with a single-byte argument + */ +#define IS_EXTENDER_CH(c) xmlIsExtender_ch(c) + +/** + * IS_IDEOGRAPHIC: + * @c: an UNICODE value (int) + * + * Macro to check the following production in the XML spec: + * + * + * [86] Ideographic ::= [#x4E00-#x9FA5] | #x3007 | [#x3021-#x3029] + */ +#define IS_IDEOGRAPHIC(c) xmlIsIdeographicQ(c) + +/** + * IS_LETTER: + * @c: an UNICODE value (int) + * + * Macro to check the following production in the XML spec: + * + * + * [84] Letter ::= BaseChar | Ideographic + */ +#define IS_LETTER(c) (IS_BASECHAR(c) || IS_IDEOGRAPHIC(c)) + +/** + * IS_LETTER_CH: + * @c: an xmlChar value (normally unsigned char) + * + * Macro behaves like IS_LETTER, but only check base chars + * + */ +#define IS_LETTER_CH(c) xmlIsBaseChar_ch(c) + +/** + * IS_ASCII_LETTER: + * @c: an xmlChar value + * + * Macro to check [a-zA-Z] + * + */ +#define IS_ASCII_LETTER(c) (((0x41 <= (c)) && ((c) <= 0x5a)) || \ + ((0x61 <= (c)) && ((c) <= 0x7a))) + +/** + * IS_ASCII_DIGIT: + * @c: an xmlChar value + * + * Macro to check [0-9] + * + */ +#define IS_ASCII_DIGIT(c) ((0x30 <= (c)) && ((c) <= 0x39)) + +/** + * IS_PUBIDCHAR: + * @c: an UNICODE value (int) + * + * Macro to check the following production in the XML spec: + * + * + * [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] + */ +#define IS_PUBIDCHAR(c) xmlIsPubidCharQ(c) + +/** + * IS_PUBIDCHAR_CH: + * @c: an xmlChar value (normally unsigned char) + * + * Same as IS_PUBIDCHAR but for single-byte value + */ +#define IS_PUBIDCHAR_CH(c) xmlIsPubidChar_ch(c) + +/** + * SKIP_EOL: + * @p: and UTF8 string pointer + * + * Skips the end of line chars. + */ +#define SKIP_EOL(p) \ + if (*(p) == 0x13) { p++ ; if (*(p) == 0x10) p++; } \ + if (*(p) == 0x10) { p++ ; if (*(p) == 0x13) p++; } + +/** + * MOVETO_ENDTAG: + * @p: and UTF8 string pointer + * + * Skips to the next '>' char. + */ +#define MOVETO_ENDTAG(p) \ + while ((*p) && (*(p) != '>')) (p)++ + +/** + * MOVETO_STARTTAG: + * @p: and UTF8 string pointer + * + * Skips to the next '<' char. + */ +#define MOVETO_STARTTAG(p) \ + while ((*p) && (*(p) != '<')) (p)++ + +/** + * Global variables used for predefined strings. + */ +XMLPUBVAR const xmlChar xmlStringText[]; +XMLPUBVAR const xmlChar xmlStringTextNoenc[]; +XMLPUBVAR const xmlChar xmlStringComment[]; + +/* + * Function to finish the work of the macros where needed. + */ +XMLPUBFUN int XMLCALL xmlIsLetter (int c); + +/** + * Parser context. + */ +XMLPUBFUN xmlParserCtxtPtr XMLCALL + xmlCreateFileParserCtxt (const char *filename); +XMLPUBFUN xmlParserCtxtPtr XMLCALL + xmlCreateURLParserCtxt (const char *filename, + int options); +XMLPUBFUN xmlParserCtxtPtr XMLCALL + xmlCreateMemoryParserCtxt(const char *buffer, + int size); +XMLPUBFUN xmlParserCtxtPtr XMLCALL + xmlCreateEntityParserCtxt(const xmlChar *URL, + const xmlChar *ID, + const xmlChar *base); +XMLPUBFUN int XMLCALL + xmlSwitchEncoding (xmlParserCtxtPtr ctxt, + xmlCharEncoding enc); +XMLPUBFUN int XMLCALL + xmlSwitchToEncoding (xmlParserCtxtPtr ctxt, + xmlCharEncodingHandlerPtr handler); +XMLPUBFUN int XMLCALL + xmlSwitchInputEncoding (xmlParserCtxtPtr ctxt, + xmlParserInputPtr input, + xmlCharEncodingHandlerPtr handler); + +#ifdef IN_LIBXML +/* internal error reporting */ +XMLPUBFUN void XMLCALL + __xmlErrEncoding (xmlParserCtxtPtr ctxt, + xmlParserErrors xmlerr, + const char *msg, + const xmlChar * str1, + const xmlChar * str2); +#endif + +/** + * Input Streams. + */ +XMLPUBFUN xmlParserInputPtr XMLCALL + xmlNewStringInputStream (xmlParserCtxtPtr ctxt, + const xmlChar *buffer); +XMLPUBFUN xmlParserInputPtr XMLCALL + xmlNewEntityInputStream (xmlParserCtxtPtr ctxt, + xmlEntityPtr entity); +XMLPUBFUN void XMLCALL + xmlPushInput (xmlParserCtxtPtr ctxt, + xmlParserInputPtr input); +XMLPUBFUN xmlChar XMLCALL + xmlPopInput (xmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlFreeInputStream (xmlParserInputPtr input); +XMLPUBFUN xmlParserInputPtr XMLCALL + xmlNewInputFromFile (xmlParserCtxtPtr ctxt, + const char *filename); +XMLPUBFUN xmlParserInputPtr XMLCALL + xmlNewInputStream (xmlParserCtxtPtr ctxt); + +/** + * Namespaces. + */ +XMLPUBFUN xmlChar * XMLCALL + xmlSplitQName (xmlParserCtxtPtr ctxt, + const xmlChar *name, + xmlChar **prefix); + +/** + * Generic production rules. + */ +XMLPUBFUN const xmlChar * XMLCALL + xmlParseName (xmlParserCtxtPtr ctxt); +XMLPUBFUN xmlChar * XMLCALL + xmlParseNmtoken (xmlParserCtxtPtr ctxt); +XMLPUBFUN xmlChar * XMLCALL + xmlParseEntityValue (xmlParserCtxtPtr ctxt, + xmlChar **orig); +XMLPUBFUN xmlChar * XMLCALL + xmlParseAttValue (xmlParserCtxtPtr ctxt); +XMLPUBFUN xmlChar * XMLCALL + xmlParseSystemLiteral (xmlParserCtxtPtr ctxt); +XMLPUBFUN xmlChar * XMLCALL + xmlParsePubidLiteral (xmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlParseCharData (xmlParserCtxtPtr ctxt, + int cdata); +XMLPUBFUN xmlChar * XMLCALL + xmlParseExternalID (xmlParserCtxtPtr ctxt, + xmlChar **publicID, + int strict); +XMLPUBFUN void XMLCALL + xmlParseComment (xmlParserCtxtPtr ctxt); +XMLPUBFUN const xmlChar * XMLCALL + xmlParsePITarget (xmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlParsePI (xmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlParseNotationDecl (xmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlParseEntityDecl (xmlParserCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + xmlParseDefaultDecl (xmlParserCtxtPtr ctxt, + xmlChar **value); +XMLPUBFUN xmlEnumerationPtr XMLCALL + xmlParseNotationType (xmlParserCtxtPtr ctxt); +XMLPUBFUN xmlEnumerationPtr XMLCALL + xmlParseEnumerationType (xmlParserCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + xmlParseEnumeratedType (xmlParserCtxtPtr ctxt, + xmlEnumerationPtr *tree); +XMLPUBFUN int XMLCALL + xmlParseAttributeType (xmlParserCtxtPtr ctxt, + xmlEnumerationPtr *tree); +XMLPUBFUN void XMLCALL + xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt); +XMLPUBFUN xmlElementContentPtr XMLCALL + xmlParseElementMixedContentDecl + (xmlParserCtxtPtr ctxt, + int inputchk); +XMLPUBFUN xmlElementContentPtr XMLCALL + xmlParseElementChildrenContentDecl + (xmlParserCtxtPtr ctxt, + int inputchk); +XMLPUBFUN int XMLCALL + xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, + const xmlChar *name, + xmlElementContentPtr *result); +XMLPUBFUN int XMLCALL + xmlParseElementDecl (xmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlParseMarkupDecl (xmlParserCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + xmlParseCharRef (xmlParserCtxtPtr ctxt); +XMLPUBFUN xmlEntityPtr XMLCALL + xmlParseEntityRef (xmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlParseReference (xmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlParsePEReference (xmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlParseDocTypeDecl (xmlParserCtxtPtr ctxt); +#ifdef LIBXML_SAX1_ENABLED +XMLPUBFUN const xmlChar * XMLCALL + xmlParseAttribute (xmlParserCtxtPtr ctxt, + xmlChar **value); +XMLPUBFUN const xmlChar * XMLCALL + xmlParseStartTag (xmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlParseEndTag (xmlParserCtxtPtr ctxt); +#endif /* LIBXML_SAX1_ENABLED */ +XMLPUBFUN void XMLCALL + xmlParseCDSect (xmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlParseContent (xmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlParseElement (xmlParserCtxtPtr ctxt); +XMLPUBFUN xmlChar * XMLCALL + xmlParseVersionNum (xmlParserCtxtPtr ctxt); +XMLPUBFUN xmlChar * XMLCALL + xmlParseVersionInfo (xmlParserCtxtPtr ctxt); +XMLPUBFUN xmlChar * XMLCALL + xmlParseEncName (xmlParserCtxtPtr ctxt); +XMLPUBFUN const xmlChar * XMLCALL + xmlParseEncodingDecl (xmlParserCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + xmlParseSDDecl (xmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlParseXMLDecl (xmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlParseTextDecl (xmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlParseMisc (xmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlParseExternalSubset (xmlParserCtxtPtr ctxt, + const xmlChar *ExternalID, + const xmlChar *SystemID); +/** + * XML_SUBSTITUTE_NONE: + * + * If no entities need to be substituted. + */ +#define XML_SUBSTITUTE_NONE 0 +/** + * XML_SUBSTITUTE_REF: + * + * Whether general entities need to be substituted. + */ +#define XML_SUBSTITUTE_REF 1 +/** + * XML_SUBSTITUTE_PEREF: + * + * Whether parameter entities need to be substituted. + */ +#define XML_SUBSTITUTE_PEREF 2 +/** + * XML_SUBSTITUTE_BOTH: + * + * Both general and parameter entities need to be substituted. + */ +#define XML_SUBSTITUTE_BOTH 3 + +XMLPUBFUN xmlChar * XMLCALL + xmlStringDecodeEntities (xmlParserCtxtPtr ctxt, + const xmlChar *str, + int what, + xmlChar end, + xmlChar end2, + xmlChar end3); +XMLPUBFUN xmlChar * XMLCALL + xmlStringLenDecodeEntities (xmlParserCtxtPtr ctxt, + const xmlChar *str, + int len, + int what, + xmlChar end, + xmlChar end2, + xmlChar end3); + +/* + * Generated by MACROS on top of parser.c c.f. PUSH_AND_POP. + */ +XMLPUBFUN int XMLCALL nodePush (xmlParserCtxtPtr ctxt, + xmlNodePtr value); +XMLPUBFUN xmlNodePtr XMLCALL nodePop (xmlParserCtxtPtr ctxt); +XMLPUBFUN int XMLCALL inputPush (xmlParserCtxtPtr ctxt, + xmlParserInputPtr value); +XMLPUBFUN xmlParserInputPtr XMLCALL inputPop (xmlParserCtxtPtr ctxt); +XMLPUBFUN const xmlChar * XMLCALL namePop (xmlParserCtxtPtr ctxt); +XMLPUBFUN int XMLCALL namePush (xmlParserCtxtPtr ctxt, + const xmlChar *value); + +/* + * other commodities shared between parser.c and parserInternals. + */ +XMLPUBFUN int XMLCALL xmlSkipBlankChars (xmlParserCtxtPtr ctxt); +XMLPUBFUN int XMLCALL xmlStringCurrentChar (xmlParserCtxtPtr ctxt, + const xmlChar *cur, + int *len); +XMLPUBFUN void XMLCALL xmlParserHandlePEReference(xmlParserCtxtPtr ctxt); +XMLPUBFUN int XMLCALL xmlCheckLanguageID (const xmlChar *lang); + +/* + * Really core function shared with HTML parser. + */ +XMLPUBFUN int XMLCALL xmlCurrentChar (xmlParserCtxtPtr ctxt, + int *len); +XMLPUBFUN int XMLCALL xmlCopyCharMultiByte (xmlChar *out, + int val); +XMLPUBFUN int XMLCALL xmlCopyChar (int len, + xmlChar *out, + int val); +XMLPUBFUN void XMLCALL xmlNextChar (xmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL xmlParserInputShrink (xmlParserInputPtr in); + +#ifdef LIBXML_HTML_ENABLED +/* + * Actually comes from the HTML parser but launched from the init stuff. + */ +XMLPUBFUN void XMLCALL htmlInitAutoClose (void); +XMLPUBFUN htmlParserCtxtPtr XMLCALL htmlCreateFileParserCtxt(const char *filename, + const char *encoding); +#endif + +/* + * Specific function to keep track of entities references + * and used by the XSLT debugger. + */ +#ifdef LIBXML_LEGACY_ENABLED +/** + * xmlEntityReferenceFunc: + * @ent: the entity + * @firstNode: the fist node in the chunk + * @lastNode: the last nod in the chunk + * + * Callback function used when one needs to be able to track back the + * provenance of a chunk of nodes inherited from an entity replacement. + */ +typedef void (*xmlEntityReferenceFunc) (xmlEntityPtr ent, + xmlNodePtr firstNode, + xmlNodePtr lastNode); + +XMLPUBFUN void XMLCALL xmlSetEntityReferenceFunc (xmlEntityReferenceFunc func); + +XMLPUBFUN xmlChar * XMLCALL + xmlParseQuotedString (xmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlParseNamespace (xmlParserCtxtPtr ctxt); +XMLPUBFUN xmlChar * XMLCALL + xmlNamespaceParseNSDef (xmlParserCtxtPtr ctxt); +XMLPUBFUN xmlChar * XMLCALL + xmlScanName (xmlParserCtxtPtr ctxt); +XMLPUBFUN xmlChar * XMLCALL + xmlNamespaceParseNCName (xmlParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL xmlParserHandleReference(xmlParserCtxtPtr ctxt); +XMLPUBFUN xmlChar * XMLCALL + xmlNamespaceParseQName (xmlParserCtxtPtr ctxt, + xmlChar **prefix); +/** + * Entities + */ +XMLPUBFUN xmlChar * XMLCALL + xmlDecodeEntities (xmlParserCtxtPtr ctxt, + int len, + int what, + xmlChar end, + xmlChar end2, + xmlChar end3); +XMLPUBFUN void XMLCALL + xmlHandleEntity (xmlParserCtxtPtr ctxt, + xmlEntityPtr entity); + +#endif /* LIBXML_LEGACY_ENABLED */ + +#ifdef IN_LIBXML +/* + * internal only + */ +XMLPUBFUN void XMLCALL + xmlErrMemory (xmlParserCtxtPtr ctxt, + const char *extra); +#endif + +#ifdef __cplusplus +} +#endif +#endif /* __XML_PARSER_INTERNALS_H__ */ diff --git a/include/libxml/pattern.h b/include/libxml/pattern.h new file mode 100644 index 0000000..e3ee76d --- /dev/null +++ b/include/libxml/pattern.h @@ -0,0 +1,91 @@ +/* + * Summary: pattern expression handling + * Description: allows to compile and test pattern expressions for nodes + * either in a tree or based on a parser state. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_PATTERN_H__ +#define __XML_PATTERN_H__ + +#include +#include +#include + +#ifdef LIBXML_PATTERN_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * xmlPattern: + * + * A compiled (XPath based) pattern to select nodes + */ +typedef struct _xmlPattern xmlPattern; +typedef xmlPattern *xmlPatternPtr; + +/** + * xmlPatternFlags: + * + * This is the set of options affecting the behaviour of pattern + * matching with this module + * + */ +typedef enum { + XML_PATTERN_DEFAULT = 0, /* simple pattern match */ + XML_PATTERN_XPATH = 1<<0, /* standard XPath pattern */ + XML_PATTERN_XSSEL = 1<<1, /* XPath subset for schema selector */ + XML_PATTERN_XSFIELD = 1<<2 /* XPath subset for schema field */ +} xmlPatternFlags; + +XMLPUBFUN void XMLCALL + xmlFreePattern (xmlPatternPtr comp); + +XMLPUBFUN void XMLCALL + xmlFreePatternList (xmlPatternPtr comp); + +XMLPUBFUN xmlPatternPtr XMLCALL + xmlPatterncompile (const xmlChar *pattern, + xmlDict *dict, + xmlPatternFlags flags, + const xmlChar **namespaces); +XMLPUBFUN int XMLCALL + xmlPatternMatch (xmlPatternPtr comp, + xmlNodePtr node); + +/* streaming interfaces */ +typedef struct _xmlStreamCtxt xmlStreamCtxt; +typedef xmlStreamCtxt *xmlStreamCtxtPtr; + +XMLPUBFUN int XMLCALL + xmlPatternStreamable (xmlPatternPtr comp); +XMLPUBFUN int XMLCALL + xmlPatternMaxDepth (xmlPatternPtr comp); +XMLPUBFUN int XMLCALL + xmlPatternFromRoot (xmlPatternPtr comp); +XMLPUBFUN xmlStreamCtxtPtr XMLCALL + xmlPatternGetStreamCtxt (xmlPatternPtr comp); +XMLPUBFUN void XMLCALL + xmlFreeStreamCtxt (xmlStreamCtxtPtr stream); +XMLPUBFUN int XMLCALL + xmlStreamPush (xmlStreamCtxtPtr stream, + const xmlChar *name, + const xmlChar *ns); +XMLPUBFUN int XMLCALL + xmlStreamPushAttr (xmlStreamCtxtPtr stream, + const xmlChar *name, + const xmlChar *ns); +XMLPUBFUN int XMLCALL + xmlStreamPop (xmlStreamCtxtPtr stream); +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_PATTERN_ENABLED */ + +#endif /* __XML_PATTERN_H__ */ diff --git a/include/libxml/relaxng.h b/include/libxml/relaxng.h new file mode 100644 index 0000000..ca3c13b --- /dev/null +++ b/include/libxml/relaxng.h @@ -0,0 +1,188 @@ +/* + * Summary: implementation of the Relax-NG validation + * Description: implementation of the Relax-NG validation + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_RELAX_NG__ +#define __XML_RELAX_NG__ + +#include +#include +#include + +#ifdef LIBXML_SCHEMAS_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _xmlRelaxNG xmlRelaxNG; +typedef xmlRelaxNG *xmlRelaxNGPtr; + + +/** + * A schemas validation context + */ +typedef void (*xmlRelaxNGValidityErrorFunc) (void *ctx, const char *msg, ...); +typedef void (*xmlRelaxNGValidityWarningFunc) (void *ctx, const char *msg, ...); + +typedef struct _xmlRelaxNGParserCtxt xmlRelaxNGParserCtxt; +typedef xmlRelaxNGParserCtxt *xmlRelaxNGParserCtxtPtr; + +typedef struct _xmlRelaxNGValidCtxt xmlRelaxNGValidCtxt; +typedef xmlRelaxNGValidCtxt *xmlRelaxNGValidCtxtPtr; + +/* + * xmlRelaxNGValidErr: + * + * List of possible Relax NG validation errors + */ +typedef enum { + XML_RELAXNG_OK = 0, + XML_RELAXNG_ERR_MEMORY, + XML_RELAXNG_ERR_TYPE, + XML_RELAXNG_ERR_TYPEVAL, + XML_RELAXNG_ERR_DUPID, + XML_RELAXNG_ERR_TYPECMP, + XML_RELAXNG_ERR_NOSTATE, + XML_RELAXNG_ERR_NODEFINE, + XML_RELAXNG_ERR_LISTEXTRA, + XML_RELAXNG_ERR_LISTEMPTY, + XML_RELAXNG_ERR_INTERNODATA, + XML_RELAXNG_ERR_INTERSEQ, + XML_RELAXNG_ERR_INTEREXTRA, + XML_RELAXNG_ERR_ELEMNAME, + XML_RELAXNG_ERR_ATTRNAME, + XML_RELAXNG_ERR_ELEMNONS, + XML_RELAXNG_ERR_ATTRNONS, + XML_RELAXNG_ERR_ELEMWRONGNS, + XML_RELAXNG_ERR_ATTRWRONGNS, + XML_RELAXNG_ERR_ELEMEXTRANS, + XML_RELAXNG_ERR_ATTREXTRANS, + XML_RELAXNG_ERR_ELEMNOTEMPTY, + XML_RELAXNG_ERR_NOELEM, + XML_RELAXNG_ERR_NOTELEM, + XML_RELAXNG_ERR_ATTRVALID, + XML_RELAXNG_ERR_CONTENTVALID, + XML_RELAXNG_ERR_EXTRACONTENT, + XML_RELAXNG_ERR_INVALIDATTR, + XML_RELAXNG_ERR_DATAELEM, + XML_RELAXNG_ERR_VALELEM, + XML_RELAXNG_ERR_LISTELEM, + XML_RELAXNG_ERR_DATATYPE, + XML_RELAXNG_ERR_VALUE, + XML_RELAXNG_ERR_LIST, + XML_RELAXNG_ERR_NOGRAMMAR, + XML_RELAXNG_ERR_EXTRADATA, + XML_RELAXNG_ERR_LACKDATA, + XML_RELAXNG_ERR_INTERNAL, + XML_RELAXNG_ERR_ELEMWRONG, + XML_RELAXNG_ERR_TEXTWRONG +} xmlRelaxNGValidErr; + +/* + * xmlRelaxNGParserFlags: + * + * List of possible Relax NG Parser flags + */ +typedef enum { + XML_RELAXNGP_NONE = 0, + XML_RELAXNGP_FREE_DOC = 1, + XML_RELAXNGP_CRNG = 2 +} xmlRelaxNGParserFlag; + +XMLPUBFUN int XMLCALL + xmlRelaxNGInitTypes (void); +XMLPUBFUN void XMLCALL + xmlRelaxNGCleanupTypes (void); + +/* + * Interfaces for parsing. + */ +XMLPUBFUN xmlRelaxNGParserCtxtPtr XMLCALL + xmlRelaxNGNewParserCtxt (const char *URL); +XMLPUBFUN xmlRelaxNGParserCtxtPtr XMLCALL + xmlRelaxNGNewMemParserCtxt (const char *buffer, + int size); +XMLPUBFUN xmlRelaxNGParserCtxtPtr XMLCALL + xmlRelaxNGNewDocParserCtxt (xmlDocPtr doc); + +XMLPUBFUN int XMLCALL + xmlRelaxParserSetFlag (xmlRelaxNGParserCtxtPtr ctxt, + int flag); + +XMLPUBFUN void XMLCALL + xmlRelaxNGFreeParserCtxt (xmlRelaxNGParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlRelaxNGSetParserErrors(xmlRelaxNGParserCtxtPtr ctxt, + xmlRelaxNGValidityErrorFunc err, + xmlRelaxNGValidityWarningFunc warn, + void *ctx); +XMLPUBFUN int XMLCALL + xmlRelaxNGGetParserErrors(xmlRelaxNGParserCtxtPtr ctxt, + xmlRelaxNGValidityErrorFunc *err, + xmlRelaxNGValidityWarningFunc *warn, + void **ctx); +XMLPUBFUN xmlRelaxNGPtr XMLCALL + xmlRelaxNGParse (xmlRelaxNGParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlRelaxNGFree (xmlRelaxNGPtr schema); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void XMLCALL + xmlRelaxNGDump (FILE *output, + xmlRelaxNGPtr schema); +XMLPUBFUN void XMLCALL + xmlRelaxNGDumpTree (FILE * output, + xmlRelaxNGPtr schema); +#endif /* LIBXML_OUTPUT_ENABLED */ +/* + * Interfaces for validating + */ +XMLPUBFUN void XMLCALL + xmlRelaxNGSetValidErrors(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGValidityErrorFunc err, + xmlRelaxNGValidityWarningFunc warn, + void *ctx); +XMLPUBFUN int XMLCALL + xmlRelaxNGGetValidErrors(xmlRelaxNGValidCtxtPtr ctxt, + xmlRelaxNGValidityErrorFunc *err, + xmlRelaxNGValidityWarningFunc *warn, + void **ctx); +XMLPUBFUN xmlRelaxNGValidCtxtPtr XMLCALL + xmlRelaxNGNewValidCtxt (xmlRelaxNGPtr schema); +XMLPUBFUN void XMLCALL + xmlRelaxNGFreeValidCtxt (xmlRelaxNGValidCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + xmlRelaxNGValidateDoc (xmlRelaxNGValidCtxtPtr ctxt, + xmlDocPtr doc); +/* + * Interfaces for progressive validation when possible + */ +XMLPUBFUN int XMLCALL + xmlRelaxNGValidatePushElement (xmlRelaxNGValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlNodePtr elem); +XMLPUBFUN int XMLCALL + xmlRelaxNGValidatePushCData (xmlRelaxNGValidCtxtPtr ctxt, + const xmlChar *data, + int len); +XMLPUBFUN int XMLCALL + xmlRelaxNGValidatePopElement (xmlRelaxNGValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlNodePtr elem); +XMLPUBFUN int XMLCALL + xmlRelaxNGValidateFullElement (xmlRelaxNGValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlNodePtr elem); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_SCHEMAS_ENABLED */ + +#endif /* __XML_RELAX_NG__ */ diff --git a/include/libxml/schemasInternals.h b/include/libxml/schemasInternals.h new file mode 100644 index 0000000..eb1f426 --- /dev/null +++ b/include/libxml/schemasInternals.h @@ -0,0 +1,905 @@ +/* + * Summary: internal interfaces for XML Schemas + * Description: internal interfaces for the XML Schemas handling + * and schema validity checking + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + + +#ifndef __XML_SCHEMA_INTERNALS_H__ +#define __XML_SCHEMA_INTERNALS_H__ + +#include + +#ifdef LIBXML_SCHEMAS_ENABLED + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + XML_SCHEMAS_UNKNOWN = 0, + XML_SCHEMAS_STRING, + XML_SCHEMAS_NORMSTRING, + XML_SCHEMAS_DECIMAL, + XML_SCHEMAS_TIME, + XML_SCHEMAS_GDAY, + XML_SCHEMAS_GMONTH, + XML_SCHEMAS_GMONTHDAY, + XML_SCHEMAS_GYEAR, + XML_SCHEMAS_GYEARMONTH, + XML_SCHEMAS_DATE, + XML_SCHEMAS_DATETIME, + XML_SCHEMAS_DURATION, + XML_SCHEMAS_FLOAT, + XML_SCHEMAS_DOUBLE, + XML_SCHEMAS_BOOLEAN, + XML_SCHEMAS_TOKEN, + XML_SCHEMAS_LANGUAGE, + XML_SCHEMAS_NMTOKEN, + XML_SCHEMAS_NMTOKENS, + XML_SCHEMAS_NAME, + XML_SCHEMAS_QNAME, + XML_SCHEMAS_NCNAME, + XML_SCHEMAS_ID, + XML_SCHEMAS_IDREF, + XML_SCHEMAS_IDREFS, + XML_SCHEMAS_ENTITY, + XML_SCHEMAS_ENTITIES, + XML_SCHEMAS_NOTATION, + XML_SCHEMAS_ANYURI, + XML_SCHEMAS_INTEGER, + XML_SCHEMAS_NPINTEGER, + XML_SCHEMAS_NINTEGER, + XML_SCHEMAS_NNINTEGER, + XML_SCHEMAS_PINTEGER, + XML_SCHEMAS_INT, + XML_SCHEMAS_UINT, + XML_SCHEMAS_LONG, + XML_SCHEMAS_ULONG, + XML_SCHEMAS_SHORT, + XML_SCHEMAS_USHORT, + XML_SCHEMAS_BYTE, + XML_SCHEMAS_UBYTE, + XML_SCHEMAS_HEXBINARY, + XML_SCHEMAS_BASE64BINARY, + XML_SCHEMAS_ANYTYPE, + XML_SCHEMAS_ANYSIMPLETYPE +} xmlSchemaValType; + +/* + * XML Schemas defines multiple type of types. + */ +typedef enum { + XML_SCHEMA_TYPE_BASIC = 1, /* A built-in datatype */ + XML_SCHEMA_TYPE_ANY, + XML_SCHEMA_TYPE_FACET, + XML_SCHEMA_TYPE_SIMPLE, + XML_SCHEMA_TYPE_COMPLEX, + XML_SCHEMA_TYPE_SEQUENCE = 6, + XML_SCHEMA_TYPE_CHOICE, + XML_SCHEMA_TYPE_ALL, + XML_SCHEMA_TYPE_SIMPLE_CONTENT, + XML_SCHEMA_TYPE_COMPLEX_CONTENT, + XML_SCHEMA_TYPE_UR, + XML_SCHEMA_TYPE_RESTRICTION, + XML_SCHEMA_TYPE_EXTENSION, + XML_SCHEMA_TYPE_ELEMENT, + XML_SCHEMA_TYPE_ATTRIBUTE, + XML_SCHEMA_TYPE_ATTRIBUTEGROUP, + XML_SCHEMA_TYPE_GROUP, + XML_SCHEMA_TYPE_NOTATION, + XML_SCHEMA_TYPE_LIST, + XML_SCHEMA_TYPE_UNION, + XML_SCHEMA_TYPE_ANY_ATTRIBUTE, + XML_SCHEMA_TYPE_IDC_UNIQUE, + XML_SCHEMA_TYPE_IDC_KEY, + XML_SCHEMA_TYPE_IDC_KEYREF, + XML_SCHEMA_TYPE_PARTICLE = 25, + XML_SCHEMA_FACET_MININCLUSIVE = 1000, + XML_SCHEMA_FACET_MINEXCLUSIVE, + XML_SCHEMA_FACET_MAXINCLUSIVE, + XML_SCHEMA_FACET_MAXEXCLUSIVE, + XML_SCHEMA_FACET_TOTALDIGITS, + XML_SCHEMA_FACET_FRACTIONDIGITS, + XML_SCHEMA_FACET_PATTERN, + XML_SCHEMA_FACET_ENUMERATION, + XML_SCHEMA_FACET_WHITESPACE, + XML_SCHEMA_FACET_LENGTH, + XML_SCHEMA_FACET_MAXLENGTH, + XML_SCHEMA_FACET_MINLENGTH, + XML_SCHEMA_EXTRA_QNAMEREF = 2000 +} xmlSchemaTypeType; + +typedef enum { + XML_SCHEMA_CONTENT_UNKNOWN = 0, + XML_SCHEMA_CONTENT_EMPTY = 1, + XML_SCHEMA_CONTENT_ELEMENTS, + XML_SCHEMA_CONTENT_MIXED, + XML_SCHEMA_CONTENT_SIMPLE, + XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS, /* obsolete, not used */ + XML_SCHEMA_CONTENT_BASIC, + XML_SCHEMA_CONTENT_ANY +} xmlSchemaContentType; + +typedef struct _xmlSchemaVal xmlSchemaVal; +typedef xmlSchemaVal *xmlSchemaValPtr; + +typedef struct _xmlSchemaType xmlSchemaType; +typedef xmlSchemaType *xmlSchemaTypePtr; + +typedef struct _xmlSchemaFacet xmlSchemaFacet; +typedef xmlSchemaFacet *xmlSchemaFacetPtr; + +/** + * Annotation + */ +typedef struct _xmlSchemaAnnot xmlSchemaAnnot; +typedef xmlSchemaAnnot *xmlSchemaAnnotPtr; +struct _xmlSchemaAnnot { + struct _xmlSchemaAnnot *next; + xmlNodePtr content; /* the annotation */ +}; + +/** + * XML_SCHEMAS_ANYATTR_SKIP: + * + * Skip unknown attribute from validation + * Obsolete, not used anymore. + */ +#define XML_SCHEMAS_ANYATTR_SKIP 1 +/** + * XML_SCHEMAS_ANYATTR_LAX: + * + * Ignore validation non definition on attributes + * Obsolete, not used anymore. + */ +#define XML_SCHEMAS_ANYATTR_LAX 2 +/** + * XML_SCHEMAS_ANYATTR_STRICT: + * + * Apply strict validation rules on attributes + * Obsolete, not used anymore. + */ +#define XML_SCHEMAS_ANYATTR_STRICT 3 +/** + * XML_SCHEMAS_ANY_SKIP: + * + * Skip unknown attribute from validation + */ +#define XML_SCHEMAS_ANY_SKIP 1 +/** + * XML_SCHEMAS_ANY_LAX: + * + * Used by wildcards. + * Validate if type found, don't worry if not found + */ +#define XML_SCHEMAS_ANY_LAX 2 +/** + * XML_SCHEMAS_ANY_STRICT: + * + * Used by wildcards. + * Apply strict validation rules + */ +#define XML_SCHEMAS_ANY_STRICT 3 +/** + * XML_SCHEMAS_ATTR_USE_PROHIBITED: + * + * Used by wildcards. + * The attribute is prohibited. + */ +#define XML_SCHEMAS_ATTR_USE_PROHIBITED 0 +/** + * XML_SCHEMAS_ATTR_USE_REQUIRED: + * + * The attribute is required. + */ +#define XML_SCHEMAS_ATTR_USE_REQUIRED 1 +/** + * XML_SCHEMAS_ATTR_USE_OPTIONAL: + * + * The attribute is optional. + */ +#define XML_SCHEMAS_ATTR_USE_OPTIONAL 2 +/** + * XML_SCHEMAS_ATTR_GLOBAL: + * + * allow elements in no namespace + */ +#define XML_SCHEMAS_ATTR_GLOBAL 1 << 0 +/** + * XML_SCHEMAS_ATTR_NSDEFAULT: + * + * allow elements in no namespace + */ +#define XML_SCHEMAS_ATTR_NSDEFAULT 1 << 7 +/** + * XML_SCHEMAS_ATTR_INTERNAL_RESOLVED: + * + * this is set when the "type" and "ref" references + * have been resolved. + */ +#define XML_SCHEMAS_ATTR_INTERNAL_RESOLVED 1 << 8 +/** + * XML_SCHEMAS_ATTR_FIXED: + * + * the attribute has a fixed value + */ +#define XML_SCHEMAS_ATTR_FIXED 1 << 9 + +/** + * xmlSchemaAttribute: + * An attribute definition. + */ + +typedef struct _xmlSchemaAttribute xmlSchemaAttribute; +typedef xmlSchemaAttribute *xmlSchemaAttributePtr; +struct _xmlSchemaAttribute { + xmlSchemaTypeType type; /* The kind of type */ + struct _xmlSchemaAttribute *next;/* the next attribute if in a group ... */ + const xmlChar *name; /* name of the declaration or empty if particle */ + const xmlChar *id; + const xmlChar *ref; /* the local name of the attribute decl. if a particle */ + const xmlChar *refNs; /* the ns URI of the attribute decl. if a particle */ + const xmlChar *typeName; /* the local name of the type definition */ + const xmlChar *typeNs; /* the ns URI of the type definition */ + xmlSchemaAnnotPtr annot; + + xmlSchemaTypePtr base; /* obsolete, not used */ + int occurs; + const xmlChar *defValue; + xmlSchemaTypePtr subtypes; /* the type definition */ + xmlNodePtr node; + const xmlChar *targetNamespace; + int flags; + const xmlChar *refPrefix; + xmlSchemaValPtr defVal; + xmlSchemaAttributePtr refDecl; +}; + +/** + * xmlSchemaAttributeLink: + * Used to build a list of attribute uses on complexType definitions. + */ +typedef struct _xmlSchemaAttributeLink xmlSchemaAttributeLink; +typedef xmlSchemaAttributeLink *xmlSchemaAttributeLinkPtr; +struct _xmlSchemaAttributeLink { + struct _xmlSchemaAttributeLink *next;/* the next attribute link ... */ + struct _xmlSchemaAttribute *attr;/* the linked attribute */ +}; + +/** + * XML_SCHEMAS_WILDCARD_COMPLETE: + * + * If the wildcard is complete. + */ +#define XML_SCHEMAS_WILDCARD_COMPLETE 1 << 0 + +/** + * xmlSchemaCharValueLink: + * Used to build a list of namespaces on wildcards. + */ +typedef struct _xmlSchemaWildcardNs xmlSchemaWildcardNs; +typedef xmlSchemaWildcardNs *xmlSchemaWildcardNsPtr; +struct _xmlSchemaWildcardNs { + struct _xmlSchemaWildcardNs *next;/* the next constraint link ... */ + const xmlChar *value;/* the value */ +}; + +/** + * xmlSchemaWildcard. + * A wildcard. + */ +typedef struct _xmlSchemaWildcard xmlSchemaWildcard; +typedef xmlSchemaWildcard *xmlSchemaWildcardPtr; +struct _xmlSchemaWildcard { + xmlSchemaTypeType type; /* The kind of type */ + const xmlChar *id; + xmlSchemaAnnotPtr annot; + xmlNodePtr node; + int minOccurs; + int maxOccurs; + int processContents; + int any; /* Indicates if the ns constraint is of ##any */ + xmlSchemaWildcardNsPtr nsSet; /* The list of allowed namespaces */ + xmlSchemaWildcardNsPtr negNsSet; /* The negated namespace */ + int flags; +}; + +/** + * XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED: + * + * The attribute wildcard has been already builded. + */ +#define XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED 1 << 0 +/** + * XML_SCHEMAS_ATTRGROUP_GLOBAL: + * + * The attribute wildcard has been already builded. + */ +#define XML_SCHEMAS_ATTRGROUP_GLOBAL 1 << 1 +/** + * XML_SCHEMAS_ATTRGROUP_MARKED: + * + * Marks the attr group as marked; used for circular checks. + */ +#define XML_SCHEMAS_ATTRGROUP_MARKED 1 << 2 + +/** + * An attribute group definition. + * + * xmlSchemaAttribute and xmlSchemaAttributeGroup start of structures + * must be kept similar + */ +typedef struct _xmlSchemaAttributeGroup xmlSchemaAttributeGroup; +typedef xmlSchemaAttributeGroup *xmlSchemaAttributeGroupPtr; +struct _xmlSchemaAttributeGroup { + xmlSchemaTypeType type; /* The kind of type */ + struct _xmlSchemaAttribute *next;/* the next attribute if in a group ... */ + const xmlChar *name; + const xmlChar *id; + const xmlChar *ref; + const xmlChar *refNs; + xmlSchemaAnnotPtr annot; + + xmlSchemaAttributePtr attributes; + xmlNodePtr node; + int flags; + xmlSchemaWildcardPtr attributeWildcard; + const xmlChar *refPrefix; + xmlSchemaAttributeGroupPtr refItem; /* The referenced attribute group */ + const xmlChar *targetNamespace; +}; + +/** + * xmlSchemaTypeLink: + * Used to build a list of types (e.g. member types of + * simpleType with variety "union"). + */ +typedef struct _xmlSchemaTypeLink xmlSchemaTypeLink; +typedef xmlSchemaTypeLink *xmlSchemaTypeLinkPtr; +struct _xmlSchemaTypeLink { + struct _xmlSchemaTypeLink *next;/* the next type link ... */ + xmlSchemaTypePtr type;/* the linked type*/ +}; + +/** + * xmlSchemaFacetLink: + * Used to build a list of facets. + */ +typedef struct _xmlSchemaFacetLink xmlSchemaFacetLink; +typedef xmlSchemaFacetLink *xmlSchemaFacetLinkPtr; +struct _xmlSchemaFacetLink { + struct _xmlSchemaFacetLink *next;/* the next facet link ... */ + xmlSchemaFacetPtr facet;/* the linked facet */ +}; + +/** + * XML_SCHEMAS_TYPE_MIXED: + * + * the element content type is mixed + */ +#define XML_SCHEMAS_TYPE_MIXED 1 << 0 +/** + * XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION: + * + * the simple or complex type has a derivation method of "extension". + */ +#define XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION 1 << 1 +/** + * XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION: + * + * the simple or complex type has a derivation method of "restriction". + */ +#define XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION 1 << 2 +/** + * XML_SCHEMAS_TYPE_GLOBAL: + * + * the type is global + */ +#define XML_SCHEMAS_TYPE_GLOBAL 1 << 3 +/** + * XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD: + * + * the complexType owns an attribute wildcard, i.e. + * it can be freed by the complexType + */ +#define XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD 1 << 4 /* Obsolete. */ +/** + * XML_SCHEMAS_TYPE_VARIETY_ABSENT: + * + * the simpleType has a variety of "absent". + */ +#define XML_SCHEMAS_TYPE_VARIETY_ABSENT 1 << 5 +/** + * XML_SCHEMAS_TYPE_VARIETY_LIST: + * + * the simpleType has a variety of "list". + */ +#define XML_SCHEMAS_TYPE_VARIETY_LIST 1 << 6 +/** + * XML_SCHEMAS_TYPE_VARIETY_UNION: + * + * the simpleType has a variety of "union". + */ +#define XML_SCHEMAS_TYPE_VARIETY_UNION 1 << 7 +/** + * XML_SCHEMAS_TYPE_VARIETY_ATOMIC: + * + * the simpleType has a variety of "union". + */ +#define XML_SCHEMAS_TYPE_VARIETY_ATOMIC 1 << 8 +/** + * XML_SCHEMAS_TYPE_FINAL_EXTENSION: + * + * the complexType has a final of "extension". + */ +#define XML_SCHEMAS_TYPE_FINAL_EXTENSION 1 << 9 +/** + * XML_SCHEMAS_TYPE_FINAL_RESTRICTION: + * + * the simpleType/complexType has a final of "restriction". + */ +#define XML_SCHEMAS_TYPE_FINAL_RESTRICTION 1 << 10 +/** + * XML_SCHEMAS_TYPE_FINAL_LIST: + * + * the simpleType has a final of "list". + */ +#define XML_SCHEMAS_TYPE_FINAL_LIST 1 << 11 +/** + * XML_SCHEMAS_TYPE_FINAL_UNION: + * + * the simpleType has a final of "union". + */ +#define XML_SCHEMAS_TYPE_FINAL_UNION 1 << 12 +/** + * XML_SCHEMAS_TYPE_FINAL_DEFAULT: + * + * the simpleType has a final of "default". + */ +#define XML_SCHEMAS_TYPE_FINAL_DEFAULT 1 << 13 +/** + * XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE: + * + * Marks the item as a builtin primitive. + */ +#define XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE 1 << 14 +/** + * XML_SCHEMAS_TYPE_MARKED: + * + * Marks the item as marked; used for circular checks. + */ +#define XML_SCHEMAS_TYPE_MARKED 1 << 16 +/** + * XML_SCHEMAS_TYPE_BLOCK_DEFAULT: + * + * the complexType did not specify 'block' so use the default of the + * item. + */ +#define XML_SCHEMAS_TYPE_BLOCK_DEFAULT 1 << 17 +/** + * XML_SCHEMAS_TYPE_BLOCK_EXTENSION: + * + * the complexType has a 'block' of "extension". + */ +#define XML_SCHEMAS_TYPE_BLOCK_EXTENSION 1 << 18 +/** + * XML_SCHEMAS_TYPE_BLOCK_RESTRICTION: + * + * the complexType has a 'block' of "restriction". + */ +#define XML_SCHEMAS_TYPE_BLOCK_RESTRICTION 1 << 19 +/** + * XML_SCHEMAS_TYPE_ABSTRACT: + * + * the simple/complexType is abstract. + */ +#define XML_SCHEMAS_TYPE_ABSTRACT 1 << 20 +/** + * XML_SCHEMAS_TYPE_FACETSNEEDVALUE: + * + * indicates if the facets need a computed value + */ +#define XML_SCHEMAS_TYPE_FACETSNEEDVALUE 1 << 21 +/** + * XML_SCHEMAS_TYPE_INTERNAL_RESOLVED: + * + * indicates that the type was typefixed + */ +#define XML_SCHEMAS_TYPE_INTERNAL_RESOLVED 1 << 22 +/** + * XML_SCHEMAS_TYPE_INTERNAL_INVALID: + * + * indicates that the type is invalid + */ +#define XML_SCHEMAS_TYPE_INTERNAL_INVALID 1 << 23 +/** + * XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE: + * + * a whitespace-facet value of "preserve" + */ +#define XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE 1 << 24 +/** + * XML_SCHEMAS_TYPE_WHITESPACE_REPLACE: + * + * a whitespace-facet value of "replace" + */ +#define XML_SCHEMAS_TYPE_WHITESPACE_REPLACE 1 << 25 +/** + * XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE: + * + * a whitespace-facet value of "collapse" + */ +#define XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE 1 << 26 +/** + * XML_SCHEMAS_TYPE_HAS_FACETS: + * + * has facets + */ +#define XML_SCHEMAS_TYPE_HAS_FACETS 1 << 27 +/** + * XML_SCHEMAS_TYPE_NORMVALUENEEDED: + * + * indicates if the facets (pattern) need a normalized value + */ +#define XML_SCHEMAS_TYPE_NORMVALUENEEDED 1 << 28 + +/** + * _xmlSchemaType: + * + * Schemas type definition. + */ +struct _xmlSchemaType { + xmlSchemaTypeType type; /* The kind of type */ + struct _xmlSchemaType *next;/* the next type if in a sequence ... */ + const xmlChar *name; + const xmlChar *id; + const xmlChar *ref; + const xmlChar *refNs; + xmlSchemaAnnotPtr annot; + xmlSchemaTypePtr subtypes; + xmlSchemaAttributePtr attributes; + xmlNodePtr node; + int minOccurs; + int maxOccurs; + + int flags; + xmlSchemaContentType contentType; + const xmlChar *base; + const xmlChar *baseNs; + xmlSchemaTypePtr baseType; + xmlSchemaFacetPtr facets; + struct _xmlSchemaType *redef;/* possible redefinitions for the type */ + int recurse; + xmlSchemaAttributeLinkPtr attributeUses; + xmlSchemaWildcardPtr attributeWildcard; + int builtInType; + xmlSchemaTypeLinkPtr memberTypes; + xmlSchemaFacetLinkPtr facetSet; + const xmlChar *refPrefix; + xmlSchemaTypePtr contentTypeDef; + xmlRegexpPtr contModel; + const xmlChar *targetNamespace; +}; + +/* + * xmlSchemaElement: + * An element definition. + * + * xmlSchemaType, xmlSchemaFacet and xmlSchemaElement start of + * structures must be kept similar + */ +/** + * XML_SCHEMAS_ELEM_NILLABLE: + * + * the element is nillable + */ +#define XML_SCHEMAS_ELEM_NILLABLE 1 << 0 +/** + * XML_SCHEMAS_ELEM_GLOBAL: + * + * the element is global + */ +#define XML_SCHEMAS_ELEM_GLOBAL 1 << 1 +/** + * XML_SCHEMAS_ELEM_DEFAULT: + * + * the element has a default value + */ +#define XML_SCHEMAS_ELEM_DEFAULT 1 << 2 +/** + * XML_SCHEMAS_ELEM_FIXED: + * + * the element has a fixed value + */ +#define XML_SCHEMAS_ELEM_FIXED 1 << 3 +/** + * XML_SCHEMAS_ELEM_ABSTRACT: + * + * the element is abstract + */ +#define XML_SCHEMAS_ELEM_ABSTRACT 1 << 4 +/** + * XML_SCHEMAS_ELEM_TOPLEVEL: + * + * the element is top level + * obsolete: use XML_SCHEMAS_ELEM_GLOBAL instead + */ +#define XML_SCHEMAS_ELEM_TOPLEVEL 1 << 5 +/** + * XML_SCHEMAS_ELEM_REF: + * + * the element is a reference to a type + */ +#define XML_SCHEMAS_ELEM_REF 1 << 6 +/** + * XML_SCHEMAS_ELEM_NSDEFAULT: + * + * allow elements in no namespace + * Obsolete, not used anymore. + */ +#define XML_SCHEMAS_ELEM_NSDEFAULT 1 << 7 +/** + * XML_SCHEMAS_ELEM_INTERNAL_RESOLVED: + * + * this is set when "type", "ref", "substitutionGroup" + * references have been resolved. + */ +#define XML_SCHEMAS_ELEM_INTERNAL_RESOLVED 1 << 8 + /** + * XML_SCHEMAS_ELEM_CIRCULAR: + * + * a helper flag for the search of circular references. + */ +#define XML_SCHEMAS_ELEM_CIRCULAR 1 << 9 +/** + * XML_SCHEMAS_ELEM_BLOCK_ABSENT: + * + * the "block" attribute is absent + */ +#define XML_SCHEMAS_ELEM_BLOCK_ABSENT 1 << 10 +/** + * XML_SCHEMAS_ELEM_BLOCK_EXTENSION: + * + * disallowed substitutions are absent + */ +#define XML_SCHEMAS_ELEM_BLOCK_EXTENSION 1 << 11 +/** + * XML_SCHEMAS_ELEM_BLOCK_RESTRICTION: + * + * disallowed substitutions: "restriction" + */ +#define XML_SCHEMAS_ELEM_BLOCK_RESTRICTION 1 << 12 +/** + * XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION: + * + * disallowed substitutions: "substituion" + */ +#define XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION 1 << 13 +/** + * XML_SCHEMAS_ELEM_FINAL_ABSENT: + * + * substitution group exclusions are absent + */ +#define XML_SCHEMAS_ELEM_FINAL_ABSENT 1 << 14 +/** + * XML_SCHEMAS_ELEM_FINAL_EXTENSION: + * + * substitution group exclusions: "extension" + */ +#define XML_SCHEMAS_ELEM_FINAL_EXTENSION 1 << 15 +/** + * XML_SCHEMAS_ELEM_FINAL_RESTRICTION: + * + * substitution group exclusions: "restriction" + */ +#define XML_SCHEMAS_ELEM_FINAL_RESTRICTION 1 << 16 +/** + * XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD: + * + * the declaration is a substitution group head + */ +#define XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD 1 << 17 +/** + * XML_SCHEMAS_ELEM_INTERNAL_CHECKED: + * + * this is set when the elem decl has been checked against + * all constraints + */ +#define XML_SCHEMAS_ELEM_INTERNAL_CHECKED 1 << 18 + +typedef struct _xmlSchemaElement xmlSchemaElement; +typedef xmlSchemaElement *xmlSchemaElementPtr; +struct _xmlSchemaElement { + xmlSchemaTypeType type; /* The kind of type */ + struct _xmlSchemaType *next;/* the next type if in a sequence ... */ + const xmlChar *name; + const xmlChar *id; + const xmlChar *ref; /* the local name of the element declaration if a particle */ + const xmlChar *refNs; /* the ns URI of the element declaration if a particle */ + xmlSchemaAnnotPtr annot; + xmlSchemaTypePtr subtypes; /* the type definition */ + xmlSchemaAttributePtr attributes; + xmlNodePtr node; + int minOccurs; + int maxOccurs; + + int flags; + const xmlChar *targetNamespace; + const xmlChar *namedType; + const xmlChar *namedTypeNs; + const xmlChar *substGroup; + const xmlChar *substGroupNs; + const xmlChar *scope; + const xmlChar *value; + struct _xmlSchemaElement *refDecl; /* This will now be used for the substitution group affiliation */ + xmlRegexpPtr contModel; + xmlSchemaContentType contentType; + const xmlChar *refPrefix; + xmlSchemaValPtr defVal; + void *idcs; +}; + +/* + * XML_SCHEMAS_FACET_UNKNOWN: + * + * unknown facet handling + */ +#define XML_SCHEMAS_FACET_UNKNOWN 0 +/* + * XML_SCHEMAS_FACET_PRESERVE: + * + * preserve the type of the facet + */ +#define XML_SCHEMAS_FACET_PRESERVE 1 +/* + * XML_SCHEMAS_FACET_REPLACE: + * + * replace the type of the facet + */ +#define XML_SCHEMAS_FACET_REPLACE 2 +/* + * XML_SCHEMAS_FACET_COLLAPSE: + * + * collapse the types of the facet + */ +#define XML_SCHEMAS_FACET_COLLAPSE 3 +/** + * A facet definition. + */ +struct _xmlSchemaFacet { + xmlSchemaTypeType type; /* The kind of type */ + struct _xmlSchemaFacet *next;/* the next type if in a sequence ... */ + const xmlChar *value; + const xmlChar *id; + xmlSchemaAnnotPtr annot; + xmlNodePtr node; + int fixed; + int whitespace; + xmlSchemaValPtr val; + xmlRegexpPtr regexp; +}; + +/** + * A notation definition. + */ +typedef struct _xmlSchemaNotation xmlSchemaNotation; +typedef xmlSchemaNotation *xmlSchemaNotationPtr; +struct _xmlSchemaNotation { + xmlSchemaTypeType type; /* The kind of type */ + const xmlChar *name; + xmlSchemaAnnotPtr annot; + const xmlChar *identifier; + const xmlChar *targetNamespace; +}; + +/** + * XML_SCHEMAS_QUALIF_ELEM: + * + * the schema requires qualified elements + */ +#define XML_SCHEMAS_QUALIF_ELEM 1 << 0 +/** + * XML_SCHEMAS_QUALIF_ATTR: + * + * the schema requires qualified attributes + */ +#define XML_SCHEMAS_QUALIF_ATTR 1 << 1 +/** + * XML_SCHEMAS_FINAL_DEFAULT_EXTENSION: + * + * the schema has "extension" in the set of finalDefault. + */ +#define XML_SCHEMAS_FINAL_DEFAULT_EXTENSION 1 << 2 +/** + * XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION: + * + * the schema has "restriction" in the set of finalDefault. + */ +#define XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION 1 << 3 +/** + * XML_SCHEMAS_FINAL_DEFAULT_LIST: + * + * the cshema has "list" in the set of finalDefault. + */ +#define XML_SCHEMAS_FINAL_DEFAULT_LIST 1 << 4 +/** + * XML_SCHEMAS_FINAL_DEFAULT_UNION: + * + * the schema has "union" in the set of finalDefault. + */ +#define XML_SCHEMAS_FINAL_DEFAULT_UNION 1 << 5 +/** + * XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION: + * + * the schema has "extension" in the set of blockDefault. + */ +#define XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION 1 << 6 +/** + * XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION: + * + * the schema has "restriction" in the set of blockDefault. + */ +#define XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION 1 << 7 +/** + * XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION: + * + * the schema has "substitution" in the set of blockDefault. + */ +#define XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION 1 << 8 +/** + * XML_SCHEMAS_INCLUDING_CONVERT_NS: + * + * the schema is currently including an other schema with + * no target namespace. + */ +#define XML_SCHEMAS_INCLUDING_CONVERT_NS 1 << 9 +/** + * _xmlSchema: + * + * A Schemas definition + */ +struct _xmlSchema { + const xmlChar *name; /* schema name */ + const xmlChar *targetNamespace; /* the target namespace */ + const xmlChar *version; + const xmlChar *id; + xmlDocPtr doc; + xmlSchemaAnnotPtr annot; + int flags; + + xmlHashTablePtr typeDecl; + xmlHashTablePtr attrDecl; + xmlHashTablePtr attrgrpDecl; + xmlHashTablePtr elemDecl; + xmlHashTablePtr notaDecl; + + xmlHashTablePtr schemasImports; + + void *_private; /* unused by the library for users or bindings */ + xmlHashTablePtr groupDecl; + xmlDictPtr dict; + void *includes; /* the includes, this is opaque for now */ + int preserve; /* whether to free the document */ + int counter; /* used to give ononymous components unique names */ + xmlHashTablePtr idcDef; + void *volatiles; /* Misc. helper items (e.g. reference items) */ +}; + +XMLPUBFUN void XMLCALL xmlSchemaFreeType (xmlSchemaTypePtr type); +XMLPUBFUN void XMLCALL xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_SCHEMAS_ENABLED */ +#endif /* __XML_SCHEMA_INTERNALS_H__ */ diff --git a/include/libxml/threads.h b/include/libxml/threads.h new file mode 100644 index 0000000..fb6b704 --- /dev/null +++ b/include/libxml/threads.h @@ -0,0 +1,81 @@ +/** + * Summary: interfaces for thread handling + * Description: set of generic threading related routines + * should work with pthreads, Windows native or TLS threads + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_THREADS_H__ +#define __XML_THREADS_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * xmlMutex are a simple mutual exception locks. + */ +typedef struct _xmlMutex xmlMutex; +typedef xmlMutex *xmlMutexPtr; + +/* + * xmlRMutex are reentrant mutual exception locks. + */ +typedef struct _xmlRMutex xmlRMutex; +typedef xmlRMutex *xmlRMutexPtr; + +#ifdef __cplusplus +} +#endif +#include +#ifdef __cplusplus +extern "C" { +#endif + +XMLPUBFUN xmlMutexPtr XMLCALL + xmlNewMutex (void); +XMLPUBFUN void XMLCALL + xmlMutexLock (xmlMutexPtr tok); +XMLPUBFUN void XMLCALL + xmlMutexUnlock (xmlMutexPtr tok); +XMLPUBFUN void XMLCALL + xmlFreeMutex (xmlMutexPtr tok); + +XMLPUBFUN xmlRMutexPtr XMLCALL + xmlNewRMutex (void); +XMLPUBFUN void XMLCALL + xmlRMutexLock (xmlRMutexPtr tok); +XMLPUBFUN void XMLCALL + xmlRMutexUnlock (xmlRMutexPtr tok); +XMLPUBFUN void XMLCALL + xmlFreeRMutex (xmlRMutexPtr tok); + +/* + * Library wide APIs. + */ +XMLPUBFUN void XMLCALL + xmlInitThreads (void); +XMLPUBFUN void XMLCALL + xmlLockLibrary (void); +XMLPUBFUN void XMLCALL + xmlUnlockLibrary(void); +XMLPUBFUN int XMLCALL + xmlGetThreadId (void); +XMLPUBFUN int XMLCALL + xmlIsMainThread (void); +XMLPUBFUN void XMLCALL + xmlCleanupThreads(void); +XMLPUBFUN xmlGlobalStatePtr XMLCALL + xmlGetGlobalState(void); + +#ifdef __cplusplus +} +#endif + + +#endif /* __XML_THREADS_H__ */ diff --git a/include/libxml/tree.h b/include/libxml/tree.h new file mode 100644 index 0000000..d995e5c --- /dev/null +++ b/include/libxml/tree.h @@ -0,0 +1,1154 @@ +/* + * Summary: interfaces for tree manipulation + * Description: this module describes the structures found in an tree resulting + * from an XML or HTML parsing, as well as the API provided for + * various processing on that tree + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_TREE_H__ +#define __XML_TREE_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Some of the basic types pointer to structures: + */ +/* xmlIO.h */ +typedef struct _xmlParserInputBuffer xmlParserInputBuffer; +typedef xmlParserInputBuffer *xmlParserInputBufferPtr; + +typedef struct _xmlOutputBuffer xmlOutputBuffer; +typedef xmlOutputBuffer *xmlOutputBufferPtr; + +/* parser.h */ +typedef struct _xmlParserInput xmlParserInput; +typedef xmlParserInput *xmlParserInputPtr; + +typedef struct _xmlParserCtxt xmlParserCtxt; +typedef xmlParserCtxt *xmlParserCtxtPtr; + +typedef struct _xmlSAXLocator xmlSAXLocator; +typedef xmlSAXLocator *xmlSAXLocatorPtr; + +typedef struct _xmlSAXHandler xmlSAXHandler; +typedef xmlSAXHandler *xmlSAXHandlerPtr; + +/* entities.h */ +typedef struct _xmlEntity xmlEntity; +typedef xmlEntity *xmlEntityPtr; + +/** + * BASE_BUFFER_SIZE: + * + * default buffer size 4000. + */ +#define BASE_BUFFER_SIZE 4096 + +/** + * XML_XML_NAMESPACE: + * + * This is the namespace for the special xml: prefix predefined in the + * XML Namespace specification. + */ +#define XML_XML_NAMESPACE \ + (const xmlChar *) "http://www.w3.org/XML/1998/namespace" + +/** + * XML_XML_ID: + * + * This is the name for the special xml:id attribute + */ +#define XML_XML_ID (const xmlChar *) "xml:id" + +/* + * The different element types carried by an XML tree. + * + * NOTE: This is synchronized with DOM Level1 values + * See http://www.w3.org/TR/REC-DOM-Level-1/ + * + * Actually this had diverged a bit, and now XML_DOCUMENT_TYPE_NODE should + * be deprecated to use an XML_DTD_NODE. + */ +typedef enum { + XML_ELEMENT_NODE= 1, + XML_ATTRIBUTE_NODE= 2, + XML_TEXT_NODE= 3, + XML_CDATA_SECTION_NODE= 4, + XML_ENTITY_REF_NODE= 5, + XML_ENTITY_NODE= 6, + XML_PI_NODE= 7, + XML_COMMENT_NODE= 8, + XML_DOCUMENT_NODE= 9, + XML_DOCUMENT_TYPE_NODE= 10, + XML_DOCUMENT_FRAG_NODE= 11, + XML_NOTATION_NODE= 12, + XML_HTML_DOCUMENT_NODE= 13, + XML_DTD_NODE= 14, + XML_ELEMENT_DECL= 15, + XML_ATTRIBUTE_DECL= 16, + XML_ENTITY_DECL= 17, + XML_NAMESPACE_DECL= 18, + XML_XINCLUDE_START= 19, + XML_XINCLUDE_END= 20 +#ifdef LIBXML_DOCB_ENABLED + ,XML_DOCB_DOCUMENT_NODE= 21 +#endif +} xmlElementType; + + +/** + * xmlNotation: + * + * A DTD Notation definition. + */ + +typedef struct _xmlNotation xmlNotation; +typedef xmlNotation *xmlNotationPtr; +struct _xmlNotation { + const xmlChar *name; /* Notation name */ + const xmlChar *PublicID; /* Public identifier, if any */ + const xmlChar *SystemID; /* System identifier, if any */ +}; + +/** + * xmlAttributeType: + * + * A DTD Attribute type definition. + */ + +typedef enum { + XML_ATTRIBUTE_CDATA = 1, + XML_ATTRIBUTE_ID, + XML_ATTRIBUTE_IDREF , + XML_ATTRIBUTE_IDREFS, + XML_ATTRIBUTE_ENTITY, + XML_ATTRIBUTE_ENTITIES, + XML_ATTRIBUTE_NMTOKEN, + XML_ATTRIBUTE_NMTOKENS, + XML_ATTRIBUTE_ENUMERATION, + XML_ATTRIBUTE_NOTATION +} xmlAttributeType; + +/** + * xmlAttributeDefault: + * + * A DTD Attribute default definition. + */ + +typedef enum { + XML_ATTRIBUTE_NONE = 1, + XML_ATTRIBUTE_REQUIRED, + XML_ATTRIBUTE_IMPLIED, + XML_ATTRIBUTE_FIXED +} xmlAttributeDefault; + +/** + * xmlEnumeration: + * + * List structure used when there is an enumeration in DTDs. + */ + +typedef struct _xmlEnumeration xmlEnumeration; +typedef xmlEnumeration *xmlEnumerationPtr; +struct _xmlEnumeration { + struct _xmlEnumeration *next; /* next one */ + const xmlChar *name; /* Enumeration name */ +}; + +/** + * xmlAttribute: + * + * An Attribute declaration in a DTD. + */ + +typedef struct _xmlAttribute xmlAttribute; +typedef xmlAttribute *xmlAttributePtr; +struct _xmlAttribute { + void *_private; /* application data */ + xmlElementType type; /* XML_ATTRIBUTE_DECL, must be second ! */ + const xmlChar *name; /* Attribute name */ + struct _xmlNode *children; /* NULL */ + struct _xmlNode *last; /* NULL */ + struct _xmlDtd *parent; /* -> DTD */ + struct _xmlNode *next; /* next sibling link */ + struct _xmlNode *prev; /* previous sibling link */ + struct _xmlDoc *doc; /* the containing document */ + + struct _xmlAttribute *nexth; /* next in hash table */ + xmlAttributeType atype; /* The attribute type */ + xmlAttributeDefault def; /* the default */ + const xmlChar *defaultValue; /* or the default value */ + xmlEnumerationPtr tree; /* or the enumeration tree if any */ + const xmlChar *prefix; /* the namespace prefix if any */ + const xmlChar *elem; /* Element holding the attribute */ +}; + +/** + * xmlElementContentType: + * + * Possible definitions of element content types. + */ +typedef enum { + XML_ELEMENT_CONTENT_PCDATA = 1, + XML_ELEMENT_CONTENT_ELEMENT, + XML_ELEMENT_CONTENT_SEQ, + XML_ELEMENT_CONTENT_OR +} xmlElementContentType; + +/** + * xmlElementContentOccur: + * + * Possible definitions of element content occurrences. + */ +typedef enum { + XML_ELEMENT_CONTENT_ONCE = 1, + XML_ELEMENT_CONTENT_OPT, + XML_ELEMENT_CONTENT_MULT, + XML_ELEMENT_CONTENT_PLUS +} xmlElementContentOccur; + +/** + * xmlElementContent: + * + * An XML Element content as stored after parsing an element definition + * in a DTD. + */ + +typedef struct _xmlElementContent xmlElementContent; +typedef xmlElementContent *xmlElementContentPtr; +struct _xmlElementContent { + xmlElementContentType type; /* PCDATA, ELEMENT, SEQ or OR */ + xmlElementContentOccur ocur; /* ONCE, OPT, MULT or PLUS */ + const xmlChar *name; /* Element name */ + struct _xmlElementContent *c1; /* first child */ + struct _xmlElementContent *c2; /* second child */ + struct _xmlElementContent *parent; /* parent */ + const xmlChar *prefix; /* Namespace prefix */ +}; + +/** + * xmlElementTypeVal: + * + * The different possibilities for an element content type. + */ + +typedef enum { + XML_ELEMENT_TYPE_UNDEFINED = 0, + XML_ELEMENT_TYPE_EMPTY = 1, + XML_ELEMENT_TYPE_ANY, + XML_ELEMENT_TYPE_MIXED, + XML_ELEMENT_TYPE_ELEMENT +} xmlElementTypeVal; + +#ifdef __cplusplus +} +#endif +#include +#ifdef __cplusplus +extern "C" { +#endif + +/** + * xmlElement: + * + * An XML Element declaration from a DTD. + */ + +typedef struct _xmlElement xmlElement; +typedef xmlElement *xmlElementPtr; +struct _xmlElement { + void *_private; /* application data */ + xmlElementType type; /* XML_ELEMENT_DECL, must be second ! */ + const xmlChar *name; /* Element name */ + struct _xmlNode *children; /* NULL */ + struct _xmlNode *last; /* NULL */ + struct _xmlDtd *parent; /* -> DTD */ + struct _xmlNode *next; /* next sibling link */ + struct _xmlNode *prev; /* previous sibling link */ + struct _xmlDoc *doc; /* the containing document */ + + xmlElementTypeVal etype; /* The type */ + xmlElementContentPtr content; /* the allowed element content */ + xmlAttributePtr attributes; /* List of the declared attributes */ + const xmlChar *prefix; /* the namespace prefix if any */ +#ifdef LIBXML_REGEXP_ENABLED + xmlRegexpPtr contModel; /* the validating regexp */ +#else + void *contModel; +#endif +}; + + +/** + * XML_LOCAL_NAMESPACE: + * + * A namespace declaration node. + */ +#define XML_LOCAL_NAMESPACE XML_NAMESPACE_DECL +typedef xmlElementType xmlNsType; + +/** + * xmlNs: + * + * An XML namespace. + * Note that prefix == NULL is valid, it defines the default namespace + * within the subtree (until overridden). + * + * xmlNsType is unified with xmlElementType. + */ + +typedef struct _xmlNs xmlNs; +typedef xmlNs *xmlNsPtr; +struct _xmlNs { + struct _xmlNs *next; /* next Ns link for this node */ + xmlNsType type; /* global or local */ + const xmlChar *href; /* URL for the namespace */ + const xmlChar *prefix; /* prefix for the namespace */ + void *_private; /* application data */ +}; + +/** + * xmlDtd: + * + * An XML DTD, as defined by parent link */ + struct _xmlNode *next; /* next sibling link */ + struct _xmlNode *prev; /* previous sibling link */ + struct _xmlDoc *doc; /* the containing document */ + + /* End of common part */ + void *notations; /* Hash table for notations if any */ + void *elements; /* Hash table for elements if any */ + void *attributes; /* Hash table for attributes if any */ + void *entities; /* Hash table for entities if any */ + const xmlChar *ExternalID; /* External identifier for PUBLIC DTD */ + const xmlChar *SystemID; /* URI for a SYSTEM or PUBLIC DTD */ + void *pentities; /* Hash table for param entities if any */ +}; + +/** + * xmlAttr: + * + * An attribute on an XML node. + */ +typedef struct _xmlAttr xmlAttr; +typedef xmlAttr *xmlAttrPtr; +struct _xmlAttr { + void *_private; /* application data */ + xmlElementType type; /* XML_ATTRIBUTE_NODE, must be second ! */ + const xmlChar *name; /* the name of the property */ + struct _xmlNode *children; /* the value of the property */ + struct _xmlNode *last; /* NULL */ + struct _xmlNode *parent; /* child->parent link */ + struct _xmlAttr *next; /* next sibling link */ + struct _xmlAttr *prev; /* previous sibling link */ + struct _xmlDoc *doc; /* the containing document */ + xmlNs *ns; /* pointer to the associated namespace */ + xmlAttributeType atype; /* the attribute type if validating */ + void *psvi; /* for type/PSVI informations */ +}; + +/** + * xmlID: + * + * An XML ID instance. + */ + +typedef struct _xmlID xmlID; +typedef xmlID *xmlIDPtr; +struct _xmlID { + struct _xmlID *next; /* next ID */ + const xmlChar *value; /* The ID name */ + xmlAttrPtr attr; /* The attribute holding it */ + const xmlChar *name; /* The attribute if attr is not available */ + int lineno; /* The line number if attr is not available */ + struct _xmlDoc *doc; /* The document holding the ID */ +}; + +/** + * xmlRef: + * + * An XML IDREF instance. + */ + +typedef struct _xmlRef xmlRef; +typedef xmlRef *xmlRefPtr; +struct _xmlRef { + struct _xmlRef *next; /* next Ref */ + const xmlChar *value; /* The Ref name */ + xmlAttrPtr attr; /* The attribute holding it */ + const xmlChar *name; /* The attribute if attr is not available */ + int lineno; /* The line number if attr is not available */ +}; + +/** + * xmlBufferAllocationScheme: + * + * A buffer allocation scheme can be defined to either match exactly the + * need or double it's allocated size each time it is found too small. + */ + +typedef enum { + XML_BUFFER_ALLOC_DOUBLEIT, + XML_BUFFER_ALLOC_EXACT, + XML_BUFFER_ALLOC_IMMUTABLE +} xmlBufferAllocationScheme; + +/** + * xmlBuffer: + * + * A buffer structure. + */ +typedef struct _xmlBuffer xmlBuffer; +typedef xmlBuffer *xmlBufferPtr; +struct _xmlBuffer { + xmlChar *content; /* The buffer content UTF8 */ + unsigned int use; /* The buffer size used */ + unsigned int size; /* The buffer size */ + xmlBufferAllocationScheme alloc; /* The realloc method */ +}; + +/** + * xmlNode: + * + * A node in an XML tree. + */ +typedef struct _xmlNode xmlNode; +typedef xmlNode *xmlNodePtr; +struct _xmlNode { + void *_private; /* application data */ + xmlElementType type; /* type number, must be second ! */ + const xmlChar *name; /* the name of the node, or the entity */ + struct _xmlNode *children; /* parent->childs link */ + struct _xmlNode *last; /* last child link */ + struct _xmlNode *parent; /* child->parent link */ + struct _xmlNode *next; /* next sibling link */ + struct _xmlNode *prev; /* previous sibling link */ + struct _xmlDoc *doc; /* the containing document */ + + /* End of common part */ + xmlNs *ns; /* pointer to the associated namespace */ + xmlChar *content; /* the content */ + struct _xmlAttr *properties;/* properties list */ + xmlNs *nsDef; /* namespace definitions on this node */ + void *psvi; /* for type/PSVI informations */ + unsigned short line; /* line number */ + unsigned short extra; /* extra data for XPath/XSLT */ +}; + +/** + * XML_GET_CONTENT: + * + * Macro to extract the content pointer of a node. + */ +#define XML_GET_CONTENT(n) \ + ((n)->type == XML_ELEMENT_NODE ? NULL : (n)->content) + +/** + * XML_GET_LINE: + * + * Macro to extract the line number of an element node. + */ +#define XML_GET_LINE(n) \ + (xmlGetLineNo(n)) + + +/** + * xmlDoc: + * + * An XML document. + */ +typedef struct _xmlDoc xmlDoc; +typedef xmlDoc *xmlDocPtr; +struct _xmlDoc { + void *_private; /* application data */ + xmlElementType type; /* XML_DOCUMENT_NODE, must be second ! */ + char *name; /* name/filename/URI of the document */ + struct _xmlNode *children; /* the document tree */ + struct _xmlNode *last; /* last child link */ + struct _xmlNode *parent; /* child->parent link */ + struct _xmlNode *next; /* next sibling link */ + struct _xmlNode *prev; /* previous sibling link */ + struct _xmlDoc *doc; /* autoreference to itself */ + + /* End of common part */ + int compression;/* level of zlib compression */ + int standalone; /* standalone document (no external refs) */ + struct _xmlDtd *intSubset; /* the document internal subset */ + struct _xmlDtd *extSubset; /* the document external subset */ + struct _xmlNs *oldNs; /* Global namespace, the old way */ + const xmlChar *version; /* the XML version string */ + const xmlChar *encoding; /* external initial encoding, if any */ + void *ids; /* Hash table for ID attributes if any */ + void *refs; /* Hash table for IDREFs attributes if any */ + const xmlChar *URL; /* The URI for that document */ + int charset; /* encoding of the in-memory content + actually an xmlCharEncoding */ + struct _xmlDict *dict; /* dict used to allocate names or NULL */ + void *psvi; /* for type/PSVI informations */ +}; + +typedef struct _xmlDOMWrapCtxt xmlDOMWrapCtxt; +typedef xmlDOMWrapCtxt *xmlDOMWrapCtxtPtr; +struct _xmlDOMWrapCtxt { + void * _private; +}; + +/** + * xmlChildrenNode: + * + * Macro for compatibility naming layer with libxml1. Maps + * to "children." + */ +#ifndef xmlChildrenNode +#define xmlChildrenNode children +#endif + +/** + * xmlRootNode: + * + * Macro for compatibility naming layer with libxml1. Maps + * to "children". + */ +#ifndef xmlRootNode +#define xmlRootNode children +#endif + +/* + * Variables. + */ + +/* + * Some helper functions + */ +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_DEBUG_ENABLED) || defined (LIBXML_HTML_ENABLED) +XMLPUBFUN int XMLCALL + xmlValidateNCName (const xmlChar *value, + int space); +#endif + +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +XMLPUBFUN int XMLCALL + xmlValidateQName (const xmlChar *value, + int space); +XMLPUBFUN int XMLCALL + xmlValidateName (const xmlChar *value, + int space); +XMLPUBFUN int XMLCALL + xmlValidateNMToken (const xmlChar *value, + int space); +#endif + +XMLPUBFUN xmlChar * XMLCALL + xmlBuildQName (const xmlChar *ncname, + const xmlChar *prefix, + xmlChar *memory, + int len); +XMLPUBFUN xmlChar * XMLCALL + xmlSplitQName2 (const xmlChar *name, + xmlChar **prefix); +XMLPUBFUN const xmlChar * XMLCALL + xmlSplitQName3 (const xmlChar *name, + int *len); + +/* + * Handling Buffers. + */ + +XMLPUBFUN void XMLCALL + xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme); +XMLPUBFUN xmlBufferAllocationScheme XMLCALL + xmlGetBufferAllocationScheme(void); + +XMLPUBFUN xmlBufferPtr XMLCALL + xmlBufferCreate (void); +XMLPUBFUN xmlBufferPtr XMLCALL + xmlBufferCreateSize (size_t size); +XMLPUBFUN xmlBufferPtr XMLCALL + xmlBufferCreateStatic (void *mem, + size_t size); +XMLPUBFUN int XMLCALL + xmlBufferResize (xmlBufferPtr buf, + unsigned int size); +XMLPUBFUN void XMLCALL + xmlBufferFree (xmlBufferPtr buf); +XMLPUBFUN int XMLCALL + xmlBufferDump (FILE *file, + xmlBufferPtr buf); +XMLPUBFUN int XMLCALL + xmlBufferAdd (xmlBufferPtr buf, + const xmlChar *str, + int len); +XMLPUBFUN int XMLCALL + xmlBufferAddHead (xmlBufferPtr buf, + const xmlChar *str, + int len); +XMLPUBFUN int XMLCALL + xmlBufferCat (xmlBufferPtr buf, + const xmlChar *str); +XMLPUBFUN int XMLCALL + xmlBufferCCat (xmlBufferPtr buf, + const char *str); +XMLPUBFUN int XMLCALL + xmlBufferShrink (xmlBufferPtr buf, + unsigned int len); +XMLPUBFUN int XMLCALL + xmlBufferGrow (xmlBufferPtr buf, + unsigned int len); +XMLPUBFUN void XMLCALL + xmlBufferEmpty (xmlBufferPtr buf); +XMLPUBFUN const xmlChar* XMLCALL + xmlBufferContent (const xmlBufferPtr buf); +XMLPUBFUN void XMLCALL + xmlBufferSetAllocationScheme(xmlBufferPtr buf, + xmlBufferAllocationScheme scheme); +XMLPUBFUN int XMLCALL + xmlBufferLength (const xmlBufferPtr buf); + +/* + * Creating/freeing new structures. + */ +XMLPUBFUN xmlDtdPtr XMLCALL + xmlCreateIntSubset (xmlDocPtr doc, + const xmlChar *name, + const xmlChar *ExternalID, + const xmlChar *SystemID); +XMLPUBFUN xmlDtdPtr XMLCALL + xmlNewDtd (xmlDocPtr doc, + const xmlChar *name, + const xmlChar *ExternalID, + const xmlChar *SystemID); +XMLPUBFUN xmlDtdPtr XMLCALL + xmlGetIntSubset (xmlDocPtr doc); +XMLPUBFUN void XMLCALL + xmlFreeDtd (xmlDtdPtr cur); +#ifdef LIBXML_LEGACY_ENABLED +XMLPUBFUN xmlNsPtr XMLCALL + xmlNewGlobalNs (xmlDocPtr doc, + const xmlChar *href, + const xmlChar *prefix); +#endif /* LIBXML_LEGACY_ENABLED */ +XMLPUBFUN xmlNsPtr XMLCALL + xmlNewNs (xmlNodePtr node, + const xmlChar *href, + const xmlChar *prefix); +XMLPUBFUN void XMLCALL + xmlFreeNs (xmlNsPtr cur); +XMLPUBFUN void XMLCALL + xmlFreeNsList (xmlNsPtr cur); +XMLPUBFUN xmlDocPtr XMLCALL + xmlNewDoc (const xmlChar *version); +XMLPUBFUN void XMLCALL + xmlFreeDoc (xmlDocPtr cur); +XMLPUBFUN xmlAttrPtr XMLCALL + xmlNewDocProp (xmlDocPtr doc, + const xmlChar *name, + const xmlChar *value); +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \ + defined(LIBXML_SCHEMAS_ENABLED) +XMLPUBFUN xmlAttrPtr XMLCALL + xmlNewProp (xmlNodePtr node, + const xmlChar *name, + const xmlChar *value); +#endif +XMLPUBFUN xmlAttrPtr XMLCALL + xmlNewNsProp (xmlNodePtr node, + xmlNsPtr ns, + const xmlChar *name, + const xmlChar *value); +XMLPUBFUN xmlAttrPtr XMLCALL + xmlNewNsPropEatName (xmlNodePtr node, + xmlNsPtr ns, + xmlChar *name, + const xmlChar *value); +XMLPUBFUN void XMLCALL + xmlFreePropList (xmlAttrPtr cur); +XMLPUBFUN void XMLCALL + xmlFreeProp (xmlAttrPtr cur); +XMLPUBFUN xmlAttrPtr XMLCALL + xmlCopyProp (xmlNodePtr target, + xmlAttrPtr cur); +XMLPUBFUN xmlAttrPtr XMLCALL + xmlCopyPropList (xmlNodePtr target, + xmlAttrPtr cur); +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN xmlDtdPtr XMLCALL + xmlCopyDtd (xmlDtdPtr dtd); +#endif /* LIBXML_TREE_ENABLED */ +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +XMLPUBFUN xmlDocPtr XMLCALL + xmlCopyDoc (xmlDocPtr doc, + int recursive); +#endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) */ +/* + * Creating new nodes. + */ +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewDocNode (xmlDocPtr doc, + xmlNsPtr ns, + const xmlChar *name, + const xmlChar *content); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewDocNodeEatName (xmlDocPtr doc, + xmlNsPtr ns, + xmlChar *name, + const xmlChar *content); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewNode (xmlNsPtr ns, + const xmlChar *name); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewNodeEatName (xmlNsPtr ns, + xmlChar *name); +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewChild (xmlNodePtr parent, + xmlNsPtr ns, + const xmlChar *name, + const xmlChar *content); +#endif +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewDocText (xmlDocPtr doc, + const xmlChar *content); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewText (const xmlChar *content); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewDocPI (xmlDocPtr doc, + const xmlChar *name, + const xmlChar *content); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewPI (const xmlChar *name, + const xmlChar *content); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewDocTextLen (xmlDocPtr doc, + const xmlChar *content, + int len); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewTextLen (const xmlChar *content, + int len); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewDocComment (xmlDocPtr doc, + const xmlChar *content); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewComment (const xmlChar *content); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewCDataBlock (xmlDocPtr doc, + const xmlChar *content, + int len); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewCharRef (xmlDocPtr doc, + const xmlChar *name); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewReference (xmlDocPtr doc, + const xmlChar *name); +XMLPUBFUN xmlNodePtr XMLCALL + xmlCopyNode (const xmlNodePtr node, + int recursive); +XMLPUBFUN xmlNodePtr XMLCALL + xmlDocCopyNode (const xmlNodePtr node, + xmlDocPtr doc, + int recursive); +XMLPUBFUN xmlNodePtr XMLCALL + xmlDocCopyNodeList (xmlDocPtr doc, + const xmlNodePtr node); +XMLPUBFUN xmlNodePtr XMLCALL + xmlCopyNodeList (const xmlNodePtr node); +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewTextChild (xmlNodePtr parent, + xmlNsPtr ns, + const xmlChar *name, + const xmlChar *content); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewDocRawNode (xmlDocPtr doc, + xmlNsPtr ns, + const xmlChar *name, + const xmlChar *content); +XMLPUBFUN xmlNodePtr XMLCALL + xmlNewDocFragment (xmlDocPtr doc); +#endif /* LIBXML_TREE_ENABLED */ + +/* + * Navigating. + */ +XMLPUBFUN long XMLCALL + xmlGetLineNo (xmlNodePtr node); +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED) +XMLPUBFUN xmlChar * XMLCALL + xmlGetNodePath (xmlNodePtr node); +#endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED) */ +XMLPUBFUN xmlNodePtr XMLCALL + xmlDocGetRootElement (xmlDocPtr doc); +XMLPUBFUN xmlNodePtr XMLCALL + xmlGetLastChild (xmlNodePtr parent); +XMLPUBFUN int XMLCALL + xmlNodeIsText (xmlNodePtr node); +XMLPUBFUN int XMLCALL + xmlIsBlankNode (xmlNodePtr node); + +/* + * Changing the structure. + */ +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED) +XMLPUBFUN xmlNodePtr XMLCALL + xmlDocSetRootElement (xmlDocPtr doc, + xmlNodePtr root); +#endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED) */ +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN void XMLCALL + xmlNodeSetName (xmlNodePtr cur, + const xmlChar *name); +#endif /* LIBXML_TREE_ENABLED */ +XMLPUBFUN xmlNodePtr XMLCALL + xmlAddChild (xmlNodePtr parent, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL + xmlAddChildList (xmlNodePtr parent, + xmlNodePtr cur); +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED) +XMLPUBFUN xmlNodePtr XMLCALL + xmlReplaceNode (xmlNodePtr old, + xmlNodePtr cur); +#endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED) */ +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \ + defined(LIBXML_SCHEMAS_ENABLED) +XMLPUBFUN xmlNodePtr XMLCALL + xmlAddPrevSibling (xmlNodePtr cur, + xmlNodePtr elem); +#endif /* LIBXML_TREE_ENABLED || LIBXML_HTML_ENABLED || LIBXML_SCHEMAS_ENABLED */ +XMLPUBFUN xmlNodePtr XMLCALL + xmlAddSibling (xmlNodePtr cur, + xmlNodePtr elem); +XMLPUBFUN xmlNodePtr XMLCALL + xmlAddNextSibling (xmlNodePtr cur, + xmlNodePtr elem); +XMLPUBFUN void XMLCALL + xmlUnlinkNode (xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL + xmlTextMerge (xmlNodePtr first, + xmlNodePtr second); +XMLPUBFUN int XMLCALL + xmlTextConcat (xmlNodePtr node, + const xmlChar *content, + int len); +XMLPUBFUN void XMLCALL + xmlFreeNodeList (xmlNodePtr cur); +XMLPUBFUN void XMLCALL + xmlFreeNode (xmlNodePtr cur); +XMLPUBFUN void XMLCALL + xmlSetTreeDoc (xmlNodePtr tree, + xmlDocPtr doc); +XMLPUBFUN void XMLCALL + xmlSetListDoc (xmlNodePtr list, + xmlDocPtr doc); +/* + * Namespaces. + */ +XMLPUBFUN xmlNsPtr XMLCALL + xmlSearchNs (xmlDocPtr doc, + xmlNodePtr node, + const xmlChar *nameSpace); +XMLPUBFUN xmlNsPtr XMLCALL + xmlSearchNsByHref (xmlDocPtr doc, + xmlNodePtr node, + const xmlChar *href); +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) +XMLPUBFUN xmlNsPtr * XMLCALL + xmlGetNsList (xmlDocPtr doc, + xmlNodePtr node); +#endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) */ + +XMLPUBFUN void XMLCALL + xmlSetNs (xmlNodePtr node, + xmlNsPtr ns); +XMLPUBFUN xmlNsPtr XMLCALL + xmlCopyNamespace (xmlNsPtr cur); +XMLPUBFUN xmlNsPtr XMLCALL + xmlCopyNamespaceList (xmlNsPtr cur); + +/* + * Changing the content. + */ +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_HTML_ENABLED) +XMLPUBFUN xmlAttrPtr XMLCALL + xmlSetProp (xmlNodePtr node, + const xmlChar *name, + const xmlChar *value); +XMLPUBFUN xmlAttrPtr XMLCALL + xmlSetNsProp (xmlNodePtr node, + xmlNsPtr ns, + const xmlChar *name, + const xmlChar *value); +#endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_HTML_ENABLED) */ +XMLPUBFUN xmlChar * XMLCALL + xmlGetNoNsProp (xmlNodePtr node, + const xmlChar *name); +XMLPUBFUN xmlChar * XMLCALL + xmlGetProp (xmlNodePtr node, + const xmlChar *name); +XMLPUBFUN xmlAttrPtr XMLCALL + xmlHasProp (xmlNodePtr node, + const xmlChar *name); +XMLPUBFUN xmlAttrPtr XMLCALL + xmlHasNsProp (xmlNodePtr node, + const xmlChar *name, + const xmlChar *nameSpace); +XMLPUBFUN xmlChar * XMLCALL + xmlGetNsProp (xmlNodePtr node, + const xmlChar *name, + const xmlChar *nameSpace); +XMLPUBFUN xmlNodePtr XMLCALL + xmlStringGetNodeList (xmlDocPtr doc, + const xmlChar *value); +XMLPUBFUN xmlNodePtr XMLCALL + xmlStringLenGetNodeList (xmlDocPtr doc, + const xmlChar *value, + int len); +XMLPUBFUN xmlChar * XMLCALL + xmlNodeListGetString (xmlDocPtr doc, + xmlNodePtr list, + int inLine); +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN xmlChar * XMLCALL + xmlNodeListGetRawString (xmlDocPtr doc, + xmlNodePtr list, + int inLine); +#endif /* LIBXML_TREE_ENABLED */ +XMLPUBFUN void XMLCALL + xmlNodeSetContent (xmlNodePtr cur, + const xmlChar *content); +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN void XMLCALL + xmlNodeSetContentLen (xmlNodePtr cur, + const xmlChar *content, + int len); +#endif /* LIBXML_TREE_ENABLED */ +XMLPUBFUN void XMLCALL + xmlNodeAddContent (xmlNodePtr cur, + const xmlChar *content); +XMLPUBFUN void XMLCALL + xmlNodeAddContentLen (xmlNodePtr cur, + const xmlChar *content, + int len); +XMLPUBFUN xmlChar * XMLCALL + xmlNodeGetContent (xmlNodePtr cur); +XMLPUBFUN int XMLCALL + xmlNodeBufGetContent (xmlBufferPtr buffer, + xmlNodePtr cur); +XMLPUBFUN xmlChar * XMLCALL + xmlNodeGetLang (xmlNodePtr cur); +XMLPUBFUN int XMLCALL + xmlNodeGetSpacePreserve (xmlNodePtr cur); +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN void XMLCALL + xmlNodeSetLang (xmlNodePtr cur, + const xmlChar *lang); +XMLPUBFUN void XMLCALL + xmlNodeSetSpacePreserve (xmlNodePtr cur, + int val); +#endif /* LIBXML_TREE_ENABLED */ +XMLPUBFUN xmlChar * XMLCALL + xmlNodeGetBase (xmlDocPtr doc, + xmlNodePtr cur); +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) +XMLPUBFUN void XMLCALL + xmlNodeSetBase (xmlNodePtr cur, + const xmlChar *uri); +#endif + +/* + * Removing content. + */ +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN int XMLCALL + xmlRemoveProp (xmlAttrPtr cur); +#endif /* LIBXML_TREE_ENABLED */ +#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +XMLPUBFUN int XMLCALL + xmlUnsetNsProp (xmlNodePtr node, + xmlNsPtr ns, + const xmlChar *name); +XMLPUBFUN int XMLCALL + xmlUnsetProp (xmlNodePtr node, + const xmlChar *name); +#endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) */ + +/* + * Internal, don't use. + */ +XMLPUBFUN void XMLCALL + xmlBufferWriteCHAR (xmlBufferPtr buf, + const xmlChar *string); +XMLPUBFUN void XMLCALL + xmlBufferWriteChar (xmlBufferPtr buf, + const char *string); +XMLPUBFUN void XMLCALL + xmlBufferWriteQuotedString(xmlBufferPtr buf, + const xmlChar *string); + +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void xmlAttrSerializeTxtContent(xmlBufferPtr buf, + xmlDocPtr doc, + xmlAttrPtr attr, + const xmlChar *string); +#endif /* LIBXML_OUTPUT_ENABLED */ + +#ifdef LIBXML_TREE_ENABLED +/* + * Namespace handling. + */ +XMLPUBFUN int XMLCALL + xmlReconciliateNs (xmlDocPtr doc, + xmlNodePtr tree); +#endif + +#ifdef LIBXML_OUTPUT_ENABLED +/* + * Saving. + */ +XMLPUBFUN void XMLCALL + xmlDocDumpFormatMemory (xmlDocPtr cur, + xmlChar **mem, + int *size, + int format); +XMLPUBFUN void XMLCALL + xmlDocDumpMemory (xmlDocPtr cur, + xmlChar **mem, + int *size); +XMLPUBFUN void XMLCALL + xmlDocDumpMemoryEnc (xmlDocPtr out_doc, + xmlChar **doc_txt_ptr, + int * doc_txt_len, + const char *txt_encoding); +XMLPUBFUN void XMLCALL + xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc, + xmlChar **doc_txt_ptr, + int * doc_txt_len, + const char *txt_encoding, + int format); +XMLPUBFUN int XMLCALL + xmlDocFormatDump (FILE *f, + xmlDocPtr cur, + int format); +XMLPUBFUN int XMLCALL + xmlDocDump (FILE *f, + xmlDocPtr cur); +XMLPUBFUN void XMLCALL + xmlElemDump (FILE *f, + xmlDocPtr doc, + xmlNodePtr cur); +XMLPUBFUN int XMLCALL + xmlSaveFile (const char *filename, + xmlDocPtr cur); +XMLPUBFUN int XMLCALL + xmlSaveFormatFile (const char *filename, + xmlDocPtr cur, + int format); +XMLPUBFUN int XMLCALL + xmlNodeDump (xmlBufferPtr buf, + xmlDocPtr doc, + xmlNodePtr cur, + int level, + int format); + +XMLPUBFUN int XMLCALL + xmlSaveFileTo (xmlOutputBufferPtr buf, + xmlDocPtr cur, + const char *encoding); +XMLPUBFUN int XMLCALL + xmlSaveFormatFileTo (xmlOutputBufferPtr buf, + xmlDocPtr cur, + const char *encoding, + int format); +XMLPUBFUN void XMLCALL + xmlNodeDumpOutput (xmlOutputBufferPtr buf, + xmlDocPtr doc, + xmlNodePtr cur, + int level, + int format, + const char *encoding); + +XMLPUBFUN int XMLCALL + xmlSaveFormatFileEnc (const char *filename, + xmlDocPtr cur, + const char *encoding, + int format); + +XMLPUBFUN int XMLCALL + xmlSaveFileEnc (const char *filename, + xmlDocPtr cur, + const char *encoding); + +#endif /* LIBXML_OUTPUT_ENABLED */ +/* + * XHTML + */ +XMLPUBFUN int XMLCALL + xmlIsXHTML (const xmlChar *systemID, + const xmlChar *publicID); + +/* + * Compression. + */ +XMLPUBFUN int XMLCALL + xmlGetDocCompressMode (xmlDocPtr doc); +XMLPUBFUN void XMLCALL + xmlSetDocCompressMode (xmlDocPtr doc, + int mode); +XMLPUBFUN int XMLCALL + xmlGetCompressMode (void); +XMLPUBFUN void XMLCALL + xmlSetCompressMode (int mode); + +/* +* DOM-wrapper helper functions. +*/ +XMLPUBFUN xmlDOMWrapCtxtPtr XMLCALL + xmlDOMWrapNewCtxt (void); +XMLPUBFUN void XMLCALL + xmlDOMWrapFreeCtxt (xmlDOMWrapCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt, + xmlNodePtr elem, + int options); +XMLPUBFUN int XMLCALL + xmlDOMWrapAdoptNode (xmlDOMWrapCtxtPtr ctxt, + xmlDocPtr sourceDoc, + xmlNodePtr node, + xmlDocPtr destDoc, + xmlNodePtr destParent, + int options); +XMLPUBFUN int XMLCALL + xmlDOMWrapRemoveNode (xmlDOMWrapCtxtPtr ctxt, + xmlDocPtr doc, + xmlNodePtr node, + int options); + +#ifdef __cplusplus +} +#endif +#ifndef __XML_PARSER_H__ +#include +#endif + +#endif /* __XML_TREE_H__ */ + diff --git a/include/libxml/uri.h b/include/libxml/uri.h new file mode 100644 index 0000000..90ed06e --- /dev/null +++ b/include/libxml/uri.h @@ -0,0 +1,84 @@ +/** + * Summary: library of generic URI related routines + * Description: library of generic URI related routines + * Implements RFC 2396 + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_URI_H__ +#define __XML_URI_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * xmlURI: + * + * A parsed URI reference. This is a struct containing the various fields + * as described in RFC 2396 but separated for further processing. + */ +typedef struct _xmlURI xmlURI; +typedef xmlURI *xmlURIPtr; +struct _xmlURI { + char *scheme; /* the URI scheme */ + char *opaque; /* opaque part */ + char *authority; /* the authority part */ + char *server; /* the server part */ + char *user; /* the user part */ + int port; /* the port number */ + char *path; /* the path string */ + char *query; /* the query string */ + char *fragment; /* the fragment identifier */ + int cleanup; /* parsing potentially unclean URI */ +}; + +/* + * This function is in tree.h: + * xmlChar * xmlNodeGetBase (xmlDocPtr doc, + * xmlNodePtr cur); + */ +XMLPUBFUN xmlURIPtr XMLCALL + xmlCreateURI (void); +XMLPUBFUN xmlChar * XMLCALL + xmlBuildURI (const xmlChar *URI, + const xmlChar *base); +XMLPUBFUN xmlChar * XMLCALL + xmlBuildRelativeURI (const xmlChar *URI, + const xmlChar *base); +XMLPUBFUN xmlURIPtr XMLCALL + xmlParseURI (const char *str); +XMLPUBFUN int XMLCALL + xmlParseURIReference (xmlURIPtr uri, + const char *str); +XMLPUBFUN xmlChar * XMLCALL + xmlSaveUri (xmlURIPtr uri); +XMLPUBFUN void XMLCALL + xmlPrintURI (FILE *stream, + xmlURIPtr uri); +XMLPUBFUN xmlChar * XMLCALL + xmlURIEscapeStr (const xmlChar *str, + const xmlChar *list); +XMLPUBFUN char * XMLCALL + xmlURIUnescapeString (const char *str, + int len, + char *target); +XMLPUBFUN int XMLCALL + xmlNormalizeURIPath (char *path); +XMLPUBFUN xmlChar * XMLCALL + xmlURIEscape (const xmlChar *str); +XMLPUBFUN void XMLCALL + xmlFreeURI (xmlURIPtr uri); +XMLPUBFUN xmlChar* XMLCALL + xmlCanonicPath (const xmlChar *path); + +#ifdef __cplusplus +} +#endif +#endif /* __XML_URI_H__ */ diff --git a/include/libxml/valid.h b/include/libxml/valid.h new file mode 100644 index 0000000..86e3fce --- /dev/null +++ b/include/libxml/valid.h @@ -0,0 +1,458 @@ +/* + * Summary: The DTD validation + * Description: API for the DTD handling and the validity checking + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + + +#ifndef __XML_VALID_H__ +#define __XML_VALID_H__ + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Validation state added for non-determinist content model. + */ +typedef struct _xmlValidState xmlValidState; +typedef xmlValidState *xmlValidStatePtr; + +/** + * xmlValidityErrorFunc: + * @ctx: usually an xmlValidCtxtPtr to a validity error context, + * but comes from ctxt->userData (which normally contains such + * a pointer); ctxt->userData can be changed by the user. + * @msg: the string to format *printf like vararg + * @...: remaining arguments to the format + * + * Callback called when a validity error is found. This is a message + * oriented function similar to an *printf function. + */ +typedef void (*xmlValidityErrorFunc) (void *ctx, + const char *msg, + ...); + +/** + * xmlValidityWarningFunc: + * @ctx: usually an xmlValidCtxtPtr to a validity error context, + * but comes from ctxt->userData (which normally contains such + * a pointer); ctxt->userData can be changed by the user. + * @msg: the string to format *printf like vararg + * @...: remaining arguments to the format + * + * Callback called when a validity warning is found. This is a message + * oriented function similar to an *printf function. + */ +typedef void (*xmlValidityWarningFunc) (void *ctx, + const char *msg, + ...); + +#ifdef IN_LIBXML +/** + * XML_CTXT_FINISH_DTD_0: + * + * Special value for finishDtd field when embedded in an xmlParserCtxt + */ +#define XML_CTXT_FINISH_DTD_0 0xabcd1234 +/** + * XML_CTXT_FINISH_DTD_1: + * + * Special value for finishDtd field when embedded in an xmlParserCtxt + */ +#define XML_CTXT_FINISH_DTD_1 0xabcd1235 +#endif + +/* + * xmlValidCtxt: + * An xmlValidCtxt is used for error reporting when validating. + */ +typedef struct _xmlValidCtxt xmlValidCtxt; +typedef xmlValidCtxt *xmlValidCtxtPtr; +struct _xmlValidCtxt { + void *userData; /* user specific data block */ + xmlValidityErrorFunc error; /* the callback in case of errors */ + xmlValidityWarningFunc warning; /* the callback in case of warning */ + + /* Node analysis stack used when validating within entities */ + xmlNodePtr node; /* Current parsed Node */ + int nodeNr; /* Depth of the parsing stack */ + int nodeMax; /* Max depth of the parsing stack */ + xmlNodePtr *nodeTab; /* array of nodes */ + + unsigned int finishDtd; /* finished validating the Dtd ? */ + xmlDocPtr doc; /* the document */ + int valid; /* temporary validity check result */ + + /* state state used for non-determinist content validation */ + xmlValidState *vstate; /* current state */ + int vstateNr; /* Depth of the validation stack */ + int vstateMax; /* Max depth of the validation stack */ + xmlValidState *vstateTab; /* array of validation states */ + +#ifdef LIBXML_REGEXP_ENABLED + xmlAutomataPtr am; /* the automata */ + xmlAutomataStatePtr state; /* used to build the automata */ +#else + void *am; + void *state; +#endif +}; + +/* + * ALL notation declarations are stored in a table. + * There is one table per DTD. + */ + +typedef struct _xmlHashTable xmlNotationTable; +typedef xmlNotationTable *xmlNotationTablePtr; + +/* + * ALL element declarations are stored in a table. + * There is one table per DTD. + */ + +typedef struct _xmlHashTable xmlElementTable; +typedef xmlElementTable *xmlElementTablePtr; + +/* + * ALL attribute declarations are stored in a table. + * There is one table per DTD. + */ + +typedef struct _xmlHashTable xmlAttributeTable; +typedef xmlAttributeTable *xmlAttributeTablePtr; + +/* + * ALL IDs attributes are stored in a table. + * There is one table per document. + */ + +typedef struct _xmlHashTable xmlIDTable; +typedef xmlIDTable *xmlIDTablePtr; + +/* + * ALL Refs attributes are stored in a table. + * There is one table per document. + */ + +typedef struct _xmlHashTable xmlRefTable; +typedef xmlRefTable *xmlRefTablePtr; + +/* Notation */ +XMLPUBFUN xmlNotationPtr XMLCALL + xmlAddNotationDecl (xmlValidCtxtPtr ctxt, + xmlDtdPtr dtd, + const xmlChar *name, + const xmlChar *PublicID, + const xmlChar *SystemID); +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN xmlNotationTablePtr XMLCALL + xmlCopyNotationTable (xmlNotationTablePtr table); +#endif /* LIBXML_TREE_ENABLED */ +XMLPUBFUN void XMLCALL + xmlFreeNotationTable (xmlNotationTablePtr table); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void XMLCALL + xmlDumpNotationDecl (xmlBufferPtr buf, + xmlNotationPtr nota); +XMLPUBFUN void XMLCALL + xmlDumpNotationTable (xmlBufferPtr buf, + xmlNotationTablePtr table); +#endif /* LIBXML_OUTPUT_ENABLED */ + +/* Element Content */ +/* the non Doc version are being deprecated */ +XMLPUBFUN xmlElementContentPtr XMLCALL + xmlNewElementContent (const xmlChar *name, + xmlElementContentType type); +XMLPUBFUN xmlElementContentPtr XMLCALL + xmlCopyElementContent (xmlElementContentPtr content); +XMLPUBFUN void XMLCALL + xmlFreeElementContent (xmlElementContentPtr cur); +/* the new versions with doc argument */ +XMLPUBFUN xmlElementContentPtr XMLCALL + xmlNewDocElementContent (xmlDocPtr doc, + const xmlChar *name, + xmlElementContentType type); +XMLPUBFUN xmlElementContentPtr XMLCALL + xmlCopyDocElementContent(xmlDocPtr doc, + xmlElementContentPtr content); +XMLPUBFUN void XMLCALL + xmlFreeDocElementContent(xmlDocPtr doc, + xmlElementContentPtr cur); +XMLPUBFUN void XMLCALL + xmlSnprintfElementContent(char *buf, + int size, + xmlElementContentPtr content, + int englob); +#ifdef LIBXML_OUTPUT_ENABLED +/* DEPRECATED */ +XMLPUBFUN void XMLCALL + xmlSprintfElementContent(char *buf, + xmlElementContentPtr content, + int englob); +#endif /* LIBXML_OUTPUT_ENABLED */ +/* DEPRECATED */ + +/* Element */ +XMLPUBFUN xmlElementPtr XMLCALL + xmlAddElementDecl (xmlValidCtxtPtr ctxt, + xmlDtdPtr dtd, + const xmlChar *name, + xmlElementTypeVal type, + xmlElementContentPtr content); +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN xmlElementTablePtr XMLCALL + xmlCopyElementTable (xmlElementTablePtr table); +#endif /* LIBXML_TREE_ENABLED */ +XMLPUBFUN void XMLCALL + xmlFreeElementTable (xmlElementTablePtr table); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void XMLCALL + xmlDumpElementTable (xmlBufferPtr buf, + xmlElementTablePtr table); +XMLPUBFUN void XMLCALL + xmlDumpElementDecl (xmlBufferPtr buf, + xmlElementPtr elem); +#endif /* LIBXML_OUTPUT_ENABLED */ + +/* Enumeration */ +XMLPUBFUN xmlEnumerationPtr XMLCALL + xmlCreateEnumeration (const xmlChar *name); +XMLPUBFUN void XMLCALL + xmlFreeEnumeration (xmlEnumerationPtr cur); +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN xmlEnumerationPtr XMLCALL + xmlCopyEnumeration (xmlEnumerationPtr cur); +#endif /* LIBXML_TREE_ENABLED */ + +/* Attribute */ +XMLPUBFUN xmlAttributePtr XMLCALL + xmlAddAttributeDecl (xmlValidCtxtPtr ctxt, + xmlDtdPtr dtd, + const xmlChar *elem, + const xmlChar *name, + const xmlChar *ns, + xmlAttributeType type, + xmlAttributeDefault def, + const xmlChar *defaultValue, + xmlEnumerationPtr tree); +#ifdef LIBXML_TREE_ENABLED +XMLPUBFUN xmlAttributeTablePtr XMLCALL + xmlCopyAttributeTable (xmlAttributeTablePtr table); +#endif /* LIBXML_TREE_ENABLED */ +XMLPUBFUN void XMLCALL + xmlFreeAttributeTable (xmlAttributeTablePtr table); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void XMLCALL + xmlDumpAttributeTable (xmlBufferPtr buf, + xmlAttributeTablePtr table); +XMLPUBFUN void XMLCALL + xmlDumpAttributeDecl (xmlBufferPtr buf, + xmlAttributePtr attr); +#endif /* LIBXML_OUTPUT_ENABLED */ + +/* IDs */ +XMLPUBFUN xmlIDPtr XMLCALL + xmlAddID (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + const xmlChar *value, + xmlAttrPtr attr); +XMLPUBFUN void XMLCALL + xmlFreeIDTable (xmlIDTablePtr table); +XMLPUBFUN xmlAttrPtr XMLCALL + xmlGetID (xmlDocPtr doc, + const xmlChar *ID); +XMLPUBFUN int XMLCALL + xmlIsID (xmlDocPtr doc, + xmlNodePtr elem, + xmlAttrPtr attr); +XMLPUBFUN int XMLCALL + xmlRemoveID (xmlDocPtr doc, + xmlAttrPtr attr); + +/* IDREFs */ +XMLPUBFUN xmlRefPtr XMLCALL + xmlAddRef (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + const xmlChar *value, + xmlAttrPtr attr); +XMLPUBFUN void XMLCALL + xmlFreeRefTable (xmlRefTablePtr table); +XMLPUBFUN int XMLCALL + xmlIsRef (xmlDocPtr doc, + xmlNodePtr elem, + xmlAttrPtr attr); +XMLPUBFUN int XMLCALL + xmlRemoveRef (xmlDocPtr doc, + xmlAttrPtr attr); +XMLPUBFUN xmlListPtr XMLCALL + xmlGetRefs (xmlDocPtr doc, + const xmlChar *ID); + +/** + * The public function calls related to validity checking. + */ +#ifdef LIBXML_VALID_ENABLED +/* Allocate/Release Validation Contexts */ +XMLPUBFUN xmlValidCtxtPtr XMLCALL + xmlNewValidCtxt(void); +XMLPUBFUN void XMLCALL + xmlFreeValidCtxt(xmlValidCtxtPtr); + +XMLPUBFUN int XMLCALL + xmlValidateRoot (xmlValidCtxtPtr ctxt, + xmlDocPtr doc); +XMLPUBFUN int XMLCALL + xmlValidateElementDecl (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlElementPtr elem); +XMLPUBFUN xmlChar * XMLCALL + xmlValidNormalizeAttributeValue(xmlDocPtr doc, + xmlNodePtr elem, + const xmlChar *name, + const xmlChar *value); +XMLPUBFUN xmlChar * XMLCALL + xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlNodePtr elem, + const xmlChar *name, + const xmlChar *value); +XMLPUBFUN int XMLCALL + xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlAttributePtr attr); +XMLPUBFUN int XMLCALL + xmlValidateAttributeValue(xmlAttributeType type, + const xmlChar *value); +XMLPUBFUN int XMLCALL + xmlValidateNotationDecl (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlNotationPtr nota); +XMLPUBFUN int XMLCALL + xmlValidateDtd (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlDtdPtr dtd); +XMLPUBFUN int XMLCALL + xmlValidateDtdFinal (xmlValidCtxtPtr ctxt, + xmlDocPtr doc); +XMLPUBFUN int XMLCALL + xmlValidateDocument (xmlValidCtxtPtr ctxt, + xmlDocPtr doc); +XMLPUBFUN int XMLCALL + xmlValidateElement (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlNodePtr elem); +XMLPUBFUN int XMLCALL + xmlValidateOneElement (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlNodePtr elem); +XMLPUBFUN int XMLCALL + xmlValidateOneAttribute (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlNodePtr elem, + xmlAttrPtr attr, + const xmlChar *value); +XMLPUBFUN int XMLCALL + xmlValidateOneNamespace (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlNodePtr elem, + const xmlChar *prefix, + xmlNsPtr ns, + const xmlChar *value); +XMLPUBFUN int XMLCALL + xmlValidateDocumentFinal(xmlValidCtxtPtr ctxt, + xmlDocPtr doc); +#endif /* LIBXML_VALID_ENABLED */ + +#if defined(LIBXML_VALID_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +XMLPUBFUN int XMLCALL + xmlValidateNotationUse (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + const xmlChar *notationName); +#endif /* LIBXML_VALID_ENABLED or LIBXML_SCHEMAS_ENABLED */ + +XMLPUBFUN int XMLCALL + xmlIsMixedElement (xmlDocPtr doc, + const xmlChar *name); +XMLPUBFUN xmlAttributePtr XMLCALL + xmlGetDtdAttrDesc (xmlDtdPtr dtd, + const xmlChar *elem, + const xmlChar *name); +XMLPUBFUN xmlAttributePtr XMLCALL + xmlGetDtdQAttrDesc (xmlDtdPtr dtd, + const xmlChar *elem, + const xmlChar *name, + const xmlChar *prefix); +XMLPUBFUN xmlNotationPtr XMLCALL + xmlGetDtdNotationDesc (xmlDtdPtr dtd, + const xmlChar *name); +XMLPUBFUN xmlElementPtr XMLCALL + xmlGetDtdQElementDesc (xmlDtdPtr dtd, + const xmlChar *name, + const xmlChar *prefix); +XMLPUBFUN xmlElementPtr XMLCALL + xmlGetDtdElementDesc (xmlDtdPtr dtd, + const xmlChar *name); + +#ifdef LIBXML_VALID_ENABLED + +XMLPUBFUN int XMLCALL + xmlValidGetPotentialChildren(xmlElementContent *ctree, + const xmlChar **list, + int *len, + int max); + +XMLPUBFUN int XMLCALL + xmlValidGetValidElements(xmlNode *prev, + xmlNode *next, + const xmlChar **names, + int max); +XMLPUBFUN int XMLCALL + xmlValidateNameValue (const xmlChar *value); +XMLPUBFUN int XMLCALL + xmlValidateNamesValue (const xmlChar *value); +XMLPUBFUN int XMLCALL + xmlValidateNmtokenValue (const xmlChar *value); +XMLPUBFUN int XMLCALL + xmlValidateNmtokensValue(const xmlChar *value); + +#ifdef LIBXML_REGEXP_ENABLED +/* + * Validation based on the regexp support + */ +XMLPUBFUN int XMLCALL + xmlValidBuildContentModel(xmlValidCtxtPtr ctxt, + xmlElementPtr elem); + +XMLPUBFUN int XMLCALL + xmlValidatePushElement (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlNodePtr elem, + const xmlChar *qname); +XMLPUBFUN int XMLCALL + xmlValidatePushCData (xmlValidCtxtPtr ctxt, + const xmlChar *data, + int len); +XMLPUBFUN int XMLCALL + xmlValidatePopElement (xmlValidCtxtPtr ctxt, + xmlDocPtr doc, + xmlNodePtr elem, + const xmlChar *qname); +#endif /* LIBXML_REGEXP_ENABLED */ +#endif /* LIBXML_VALID_ENABLED */ +#ifdef __cplusplus +} +#endif +#endif /* __XML_VALID_H__ */ diff --git a/include/libxml/xinclude.h b/include/libxml/xinclude.h new file mode 100644 index 0000000..4bb0aab --- /dev/null +++ b/include/libxml/xinclude.h @@ -0,0 +1,121 @@ +/* + * Summary: implementation of XInclude + * Description: API to handle XInclude processing, + * implements the + * World Wide Web Consortium Last Call Working Draft 10 November 2003 + * http://www.w3.org/TR/2003/WD-xinclude-20031110 + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_XINCLUDE_H__ +#define __XML_XINCLUDE_H__ + +#include +#include + +#ifdef LIBXML_XINCLUDE_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * XINCLUDE_NS: + * + * Macro defining the Xinclude namespace: http://www.w3.org/2003/XInclude + */ +#define XINCLUDE_NS (const xmlChar *) "http://www.w3.org/2003/XInclude" +/** + * XINCLUDE_OLD_NS: + * + * Macro defining the draft Xinclude namespace: http://www.w3.org/2001/XInclude + */ +#define XINCLUDE_OLD_NS (const xmlChar *) "http://www.w3.org/2001/XInclude" +/** + * XINCLUDE_NODE: + * + * Macro defining "include" + */ +#define XINCLUDE_NODE (const xmlChar *) "include" +/** + * XINCLUDE_FALLBACK: + * + * Macro defining "fallback" + */ +#define XINCLUDE_FALLBACK (const xmlChar *) "fallback" +/** + * XINCLUDE_HREF: + * + * Macro defining "href" + */ +#define XINCLUDE_HREF (const xmlChar *) "href" +/** + * XINCLUDE_PARSE: + * + * Macro defining "parse" + */ +#define XINCLUDE_PARSE (const xmlChar *) "parse" +/** + * XINCLUDE_PARSE_XML: + * + * Macro defining "xml" + */ +#define XINCLUDE_PARSE_XML (const xmlChar *) "xml" +/** + * XINCLUDE_PARSE_TEXT: + * + * Macro defining "text" + */ +#define XINCLUDE_PARSE_TEXT (const xmlChar *) "text" +/** + * XINCLUDE_PARSE_ENCODING: + * + * Macro defining "encoding" + */ +#define XINCLUDE_PARSE_ENCODING (const xmlChar *) "encoding" +/** + * XINCLUDE_PARSE_XPOINTER: + * + * Macro defining "xpointer" + */ +#define XINCLUDE_PARSE_XPOINTER (const xmlChar *) "xpointer" + +typedef struct _xmlXIncludeCtxt xmlXIncludeCtxt; +typedef xmlXIncludeCtxt *xmlXIncludeCtxtPtr; + +/* + * standalone processing + */ +XMLPUBFUN int XMLCALL + xmlXIncludeProcess (xmlDocPtr doc); +XMLPUBFUN int XMLCALL + xmlXIncludeProcessFlags (xmlDocPtr doc, + int flags); +XMLPUBFUN int XMLCALL + xmlXIncludeProcessTree (xmlNodePtr tree); +XMLPUBFUN int XMLCALL + xmlXIncludeProcessTreeFlags(xmlNodePtr tree, + int flags); +/* + * contextual processing + */ +XMLPUBFUN xmlXIncludeCtxtPtr XMLCALL + xmlXIncludeNewContext (xmlDocPtr doc); +XMLPUBFUN int XMLCALL + xmlXIncludeSetFlags (xmlXIncludeCtxtPtr ctxt, + int flags); +XMLPUBFUN void XMLCALL + xmlXIncludeFreeContext (xmlXIncludeCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + xmlXIncludeProcessNode (xmlXIncludeCtxtPtr ctxt, + xmlNodePtr tree); +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_XINCLUDE_ENABLED */ + +#endif /* __XML_XINCLUDE_H__ */ diff --git a/include/libxml/xlink.h b/include/libxml/xlink.h new file mode 100644 index 0000000..083c7ed --- /dev/null +++ b/include/libxml/xlink.h @@ -0,0 +1,189 @@ +/* + * Summary: unfinished XLink detection module + * Description: unfinished XLink detection module + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_XLINK_H__ +#define __XML_XLINK_H__ + +#include +#include + +#ifdef LIBXML_XPTR_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Various defines for the various Link properties. + * + * NOTE: the link detection layer will try to resolve QName expansion + * of namespaces. If "foo" is the prefix for "http://foo.com/" + * then the link detection layer will expand role="foo:myrole" + * to "http://foo.com/:myrole". + * NOTE: the link detection layer will expand URI-Refences found on + * href attributes by using the base mechanism if found. + */ +typedef xmlChar *xlinkHRef; +typedef xmlChar *xlinkRole; +typedef xmlChar *xlinkTitle; + +typedef enum { + XLINK_TYPE_NONE = 0, + XLINK_TYPE_SIMPLE, + XLINK_TYPE_EXTENDED, + XLINK_TYPE_EXTENDED_SET +} xlinkType; + +typedef enum { + XLINK_SHOW_NONE = 0, + XLINK_SHOW_NEW, + XLINK_SHOW_EMBED, + XLINK_SHOW_REPLACE +} xlinkShow; + +typedef enum { + XLINK_ACTUATE_NONE = 0, + XLINK_ACTUATE_AUTO, + XLINK_ACTUATE_ONREQUEST +} xlinkActuate; + +/** + * xlinkNodeDetectFunc: + * @ctx: user data pointer + * @node: the node to check + * + * This is the prototype for the link detection routine. + * It calls the default link detection callbacks upon link detection. + */ +typedef void (*xlinkNodeDetectFunc) (void *ctx, xmlNodePtr node); + +/* + * The link detection module interact with the upper layers using + * a set of callback registered at parsing time. + */ + +/** + * xlinkSimpleLinkFunk: + * @ctx: user data pointer + * @node: the node carrying the link + * @href: the target of the link + * @role: the role string + * @title: the link title + * + * This is the prototype for a simple link detection callback. + */ +typedef void +(*xlinkSimpleLinkFunk) (void *ctx, + xmlNodePtr node, + const xlinkHRef href, + const xlinkRole role, + const xlinkTitle title); + +/** + * xlinkExtendedLinkFunk: + * @ctx: user data pointer + * @node: the node carrying the link + * @nbLocators: the number of locators detected on the link + * @hrefs: pointer to the array of locator hrefs + * @roles: pointer to the array of locator roles + * @nbArcs: the number of arcs detected on the link + * @from: pointer to the array of source roles found on the arcs + * @to: pointer to the array of target roles found on the arcs + * @show: array of values for the show attributes found on the arcs + * @actuate: array of values for the actuate attributes found on the arcs + * @nbTitles: the number of titles detected on the link + * @title: array of titles detected on the link + * @langs: array of xml:lang values for the titles + * + * This is the prototype for a extended link detection callback. + */ +typedef void +(*xlinkExtendedLinkFunk)(void *ctx, + xmlNodePtr node, + int nbLocators, + const xlinkHRef *hrefs, + const xlinkRole *roles, + int nbArcs, + const xlinkRole *from, + const xlinkRole *to, + xlinkShow *show, + xlinkActuate *actuate, + int nbTitles, + const xlinkTitle *titles, + const xmlChar **langs); + +/** + * xlinkExtendedLinkSetFunk: + * @ctx: user data pointer + * @node: the node carrying the link + * @nbLocators: the number of locators detected on the link + * @hrefs: pointer to the array of locator hrefs + * @roles: pointer to the array of locator roles + * @nbTitles: the number of titles detected on the link + * @title: array of titles detected on the link + * @langs: array of xml:lang values for the titles + * + * This is the prototype for a extended link set detection callback. + */ +typedef void +(*xlinkExtendedLinkSetFunk) (void *ctx, + xmlNodePtr node, + int nbLocators, + const xlinkHRef *hrefs, + const xlinkRole *roles, + int nbTitles, + const xlinkTitle *titles, + const xmlChar **langs); + +/** + * This is the structure containing a set of Links detection callbacks. + * + * There is no default xlink callbacks, if one want to get link + * recognition activated, those call backs must be provided before parsing. + */ +typedef struct _xlinkHandler xlinkHandler; +typedef xlinkHandler *xlinkHandlerPtr; +struct _xlinkHandler { + xlinkSimpleLinkFunk simple; + xlinkExtendedLinkFunk extended; + xlinkExtendedLinkSetFunk set; +}; + +/* + * The default detection routine, can be overridden, they call the default + * detection callbacks. + */ + +XMLPUBFUN xlinkNodeDetectFunc XMLCALL + xlinkGetDefaultDetect (void); +XMLPUBFUN void XMLCALL + xlinkSetDefaultDetect (xlinkNodeDetectFunc func); + +/* + * Routines to set/get the default handlers. + */ +XMLPUBFUN xlinkHandlerPtr XMLCALL + xlinkGetDefaultHandler (void); +XMLPUBFUN void XMLCALL + xlinkSetDefaultHandler (xlinkHandlerPtr handler); + +/* + * Link detection module itself. + */ +XMLPUBFUN xlinkType XMLCALL + xlinkIsLink (xmlDocPtr doc, + xmlNodePtr node); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_XPTR_ENABLED */ + +#endif /* __XML_XLINK_H__ */ diff --git a/include/libxml/xmlIO.h b/include/libxml/xmlIO.h new file mode 100644 index 0000000..0f7b8a8 --- /dev/null +++ b/include/libxml/xmlIO.h @@ -0,0 +1,356 @@ +/* + * Summary: interface for the I/O interfaces used by the parser + * Description: interface for the I/O interfaces used by the parser + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_IO_H__ +#define __XML_IO_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Those are the functions and datatypes for the parser input + * I/O structures. + */ + +/** + * xmlInputMatchCallback: + * @filename: the filename or URI + * + * Callback used in the I/O Input API to detect if the current handler + * can provide input fonctionnalities for this resource. + * + * Returns 1 if yes and 0 if another Input module should be used + */ +typedef int (*xmlInputMatchCallback) (char const *filename); +/** + * xmlInputOpenCallback: + * @filename: the filename or URI + * + * Callback used in the I/O Input API to open the resource + * + * Returns an Input context or NULL in case or error + */ +typedef void * (*xmlInputOpenCallback) (char const *filename); +/** + * xmlInputReadCallback: + * @context: an Input context + * @buffer: the buffer to store data read + * @len: the length of the buffer in bytes + * + * Callback used in the I/O Input API to read the resource + * + * Returns the number of bytes read or -1 in case of error + */ +typedef int (*xmlInputReadCallback) (void * context, char * buffer, int len); +/** + * xmlInputCloseCallback: + * @context: an Input context + * + * Callback used in the I/O Input API to close the resource + * + * Returns 0 or -1 in case of error + */ +typedef int (*xmlInputCloseCallback) (void * context); + +#ifdef LIBXML_OUTPUT_ENABLED +/* + * Those are the functions and datatypes for the library output + * I/O structures. + */ + +/** + * xmlOutputMatchCallback: + * @filename: the filename or URI + * + * Callback used in the I/O Output API to detect if the current handler + * can provide output fonctionnalities for this resource. + * + * Returns 1 if yes and 0 if another Output module should be used + */ +typedef int (*xmlOutputMatchCallback) (char const *filename); +/** + * xmlOutputOpenCallback: + * @filename: the filename or URI + * + * Callback used in the I/O Output API to open the resource + * + * Returns an Output context or NULL in case or error + */ +typedef void * (*xmlOutputOpenCallback) (char const *filename); +/** + * xmlOutputWriteCallback: + * @context: an Output context + * @buffer: the buffer of data to write + * @len: the length of the buffer in bytes + * + * Callback used in the I/O Output API to write to the resource + * + * Returns the number of bytes written or -1 in case of error + */ +typedef int (*xmlOutputWriteCallback) (void * context, const char * buffer, + int len); +/** + * xmlOutputCloseCallback: + * @context: an Output context + * + * Callback used in the I/O Output API to close the resource + * + * Returns 0 or -1 in case of error + */ +typedef int (*xmlOutputCloseCallback) (void * context); +#endif /* LIBXML_OUTPUT_ENABLED */ + +#ifdef __cplusplus +} +#endif + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +struct _xmlParserInputBuffer { + void* context; + xmlInputReadCallback readcallback; + xmlInputCloseCallback closecallback; + + xmlCharEncodingHandlerPtr encoder; /* I18N conversions to UTF-8 */ + + xmlBufferPtr buffer; /* Local buffer encoded in UTF-8 */ + xmlBufferPtr raw; /* if encoder != NULL buffer for raw input */ + int compressed; /* -1=unknown, 0=not compressed, 1=compressed */ + int error; + unsigned long rawconsumed;/* amount consumed from raw */ +}; + + +#ifdef LIBXML_OUTPUT_ENABLED +struct _xmlOutputBuffer { + void* context; + xmlOutputWriteCallback writecallback; + xmlOutputCloseCallback closecallback; + + xmlCharEncodingHandlerPtr encoder; /* I18N conversions to UTF-8 */ + + xmlBufferPtr buffer; /* Local buffer encoded in UTF-8 or ISOLatin */ + xmlBufferPtr conv; /* if encoder != NULL buffer for output */ + int written; /* total number of byte written */ + int error; +}; +#endif /* LIBXML_OUTPUT_ENABLED */ + +/* + * Interfaces for input + */ +XMLPUBFUN void XMLCALL + xmlCleanupInputCallbacks (void); + +XMLPUBFUN int XMLCALL + xmlPopInputCallbacks (void); + +XMLPUBFUN void XMLCALL + xmlRegisterDefaultInputCallbacks (void); +XMLPUBFUN xmlParserInputBufferPtr XMLCALL + xmlAllocParserInputBuffer (xmlCharEncoding enc); + +XMLPUBFUN xmlParserInputBufferPtr XMLCALL + xmlParserInputBufferCreateFilename (const char *URI, + xmlCharEncoding enc); +XMLPUBFUN xmlParserInputBufferPtr XMLCALL + xmlParserInputBufferCreateFile (FILE *file, + xmlCharEncoding enc); +XMLPUBFUN xmlParserInputBufferPtr XMLCALL + xmlParserInputBufferCreateFd (int fd, + xmlCharEncoding enc); +XMLPUBFUN xmlParserInputBufferPtr XMLCALL + xmlParserInputBufferCreateMem (const char *mem, int size, + xmlCharEncoding enc); +XMLPUBFUN xmlParserInputBufferPtr XMLCALL + xmlParserInputBufferCreateStatic (const char *mem, int size, + xmlCharEncoding enc); +XMLPUBFUN xmlParserInputBufferPtr XMLCALL + xmlParserInputBufferCreateIO (xmlInputReadCallback ioread, + xmlInputCloseCallback ioclose, + void *ioctx, + xmlCharEncoding enc); +XMLPUBFUN int XMLCALL + xmlParserInputBufferRead (xmlParserInputBufferPtr in, + int len); +XMLPUBFUN int XMLCALL + xmlParserInputBufferGrow (xmlParserInputBufferPtr in, + int len); +XMLPUBFUN int XMLCALL + xmlParserInputBufferPush (xmlParserInputBufferPtr in, + int len, + const char *buf); +XMLPUBFUN void XMLCALL + xmlFreeParserInputBuffer (xmlParserInputBufferPtr in); +XMLPUBFUN char * XMLCALL + xmlParserGetDirectory (const char *filename); + +XMLPUBFUN int XMLCALL + xmlRegisterInputCallbacks (xmlInputMatchCallback matchFunc, + xmlInputOpenCallback openFunc, + xmlInputReadCallback readFunc, + xmlInputCloseCallback closeFunc); + +xmlParserInputBufferPtr + __xmlParserInputBufferCreateFilename(const char *URI, + xmlCharEncoding enc); + +#ifdef LIBXML_OUTPUT_ENABLED +/* + * Interfaces for output + */ +XMLPUBFUN void XMLCALL + xmlCleanupOutputCallbacks (void); +XMLPUBFUN void XMLCALL + xmlRegisterDefaultOutputCallbacks(void); +XMLPUBFUN xmlOutputBufferPtr XMLCALL + xmlAllocOutputBuffer (xmlCharEncodingHandlerPtr encoder); + +XMLPUBFUN xmlOutputBufferPtr XMLCALL + xmlOutputBufferCreateFilename (const char *URI, + xmlCharEncodingHandlerPtr encoder, + int compression); + +XMLPUBFUN xmlOutputBufferPtr XMLCALL + xmlOutputBufferCreateFile (FILE *file, + xmlCharEncodingHandlerPtr encoder); + +XMLPUBFUN xmlOutputBufferPtr XMLCALL + xmlOutputBufferCreateFd (int fd, + xmlCharEncodingHandlerPtr encoder); + +XMLPUBFUN xmlOutputBufferPtr XMLCALL + xmlOutputBufferCreateIO (xmlOutputWriteCallback iowrite, + xmlOutputCloseCallback ioclose, + void *ioctx, + xmlCharEncodingHandlerPtr encoder); + +XMLPUBFUN int XMLCALL + xmlOutputBufferWrite (xmlOutputBufferPtr out, + int len, + const char *buf); +XMLPUBFUN int XMLCALL + xmlOutputBufferWriteString (xmlOutputBufferPtr out, + const char *str); +XMLPUBFUN int XMLCALL + xmlOutputBufferWriteEscape (xmlOutputBufferPtr out, + const xmlChar *str, + xmlCharEncodingOutputFunc escaping); + +XMLPUBFUN int XMLCALL + xmlOutputBufferFlush (xmlOutputBufferPtr out); +XMLPUBFUN int XMLCALL + xmlOutputBufferClose (xmlOutputBufferPtr out); + +XMLPUBFUN int XMLCALL + xmlRegisterOutputCallbacks (xmlOutputMatchCallback matchFunc, + xmlOutputOpenCallback openFunc, + xmlOutputWriteCallback writeFunc, + xmlOutputCloseCallback closeFunc); + +xmlOutputBufferPtr + __xmlOutputBufferCreateFilename(const char *URI, + xmlCharEncodingHandlerPtr encoder, + int compression); + +#ifdef LIBXML_HTTP_ENABLED +/* This function only exists if HTTP support built into the library */ +XMLPUBFUN void XMLCALL + xmlRegisterHTTPPostCallbacks (void ); +#endif /* LIBXML_HTTP_ENABLED */ + +#endif /* LIBXML_OUTPUT_ENABLED */ + +XMLPUBFUN xmlParserInputPtr XMLCALL + xmlCheckHTTPInput (xmlParserCtxtPtr ctxt, + xmlParserInputPtr ret); + +/* + * A predefined entity loader disabling network accesses + */ +XMLPUBFUN xmlParserInputPtr XMLCALL + xmlNoNetExternalEntityLoader (const char *URL, + const char *ID, + xmlParserCtxtPtr ctxt); + +/* + * xmlNormalizeWindowsPath is obsolete, don't use it. + * Check xmlCanonicPath in uri.h for a better alternative. + */ +XMLPUBFUN xmlChar * XMLCALL + xmlNormalizeWindowsPath (const xmlChar *path); + +XMLPUBFUN int XMLCALL + xmlCheckFilename (const char *path); +/** + * Default 'file://' protocol callbacks + */ +XMLPUBFUN int XMLCALL + xmlFileMatch (const char *filename); +XMLPUBFUN void * XMLCALL + xmlFileOpen (const char *filename); +XMLPUBFUN int XMLCALL + xmlFileRead (void * context, + char * buffer, + int len); +XMLPUBFUN int XMLCALL + xmlFileClose (void * context); + +/** + * Default 'http://' protocol callbacks + */ +#ifdef LIBXML_HTTP_ENABLED +XMLPUBFUN int XMLCALL + xmlIOHTTPMatch (const char *filename); +XMLPUBFUN void * XMLCALL + xmlIOHTTPOpen (const char *filename); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void * XMLCALL + xmlIOHTTPOpenW (const char * post_uri, + int compression ); +#endif /* LIBXML_OUTPUT_ENABLED */ +XMLPUBFUN int XMLCALL + xmlIOHTTPRead (void * context, + char * buffer, + int len); +XMLPUBFUN int XMLCALL + xmlIOHTTPClose (void * context); +#endif /* LIBXML_HTTP_ENABLED */ + +/** + * Default 'ftp://' protocol callbacks + */ +#ifdef LIBXML_FTP_ENABLED +XMLPUBFUN int XMLCALL + xmlIOFTPMatch (const char *filename); +XMLPUBFUN void * XMLCALL + xmlIOFTPOpen (const char *filename); +XMLPUBFUN int XMLCALL + xmlIOFTPRead (void * context, + char * buffer, + int len); +XMLPUBFUN int XMLCALL + xmlIOFTPClose (void * context); +#endif /* LIBXML_FTP_ENABLED */ + +#ifdef __cplusplus +} +#endif + +#endif /* __XML_IO_H__ */ diff --git a/include/libxml/xmlautomata.h b/include/libxml/xmlautomata.h new file mode 100644 index 0000000..d29ddcf --- /dev/null +++ b/include/libxml/xmlautomata.h @@ -0,0 +1,138 @@ +/* + * Summary: API to build regexp automata + * Description: the API to build regexp automata + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_AUTOMATA_H__ +#define __XML_AUTOMATA_H__ + +#include +#include + +#ifdef LIBXML_REGEXP_ENABLED +#ifdef LIBXML_AUTOMATA_ENABLED +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * xmlAutomataPtr: + * + * A libxml automata description, It can be compiled into a regexp + */ +typedef struct _xmlAutomata xmlAutomata; +typedef xmlAutomata *xmlAutomataPtr; + +/** + * xmlAutomataStatePtr: + * + * A state int the automata description, + */ +typedef struct _xmlAutomataState xmlAutomataState; +typedef xmlAutomataState *xmlAutomataStatePtr; + +/* + * Building API + */ +XMLPUBFUN xmlAutomataPtr XMLCALL + xmlNewAutomata (void); +XMLPUBFUN void XMLCALL + xmlFreeAutomata (xmlAutomataPtr am); + +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataGetInitState (xmlAutomataPtr am); +XMLPUBFUN int XMLCALL + xmlAutomataSetFinalState (xmlAutomataPtr am, + xmlAutomataStatePtr state); +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewState (xmlAutomataPtr am); +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewTransition (xmlAutomataPtr am, + xmlAutomataStatePtr from, + xmlAutomataStatePtr to, + const xmlChar *token, + void *data); +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewTransition2 (xmlAutomataPtr am, + xmlAutomataStatePtr from, + xmlAutomataStatePtr to, + const xmlChar *token, + const xmlChar *token2, + void *data); +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewCountTrans (xmlAutomataPtr am, + xmlAutomataStatePtr from, + xmlAutomataStatePtr to, + const xmlChar *token, + int min, + int max, + void *data); +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewCountTrans2 (xmlAutomataPtr am, + xmlAutomataStatePtr from, + xmlAutomataStatePtr to, + const xmlChar *token, + const xmlChar *token2, + int min, + int max, + void *data); +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewOnceTrans (xmlAutomataPtr am, + xmlAutomataStatePtr from, + xmlAutomataStatePtr to, + const xmlChar *token, + int min, + int max, + void *data); +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewOnceTrans2 (xmlAutomataPtr am, + xmlAutomataStatePtr from, + xmlAutomataStatePtr to, + const xmlChar *token, + const xmlChar *token2, + int min, + int max, + void *data); +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewAllTrans (xmlAutomataPtr am, + xmlAutomataStatePtr from, + xmlAutomataStatePtr to, + int lax); +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewEpsilon (xmlAutomataPtr am, + xmlAutomataStatePtr from, + xmlAutomataStatePtr to); +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewCountedTrans (xmlAutomataPtr am, + xmlAutomataStatePtr from, + xmlAutomataStatePtr to, + int counter); +XMLPUBFUN xmlAutomataStatePtr XMLCALL + xmlAutomataNewCounterTrans (xmlAutomataPtr am, + xmlAutomataStatePtr from, + xmlAutomataStatePtr to, + int counter); +XMLPUBFUN int XMLCALL + xmlAutomataNewCounter (xmlAutomataPtr am, + int min, + int max); + +XMLPUBFUN xmlRegexpPtr XMLCALL + xmlAutomataCompile (xmlAutomataPtr am); +XMLPUBFUN int XMLCALL + xmlAutomataIsDeterminist (xmlAutomataPtr am); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_AUTOMATA_ENABLED */ +#endif /* LIBXML_REGEXP_ENABLED */ + +#endif /* __XML_AUTOMATA_H__ */ diff --git a/include/libxml/xmlerror.h b/include/libxml/xmlerror.h new file mode 100644 index 0000000..04da1a6 --- /dev/null +++ b/include/libxml/xmlerror.h @@ -0,0 +1,918 @@ +/* + * Summary: error handling + * Description: the API used to report errors + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#include + +#ifndef __XML_ERROR_H__ +#define __XML_ERROR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * xmlErrorLevel: + * + * Indicates the level of an error + */ +typedef enum { + XML_ERR_NONE = 0, + XML_ERR_WARNING = 1, /* A simple warning */ + XML_ERR_ERROR = 2, /* A recoverable error */ + XML_ERR_FATAL = 3 /* A fatal error */ +} xmlErrorLevel; + +/** + * xmlErrorDomain: + * + * Indicates where an error may have come from + */ +typedef enum { + XML_FROM_NONE = 0, + XML_FROM_PARSER, /* The XML parser */ + XML_FROM_TREE, /* The tree module */ + XML_FROM_NAMESPACE, /* The XML Namespace module */ + XML_FROM_DTD, /* The XML DTD validation with parser context*/ + XML_FROM_HTML, /* The HTML parser */ + XML_FROM_MEMORY, /* The memory allocator */ + XML_FROM_OUTPUT, /* The serialization code */ + XML_FROM_IO, /* The Input/Output stack */ + XML_FROM_FTP, /* The FTP module */ + XML_FROM_HTTP, /* The HTTP module */ + XML_FROM_XINCLUDE, /* The XInclude processing */ + XML_FROM_XPATH, /* The XPath module */ + XML_FROM_XPOINTER, /* The XPointer module */ + XML_FROM_REGEXP, /* The regular expressions module */ + XML_FROM_DATATYPE, /* The W3C XML Schemas Datatype module */ + XML_FROM_SCHEMASP, /* The W3C XML Schemas parser module */ + XML_FROM_SCHEMASV, /* The W3C XML Schemas validation module */ + XML_FROM_RELAXNGP, /* The Relax-NG parser module */ + XML_FROM_RELAXNGV, /* The Relax-NG validator module */ + XML_FROM_CATALOG, /* The Catalog module */ + XML_FROM_C14N, /* The Canonicalization module */ + XML_FROM_XSLT, /* The XSLT engine from libxslt */ + XML_FROM_VALID, /* The XML DTD validation with valid context */ + XML_FROM_CHECK, /* The error checking module */ + XML_FROM_WRITER, /* The xmlwriter module */ + XML_FROM_MODULE /* The dynamically loaded module module*/ +} xmlErrorDomain; + +/** + * xmlError: + * + * An XML Error instance. + */ + +typedef struct _xmlError xmlError; +typedef xmlError *xmlErrorPtr; +struct _xmlError { + int domain; /* What part of the library raised this error */ + int code; /* The error code, e.g. an xmlParserError */ + char *message;/* human-readable informative error message */ + xmlErrorLevel level;/* how consequent is the error */ + char *file; /* the filename */ + int line; /* the line number if available */ + char *str1; /* extra string information */ + char *str2; /* extra string information */ + char *str3; /* extra string information */ + int int1; /* extra number information */ + int int2; /* column number of the error or 0 if N/A (todo: rename this field when we would break ABI) */ + void *ctxt; /* the parser context if available */ + void *node; /* the node in the tree */ +}; + +/** + * xmlParserError: + * + * This is an error that the XML (or HTML) parser can generate + */ +typedef enum { + XML_ERR_OK = 0, + XML_ERR_INTERNAL_ERROR, /* 1 */ + XML_ERR_NO_MEMORY, /* 2 */ + XML_ERR_DOCUMENT_START, /* 3 */ + XML_ERR_DOCUMENT_EMPTY, /* 4 */ + XML_ERR_DOCUMENT_END, /* 5 */ + XML_ERR_INVALID_HEX_CHARREF, /* 6 */ + XML_ERR_INVALID_DEC_CHARREF, /* 7 */ + XML_ERR_INVALID_CHARREF, /* 8 */ + XML_ERR_INVALID_CHAR, /* 9 */ + XML_ERR_CHARREF_AT_EOF, /* 10 */ + XML_ERR_CHARREF_IN_PROLOG, /* 11 */ + XML_ERR_CHARREF_IN_EPILOG, /* 12 */ + XML_ERR_CHARREF_IN_DTD, /* 13 */ + XML_ERR_ENTITYREF_AT_EOF, /* 14 */ + XML_ERR_ENTITYREF_IN_PROLOG, /* 15 */ + XML_ERR_ENTITYREF_IN_EPILOG, /* 16 */ + XML_ERR_ENTITYREF_IN_DTD, /* 17 */ + XML_ERR_PEREF_AT_EOF, /* 18 */ + XML_ERR_PEREF_IN_PROLOG, /* 19 */ + XML_ERR_PEREF_IN_EPILOG, /* 20 */ + XML_ERR_PEREF_IN_INT_SUBSET, /* 21 */ + XML_ERR_ENTITYREF_NO_NAME, /* 22 */ + XML_ERR_ENTITYREF_SEMICOL_MISSING, /* 23 */ + XML_ERR_PEREF_NO_NAME, /* 24 */ + XML_ERR_PEREF_SEMICOL_MISSING, /* 25 */ + XML_ERR_UNDECLARED_ENTITY, /* 26 */ + XML_WAR_UNDECLARED_ENTITY, /* 27 */ + XML_ERR_UNPARSED_ENTITY, /* 28 */ + XML_ERR_ENTITY_IS_EXTERNAL, /* 29 */ + XML_ERR_ENTITY_IS_PARAMETER, /* 30 */ + XML_ERR_UNKNOWN_ENCODING, /* 31 */ + XML_ERR_UNSUPPORTED_ENCODING, /* 32 */ + XML_ERR_STRING_NOT_STARTED, /* 33 */ + XML_ERR_STRING_NOT_CLOSED, /* 34 */ + XML_ERR_NS_DECL_ERROR, /* 35 */ + XML_ERR_ENTITY_NOT_STARTED, /* 36 */ + XML_ERR_ENTITY_NOT_FINISHED, /* 37 */ + XML_ERR_LT_IN_ATTRIBUTE, /* 38 */ + XML_ERR_ATTRIBUTE_NOT_STARTED, /* 39 */ + XML_ERR_ATTRIBUTE_NOT_FINISHED, /* 40 */ + XML_ERR_ATTRIBUTE_WITHOUT_VALUE, /* 41 */ + XML_ERR_ATTRIBUTE_REDEFINED, /* 42 */ + XML_ERR_LITERAL_NOT_STARTED, /* 43 */ + XML_ERR_LITERAL_NOT_FINISHED, /* 44 */ + XML_ERR_COMMENT_NOT_FINISHED, /* 45 */ + XML_ERR_PI_NOT_STARTED, /* 46 */ + XML_ERR_PI_NOT_FINISHED, /* 47 */ + XML_ERR_NOTATION_NOT_STARTED, /* 48 */ + XML_ERR_NOTATION_NOT_FINISHED, /* 49 */ + XML_ERR_ATTLIST_NOT_STARTED, /* 50 */ + XML_ERR_ATTLIST_NOT_FINISHED, /* 51 */ + XML_ERR_MIXED_NOT_STARTED, /* 52 */ + XML_ERR_MIXED_NOT_FINISHED, /* 53 */ + XML_ERR_ELEMCONTENT_NOT_STARTED, /* 54 */ + XML_ERR_ELEMCONTENT_NOT_FINISHED, /* 55 */ + XML_ERR_XMLDECL_NOT_STARTED, /* 56 */ + XML_ERR_XMLDECL_NOT_FINISHED, /* 57 */ + XML_ERR_CONDSEC_NOT_STARTED, /* 58 */ + XML_ERR_CONDSEC_NOT_FINISHED, /* 59 */ + XML_ERR_EXT_SUBSET_NOT_FINISHED, /* 60 */ + XML_ERR_DOCTYPE_NOT_FINISHED, /* 61 */ + XML_ERR_MISPLACED_CDATA_END, /* 62 */ + XML_ERR_CDATA_NOT_FINISHED, /* 63 */ + XML_ERR_RESERVED_XML_NAME, /* 64 */ + XML_ERR_SPACE_REQUIRED, /* 65 */ + XML_ERR_SEPARATOR_REQUIRED, /* 66 */ + XML_ERR_NMTOKEN_REQUIRED, /* 67 */ + XML_ERR_NAME_REQUIRED, /* 68 */ + XML_ERR_PCDATA_REQUIRED, /* 69 */ + XML_ERR_URI_REQUIRED, /* 70 */ + XML_ERR_PUBID_REQUIRED, /* 71 */ + XML_ERR_LT_REQUIRED, /* 72 */ + XML_ERR_GT_REQUIRED, /* 73 */ + XML_ERR_LTSLASH_REQUIRED, /* 74 */ + XML_ERR_EQUAL_REQUIRED, /* 75 */ + XML_ERR_TAG_NAME_MISMATCH, /* 76 */ + XML_ERR_TAG_NOT_FINISHED, /* 77 */ + XML_ERR_STANDALONE_VALUE, /* 78 */ + XML_ERR_ENCODING_NAME, /* 79 */ + XML_ERR_HYPHEN_IN_COMMENT, /* 80 */ + XML_ERR_INVALID_ENCODING, /* 81 */ + XML_ERR_EXT_ENTITY_STANDALONE, /* 82 */ + XML_ERR_CONDSEC_INVALID, /* 83 */ + XML_ERR_VALUE_REQUIRED, /* 84 */ + XML_ERR_NOT_WELL_BALANCED, /* 85 */ + XML_ERR_EXTRA_CONTENT, /* 86 */ + XML_ERR_ENTITY_CHAR_ERROR, /* 87 */ + XML_ERR_ENTITY_PE_INTERNAL, /* 88 */ + XML_ERR_ENTITY_LOOP, /* 89 */ + XML_ERR_ENTITY_BOUNDARY, /* 90 */ + XML_ERR_INVALID_URI, /* 91 */ + XML_ERR_URI_FRAGMENT, /* 92 */ + XML_WAR_CATALOG_PI, /* 93 */ + XML_ERR_NO_DTD, /* 94 */ + XML_ERR_CONDSEC_INVALID_KEYWORD, /* 95 */ + XML_ERR_VERSION_MISSING, /* 96 */ + XML_WAR_UNKNOWN_VERSION, /* 97 */ + XML_WAR_LANG_VALUE, /* 98 */ + XML_WAR_NS_URI, /* 99 */ + XML_WAR_NS_URI_RELATIVE, /* 100 */ + XML_ERR_MISSING_ENCODING, /* 101 */ + XML_WAR_SPACE_VALUE, /* 102 */ + XML_ERR_NOT_STANDALONE, /* 103 */ + XML_ERR_ENTITY_PROCESSING, /* 104 */ + XML_ERR_NOTATION_PROCESSING, /* 105 */ + XML_WAR_NS_COLUMN, /* 106 */ + XML_WAR_ENTITY_REDEFINED, /* 107 */ + XML_NS_ERR_XML_NAMESPACE = 200, + XML_NS_ERR_UNDEFINED_NAMESPACE, /* 201 */ + XML_NS_ERR_QNAME, /* 202 */ + XML_NS_ERR_ATTRIBUTE_REDEFINED, /* 203 */ + XML_NS_ERR_EMPTY, /* 204 */ + XML_DTD_ATTRIBUTE_DEFAULT = 500, + XML_DTD_ATTRIBUTE_REDEFINED, /* 501 */ + XML_DTD_ATTRIBUTE_VALUE, /* 502 */ + XML_DTD_CONTENT_ERROR, /* 503 */ + XML_DTD_CONTENT_MODEL, /* 504 */ + XML_DTD_CONTENT_NOT_DETERMINIST, /* 505 */ + XML_DTD_DIFFERENT_PREFIX, /* 506 */ + XML_DTD_ELEM_DEFAULT_NAMESPACE, /* 507 */ + XML_DTD_ELEM_NAMESPACE, /* 508 */ + XML_DTD_ELEM_REDEFINED, /* 509 */ + XML_DTD_EMPTY_NOTATION, /* 510 */ + XML_DTD_ENTITY_TYPE, /* 511 */ + XML_DTD_ID_FIXED, /* 512 */ + XML_DTD_ID_REDEFINED, /* 513 */ + XML_DTD_ID_SUBSET, /* 514 */ + XML_DTD_INVALID_CHILD, /* 515 */ + XML_DTD_INVALID_DEFAULT, /* 516 */ + XML_DTD_LOAD_ERROR, /* 517 */ + XML_DTD_MISSING_ATTRIBUTE, /* 518 */ + XML_DTD_MIXED_CORRUPT, /* 519 */ + XML_DTD_MULTIPLE_ID, /* 520 */ + XML_DTD_NO_DOC, /* 521 */ + XML_DTD_NO_DTD, /* 522 */ + XML_DTD_NO_ELEM_NAME, /* 523 */ + XML_DTD_NO_PREFIX, /* 524 */ + XML_DTD_NO_ROOT, /* 525 */ + XML_DTD_NOTATION_REDEFINED, /* 526 */ + XML_DTD_NOTATION_VALUE, /* 527 */ + XML_DTD_NOT_EMPTY, /* 528 */ + XML_DTD_NOT_PCDATA, /* 529 */ + XML_DTD_NOT_STANDALONE, /* 530 */ + XML_DTD_ROOT_NAME, /* 531 */ + XML_DTD_STANDALONE_WHITE_SPACE, /* 532 */ + XML_DTD_UNKNOWN_ATTRIBUTE, /* 533 */ + XML_DTD_UNKNOWN_ELEM, /* 534 */ + XML_DTD_UNKNOWN_ENTITY, /* 535 */ + XML_DTD_UNKNOWN_ID, /* 536 */ + XML_DTD_UNKNOWN_NOTATION, /* 537 */ + XML_DTD_STANDALONE_DEFAULTED, /* 538 */ + XML_DTD_XMLID_VALUE, /* 539 */ + XML_DTD_XMLID_TYPE, /* 540 */ + XML_HTML_STRUCURE_ERROR = 800, + XML_HTML_UNKNOWN_TAG, /* 801 */ + XML_RNGP_ANYNAME_ATTR_ANCESTOR = 1000, + XML_RNGP_ATTR_CONFLICT, /* 1001 */ + XML_RNGP_ATTRIBUTE_CHILDREN, /* 1002 */ + XML_RNGP_ATTRIBUTE_CONTENT, /* 1003 */ + XML_RNGP_ATTRIBUTE_EMPTY, /* 1004 */ + XML_RNGP_ATTRIBUTE_NOOP, /* 1005 */ + XML_RNGP_CHOICE_CONTENT, /* 1006 */ + XML_RNGP_CHOICE_EMPTY, /* 1007 */ + XML_RNGP_CREATE_FAILURE, /* 1008 */ + XML_RNGP_DATA_CONTENT, /* 1009 */ + XML_RNGP_DEF_CHOICE_AND_INTERLEAVE, /* 1010 */ + XML_RNGP_DEFINE_CREATE_FAILED, /* 1011 */ + XML_RNGP_DEFINE_EMPTY, /* 1012 */ + XML_RNGP_DEFINE_MISSING, /* 1013 */ + XML_RNGP_DEFINE_NAME_MISSING, /* 1014 */ + XML_RNGP_ELEM_CONTENT_EMPTY, /* 1015 */ + XML_RNGP_ELEM_CONTENT_ERROR, /* 1016 */ + XML_RNGP_ELEMENT_EMPTY, /* 1017 */ + XML_RNGP_ELEMENT_CONTENT, /* 1018 */ + XML_RNGP_ELEMENT_NAME, /* 1019 */ + XML_RNGP_ELEMENT_NO_CONTENT, /* 1020 */ + XML_RNGP_ELEM_TEXT_CONFLICT, /* 1021 */ + XML_RNGP_EMPTY, /* 1022 */ + XML_RNGP_EMPTY_CONSTRUCT, /* 1023 */ + XML_RNGP_EMPTY_CONTENT, /* 1024 */ + XML_RNGP_EMPTY_NOT_EMPTY, /* 1025 */ + XML_RNGP_ERROR_TYPE_LIB, /* 1026 */ + XML_RNGP_EXCEPT_EMPTY, /* 1027 */ + XML_RNGP_EXCEPT_MISSING, /* 1028 */ + XML_RNGP_EXCEPT_MULTIPLE, /* 1029 */ + XML_RNGP_EXCEPT_NO_CONTENT, /* 1030 */ + XML_RNGP_EXTERNALREF_EMTPY, /* 1031 */ + XML_RNGP_EXTERNAL_REF_FAILURE, /* 1032 */ + XML_RNGP_EXTERNALREF_RECURSE, /* 1033 */ + XML_RNGP_FORBIDDEN_ATTRIBUTE, /* 1034 */ + XML_RNGP_FOREIGN_ELEMENT, /* 1035 */ + XML_RNGP_GRAMMAR_CONTENT, /* 1036 */ + XML_RNGP_GRAMMAR_EMPTY, /* 1037 */ + XML_RNGP_GRAMMAR_MISSING, /* 1038 */ + XML_RNGP_GRAMMAR_NO_START, /* 1039 */ + XML_RNGP_GROUP_ATTR_CONFLICT, /* 1040 */ + XML_RNGP_HREF_ERROR, /* 1041 */ + XML_RNGP_INCLUDE_EMPTY, /* 1042 */ + XML_RNGP_INCLUDE_FAILURE, /* 1043 */ + XML_RNGP_INCLUDE_RECURSE, /* 1044 */ + XML_RNGP_INTERLEAVE_ADD, /* 1045 */ + XML_RNGP_INTERLEAVE_CREATE_FAILED, /* 1046 */ + XML_RNGP_INTERLEAVE_EMPTY, /* 1047 */ + XML_RNGP_INTERLEAVE_NO_CONTENT, /* 1048 */ + XML_RNGP_INVALID_DEFINE_NAME, /* 1049 */ + XML_RNGP_INVALID_URI, /* 1050 */ + XML_RNGP_INVALID_VALUE, /* 1051 */ + XML_RNGP_MISSING_HREF, /* 1052 */ + XML_RNGP_NAME_MISSING, /* 1053 */ + XML_RNGP_NEED_COMBINE, /* 1054 */ + XML_RNGP_NOTALLOWED_NOT_EMPTY, /* 1055 */ + XML_RNGP_NSNAME_ATTR_ANCESTOR, /* 1056 */ + XML_RNGP_NSNAME_NO_NS, /* 1057 */ + XML_RNGP_PARAM_FORBIDDEN, /* 1058 */ + XML_RNGP_PARAM_NAME_MISSING, /* 1059 */ + XML_RNGP_PARENTREF_CREATE_FAILED, /* 1060 */ + XML_RNGP_PARENTREF_NAME_INVALID, /* 1061 */ + XML_RNGP_PARENTREF_NO_NAME, /* 1062 */ + XML_RNGP_PARENTREF_NO_PARENT, /* 1063 */ + XML_RNGP_PARENTREF_NOT_EMPTY, /* 1064 */ + XML_RNGP_PARSE_ERROR, /* 1065 */ + XML_RNGP_PAT_ANYNAME_EXCEPT_ANYNAME, /* 1066 */ + XML_RNGP_PAT_ATTR_ATTR, /* 1067 */ + XML_RNGP_PAT_ATTR_ELEM, /* 1068 */ + XML_RNGP_PAT_DATA_EXCEPT_ATTR, /* 1069 */ + XML_RNGP_PAT_DATA_EXCEPT_ELEM, /* 1070 */ + XML_RNGP_PAT_DATA_EXCEPT_EMPTY, /* 1071 */ + XML_RNGP_PAT_DATA_EXCEPT_GROUP, /* 1072 */ + XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE, /* 1073 */ + XML_RNGP_PAT_DATA_EXCEPT_LIST, /* 1074 */ + XML_RNGP_PAT_DATA_EXCEPT_ONEMORE, /* 1075 */ + XML_RNGP_PAT_DATA_EXCEPT_REF, /* 1076 */ + XML_RNGP_PAT_DATA_EXCEPT_TEXT, /* 1077 */ + XML_RNGP_PAT_LIST_ATTR, /* 1078 */ + XML_RNGP_PAT_LIST_ELEM, /* 1079 */ + XML_RNGP_PAT_LIST_INTERLEAVE, /* 1080 */ + XML_RNGP_PAT_LIST_LIST, /* 1081 */ + XML_RNGP_PAT_LIST_REF, /* 1082 */ + XML_RNGP_PAT_LIST_TEXT, /* 1083 */ + XML_RNGP_PAT_NSNAME_EXCEPT_ANYNAME, /* 1084 */ + XML_RNGP_PAT_NSNAME_EXCEPT_NSNAME, /* 1085 */ + XML_RNGP_PAT_ONEMORE_GROUP_ATTR, /* 1086 */ + XML_RNGP_PAT_ONEMORE_INTERLEAVE_ATTR, /* 1087 */ + XML_RNGP_PAT_START_ATTR, /* 1088 */ + XML_RNGP_PAT_START_DATA, /* 1089 */ + XML_RNGP_PAT_START_EMPTY, /* 1090 */ + XML_RNGP_PAT_START_GROUP, /* 1091 */ + XML_RNGP_PAT_START_INTERLEAVE, /* 1092 */ + XML_RNGP_PAT_START_LIST, /* 1093 */ + XML_RNGP_PAT_START_ONEMORE, /* 1094 */ + XML_RNGP_PAT_START_TEXT, /* 1095 */ + XML_RNGP_PAT_START_VALUE, /* 1096 */ + XML_RNGP_PREFIX_UNDEFINED, /* 1097 */ + XML_RNGP_REF_CREATE_FAILED, /* 1098 */ + XML_RNGP_REF_CYCLE, /* 1099 */ + XML_RNGP_REF_NAME_INVALID, /* 1100 */ + XML_RNGP_REF_NO_DEF, /* 1101 */ + XML_RNGP_REF_NO_NAME, /* 1102 */ + XML_RNGP_REF_NOT_EMPTY, /* 1103 */ + XML_RNGP_START_CHOICE_AND_INTERLEAVE, /* 1104 */ + XML_RNGP_START_CONTENT, /* 1105 */ + XML_RNGP_START_EMPTY, /* 1106 */ + XML_RNGP_START_MISSING, /* 1107 */ + XML_RNGP_TEXT_EXPECTED, /* 1108 */ + XML_RNGP_TEXT_HAS_CHILD, /* 1109 */ + XML_RNGP_TYPE_MISSING, /* 1110 */ + XML_RNGP_TYPE_NOT_FOUND, /* 1111 */ + XML_RNGP_TYPE_VALUE, /* 1112 */ + XML_RNGP_UNKNOWN_ATTRIBUTE, /* 1113 */ + XML_RNGP_UNKNOWN_COMBINE, /* 1114 */ + XML_RNGP_UNKNOWN_CONSTRUCT, /* 1115 */ + XML_RNGP_UNKNOWN_TYPE_LIB, /* 1116 */ + XML_RNGP_URI_FRAGMENT, /* 1117 */ + XML_RNGP_URI_NOT_ABSOLUTE, /* 1118 */ + XML_RNGP_VALUE_EMPTY, /* 1119 */ + XML_RNGP_VALUE_NO_CONTENT, /* 1120 */ + XML_RNGP_XMLNS_NAME, /* 1121 */ + XML_RNGP_XML_NS, /* 1122 */ + XML_XPATH_EXPRESSION_OK = 1200, + XML_XPATH_NUMBER_ERROR, /* 1201 */ + XML_XPATH_UNFINISHED_LITERAL_ERROR, /* 1202 */ + XML_XPATH_START_LITERAL_ERROR, /* 1203 */ + XML_XPATH_VARIABLE_REF_ERROR, /* 1204 */ + XML_XPATH_UNDEF_VARIABLE_ERROR, /* 1205 */ + XML_XPATH_INVALID_PREDICATE_ERROR, /* 1206 */ + XML_XPATH_EXPR_ERROR, /* 1207 */ + XML_XPATH_UNCLOSED_ERROR, /* 1208 */ + XML_XPATH_UNKNOWN_FUNC_ERROR, /* 1209 */ + XML_XPATH_INVALID_OPERAND, /* 1210 */ + XML_XPATH_INVALID_TYPE, /* 1211 */ + XML_XPATH_INVALID_ARITY, /* 1212 */ + XML_XPATH_INVALID_CTXT_SIZE, /* 1213 */ + XML_XPATH_INVALID_CTXT_POSITION, /* 1214 */ + XML_XPATH_MEMORY_ERROR, /* 1215 */ + XML_XPTR_SYNTAX_ERROR, /* 1216 */ + XML_XPTR_RESOURCE_ERROR, /* 1217 */ + XML_XPTR_SUB_RESOURCE_ERROR, /* 1218 */ + XML_XPATH_UNDEF_PREFIX_ERROR, /* 1219 */ + XML_XPATH_ENCODING_ERROR, /* 1220 */ + XML_XPATH_INVALID_CHAR_ERROR, /* 1221 */ + XML_TREE_INVALID_HEX = 1300, + XML_TREE_INVALID_DEC, /* 1301 */ + XML_TREE_UNTERMINATED_ENTITY, /* 1302 */ + XML_SAVE_NOT_UTF8 = 1400, + XML_SAVE_CHAR_INVALID, /* 1401 */ + XML_SAVE_NO_DOCTYPE, /* 1402 */ + XML_SAVE_UNKNOWN_ENCODING, /* 1403 */ + XML_REGEXP_COMPILE_ERROR = 1450, + XML_IO_UNKNOWN = 1500, + XML_IO_EACCES, /* 1501 */ + XML_IO_EAGAIN, /* 1502 */ + XML_IO_EBADF, /* 1503 */ + XML_IO_EBADMSG, /* 1504 */ + XML_IO_EBUSY, /* 1505 */ + XML_IO_ECANCELED, /* 1506 */ + XML_IO_ECHILD, /* 1507 */ + XML_IO_EDEADLK, /* 1508 */ + XML_IO_EDOM, /* 1509 */ + XML_IO_EEXIST, /* 1510 */ + XML_IO_EFAULT, /* 1511 */ + XML_IO_EFBIG, /* 1512 */ + XML_IO_EINPROGRESS, /* 1513 */ + XML_IO_EINTR, /* 1514 */ + XML_IO_EINVAL, /* 1515 */ + XML_IO_EIO, /* 1516 */ + XML_IO_EISDIR, /* 1517 */ + XML_IO_EMFILE, /* 1518 */ + XML_IO_EMLINK, /* 1519 */ + XML_IO_EMSGSIZE, /* 1520 */ + XML_IO_ENAMETOOLONG, /* 1521 */ + XML_IO_ENFILE, /* 1522 */ + XML_IO_ENODEV, /* 1523 */ + XML_IO_ENOENT, /* 1524 */ + XML_IO_ENOEXEC, /* 1525 */ + XML_IO_ENOLCK, /* 1526 */ + XML_IO_ENOMEM, /* 1527 */ + XML_IO_ENOSPC, /* 1528 */ + XML_IO_ENOSYS, /* 1529 */ + XML_IO_ENOTDIR, /* 1530 */ + XML_IO_ENOTEMPTY, /* 1531 */ + XML_IO_ENOTSUP, /* 1532 */ + XML_IO_ENOTTY, /* 1533 */ + XML_IO_ENXIO, /* 1534 */ + XML_IO_EPERM, /* 1535 */ + XML_IO_EPIPE, /* 1536 */ + XML_IO_ERANGE, /* 1537 */ + XML_IO_EROFS, /* 1538 */ + XML_IO_ESPIPE, /* 1539 */ + XML_IO_ESRCH, /* 1540 */ + XML_IO_ETIMEDOUT, /* 1541 */ + XML_IO_EXDEV, /* 1542 */ + XML_IO_NETWORK_ATTEMPT, /* 1543 */ + XML_IO_ENCODER, /* 1544 */ + XML_IO_FLUSH, /* 1545 */ + XML_IO_WRITE, /* 1546 */ + XML_IO_NO_INPUT, /* 1547 */ + XML_IO_BUFFER_FULL, /* 1548 */ + XML_IO_LOAD_ERROR, /* 1549 */ + XML_IO_ENOTSOCK, /* 1550 */ + XML_IO_EISCONN, /* 1551 */ + XML_IO_ECONNREFUSED, /* 1552 */ + XML_IO_ENETUNREACH, /* 1553 */ + XML_IO_EADDRINUSE, /* 1554 */ + XML_IO_EALREADY, /* 1555 */ + XML_IO_EAFNOSUPPORT, /* 1556 */ + XML_XINCLUDE_RECURSION=1600, + XML_XINCLUDE_PARSE_VALUE, /* 1601 */ + XML_XINCLUDE_ENTITY_DEF_MISMATCH, /* 1602 */ + XML_XINCLUDE_NO_HREF, /* 1603 */ + XML_XINCLUDE_NO_FALLBACK, /* 1604 */ + XML_XINCLUDE_HREF_URI, /* 1605 */ + XML_XINCLUDE_TEXT_FRAGMENT, /* 1606 */ + XML_XINCLUDE_TEXT_DOCUMENT, /* 1607 */ + XML_XINCLUDE_INVALID_CHAR, /* 1608 */ + XML_XINCLUDE_BUILD_FAILED, /* 1609 */ + XML_XINCLUDE_UNKNOWN_ENCODING, /* 1610 */ + XML_XINCLUDE_MULTIPLE_ROOT, /* 1611 */ + XML_XINCLUDE_XPTR_FAILED, /* 1612 */ + XML_XINCLUDE_XPTR_RESULT, /* 1613 */ + XML_XINCLUDE_INCLUDE_IN_INCLUDE, /* 1614 */ + XML_XINCLUDE_FALLBACKS_IN_INCLUDE, /* 1615 */ + XML_XINCLUDE_FALLBACK_NOT_IN_INCLUDE, /* 1616 */ + XML_XINCLUDE_DEPRECATED_NS, /* 1617 */ + XML_XINCLUDE_FRAGMENT_ID, /* 1618 */ + XML_CATALOG_MISSING_ATTR = 1650, + XML_CATALOG_ENTRY_BROKEN, /* 1651 */ + XML_CATALOG_PREFER_VALUE, /* 1652 */ + XML_CATALOG_NOT_CATALOG, /* 1653 */ + XML_CATALOG_RECURSION, /* 1654 */ + XML_SCHEMAP_PREFIX_UNDEFINED = 1700, + XML_SCHEMAP_ATTRFORMDEFAULT_VALUE, /* 1701 */ + XML_SCHEMAP_ATTRGRP_NONAME_NOREF, /* 1702 */ + XML_SCHEMAP_ATTR_NONAME_NOREF, /* 1703 */ + XML_SCHEMAP_COMPLEXTYPE_NONAME_NOREF, /* 1704 */ + XML_SCHEMAP_ELEMFORMDEFAULT_VALUE, /* 1705 */ + XML_SCHEMAP_ELEM_NONAME_NOREF, /* 1706 */ + XML_SCHEMAP_EXTENSION_NO_BASE, /* 1707 */ + XML_SCHEMAP_FACET_NO_VALUE, /* 1708 */ + XML_SCHEMAP_FAILED_BUILD_IMPORT, /* 1709 */ + XML_SCHEMAP_GROUP_NONAME_NOREF, /* 1710 */ + XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI, /* 1711 */ + XML_SCHEMAP_IMPORT_REDEFINE_NSNAME, /* 1712 */ + XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI, /* 1713 */ + XML_SCHEMAP_INVALID_BOOLEAN, /* 1714 */ + XML_SCHEMAP_INVALID_ENUM, /* 1715 */ + XML_SCHEMAP_INVALID_FACET, /* 1716 */ + XML_SCHEMAP_INVALID_FACET_VALUE, /* 1717 */ + XML_SCHEMAP_INVALID_MAXOCCURS, /* 1718 */ + XML_SCHEMAP_INVALID_MINOCCURS, /* 1719 */ + XML_SCHEMAP_INVALID_REF_AND_SUBTYPE, /* 1720 */ + XML_SCHEMAP_INVALID_WHITE_SPACE, /* 1721 */ + XML_SCHEMAP_NOATTR_NOREF, /* 1722 */ + XML_SCHEMAP_NOTATION_NO_NAME, /* 1723 */ + XML_SCHEMAP_NOTYPE_NOREF, /* 1724 */ + XML_SCHEMAP_REF_AND_SUBTYPE, /* 1725 */ + XML_SCHEMAP_RESTRICTION_NONAME_NOREF, /* 1726 */ + XML_SCHEMAP_SIMPLETYPE_NONAME, /* 1727 */ + XML_SCHEMAP_TYPE_AND_SUBTYPE, /* 1728 */ + XML_SCHEMAP_UNKNOWN_ALL_CHILD, /* 1729 */ + XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD, /* 1730 */ + XML_SCHEMAP_UNKNOWN_ATTR_CHILD, /* 1731 */ + XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD, /* 1732 */ + XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP, /* 1733 */ + XML_SCHEMAP_UNKNOWN_BASE_TYPE, /* 1734 */ + XML_SCHEMAP_UNKNOWN_CHOICE_CHILD, /* 1735 */ + XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD, /* 1736 */ + XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD, /* 1737 */ + XML_SCHEMAP_UNKNOWN_ELEM_CHILD, /* 1738 */ + XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD, /* 1739 */ + XML_SCHEMAP_UNKNOWN_FACET_CHILD, /* 1740 */ + XML_SCHEMAP_UNKNOWN_FACET_TYPE, /* 1741 */ + XML_SCHEMAP_UNKNOWN_GROUP_CHILD, /* 1742 */ + XML_SCHEMAP_UNKNOWN_IMPORT_CHILD, /* 1743 */ + XML_SCHEMAP_UNKNOWN_LIST_CHILD, /* 1744 */ + XML_SCHEMAP_UNKNOWN_NOTATION_CHILD, /* 1745 */ + XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD, /* 1746 */ + XML_SCHEMAP_UNKNOWN_REF, /* 1747 */ + XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD, /* 1748 */ + XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD, /* 1749 */ + XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD, /* 1750 */ + XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD, /* 1751 */ + XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD, /* 1752 */ + XML_SCHEMAP_UNKNOWN_TYPE, /* 1753 */ + XML_SCHEMAP_UNKNOWN_UNION_CHILD, /* 1754 */ + XML_SCHEMAP_ELEM_DEFAULT_FIXED, /* 1755 */ + XML_SCHEMAP_REGEXP_INVALID, /* 1756 */ + XML_SCHEMAP_FAILED_LOAD, /* 1757 */ + XML_SCHEMAP_NOTHING_TO_PARSE, /* 1758 */ + XML_SCHEMAP_NOROOT, /* 1759 */ + XML_SCHEMAP_REDEFINED_GROUP, /* 1760 */ + XML_SCHEMAP_REDEFINED_TYPE, /* 1761 */ + XML_SCHEMAP_REDEFINED_ELEMENT, /* 1762 */ + XML_SCHEMAP_REDEFINED_ATTRGROUP, /* 1763 */ + XML_SCHEMAP_REDEFINED_ATTR, /* 1764 */ + XML_SCHEMAP_REDEFINED_NOTATION, /* 1765 */ + XML_SCHEMAP_FAILED_PARSE, /* 1766 */ + XML_SCHEMAP_UNKNOWN_PREFIX, /* 1767 */ + XML_SCHEMAP_DEF_AND_PREFIX, /* 1768 */ + XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD, /* 1769 */ + XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI, /* 1770 */ + XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI, /* 1771 */ + XML_SCHEMAP_NOT_SCHEMA, /* 1772 */ + XML_SCHEMAP_UNKNOWN_MEMBER_TYPE, /* 1773 */ + XML_SCHEMAP_INVALID_ATTR_USE, /* 1774 */ + XML_SCHEMAP_RECURSIVE, /* 1775 */ + XML_SCHEMAP_SUPERNUMEROUS_LIST_ITEM_TYPE, /* 1776 */ + XML_SCHEMAP_INVALID_ATTR_COMBINATION, /* 1777 */ + XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION, /* 1778 */ + XML_SCHEMAP_MISSING_SIMPLETYPE_CHILD, /* 1779 */ + XML_SCHEMAP_INVALID_ATTR_NAME, /* 1780 */ + XML_SCHEMAP_REF_AND_CONTENT, /* 1781 */ + XML_SCHEMAP_CT_PROPS_CORRECT_1, /* 1782 */ + XML_SCHEMAP_CT_PROPS_CORRECT_2, /* 1783 */ + XML_SCHEMAP_CT_PROPS_CORRECT_3, /* 1784 */ + XML_SCHEMAP_CT_PROPS_CORRECT_4, /* 1785 */ + XML_SCHEMAP_CT_PROPS_CORRECT_5, /* 1786 */ + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, /* 1787 */ + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1, /* 1788 */ + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2, /* 1789 */ + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2, /* 1790 */ + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3, /* 1791 */ + XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER, /* 1792 */ + XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE, /* 1793 */ + XML_SCHEMAP_UNION_NOT_EXPRESSIBLE, /* 1794 */ + XML_SCHEMAP_SRC_IMPORT_3_1, /* 1795 */ + XML_SCHEMAP_SRC_IMPORT_3_2, /* 1796 */ + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1, /* 1797 */ + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2, /* 1798 */ + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3, /* 1799 */ + XML_SCHEMAP_COS_CT_EXTENDS_1_3, /* 1800 */ + XML_SCHEMAV_NOROOT = 1801, + XML_SCHEMAV_UNDECLAREDELEM, /* 1802 */ + XML_SCHEMAV_NOTTOPLEVEL, /* 1803 */ + XML_SCHEMAV_MISSING, /* 1804 */ + XML_SCHEMAV_WRONGELEM, /* 1805 */ + XML_SCHEMAV_NOTYPE, /* 1806 */ + XML_SCHEMAV_NOROLLBACK, /* 1807 */ + XML_SCHEMAV_ISABSTRACT, /* 1808 */ + XML_SCHEMAV_NOTEMPTY, /* 1809 */ + XML_SCHEMAV_ELEMCONT, /* 1810 */ + XML_SCHEMAV_HAVEDEFAULT, /* 1811 */ + XML_SCHEMAV_NOTNILLABLE, /* 1812 */ + XML_SCHEMAV_EXTRACONTENT, /* 1813 */ + XML_SCHEMAV_INVALIDATTR, /* 1814 */ + XML_SCHEMAV_INVALIDELEM, /* 1815 */ + XML_SCHEMAV_NOTDETERMINIST, /* 1816 */ + XML_SCHEMAV_CONSTRUCT, /* 1817 */ + XML_SCHEMAV_INTERNAL, /* 1818 */ + XML_SCHEMAV_NOTSIMPLE, /* 1819 */ + XML_SCHEMAV_ATTRUNKNOWN, /* 1820 */ + XML_SCHEMAV_ATTRINVALID, /* 1821 */ + XML_SCHEMAV_VALUE, /* 1822 */ + XML_SCHEMAV_FACET, /* 1823 */ + XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, /* 1824 */ + XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2, /* 1825 */ + XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3, /* 1826 */ + XML_SCHEMAV_CVC_TYPE_3_1_1, /* 1827 */ + XML_SCHEMAV_CVC_TYPE_3_1_2, /* 1828 */ + XML_SCHEMAV_CVC_FACET_VALID, /* 1829 */ + XML_SCHEMAV_CVC_LENGTH_VALID, /* 1830 */ + XML_SCHEMAV_CVC_MINLENGTH_VALID, /* 1831 */ + XML_SCHEMAV_CVC_MAXLENGTH_VALID, /* 1832 */ + XML_SCHEMAV_CVC_MININCLUSIVE_VALID, /* 1833 */ + XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID, /* 1834 */ + XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID, /* 1835 */ + XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID, /* 1836 */ + XML_SCHEMAV_CVC_TOTALDIGITS_VALID, /* 1837 */ + XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID, /* 1838 */ + XML_SCHEMAV_CVC_PATTERN_VALID, /* 1839 */ + XML_SCHEMAV_CVC_ENUMERATION_VALID, /* 1840 */ + XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, /* 1841 */ + XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2, /* 1842 */ + XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, /* 1843 */ + XML_SCHEMAV_CVC_COMPLEX_TYPE_2_4, /* 1844 */ + XML_SCHEMAV_CVC_ELT_1, /* 1845 */ + XML_SCHEMAV_CVC_ELT_2, /* 1846 */ + XML_SCHEMAV_CVC_ELT_3_1, /* 1847 */ + XML_SCHEMAV_CVC_ELT_3_2_1, /* 1848 */ + XML_SCHEMAV_CVC_ELT_3_2_2, /* 1849 */ + XML_SCHEMAV_CVC_ELT_4_1, /* 1850 */ + XML_SCHEMAV_CVC_ELT_4_2, /* 1851 */ + XML_SCHEMAV_CVC_ELT_4_3, /* 1852 */ + XML_SCHEMAV_CVC_ELT_5_1_1, /* 1853 */ + XML_SCHEMAV_CVC_ELT_5_1_2, /* 1854 */ + XML_SCHEMAV_CVC_ELT_5_2_1, /* 1855 */ + XML_SCHEMAV_CVC_ELT_5_2_2_1, /* 1856 */ + XML_SCHEMAV_CVC_ELT_5_2_2_2_1, /* 1857 */ + XML_SCHEMAV_CVC_ELT_5_2_2_2_2, /* 1858 */ + XML_SCHEMAV_CVC_ELT_6, /* 1859 */ + XML_SCHEMAV_CVC_ELT_7, /* 1860 */ + XML_SCHEMAV_CVC_ATTRIBUTE_1, /* 1861 */ + XML_SCHEMAV_CVC_ATTRIBUTE_2, /* 1862 */ + XML_SCHEMAV_CVC_ATTRIBUTE_3, /* 1863 */ + XML_SCHEMAV_CVC_ATTRIBUTE_4, /* 1864 */ + XML_SCHEMAV_CVC_COMPLEX_TYPE_3_1, /* 1865 */ + XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, /* 1866 */ + XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, /* 1867 */ + XML_SCHEMAV_CVC_COMPLEX_TYPE_4, /* 1868 */ + XML_SCHEMAV_CVC_COMPLEX_TYPE_5_1, /* 1869 */ + XML_SCHEMAV_CVC_COMPLEX_TYPE_5_2, /* 1870 */ + XML_SCHEMAV_ELEMENT_CONTENT, /* 1871 */ + XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING, /* 1872 */ + XML_SCHEMAV_CVC_COMPLEX_TYPE_1, /* 1873 */ + XML_SCHEMAV_CVC_AU, /* 1874 */ + XML_SCHEMAV_CVC_TYPE_1, /* 1875 */ + XML_SCHEMAV_CVC_TYPE_2, /* 1876 */ + XML_SCHEMAV_CVC_IDC, /* 1877 */ + XML_SCHEMAV_CVC_WILDCARD, /* 1878 */ + XML_XPTR_UNKNOWN_SCHEME = 1900, + XML_XPTR_CHILDSEQ_START, /* 1901 */ + XML_XPTR_EVAL_FAILED, /* 1902 */ + XML_XPTR_EXTRA_OBJECTS, /* 1903 */ + XML_C14N_CREATE_CTXT = 1950, + XML_C14N_REQUIRES_UTF8, /* 1951 */ + XML_C14N_CREATE_STACK, /* 1952 */ + XML_C14N_INVALID_NODE, /* 1953 */ + XML_C14N_UNKNOW_NODE, /* 1954 */ + XML_C14N_RELATIVE_NAMESPACE, /* 1955 */ + XML_FTP_PASV_ANSWER = 2000, + XML_FTP_EPSV_ANSWER, /* 2001 */ + XML_FTP_ACCNT, /* 2002 */ + XML_FTP_URL_SYNTAX, /* 2003 */ + XML_HTTP_URL_SYNTAX = 2020, + XML_HTTP_USE_IP, /* 2021 */ + XML_HTTP_UNKNOWN_HOST, /* 2022 */ + XML_SCHEMAP_SRC_SIMPLE_TYPE_1 = 3000, + XML_SCHEMAP_SRC_SIMPLE_TYPE_2, /* 3001 */ + XML_SCHEMAP_SRC_SIMPLE_TYPE_3, /* 3002 */ + XML_SCHEMAP_SRC_SIMPLE_TYPE_4, /* 3003 */ + XML_SCHEMAP_SRC_RESOLVE, /* 3004 */ + XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE, /* 3005 */ + XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE, /* 3006 */ + XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES, /* 3007 */ + XML_SCHEMAP_ST_PROPS_CORRECT_1, /* 3008 */ + XML_SCHEMAP_ST_PROPS_CORRECT_2, /* 3009 */ + XML_SCHEMAP_ST_PROPS_CORRECT_3, /* 3010 */ + XML_SCHEMAP_COS_ST_RESTRICTS_1_1, /* 3011 */ + XML_SCHEMAP_COS_ST_RESTRICTS_1_2, /* 3012 */ + XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1, /* 3013 */ + XML_SCHEMAP_COS_ST_RESTRICTS_1_3_2, /* 3014 */ + XML_SCHEMAP_COS_ST_RESTRICTS_2_1, /* 3015 */ + XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1, /* 3016 */ + XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2, /* 3017 */ + XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1, /* 3018 */ + XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2, /* 3019 */ + XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3, /* 3020 */ + XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4, /* 3021 */ + XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_5, /* 3022 */ + XML_SCHEMAP_COS_ST_RESTRICTS_3_1, /* 3023 */ + XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1, /* 3024 */ + XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2, /* 3025 */ + XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2, /* 3026 */ + XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1, /* 3027 */ + XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3, /* 3028 */ + XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4, /* 3029 */ + XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_5, /* 3030 */ + XML_SCHEMAP_COS_ST_DERIVED_OK_2_1, /* 3031 */ + XML_SCHEMAP_COS_ST_DERIVED_OK_2_2, /* 3032 */ + XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, /* 3033 */ + XML_SCHEMAP_S4S_ELEM_MISSING, /* 3034 */ + XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, /* 3035 */ + XML_SCHEMAP_S4S_ATTR_MISSING, /* 3036 */ + XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, /* 3037 */ + XML_SCHEMAP_SRC_ELEMENT_1, /* 3038 */ + XML_SCHEMAP_SRC_ELEMENT_2_1, /* 3039 */ + XML_SCHEMAP_SRC_ELEMENT_2_2, /* 3040 */ + XML_SCHEMAP_SRC_ELEMENT_3, /* 3041 */ + XML_SCHEMAP_P_PROPS_CORRECT_1, /* 3042 */ + XML_SCHEMAP_P_PROPS_CORRECT_2_1, /* 3043 */ + XML_SCHEMAP_P_PROPS_CORRECT_2_2, /* 3044 */ + XML_SCHEMAP_E_PROPS_CORRECT_2, /* 3045 */ + XML_SCHEMAP_E_PROPS_CORRECT_3, /* 3046 */ + XML_SCHEMAP_E_PROPS_CORRECT_4, /* 3047 */ + XML_SCHEMAP_E_PROPS_CORRECT_5, /* 3048 */ + XML_SCHEMAP_E_PROPS_CORRECT_6, /* 3049 */ + XML_SCHEMAP_SRC_INCLUDE, /* 3050 */ + XML_SCHEMAP_SRC_ATTRIBUTE_1, /* 3051 */ + XML_SCHEMAP_SRC_ATTRIBUTE_2, /* 3052 */ + XML_SCHEMAP_SRC_ATTRIBUTE_3_1, /* 3053 */ + XML_SCHEMAP_SRC_ATTRIBUTE_3_2, /* 3054 */ + XML_SCHEMAP_SRC_ATTRIBUTE_4, /* 3055 */ + XML_SCHEMAP_NO_XMLNS, /* 3056 */ + XML_SCHEMAP_NO_XSI, /* 3057 */ + XML_SCHEMAP_COS_VALID_DEFAULT_1, /* 3058 */ + XML_SCHEMAP_COS_VALID_DEFAULT_2_1, /* 3059 */ + XML_SCHEMAP_COS_VALID_DEFAULT_2_2_1, /* 3060 */ + XML_SCHEMAP_COS_VALID_DEFAULT_2_2_2, /* 3061 */ + XML_SCHEMAP_CVC_SIMPLE_TYPE, /* 3062 */ + XML_SCHEMAP_COS_CT_EXTENDS_1_1, /* 3063 */ + XML_SCHEMAP_SRC_IMPORT_1_1, /* 3064 */ + XML_SCHEMAP_SRC_IMPORT_1_2, /* 3065 */ + XML_SCHEMAP_SRC_IMPORT_2, /* 3066 */ + XML_SCHEMAP_SRC_IMPORT_2_1, /* 3067 */ + XML_SCHEMAP_SRC_IMPORT_2_2, /* 3068 */ + XML_SCHEMAP_INTERNAL, /* 3069 non-W3C */ + XML_SCHEMAP_NOT_DETERMINISTIC, /* 3070 non-W3C */ + XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_1, /* 3071 */ + XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_2, /* 3072 */ + XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3, /* 3073 */ + XML_SCHEMAP_MG_PROPS_CORRECT_1, /* 3074 */ + XML_SCHEMAP_MG_PROPS_CORRECT_2, /* 3075 */ + XML_SCHEMAP_SRC_CT_1, /* 3076 */ + XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3, /* 3077 */ + XML_SCHEMAP_AU_PROPS_CORRECT_2, /* 3078 */ + XML_SCHEMAP_A_PROPS_CORRECT_2, /* 3079 */ + XML_SCHEMAP_C_PROPS_CORRECT, /* 3080 */ + XML_MODULE_OPEN = 4900, /* 4900 */ + XML_MODULE_CLOSE, /* 4901 */ + XML_CHECK_FOUND_ELEMENT = 5000, + XML_CHECK_FOUND_ATTRIBUTE, /* 5001 */ + XML_CHECK_FOUND_TEXT, /* 5002 */ + XML_CHECK_FOUND_CDATA, /* 5003 */ + XML_CHECK_FOUND_ENTITYREF, /* 5004 */ + XML_CHECK_FOUND_ENTITY, /* 5005 */ + XML_CHECK_FOUND_PI, /* 5006 */ + XML_CHECK_FOUND_COMMENT, /* 5007 */ + XML_CHECK_FOUND_DOCTYPE, /* 5008 */ + XML_CHECK_FOUND_FRAGMENT, /* 5009 */ + XML_CHECK_FOUND_NOTATION, /* 5010 */ + XML_CHECK_UNKNOWN_NODE, /* 5011 */ + XML_CHECK_ENTITY_TYPE, /* 5012 */ + XML_CHECK_NO_PARENT, /* 5013 */ + XML_CHECK_NO_DOC, /* 5014 */ + XML_CHECK_NO_NAME, /* 5015 */ + XML_CHECK_NO_ELEM, /* 5016 */ + XML_CHECK_WRONG_DOC, /* 5017 */ + XML_CHECK_NO_PREV, /* 5018 */ + XML_CHECK_WRONG_PREV, /* 5019 */ + XML_CHECK_NO_NEXT, /* 5020 */ + XML_CHECK_WRONG_NEXT, /* 5021 */ + XML_CHECK_NOT_DTD, /* 5022 */ + XML_CHECK_NOT_ATTR, /* 5023 */ + XML_CHECK_NOT_ATTR_DECL, /* 5024 */ + XML_CHECK_NOT_ELEM_DECL, /* 5025 */ + XML_CHECK_NOT_ENTITY_DECL, /* 5026 */ + XML_CHECK_NOT_NS_DECL, /* 5027 */ + XML_CHECK_NO_HREF, /* 5028 */ + XML_CHECK_WRONG_PARENT,/* 5029 */ + XML_CHECK_NS_SCOPE, /* 5030 */ + XML_CHECK_NS_ANCESTOR, /* 5031 */ + XML_CHECK_NOT_UTF8, /* 5032 */ + XML_CHECK_NO_DICT, /* 5033 */ + XML_CHECK_NOT_NCNAME, /* 5034 */ + XML_CHECK_OUTSIDE_DICT, /* 5035 */ + XML_CHECK_WRONG_NAME, /* 5036 */ + XML_CHECK_NAME_NOT_NULL /* 5037 */ +#if 0 + XML_CHECK_, /* 5033 */ + XML_CHECK_X /* 503 */ +#endif +} xmlParserErrors; + +/** + * xmlGenericErrorFunc: + * @ctx: a parsing context + * @msg: the message + * @...: the extra arguments of the varags to format the message + * + * Signature of the function to use when there is an error and + * no parsing or validity context available . + */ +typedef void (*xmlGenericErrorFunc) (void *ctx, + const char *msg, + ...); +/** + * xmlStructuredErrorFunc: + * @userData: user provided data for the error callback + * @error: the error being raised. + * + * Signature of the function to use when there is an error and + * the module handles the new error reporting mechanism. + */ +typedef void (*xmlStructuredErrorFunc) (void *userData, xmlErrorPtr error); + +/* + * Use the following function to reset the two global variables + * xmlGenericError and xmlGenericErrorContext. + */ +XMLPUBFUN void XMLCALL + xmlSetGenericErrorFunc (void *ctx, + xmlGenericErrorFunc handler); +XMLPUBFUN void XMLCALL + initGenericErrorDefaultFunc (xmlGenericErrorFunc *handler); + +XMLPUBFUN void XMLCALL + xmlSetStructuredErrorFunc (void *ctx, + xmlStructuredErrorFunc handler); +/* + * Default message routines used by SAX and Valid context for error + * and warning reporting. + */ +XMLPUBFUN void XMLCALL + xmlParserError (void *ctx, + const char *msg, + ...); +XMLPUBFUN void XMLCALL + xmlParserWarning (void *ctx, + const char *msg, + ...); +XMLPUBFUN void XMLCALL + xmlParserValidityError (void *ctx, + const char *msg, + ...); +XMLPUBFUN void XMLCALL + xmlParserValidityWarning (void *ctx, + const char *msg, + ...); +XMLPUBFUN void XMLCALL + xmlParserPrintFileInfo (xmlParserInputPtr input); +XMLPUBFUN void XMLCALL + xmlParserPrintFileContext (xmlParserInputPtr input); + +/* + * Extended error information routines + */ +XMLPUBFUN xmlErrorPtr XMLCALL + xmlGetLastError (void); +XMLPUBFUN void XMLCALL + xmlResetLastError (void); +XMLPUBFUN xmlErrorPtr XMLCALL + xmlCtxtGetLastError (void *ctx); +XMLPUBFUN void XMLCALL + xmlCtxtResetLastError (void *ctx); +XMLPUBFUN void XMLCALL + xmlResetError (xmlErrorPtr err); +XMLPUBFUN int XMLCALL + xmlCopyError (xmlErrorPtr from, + xmlErrorPtr to); + +#ifdef IN_LIBXML +/* + * Internal callback reporting routine + */ +XMLPUBFUN void XMLCALL + __xmlRaiseError (xmlStructuredErrorFunc schannel, + xmlGenericErrorFunc channel, + void *data, + void *ctx, + void *node, + int domain, + int code, + xmlErrorLevel level, + const char *file, + int line, + const char *str1, + const char *str2, + const char *str3, + int int1, + int col, + const char *msg, + ...); +XMLPUBFUN void XMLCALL + __xmlSimpleError (int domain, + int code, + xmlNodePtr node, + const char *msg, + const char *extra); +#endif +#ifdef __cplusplus +} +#endif +#endif /* __XML_ERROR_H__ */ diff --git a/include/libxml/xmlexports.h b/include/libxml/xmlexports.h new file mode 100644 index 0000000..ee03cad --- /dev/null +++ b/include/libxml/xmlexports.h @@ -0,0 +1,138 @@ +/* + * Summary: macros for marking symbols as exportable/importable. + * Description: macros for marking symbols as exportable/importable. + * + * Copy: See Copyright for the status of this software. + * + * Author: Igor Zlatovic + */ + +#ifndef __XML_EXPORTS_H__ +#define __XML_EXPORTS_H__ + +/** + * XMLPUBFUN, XMLPUBVAR, XMLCALL + * + * Macros which declare an exportable function, an exportable variable and + * the calling convention used for functions. + * + * Please use an extra block for every platform/compiler combination when + * modifying this, rather than overlong #ifdef lines. This helps + * readability as well as the fact that different compilers on the same + * platform might need different definitions. + */ + +/** + * XMLPUBFUN: + * + * Macros which declare an exportable function + */ +#define XMLPUBFUN +/** + * XMLPUBVAR: + * + * Macros which declare an exportable variable + */ +#define XMLPUBVAR extern +/** + * XMLCALL: + * + * Macros which declare the called convention for exported functions + */ +#define XMLCALL + +/** DOC_DISABLE */ + +/* Windows platform with MS compiler */ +#if defined(_WIN32) && defined(_MSC_VER) + #undef XMLPUBFUN + #undef XMLPUBVAR + #undef XMLCALL + #if defined(IN_LIBXML) && !defined(LIBXML_STATIC) + #define XMLPUBFUN __declspec(dllexport) + #define XMLPUBVAR __declspec(dllexport) + #else + #define XMLPUBFUN + #if !defined(LIBXML_STATIC) + #define XMLPUBVAR __declspec(dllimport) extern + #else + #define XMLPUBVAR extern + #endif + #endif + #define XMLCALL __cdecl + #if !defined _REENTRANT + #define _REENTRANT + #endif +#endif + +/* Windows platform with Borland compiler */ +#if defined(_WIN32) && defined(__BORLANDC__) + #undef XMLPUBFUN + #undef XMLPUBVAR + #undef XMLCALL + #if defined(IN_LIBXML) && !defined(LIBXML_STATIC) + #define XMLPUBFUN __declspec(dllexport) + #define XMLPUBVAR __declspec(dllexport) extern + #else + #define XMLPUBFUN + #if !defined(LIBXML_STATIC) + #define XMLPUBVAR __declspec(dllimport) extern + #else + #define XMLPUBVAR extern + #endif + #endif + #define XMLCALL __cdecl + #if !defined _REENTRANT + #define _REENTRANT + #endif +#endif + +/* Windows platform with GNU compiler (Mingw) */ +#if defined(_WIN32) && defined(__MINGW32__) + #undef XMLPUBFUN + #undef XMLPUBVAR + #undef XMLCALL + #if defined(IN_LIBXML) && !defined(LIBXML_STATIC) + #define XMLPUBFUN __declspec(dllexport) + #define XMLPUBVAR __declspec(dllexport) + #else + #define XMLPUBFUN + #if !defined(LIBXML_STATIC) + #define XMLPUBVAR __declspec(dllimport) extern + #else + #define XMLPUBVAR extern + #endif + #endif + #define XMLCALL __cdecl + #if !defined _REENTRANT + #define _REENTRANT + #endif +#endif + +/* Cygwin platform, GNU compiler */ +#if defined(_WIN32) && defined(__CYGWIN__) + #undef XMLPUBFUN + #undef XMLPUBVAR + #undef XMLCALL + #if defined(IN_LIBXML) && !defined(LIBXML_STATIC) + #define XMLPUBFUN __declspec(dllexport) + #define XMLPUBVAR __declspec(dllexport) + #else + #define XMLPUBFUN + #if !defined(LIBXML_STATIC) + #define XMLPUBVAR __declspec(dllimport) extern + #else + #define XMLPUBVAR + #endif + #endif + #define XMLCALL __cdecl +#endif + +/* Compatibility */ +#if !defined(LIBXML_DLL_IMPORT) +#define LIBXML_DLL_IMPORT XMLPUBVAR +#endif + +#endif /* __XML_EXPORTS_H__ */ + + diff --git a/include/libxml/xmlmemory.h b/include/libxml/xmlmemory.h new file mode 100644 index 0000000..235721c --- /dev/null +++ b/include/libxml/xmlmemory.h @@ -0,0 +1,222 @@ +/* + * Summary: interface for the memory allocator + * Description: provides interfaces for the memory allocator, + * including debugging capabilities. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + + +#ifndef __DEBUG_MEMORY_ALLOC__ +#define __DEBUG_MEMORY_ALLOC__ + +#include +#include + +/** + * DEBUG_MEMORY: + * + * DEBUG_MEMORY replaces the allocator with a collect and debug + * shell to the libc allocator. + * DEBUG_MEMORY should only be activated when debugging + * libxml i.e. if libxml has been configured with --with-debug-mem too. + */ +/* #define DEBUG_MEMORY_FREED */ +/* #define DEBUG_MEMORY_LOCATION */ + +#ifdef DEBUG +#ifndef DEBUG_MEMORY +#define DEBUG_MEMORY +#endif +#endif + +/** + * DEBUG_MEMORY_LOCATION: + * + * DEBUG_MEMORY_LOCATION should be activated only when debugging + * libxml i.e. if libxml has been configured with --with-debug-mem too. + */ +#ifdef DEBUG_MEMORY_LOCATION +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The XML memory wrapper support 4 basic overloadable functions. + */ +/** + * xmlFreeFunc: + * @mem: an already allocated block of memory + * + * Signature for a free() implementation. + */ +typedef void (XMLCALL *xmlFreeFunc)(void *mem); +/** + * xmlMallocFunc: + * @size: the size requested in bytes + * + * Signature for a malloc() implementation. + * + * Returns a pointer to the newly allocated block or NULL in case of error. + */ +typedef void *(XMLCALL *xmlMallocFunc)(size_t size); + +/** + * xmlReallocFunc: + * @mem: an already allocated block of memory + * @size: the new size requested in bytes + * + * Signature for a realloc() implementation. + * + * Returns a pointer to the newly reallocated block or NULL in case of error. + */ +typedef void *(XMLCALL *xmlReallocFunc)(void *mem, size_t size); + +/** + * xmlStrdupFunc: + * @str: a zero terminated string + * + * Signature for an strdup() implementation. + * + * Returns the copy of the string or NULL in case of error. + */ +typedef char *(XMLCALL *xmlStrdupFunc)(const char *str); + +/* + * The 4 interfaces used for all memory handling within libxml. +LIBXML_DLL_IMPORT extern xmlFreeFunc xmlFree; +LIBXML_DLL_IMPORT extern xmlMallocFunc xmlMalloc; +LIBXML_DLL_IMPORT extern xmlMallocFunc xmlMallocAtomic; +LIBXML_DLL_IMPORT extern xmlReallocFunc xmlRealloc; +LIBXML_DLL_IMPORT extern xmlStrdupFunc xmlMemStrdup; + */ + +/* + * The way to overload the existing functions. + * The xmlGc function have an extra entry for atomic block + * allocations useful for garbage collected memory allocators + */ +XMLPUBFUN int XMLCALL + xmlMemSetup (xmlFreeFunc freeFunc, + xmlMallocFunc mallocFunc, + xmlReallocFunc reallocFunc, + xmlStrdupFunc strdupFunc); +XMLPUBFUN int XMLCALL + xmlMemGet (xmlFreeFunc *freeFunc, + xmlMallocFunc *mallocFunc, + xmlReallocFunc *reallocFunc, + xmlStrdupFunc *strdupFunc); +XMLPUBFUN int XMLCALL + xmlGcMemSetup (xmlFreeFunc freeFunc, + xmlMallocFunc mallocFunc, + xmlMallocFunc mallocAtomicFunc, + xmlReallocFunc reallocFunc, + xmlStrdupFunc strdupFunc); +XMLPUBFUN int XMLCALL + xmlGcMemGet (xmlFreeFunc *freeFunc, + xmlMallocFunc *mallocFunc, + xmlMallocFunc *mallocAtomicFunc, + xmlReallocFunc *reallocFunc, + xmlStrdupFunc *strdupFunc); + +/* + * Initialization of the memory layer. + */ +XMLPUBFUN int XMLCALL + xmlInitMemory (void); + +/* + * Cleanup of the memory layer. + */ +XMLPUBFUN void XMLCALL + xmlCleanupMemory (void); +/* + * These are specific to the XML debug memory wrapper. + */ +XMLPUBFUN int XMLCALL + xmlMemUsed (void); +XMLPUBFUN int XMLCALL + xmlMemBlocks (void); +XMLPUBFUN void XMLCALL + xmlMemDisplay (FILE *fp); +XMLPUBFUN void XMLCALL + xmlMemShow (FILE *fp, int nr); +XMLPUBFUN void XMLCALL + xmlMemoryDump (void); +XMLPUBFUN void * XMLCALL + xmlMemMalloc (size_t size); +XMLPUBFUN void * XMLCALL + xmlMemRealloc (void *ptr,size_t size); +XMLPUBFUN void XMLCALL + xmlMemFree (void *ptr); +XMLPUBFUN char * XMLCALL + xmlMemoryStrdup (const char *str); +XMLPUBFUN void * XMLCALL + xmlMallocLoc (size_t size, const char *file, int line); +XMLPUBFUN void * XMLCALL + xmlReallocLoc (void *ptr, size_t size, const char *file, int line); +XMLPUBFUN void * XMLCALL + xmlMallocAtomicLoc (size_t size, const char *file, int line); +XMLPUBFUN char * XMLCALL + xmlMemStrdupLoc (const char *str, const char *file, int line); + + +#ifdef DEBUG_MEMORY_LOCATION +/** + * xmlMalloc: + * @size: number of bytes to allocate + * + * Wrapper for the malloc() function used in the XML library. + * + * Returns the pointer to the allocated area or NULL in case of error. + */ +#define xmlMalloc(size) xmlMallocLoc((size), __FILE__, __LINE__) +/** + * xmlMallocAtomic: + * @size: number of bytes to allocate + * + * Wrapper for the malloc() function used in the XML library for allocation + * of block not containing pointers to other areas. + * + * Returns the pointer to the allocated area or NULL in case of error. + */ +#define xmlMallocAtomic(size) xmlMallocAtomicLoc((size), __FILE__, __LINE__) +/** + * xmlRealloc: + * @ptr: pointer to the existing allocated area + * @size: number of bytes to allocate + * + * Wrapper for the realloc() function used in the XML library. + * + * Returns the pointer to the allocated area or NULL in case of error. + */ +#define xmlRealloc(ptr, size) xmlReallocLoc((ptr), (size), __FILE__, __LINE__) +/** + * xmlMemStrdup: + * @str: pointer to the existing string + * + * Wrapper for the strdup() function, xmlStrdup() is usually preferred. + * + * Returns the pointer to the allocated area or NULL in case of error. + */ +#define xmlMemStrdup(str) xmlMemStrdupLoc((str), __FILE__, __LINE__) + +#endif /* DEBUG_MEMORY_LOCATION */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#ifndef __XML_GLOBALS_H +#ifndef __XML_THREADS_H__ +#include +#include +#endif +#endif + +#endif /* __DEBUG_MEMORY_ALLOC__ */ + diff --git a/include/libxml/xmlmodule.h b/include/libxml/xmlmodule.h new file mode 100644 index 0000000..8f4a560 --- /dev/null +++ b/include/libxml/xmlmodule.h @@ -0,0 +1,57 @@ +/* + * Summary: dynamic module loading + * Description: basic API for dynamic module loading, used by + * libexslt added in 2.6.17 + * + * Copy: See Copyright for the status of this software. + * + * Author: Joel W. Reed + */ + +#ifndef __XML_MODULE_H__ +#define __XML_MODULE_H__ + +#include + +#ifdef LIBXML_MODULES_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * xmlModulePtr: + * + * A handle to a dynamically loaded module + */ +typedef struct _xmlModule xmlModule; +typedef xmlModule *xmlModulePtr; + +/** + * xmlModuleOption: + * + * enumeration of options that can be passed down to xmlModuleOpen() + */ +typedef enum { + XML_MODULE_LAZY = 1, /* lazy binding */ + XML_MODULE_LOCAL= 2 /* local binding */ +} xmlModuleOption; + +XMLPUBFUN xmlModulePtr XMLCALL xmlModuleOpen (const char *filename, + int options); + +XMLPUBFUN int XMLCALL xmlModuleSymbol (xmlModulePtr module, + const char* name, + void **result); + +XMLPUBFUN int XMLCALL xmlModuleClose (xmlModulePtr module); + +XMLPUBFUN int XMLCALL xmlModuleFree (xmlModulePtr module); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_MODULES_ENABLED */ + +#endif /*__XML_MODULE_H__ */ diff --git a/include/libxml/xmlreader.h b/include/libxml/xmlreader.h new file mode 100644 index 0000000..f016546 --- /dev/null +++ b/include/libxml/xmlreader.h @@ -0,0 +1,399 @@ +/* + * Summary: the XMLReader implementation + * Description: API of the XML streaming API based on C# interfaces. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_XMLREADER_H__ +#define __XML_XMLREADER_H__ + +#include +#include +#include +#ifdef LIBXML_SCHEMAS_ENABLED +#include +#include +#endif + +#ifdef LIBXML_READER_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * xmlTextReaderMode: + * + * Internal state values for the reader. + */ +typedef enum { + XML_TEXTREADER_MODE_INITIAL = 0, + XML_TEXTREADER_MODE_INTERACTIVE = 1, + XML_TEXTREADER_MODE_ERROR = 2, + XML_TEXTREADER_MODE_EOF =3, + XML_TEXTREADER_MODE_CLOSED = 4, + XML_TEXTREADER_MODE_READING = 5 +} xmlTextReaderMode; + +/** + * xmlParserProperties: + * + * Some common options to use with xmlTextReaderSetParserProp, but it + * is better to use xmlParserOption and the xmlReaderNewxxx and + * xmlReaderForxxx APIs now. + */ +typedef enum { + XML_PARSER_LOADDTD = 1, + XML_PARSER_DEFAULTATTRS = 2, + XML_PARSER_VALIDATE = 3, + XML_PARSER_SUBST_ENTITIES = 4 +} xmlParserProperties; + +/** + * xmlParserSeverities: + * + * How severe an error callback is when the per-reader error callback API + * is used. + */ +typedef enum { + XML_PARSER_SEVERITY_VALIDITY_WARNING = 1, + XML_PARSER_SEVERITY_VALIDITY_ERROR = 2, + XML_PARSER_SEVERITY_WARNING = 3, + XML_PARSER_SEVERITY_ERROR = 4 +} xmlParserSeverities; + +/** + * xmlReaderTypes: + * + * Predefined constants for the different types of nodes. + */ +typedef enum { + XML_READER_TYPE_NONE = 0, + XML_READER_TYPE_ELEMENT = 1, + XML_READER_TYPE_ATTRIBUTE = 2, + XML_READER_TYPE_TEXT = 3, + XML_READER_TYPE_CDATA = 4, + XML_READER_TYPE_ENTITY_REFERENCE = 5, + XML_READER_TYPE_ENTITY = 6, + XML_READER_TYPE_PROCESSING_INSTRUCTION = 7, + XML_READER_TYPE_COMMENT = 8, + XML_READER_TYPE_DOCUMENT = 9, + XML_READER_TYPE_DOCUMENT_TYPE = 10, + XML_READER_TYPE_DOCUMENT_FRAGMENT = 11, + XML_READER_TYPE_NOTATION = 12, + XML_READER_TYPE_WHITESPACE = 13, + XML_READER_TYPE_SIGNIFICANT_WHITESPACE = 14, + XML_READER_TYPE_END_ELEMENT = 15, + XML_READER_TYPE_END_ENTITY = 16, + XML_READER_TYPE_XML_DECLARATION = 17 +} xmlReaderTypes; + +/** + * xmlTextReader: + * + * Structure for an xmlReader context. + */ +typedef struct _xmlTextReader xmlTextReader; + +/** + * xmlTextReaderPtr: + * + * Pointer to an xmlReader context. + */ +typedef xmlTextReader *xmlTextReaderPtr; + +/* + * Constructors & Destructor + */ +XMLPUBFUN xmlTextReaderPtr XMLCALL + xmlNewTextReader (xmlParserInputBufferPtr input, + const char *URI); +XMLPUBFUN xmlTextReaderPtr XMLCALL + xmlNewTextReaderFilename(const char *URI); +XMLPUBFUN void XMLCALL + xmlFreeTextReader (xmlTextReaderPtr reader); + +/* + * Iterators + */ +XMLPUBFUN int XMLCALL + xmlTextReaderRead (xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderReadInnerXml (xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderReadOuterXml (xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderReadString (xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderReadAttributeValue (xmlTextReaderPtr reader); + +/* + * Attributes of the node + */ +XMLPUBFUN int XMLCALL + xmlTextReaderAttributeCount(xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderDepth (xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderHasAttributes(xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderHasValue(xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderIsDefault (xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderNodeType (xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderQuoteChar (xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderReadState (xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader); + +XMLPUBFUN const xmlChar * XMLCALL + xmlTextReaderConstBaseUri (xmlTextReaderPtr reader); +XMLPUBFUN const xmlChar * XMLCALL + xmlTextReaderConstLocalName (xmlTextReaderPtr reader); +XMLPUBFUN const xmlChar * XMLCALL + xmlTextReaderConstName (xmlTextReaderPtr reader); +XMLPUBFUN const xmlChar * XMLCALL + xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader); +XMLPUBFUN const xmlChar * XMLCALL + xmlTextReaderConstPrefix (xmlTextReaderPtr reader); +XMLPUBFUN const xmlChar * XMLCALL + xmlTextReaderConstXmlLang (xmlTextReaderPtr reader); +XMLPUBFUN const xmlChar * XMLCALL + xmlTextReaderConstString (xmlTextReaderPtr reader, + const xmlChar *str); +XMLPUBFUN const xmlChar * XMLCALL + xmlTextReaderConstValue (xmlTextReaderPtr reader); + +/* + * use the Const version of the routine for + * better performance and simpler code + */ +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderBaseUri (xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderLocalName (xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderName (xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderNamespaceUri(xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderPrefix (xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderXmlLang (xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderValue (xmlTextReaderPtr reader); + +/* + * Methods of the XmlTextReader + */ +XMLPUBFUN int XMLCALL + xmlTextReaderClose (xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderGetAttributeNo (xmlTextReaderPtr reader, + int no); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderGetAttribute (xmlTextReaderPtr reader, + const xmlChar *name); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderGetAttributeNs (xmlTextReaderPtr reader, + const xmlChar *localName, + const xmlChar *namespaceURI); +XMLPUBFUN xmlParserInputBufferPtr XMLCALL + xmlTextReaderGetRemainder (xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, + const xmlChar *prefix); +XMLPUBFUN int XMLCALL + xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, + int no); +XMLPUBFUN int XMLCALL + xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, + const xmlChar *name); +XMLPUBFUN int XMLCALL + xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader, + const xmlChar *localName, + const xmlChar *namespaceURI); +XMLPUBFUN int XMLCALL + xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderMoveToElement (xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderNormalization (xmlTextReaderPtr reader); +XMLPUBFUN const xmlChar * XMLCALL + xmlTextReaderConstEncoding (xmlTextReaderPtr reader); + +/* + * Extensions + */ +XMLPUBFUN int XMLCALL + xmlTextReaderSetParserProp (xmlTextReaderPtr reader, + int prop, + int value); +XMLPUBFUN int XMLCALL + xmlTextReaderGetParserProp (xmlTextReaderPtr reader, + int prop); +XMLPUBFUN xmlNodePtr XMLCALL + xmlTextReaderCurrentNode (xmlTextReaderPtr reader); + +XMLPUBFUN int XMLCALL + xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader); + +XMLPUBFUN int XMLCALL + xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader); + +XMLPUBFUN xmlNodePtr XMLCALL + xmlTextReaderPreserve (xmlTextReaderPtr reader); +#ifdef LIBXML_PATTERN_ENABLED +XMLPUBFUN int XMLCALL + xmlTextReaderPreservePattern(xmlTextReaderPtr reader, + const xmlChar *pattern, + const xmlChar **namespaces); +#endif /* LIBXML_PATTERN_ENABLED */ +XMLPUBFUN xmlDocPtr XMLCALL + xmlTextReaderCurrentDoc (xmlTextReaderPtr reader); +XMLPUBFUN xmlNodePtr XMLCALL + xmlTextReaderExpand (xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderNext (xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderNextSibling (xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderIsValid (xmlTextReaderPtr reader); +#ifdef LIBXML_SCHEMAS_ENABLED +XMLPUBFUN int XMLCALL + xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, + const char *rng); +XMLPUBFUN int XMLCALL + xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, + xmlRelaxNGPtr schema); +XMLPUBFUN int XMLCALL + xmlTextReaderSchemaValidate (xmlTextReaderPtr reader, + const char *xsd); +XMLPUBFUN int XMLCALL + xmlTextReaderSetSchema (xmlTextReaderPtr reader, + xmlSchemaPtr schema); +#endif +XMLPUBFUN const xmlChar * XMLCALL + xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderStandalone (xmlTextReaderPtr reader); + + +/* + * Index lookup + */ +XMLPUBFUN long XMLCALL + xmlTextReaderByteConsumed (xmlTextReaderPtr reader); + +/* + * New more complete APIs for simpler creation and reuse of readers + */ +XMLPUBFUN xmlTextReaderPtr XMLCALL + xmlReaderWalker (xmlDocPtr doc); +XMLPUBFUN xmlTextReaderPtr XMLCALL + xmlReaderForDoc (const xmlChar * cur, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN xmlTextReaderPtr XMLCALL + xmlReaderForFile (const char *filename, + const char *encoding, + int options); +XMLPUBFUN xmlTextReaderPtr XMLCALL + xmlReaderForMemory (const char *buffer, + int size, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN xmlTextReaderPtr XMLCALL + xmlReaderForFd (int fd, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN xmlTextReaderPtr XMLCALL + xmlReaderForIO (xmlInputReadCallback ioread, + xmlInputCloseCallback ioclose, + void *ioctx, + const char *URL, + const char *encoding, + int options); + +XMLPUBFUN int XMLCALL + xmlReaderNewWalker (xmlTextReaderPtr reader, + xmlDocPtr doc); +XMLPUBFUN int XMLCALL + xmlReaderNewDoc (xmlTextReaderPtr reader, + const xmlChar * cur, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN int XMLCALL + xmlReaderNewFile (xmlTextReaderPtr reader, + const char *filename, + const char *encoding, + int options); +XMLPUBFUN int XMLCALL + xmlReaderNewMemory (xmlTextReaderPtr reader, + const char *buffer, + int size, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN int XMLCALL + xmlReaderNewFd (xmlTextReaderPtr reader, + int fd, + const char *URL, + const char *encoding, + int options); +XMLPUBFUN int XMLCALL + xmlReaderNewIO (xmlTextReaderPtr reader, + xmlInputReadCallback ioread, + xmlInputCloseCallback ioclose, + void *ioctx, + const char *URL, + const char *encoding, + int options); +/* + * Error handling extensions + */ +typedef void * xmlTextReaderLocatorPtr; +typedef void (XMLCALL *xmlTextReaderErrorFunc) (void *arg, + const char *msg, + xmlParserSeverities severity, + xmlTextReaderLocatorPtr locator); +XMLPUBFUN int XMLCALL + xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator); +/*int xmlTextReaderLocatorLinePosition(xmlTextReaderLocatorPtr locator);*/ +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderLocatorBaseURI (xmlTextReaderLocatorPtr locator); +XMLPUBFUN void XMLCALL + xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader, + xmlTextReaderErrorFunc f, + void *arg); +XMLPUBFUN void XMLCALL + xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader, + xmlStructuredErrorFunc f, + void *arg); +XMLPUBFUN void XMLCALL + xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader, + xmlTextReaderErrorFunc *f, + void **arg); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_READER_ENABLED */ + +#endif /* __XML_XMLREADER_H__ */ + diff --git a/include/libxml/xmlregexp.h b/include/libxml/xmlregexp.h new file mode 100644 index 0000000..a7b3b29 --- /dev/null +++ b/include/libxml/xmlregexp.h @@ -0,0 +1,108 @@ +/* + * Summary: regular expressions handling + * Description: basic API for libxml regular expressions handling used + * for XML Schemas and validation. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_REGEXP_H__ +#define __XML_REGEXP_H__ + +#include + +#ifdef LIBXML_REGEXP_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * xmlRegexpPtr: + * + * A libxml regular expression, they can actually be far more complex + * thank the POSIX regex expressions. + */ +typedef struct _xmlRegexp xmlRegexp; +typedef xmlRegexp *xmlRegexpPtr; + +/** + * xmlRegExecCtxtPtr: + * + * A libxml progressive regular expression evaluation context + */ +typedef struct _xmlRegExecCtxt xmlRegExecCtxt; +typedef xmlRegExecCtxt *xmlRegExecCtxtPtr; + +#ifdef __cplusplus +} +#endif +#include +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The POSIX like API + */ +XMLPUBFUN xmlRegexpPtr XMLCALL + xmlRegexpCompile (const xmlChar *regexp); +XMLPUBFUN void XMLCALL xmlRegFreeRegexp(xmlRegexpPtr regexp); +XMLPUBFUN int XMLCALL + xmlRegexpExec (xmlRegexpPtr comp, + const xmlChar *value); +XMLPUBFUN void XMLCALL + xmlRegexpPrint (FILE *output, + xmlRegexpPtr regexp); +XMLPUBFUN int XMLCALL + xmlRegexpIsDeterminist(xmlRegexpPtr comp); + +/* + * Callback function when doing a transition in the automata + */ +typedef void (*xmlRegExecCallbacks) (xmlRegExecCtxtPtr exec, + const xmlChar *token, + void *transdata, + void *inputdata); + +/* + * The progressive API + */ +XMLPUBFUN xmlRegExecCtxtPtr XMLCALL + xmlRegNewExecCtxt (xmlRegexpPtr comp, + xmlRegExecCallbacks callback, + void *data); +XMLPUBFUN void XMLCALL + xmlRegFreeExecCtxt (xmlRegExecCtxtPtr exec); +XMLPUBFUN int XMLCALL + xmlRegExecPushString(xmlRegExecCtxtPtr exec, + const xmlChar *value, + void *data); +XMLPUBFUN int XMLCALL + xmlRegExecPushString2(xmlRegExecCtxtPtr exec, + const xmlChar *value, + const xmlChar *value2, + void *data); + +XMLPUBFUN int XMLCALL + xmlRegExecNextValues(xmlRegExecCtxtPtr exec, + int *nbval, + int *nbneg, + xmlChar **values, + int *terminal); +XMLPUBFUN int XMLCALL + xmlRegExecErrInfo (xmlRegExecCtxtPtr exec, + const xmlChar **string, + int *nbval, + int *nbneg, + xmlChar **values, + int *terminal); +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_REGEXP_ENABLED */ + +#endif /*__XML_REGEXP_H__ */ diff --git a/include/libxml/xmlsave.h b/include/libxml/xmlsave.h new file mode 100644 index 0000000..534fefd --- /dev/null +++ b/include/libxml/xmlsave.h @@ -0,0 +1,83 @@ +/* + * Summary: the XML document serializer + * Description: API to save document or subtree of document + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_XMLSAVE_H__ +#define __XML_XMLSAVE_H__ + +#include +#include +#include +#include + +#ifdef LIBXML_OUTPUT_ENABLED +#ifdef __cplusplus +extern "C" { +#endif + +/** + * xmlSaveOption: + * + * This is the set of XML save options that can be passed down + * to the xmlSaveToFd() and similar calls. + */ +typedef enum { + XML_SAVE_FORMAT = 1<<0 /* format save output */ +} xmlSaveOption; + + +typedef struct _xmlSaveCtxt xmlSaveCtxt; +typedef xmlSaveCtxt *xmlSaveCtxtPtr; + +XMLPUBFUN xmlSaveCtxtPtr XMLCALL + xmlSaveToFd (int fd, + const char *encoding, + int options); +XMLPUBFUN xmlSaveCtxtPtr XMLCALL + xmlSaveToFilename (const char *filename, + const char *encoding, + int options); +/****** + Not yet implemented. + +XMLPUBFUN xmlSaveCtxtPtr XMLCALL + xmlSaveToBuffer (xmlBufferPtr buffer, + const char *encoding, + int options); + ******/ +XMLPUBFUN xmlSaveCtxtPtr XMLCALL + xmlSaveToIO (xmlOutputWriteCallback iowrite, + xmlOutputCloseCallback ioclose, + void *ioctx, + const char *encoding, + int options); + +XMLPUBFUN long XMLCALL + xmlSaveDoc (xmlSaveCtxtPtr ctxt, + xmlDocPtr doc); +XMLPUBFUN long XMLCALL + xmlSaveTree (xmlSaveCtxtPtr ctxt, + xmlNodePtr node); + +XMLPUBFUN int XMLCALL + xmlSaveFlush (xmlSaveCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + xmlSaveClose (xmlSaveCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + xmlSaveSetEscape (xmlSaveCtxtPtr ctxt, + xmlCharEncodingOutputFunc escape); +XMLPUBFUN int XMLCALL + xmlSaveSetAttrEscape (xmlSaveCtxtPtr ctxt, + xmlCharEncodingOutputFunc escape); +#ifdef __cplusplus +} +#endif +#endif /* LIBXML_OUTPUT_ENABLED */ +#endif /* __XML_XMLSAVE_H__ */ + + diff --git a/include/libxml/xmlschemas.h b/include/libxml/xmlschemas.h new file mode 100644 index 0000000..6cecffd --- /dev/null +++ b/include/libxml/xmlschemas.h @@ -0,0 +1,190 @@ +/* + * Summary: incomplete XML Schemas structure implementation + * Description: interface to the XML Schemas handling and schema validity + * checking, it is incomplete right now. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + + +#ifndef __XML_SCHEMA_H__ +#define __XML_SCHEMA_H__ + +#include + +#ifdef LIBXML_SCHEMAS_ENABLED + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This error codes are obsolete; not used any more. + */ +typedef enum { + XML_SCHEMAS_ERR_OK = 0, + XML_SCHEMAS_ERR_NOROOT = 1, + XML_SCHEMAS_ERR_UNDECLAREDELEM, + XML_SCHEMAS_ERR_NOTTOPLEVEL, + XML_SCHEMAS_ERR_MISSING, + XML_SCHEMAS_ERR_WRONGELEM, + XML_SCHEMAS_ERR_NOTYPE, + XML_SCHEMAS_ERR_NOROLLBACK, + XML_SCHEMAS_ERR_ISABSTRACT, + XML_SCHEMAS_ERR_NOTEMPTY, + XML_SCHEMAS_ERR_ELEMCONT, + XML_SCHEMAS_ERR_HAVEDEFAULT, + XML_SCHEMAS_ERR_NOTNILLABLE, + XML_SCHEMAS_ERR_EXTRACONTENT, + XML_SCHEMAS_ERR_INVALIDATTR, + XML_SCHEMAS_ERR_INVALIDELEM, + XML_SCHEMAS_ERR_NOTDETERMINIST, + XML_SCHEMAS_ERR_CONSTRUCT, + XML_SCHEMAS_ERR_INTERNAL, + XML_SCHEMAS_ERR_NOTSIMPLE, + XML_SCHEMAS_ERR_ATTRUNKNOWN, + XML_SCHEMAS_ERR_ATTRINVALID, + XML_SCHEMAS_ERR_VALUE, + XML_SCHEMAS_ERR_FACET, + XML_SCHEMAS_ERR_, + XML_SCHEMAS_ERR_XXX +} xmlSchemaValidError; + +/* +* ATTENTION: Change xmlSchemaSetValidOptions's check +* for invalid values, if adding to the validation +* options below. +*/ +/** + * xmlSchemaValidOption: + * + * This is the set of XML Schema validation options. + */ +typedef enum { + XML_SCHEMA_VAL_VC_I_CREATE = 1<<0 + /* Default/fixed: create an attribute node + * or an element's text node on the instance. + */ +} xmlSchemaValidOption; + +/* + XML_SCHEMA_VAL_XSI_ASSEMBLE = 1<<1, + * assemble schemata using + * xsi:schemaLocation and + * xsi:noNamespaceSchemaLocation +*/ + +/** + * The schemas related types are kept internal + */ +typedef struct _xmlSchema xmlSchema; +typedef xmlSchema *xmlSchemaPtr; + +/** + * A schemas validation context + */ +typedef void (*xmlSchemaValidityErrorFunc) (void *ctx, const char *msg, ...); +typedef void (*xmlSchemaValidityWarningFunc) (void *ctx, const char *msg, ...); + +typedef struct _xmlSchemaParserCtxt xmlSchemaParserCtxt; +typedef xmlSchemaParserCtxt *xmlSchemaParserCtxtPtr; + +typedef struct _xmlSchemaValidCtxt xmlSchemaValidCtxt; +typedef xmlSchemaValidCtxt *xmlSchemaValidCtxtPtr; + +/* + * Interfaces for parsing. + */ +XMLPUBFUN xmlSchemaParserCtxtPtr XMLCALL + xmlSchemaNewParserCtxt (const char *URL); +XMLPUBFUN xmlSchemaParserCtxtPtr XMLCALL + xmlSchemaNewMemParserCtxt (const char *buffer, + int size); +XMLPUBFUN xmlSchemaParserCtxtPtr XMLCALL + xmlSchemaNewDocParserCtxt (xmlDocPtr doc); +XMLPUBFUN void XMLCALL + xmlSchemaFreeParserCtxt (xmlSchemaParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlSchemaSetParserErrors (xmlSchemaParserCtxtPtr ctxt, + xmlSchemaValidityErrorFunc err, + xmlSchemaValidityWarningFunc warn, + void *ctx); +XMLPUBFUN int XMLCALL + xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt, + xmlSchemaValidityErrorFunc * err, + xmlSchemaValidityWarningFunc * warn, + void **ctx); +XMLPUBFUN int XMLCALL + xmlSchemaIsValid (xmlSchemaValidCtxtPtr ctxt); + +XMLPUBFUN xmlSchemaPtr XMLCALL + xmlSchemaParse (xmlSchemaParserCtxtPtr ctxt); +XMLPUBFUN void XMLCALL + xmlSchemaFree (xmlSchemaPtr schema); +#ifdef LIBXML_OUTPUT_ENABLED +XMLPUBFUN void XMLCALL + xmlSchemaDump (FILE *output, + xmlSchemaPtr schema); +#endif /* LIBXML_OUTPUT_ENABLED */ +/* + * Interfaces for validating + */ +XMLPUBFUN void XMLCALL + xmlSchemaSetValidErrors (xmlSchemaValidCtxtPtr ctxt, + xmlSchemaValidityErrorFunc err, + xmlSchemaValidityWarningFunc warn, + void *ctx); +XMLPUBFUN int XMLCALL + xmlSchemaGetValidErrors (xmlSchemaValidCtxtPtr ctxt, + xmlSchemaValidityErrorFunc *err, + xmlSchemaValidityWarningFunc *warn, + void **ctx); +XMLPUBFUN int XMLCALL + xmlSchemaSetValidOptions (xmlSchemaValidCtxtPtr ctxt, + int options); +XMLPUBFUN int XMLCALL + xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt); + +XMLPUBFUN xmlSchemaValidCtxtPtr XMLCALL + xmlSchemaNewValidCtxt (xmlSchemaPtr schema); +XMLPUBFUN void XMLCALL + xmlSchemaFreeValidCtxt (xmlSchemaValidCtxtPtr ctxt); +XMLPUBFUN int XMLCALL + xmlSchemaValidateDoc (xmlSchemaValidCtxtPtr ctxt, + xmlDocPtr instance); +XMLPUBFUN int XMLCALL + xmlSchemaValidateOneElement (xmlSchemaValidCtxtPtr ctxt, + xmlNodePtr elem); +XMLPUBFUN int XMLCALL + xmlSchemaValidateStream (xmlSchemaValidCtxtPtr ctxt, + xmlParserInputBufferPtr input, + xmlCharEncoding enc, + xmlSAXHandlerPtr sax, + void *user_data); +XMLPUBFUN int XMLCALL + xmlSchemaValidateFile (xmlSchemaValidCtxtPtr ctxt, + const char * filename, + int options); + +/* + * Interface to insert Schemas SAX velidation in a SAX stream + */ +typedef struct _xmlSchemaSAXPlug xmlSchemaSAXPlugStruct; +typedef xmlSchemaSAXPlugStruct *xmlSchemaSAXPlugPtr; + +XMLPUBFUN xmlSchemaSAXPlugPtr XMLCALL + xmlSchemaSAXPlug (xmlSchemaValidCtxtPtr ctxt, + xmlSAXHandlerPtr *sax, + void **user_data); +XMLPUBFUN int XMLCALL + xmlSchemaSAXUnplug (xmlSchemaSAXPlugPtr plug); +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_SCHEMAS_ENABLED */ +#endif /* __XML_SCHEMA_H__ */ diff --git a/include/libxml/xmlschemastypes.h b/include/libxml/xmlschemastypes.h new file mode 100644 index 0000000..9a3a7a1 --- /dev/null +++ b/include/libxml/xmlschemastypes.h @@ -0,0 +1,151 @@ +/* + * Summary: implementation of XML Schema Datatypes + * Description: module providing the XML Schema Datatypes implementation + * both definition and validity checking + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + + +#ifndef __XML_SCHEMA_TYPES_H__ +#define __XML_SCHEMA_TYPES_H__ + +#include + +#ifdef LIBXML_SCHEMAS_ENABLED + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + XML_SCHEMA_WHITESPACE_UNKNOWN = 0, + XML_SCHEMA_WHITESPACE_PRESERVE = 1, + XML_SCHEMA_WHITESPACE_REPLACE = 2, + XML_SCHEMA_WHITESPACE_COLLAPSE = 3 +} xmlSchemaWhitespaceValueType; + +XMLPUBFUN void XMLCALL + xmlSchemaInitTypes (void); +XMLPUBFUN void XMLCALL + xmlSchemaCleanupTypes (void); +XMLPUBFUN xmlSchemaTypePtr XMLCALL + xmlSchemaGetPredefinedType (const xmlChar *name, + const xmlChar *ns); +XMLPUBFUN int XMLCALL + xmlSchemaValidatePredefinedType (xmlSchemaTypePtr type, + const xmlChar *value, + xmlSchemaValPtr *val); +XMLPUBFUN int XMLCALL + xmlSchemaValPredefTypeNode (xmlSchemaTypePtr type, + const xmlChar *value, + xmlSchemaValPtr *val, + xmlNodePtr node); +XMLPUBFUN int XMLCALL + xmlSchemaValidateFacet (xmlSchemaTypePtr base, + xmlSchemaFacetPtr facet, + const xmlChar *value, + xmlSchemaValPtr val); +XMLPUBFUN int XMLCALL + xmlSchemaValidateFacetWhtsp (xmlSchemaFacetPtr facet, + xmlSchemaWhitespaceValueType fws, + xmlSchemaValType valType, + const xmlChar *value, + xmlSchemaValPtr val, + xmlSchemaWhitespaceValueType ws); +XMLPUBFUN void XMLCALL + xmlSchemaFreeValue (xmlSchemaValPtr val); +XMLPUBFUN xmlSchemaFacetPtr XMLCALL + xmlSchemaNewFacet (void); +XMLPUBFUN int XMLCALL + xmlSchemaCheckFacet (xmlSchemaFacetPtr facet, + xmlSchemaTypePtr typeDecl, + xmlSchemaParserCtxtPtr ctxt, + const xmlChar *name); +XMLPUBFUN void XMLCALL + xmlSchemaFreeFacet (xmlSchemaFacetPtr facet); +XMLPUBFUN int XMLCALL + xmlSchemaCompareValues (xmlSchemaValPtr x, + xmlSchemaValPtr y); +XMLPUBFUN xmlSchemaTypePtr XMLCALL + xmlSchemaGetBuiltInListSimpleTypeItemType (xmlSchemaTypePtr type); +XMLPUBFUN int XMLCALL + xmlSchemaValidateListSimpleTypeFacet (xmlSchemaFacetPtr facet, + const xmlChar *value, + unsigned long actualLen, + unsigned long *expectedLen); +XMLPUBFUN xmlSchemaTypePtr XMLCALL + xmlSchemaGetBuiltInType (xmlSchemaValType type); +XMLPUBFUN int XMLCALL + xmlSchemaIsBuiltInTypeFacet (xmlSchemaTypePtr type, + int facetType); +XMLPUBFUN xmlChar * XMLCALL + xmlSchemaCollapseString (const xmlChar *value); +XMLPUBFUN xmlChar * XMLCALL + xmlSchemaWhiteSpaceReplace (const xmlChar *value); +XMLPUBFUN unsigned long XMLCALL + xmlSchemaGetFacetValueAsULong (xmlSchemaFacetPtr facet); +XMLPUBFUN int XMLCALL + xmlSchemaValidateLengthFacet (xmlSchemaTypePtr type, + xmlSchemaFacetPtr facet, + const xmlChar *value, + xmlSchemaValPtr val, + unsigned long *length); +XMLPUBFUN int XMLCALL + xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet, + xmlSchemaValType valType, + const xmlChar *value, + xmlSchemaValPtr val, + unsigned long *length, + xmlSchemaWhitespaceValueType ws); +XMLPUBFUN int XMLCALL + xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type, + const xmlChar *value, + xmlSchemaValPtr *val, + xmlNodePtr node); +XMLPUBFUN int XMLCALL + xmlSchemaGetCanonValue (xmlSchemaValPtr val, + const xmlChar **retValue); +XMLPUBFUN int XMLCALL + xmlSchemaGetCanonValueWhtsp (xmlSchemaValPtr val, + const xmlChar **retValue, + xmlSchemaWhitespaceValueType ws); +XMLPUBFUN int XMLCALL + xmlSchemaValueAppend (xmlSchemaValPtr prev, + xmlSchemaValPtr cur); +XMLPUBFUN xmlSchemaValPtr XMLCALL + xmlSchemaValueGetNext (xmlSchemaValPtr cur); +XMLPUBFUN const xmlChar * XMLCALL + xmlSchemaValueGetAsString (xmlSchemaValPtr val); +XMLPUBFUN int XMLCALL + xmlSchemaValueGetAsBoolean (xmlSchemaValPtr val); +XMLPUBFUN xmlSchemaValPtr XMLCALL + xmlSchemaNewStringValue (xmlSchemaValType type, + const xmlChar *value); +XMLPUBFUN xmlSchemaValPtr XMLCALL + xmlSchemaNewNOTATIONValue (const xmlChar *name, + const xmlChar *ns); +XMLPUBFUN xmlSchemaValPtr XMLCALL + xmlSchemaNewQNameValue (const xmlChar *namespaceName, + const xmlChar *localName); +XMLPUBFUN int XMLCALL + xmlSchemaCompareValuesWhtsp (xmlSchemaValPtr x, + xmlSchemaWhitespaceValueType xws, + xmlSchemaValPtr y, + xmlSchemaWhitespaceValueType yws); +XMLPUBFUN xmlSchemaValPtr XMLCALL + xmlSchemaCopyValue (xmlSchemaValPtr val); +XMLPUBFUN xmlSchemaValType XMLCALL + xmlSchemaGetValType (xmlSchemaValPtr val); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_SCHEMAS_ENABLED */ +#endif /* __XML_SCHEMA_TYPES_H__ */ diff --git a/include/libxml/xmlstring.h b/include/libxml/xmlstring.h new file mode 100644 index 0000000..39f846e --- /dev/null +++ b/include/libxml/xmlstring.h @@ -0,0 +1,141 @@ +/* + * Summary: set of routines to process strings + * Description: type and interfaces needed for the internal string handling + * of the library, especially UTF8 processing. + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_STRING_H__ +#define __XML_STRING_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * xmlChar: + * + * This is a basic byte in an UTF-8 encoded string. + * It's unsigned allowing to pinpoint case where char * are assigned + * to xmlChar * (possibly making serialization back impossible). + */ + +typedef unsigned char xmlChar; + +/** + * BAD_CAST: + * + * Macro to cast a string to an xmlChar * when one know its safe. + */ +#define BAD_CAST (xmlChar *) + +/* + * xmlChar handling + */ +XMLPUBFUN xmlChar * XMLCALL + xmlStrdup (const xmlChar *cur); +XMLPUBFUN xmlChar * XMLCALL + xmlStrndup (const xmlChar *cur, + int len); +XMLPUBFUN xmlChar * XMLCALL + xmlCharStrndup (const char *cur, + int len); +XMLPUBFUN xmlChar * XMLCALL + xmlCharStrdup (const char *cur); +XMLPUBFUN xmlChar * XMLCALL + xmlStrsub (const xmlChar *str, + int start, + int len); +XMLPUBFUN const xmlChar * XMLCALL + xmlStrchr (const xmlChar *str, + xmlChar val); +XMLPUBFUN const xmlChar * XMLCALL + xmlStrstr (const xmlChar *str, + const xmlChar *val); +XMLPUBFUN const xmlChar * XMLCALL + xmlStrcasestr (const xmlChar *str, + xmlChar *val); +XMLPUBFUN int XMLCALL + xmlStrcmp (const xmlChar *str1, + const xmlChar *str2); +XMLPUBFUN int XMLCALL + xmlStrncmp (const xmlChar *str1, + const xmlChar *str2, + int len); +XMLPUBFUN int XMLCALL + xmlStrcasecmp (const xmlChar *str1, + const xmlChar *str2); +XMLPUBFUN int XMLCALL + xmlStrncasecmp (const xmlChar *str1, + const xmlChar *str2, + int len); +XMLPUBFUN int XMLCALL + xmlStrEqual (const xmlChar *str1, + const xmlChar *str2); +XMLPUBFUN int XMLCALL + xmlStrQEqual (const xmlChar *pref, + const xmlChar *name, + const xmlChar *str); +XMLPUBFUN int XMLCALL + xmlStrlen (const xmlChar *str); +XMLPUBFUN xmlChar * XMLCALL + xmlStrcat (xmlChar *cur, + const xmlChar *add); +XMLPUBFUN xmlChar * XMLCALL + xmlStrncat (xmlChar *cur, + const xmlChar *add, + int len); +XMLPUBFUN xmlChar * XMLCALL + xmlStrncatNew (const xmlChar *str1, + const xmlChar *str2, + int len); +XMLPUBFUN int XMLCALL + xmlStrPrintf (xmlChar *buf, + int len, + const xmlChar *msg, + ...); +XMLPUBFUN int XMLCALL + xmlStrVPrintf (xmlChar *buf, + int len, + const xmlChar *msg, + va_list ap); + +XMLPUBFUN int XMLCALL + xmlGetUTF8Char (const unsigned char *utf, + int *len); +XMLPUBFUN int XMLCALL + xmlCheckUTF8 (const unsigned char *utf); +XMLPUBFUN int XMLCALL + xmlUTF8Strsize (const xmlChar *utf, + int len); +XMLPUBFUN xmlChar * XMLCALL + xmlUTF8Strndup (const xmlChar *utf, + int len); +XMLPUBFUN const xmlChar * XMLCALL + xmlUTF8Strpos (const xmlChar *utf, + int pos); +XMLPUBFUN int XMLCALL + xmlUTF8Strloc (const xmlChar *utf, + const xmlChar *utfchar); +XMLPUBFUN xmlChar * XMLCALL + xmlUTF8Strsub (const xmlChar *utf, + int start, + int len); +XMLPUBFUN int XMLCALL + xmlUTF8Strlen (const xmlChar *utf); +XMLPUBFUN int XMLCALL + xmlUTF8Size (const xmlChar *utf); +XMLPUBFUN int XMLCALL + xmlUTF8Charcmp (const xmlChar *utf1, + const xmlChar *utf2); + +#ifdef __cplusplus +} +#endif +#endif /* __XML_STRING_H__ */ diff --git a/include/libxml/xmlunicode.h b/include/libxml/xmlunicode.h new file mode 100644 index 0000000..3882b1f --- /dev/null +++ b/include/libxml/xmlunicode.h @@ -0,0 +1,202 @@ +/* + * Summary: Unicode character APIs + * Description: API for the Unicode character APIs + * + * This file is automatically generated from the + * UCS description files of the Unicode Character Database + * http://www.unicode.org/Public/4.0-Update1/UCD-4.0.1d5b.html + * using the genUnicode.py Python script. + * + * Generation date: Mon Nov 10 22:35:10 2003 + * Sources: Blocks-4.0.1d1b.txt UnicodeData-4.0.1d1b.txt + * Author: Daniel Veillard + */ + +#ifndef __XML_UNICODE_H__ +#define __XML_UNICODE_H__ + +#include + +#ifdef LIBXML_UNICODE_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +XMLPUBFUN int XMLCALL xmlUCSIsAegeanNumbers (int code); +XMLPUBFUN int XMLCALL xmlUCSIsAlphabeticPresentationForms (int code); +XMLPUBFUN int XMLCALL xmlUCSIsArabic (int code); +XMLPUBFUN int XMLCALL xmlUCSIsArabicPresentationFormsA (int code); +XMLPUBFUN int XMLCALL xmlUCSIsArabicPresentationFormsB (int code); +XMLPUBFUN int XMLCALL xmlUCSIsArmenian (int code); +XMLPUBFUN int XMLCALL xmlUCSIsArrows (int code); +XMLPUBFUN int XMLCALL xmlUCSIsBasicLatin (int code); +XMLPUBFUN int XMLCALL xmlUCSIsBengali (int code); +XMLPUBFUN int XMLCALL xmlUCSIsBlockElements (int code); +XMLPUBFUN int XMLCALL xmlUCSIsBopomofo (int code); +XMLPUBFUN int XMLCALL xmlUCSIsBopomofoExtended (int code); +XMLPUBFUN int XMLCALL xmlUCSIsBoxDrawing (int code); +XMLPUBFUN int XMLCALL xmlUCSIsBraillePatterns (int code); +XMLPUBFUN int XMLCALL xmlUCSIsBuhid (int code); +XMLPUBFUN int XMLCALL xmlUCSIsByzantineMusicalSymbols (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCJKCompatibility (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCJKCompatibilityForms (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCJKCompatibilityIdeographs (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCJKCompatibilityIdeographsSupplement (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCJKRadicalsSupplement (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCJKSymbolsandPunctuation (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCJKUnifiedIdeographs (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCJKUnifiedIdeographsExtensionA (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCJKUnifiedIdeographsExtensionB (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCherokee (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCombiningDiacriticalMarks (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCombiningDiacriticalMarksforSymbols (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCombiningHalfMarks (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCombiningMarksforSymbols (int code); +XMLPUBFUN int XMLCALL xmlUCSIsControlPictures (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCurrencySymbols (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCypriotSyllabary (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCyrillic (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCyrillicSupplement (int code); +XMLPUBFUN int XMLCALL xmlUCSIsDeseret (int code); +XMLPUBFUN int XMLCALL xmlUCSIsDevanagari (int code); +XMLPUBFUN int XMLCALL xmlUCSIsDingbats (int code); +XMLPUBFUN int XMLCALL xmlUCSIsEnclosedAlphanumerics (int code); +XMLPUBFUN int XMLCALL xmlUCSIsEnclosedCJKLettersandMonths (int code); +XMLPUBFUN int XMLCALL xmlUCSIsEthiopic (int code); +XMLPUBFUN int XMLCALL xmlUCSIsGeneralPunctuation (int code); +XMLPUBFUN int XMLCALL xmlUCSIsGeometricShapes (int code); +XMLPUBFUN int XMLCALL xmlUCSIsGeorgian (int code); +XMLPUBFUN int XMLCALL xmlUCSIsGothic (int code); +XMLPUBFUN int XMLCALL xmlUCSIsGreek (int code); +XMLPUBFUN int XMLCALL xmlUCSIsGreekExtended (int code); +XMLPUBFUN int XMLCALL xmlUCSIsGreekandCoptic (int code); +XMLPUBFUN int XMLCALL xmlUCSIsGujarati (int code); +XMLPUBFUN int XMLCALL xmlUCSIsGurmukhi (int code); +XMLPUBFUN int XMLCALL xmlUCSIsHalfwidthandFullwidthForms (int code); +XMLPUBFUN int XMLCALL xmlUCSIsHangulCompatibilityJamo (int code); +XMLPUBFUN int XMLCALL xmlUCSIsHangulJamo (int code); +XMLPUBFUN int XMLCALL xmlUCSIsHangulSyllables (int code); +XMLPUBFUN int XMLCALL xmlUCSIsHanunoo (int code); +XMLPUBFUN int XMLCALL xmlUCSIsHebrew (int code); +XMLPUBFUN int XMLCALL xmlUCSIsHighPrivateUseSurrogates (int code); +XMLPUBFUN int XMLCALL xmlUCSIsHighSurrogates (int code); +XMLPUBFUN int XMLCALL xmlUCSIsHiragana (int code); +XMLPUBFUN int XMLCALL xmlUCSIsIPAExtensions (int code); +XMLPUBFUN int XMLCALL xmlUCSIsIdeographicDescriptionCharacters (int code); +XMLPUBFUN int XMLCALL xmlUCSIsKanbun (int code); +XMLPUBFUN int XMLCALL xmlUCSIsKangxiRadicals (int code); +XMLPUBFUN int XMLCALL xmlUCSIsKannada (int code); +XMLPUBFUN int XMLCALL xmlUCSIsKatakana (int code); +XMLPUBFUN int XMLCALL xmlUCSIsKatakanaPhoneticExtensions (int code); +XMLPUBFUN int XMLCALL xmlUCSIsKhmer (int code); +XMLPUBFUN int XMLCALL xmlUCSIsKhmerSymbols (int code); +XMLPUBFUN int XMLCALL xmlUCSIsLao (int code); +XMLPUBFUN int XMLCALL xmlUCSIsLatin1Supplement (int code); +XMLPUBFUN int XMLCALL xmlUCSIsLatinExtendedA (int code); +XMLPUBFUN int XMLCALL xmlUCSIsLatinExtendedB (int code); +XMLPUBFUN int XMLCALL xmlUCSIsLatinExtendedAdditional (int code); +XMLPUBFUN int XMLCALL xmlUCSIsLetterlikeSymbols (int code); +XMLPUBFUN int XMLCALL xmlUCSIsLimbu (int code); +XMLPUBFUN int XMLCALL xmlUCSIsLinearBIdeograms (int code); +XMLPUBFUN int XMLCALL xmlUCSIsLinearBSyllabary (int code); +XMLPUBFUN int XMLCALL xmlUCSIsLowSurrogates (int code); +XMLPUBFUN int XMLCALL xmlUCSIsMalayalam (int code); +XMLPUBFUN int XMLCALL xmlUCSIsMathematicalAlphanumericSymbols (int code); +XMLPUBFUN int XMLCALL xmlUCSIsMathematicalOperators (int code); +XMLPUBFUN int XMLCALL xmlUCSIsMiscellaneousMathematicalSymbolsA (int code); +XMLPUBFUN int XMLCALL xmlUCSIsMiscellaneousMathematicalSymbolsB (int code); +XMLPUBFUN int XMLCALL xmlUCSIsMiscellaneousSymbols (int code); +XMLPUBFUN int XMLCALL xmlUCSIsMiscellaneousSymbolsandArrows (int code); +XMLPUBFUN int XMLCALL xmlUCSIsMiscellaneousTechnical (int code); +XMLPUBFUN int XMLCALL xmlUCSIsMongolian (int code); +XMLPUBFUN int XMLCALL xmlUCSIsMusicalSymbols (int code); +XMLPUBFUN int XMLCALL xmlUCSIsMyanmar (int code); +XMLPUBFUN int XMLCALL xmlUCSIsNumberForms (int code); +XMLPUBFUN int XMLCALL xmlUCSIsOgham (int code); +XMLPUBFUN int XMLCALL xmlUCSIsOldItalic (int code); +XMLPUBFUN int XMLCALL xmlUCSIsOpticalCharacterRecognition (int code); +XMLPUBFUN int XMLCALL xmlUCSIsOriya (int code); +XMLPUBFUN int XMLCALL xmlUCSIsOsmanya (int code); +XMLPUBFUN int XMLCALL xmlUCSIsPhoneticExtensions (int code); +XMLPUBFUN int XMLCALL xmlUCSIsPrivateUse (int code); +XMLPUBFUN int XMLCALL xmlUCSIsPrivateUseArea (int code); +XMLPUBFUN int XMLCALL xmlUCSIsRunic (int code); +XMLPUBFUN int XMLCALL xmlUCSIsShavian (int code); +XMLPUBFUN int XMLCALL xmlUCSIsSinhala (int code); +XMLPUBFUN int XMLCALL xmlUCSIsSmallFormVariants (int code); +XMLPUBFUN int XMLCALL xmlUCSIsSpacingModifierLetters (int code); +XMLPUBFUN int XMLCALL xmlUCSIsSpecials (int code); +XMLPUBFUN int XMLCALL xmlUCSIsSuperscriptsandSubscripts (int code); +XMLPUBFUN int XMLCALL xmlUCSIsSupplementalArrowsA (int code); +XMLPUBFUN int XMLCALL xmlUCSIsSupplementalArrowsB (int code); +XMLPUBFUN int XMLCALL xmlUCSIsSupplementalMathematicalOperators (int code); +XMLPUBFUN int XMLCALL xmlUCSIsSupplementaryPrivateUseAreaA (int code); +XMLPUBFUN int XMLCALL xmlUCSIsSupplementaryPrivateUseAreaB (int code); +XMLPUBFUN int XMLCALL xmlUCSIsSyriac (int code); +XMLPUBFUN int XMLCALL xmlUCSIsTagalog (int code); +XMLPUBFUN int XMLCALL xmlUCSIsTagbanwa (int code); +XMLPUBFUN int XMLCALL xmlUCSIsTags (int code); +XMLPUBFUN int XMLCALL xmlUCSIsTaiLe (int code); +XMLPUBFUN int XMLCALL xmlUCSIsTaiXuanJingSymbols (int code); +XMLPUBFUN int XMLCALL xmlUCSIsTamil (int code); +XMLPUBFUN int XMLCALL xmlUCSIsTelugu (int code); +XMLPUBFUN int XMLCALL xmlUCSIsThaana (int code); +XMLPUBFUN int XMLCALL xmlUCSIsThai (int code); +XMLPUBFUN int XMLCALL xmlUCSIsTibetan (int code); +XMLPUBFUN int XMLCALL xmlUCSIsUgaritic (int code); +XMLPUBFUN int XMLCALL xmlUCSIsUnifiedCanadianAboriginalSyllabics (int code); +XMLPUBFUN int XMLCALL xmlUCSIsVariationSelectors (int code); +XMLPUBFUN int XMLCALL xmlUCSIsVariationSelectorsSupplement (int code); +XMLPUBFUN int XMLCALL xmlUCSIsYiRadicals (int code); +XMLPUBFUN int XMLCALL xmlUCSIsYiSyllables (int code); +XMLPUBFUN int XMLCALL xmlUCSIsYijingHexagramSymbols (int code); + +XMLPUBFUN int XMLCALL xmlUCSIsBlock (int code, const char *block); + +XMLPUBFUN int XMLCALL xmlUCSIsCatC (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatCc (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatCf (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatCo (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatCs (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatL (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatLl (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatLm (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatLo (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatLt (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatLu (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatM (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatMc (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatMe (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatMn (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatN (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatNd (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatNl (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatNo (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatP (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatPc (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatPd (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatPe (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatPf (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatPi (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatPo (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatPs (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatS (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatSc (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatSk (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatSm (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatSo (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatZ (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatZl (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatZp (int code); +XMLPUBFUN int XMLCALL xmlUCSIsCatZs (int code); + +XMLPUBFUN int XMLCALL xmlUCSIsCat (int code, const char *cat); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_UNICODE_ENABLED */ + +#endif /* __XML_UNICODE_H__ */ diff --git a/include/libxml/xmlversion.h b/include/libxml/xmlversion.h new file mode 100644 index 0000000..b58982b --- /dev/null +++ b/include/libxml/xmlversion.h @@ -0,0 +1,373 @@ +/* + * Summary: compile-time version informations + * Description: compile-time version informations for the XML library + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_VERSION_H__ +#define __XML_VERSION_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * use those to be sure nothing nasty will happen if + * your library and includes mismatch + */ +#ifndef LIBXML2_COMPILING_MSCCDEF +XMLPUBFUN void XMLCALL xmlCheckVersion(int version); +#endif /* LIBXML2_COMPILING_MSCCDEF */ + +/** + * LIBXML_DOTTED_VERSION: + * + * the version string like "1.2.3" + */ +#define LIBXML_DOTTED_VERSION "2.6.20" + +/** + * LIBXML_VERSION: + * + * the version number: 1.2.3 value is 1002003 + */ +#define LIBXML_VERSION 20620 + +/** + * LIBXML_VERSION_STRING: + * + * the version number string, 1.2.3 value is "1002003" + */ +#define LIBXML_VERSION_STRING "20620" + +/** + * LIBXML_VERSION_EXTRA: + * + * extra version information, used to show a CVS compilation + */ +#define LIBXML_VERSION_EXTRA "" + +/** + * LIBXML_TEST_VERSION: + * + * Macro to check that the libxml version in use is compatible with + * the version the software has been compiled against + */ +#define LIBXML_TEST_VERSION xmlCheckVersion(20620); + +#ifndef VMS +#if 0 +/** + * WITH_TRIO: + * + * defined if the trio support need to be configured in + */ +#define WITH_TRIO +#else +/** + * WITHOUT_TRIO: + * + * defined if the trio support should not be configured in + */ +#define WITHOUT_TRIO +#endif +#else /* VMS */ +/** + * WITH_TRIO: + * + * defined if the trio support need to be configured in + */ +#define WITH_TRIO 1 +#endif /* VMS */ + +/** + * LIBXML_THREAD_ENABLED: + * + * Whether the thread support is configured in + */ +#if 1 +#if defined(_REENTRANT) || defined(__MT__) || (_POSIX_C_SOURCE - 0 >= 199506L) +#define LIBXML_THREAD_ENABLED +#endif +#endif + +/** + * LIBXML_TREE_ENABLED: + * + * Whether the DOM like tree manipulation API support is configured in + */ +#if 1 +#define LIBXML_TREE_ENABLED +#endif + +/** + * LIBXML_OUTPUT_ENABLED: + * + * Whether the serialization/saving support is configured in + */ +#if 1 +#define LIBXML_OUTPUT_ENABLED +#endif + +/** + * LIBXML_PUSH_ENABLED: + * + * Whether the push parsing interfaces are configured in + */ +#if 1 +#define LIBXML_PUSH_ENABLED +#endif + +/** + * LIBXML_READER_ENABLED: + * + * Whether the xmlReader parsing interface is configured in + */ +#if 1 +#define LIBXML_READER_ENABLED +#endif + +/** + * LIBXML_PATTERN_ENABLED: + * + * Whether the xmlPattern node selection interface is configured in + */ +#if 1 +#define LIBXML_PATTERN_ENABLED +#endif + +/** + * LIBXML_WRITER_ENABLED: + * + * Whether the xmlWriter saving interface is configured in + */ +#if 1 +#define LIBXML_WRITER_ENABLED +#endif + +/** + * LIBXML_SAX1_ENABLED: + * + * Whether the older SAX1 interface is configured in + */ +#if 1 +#define LIBXML_SAX1_ENABLED +#endif + +/** + * LIBXML_FTP_ENABLED: + * + * Whether the FTP support is configured in + */ +#if 1 +#define LIBXML_FTP_ENABLED +#endif + +/** + * LIBXML_HTTP_ENABLED: + * + * Whether the HTTP support is configured in + */ +#if 1 +#define LIBXML_HTTP_ENABLED +#endif + +/** + * LIBXML_VALID_ENABLED: + * + * Whether the DTD validation support is configured in + */ +#if 1 +#define LIBXML_VALID_ENABLED +#endif + +/** + * LIBXML_HTML_ENABLED: + * + * Whether the HTML support is configured in + */ +#if 1 +#define LIBXML_HTML_ENABLED +#endif + +/** + * LIBXML_LEGACY_ENABLED: + * + * Whether the deprecated APIs are compiled in for compatibility + */ +#if 1 +#define LIBXML_LEGACY_ENABLED +#endif + +/** + * LIBXML_C14N_ENABLED: + * + * Whether the Canonicalization support is configured in + */ +#if 1 +#define LIBXML_C14N_ENABLED +#endif + +/** + * LIBXML_CATALOG_ENABLED: + * + * Whether the Catalog support is configured in + */ +#if 1 +#define LIBXML_CATALOG_ENABLED +#endif + +/** + * LIBXML_DOCB_ENABLED: + * + * Whether the SGML Docbook support is configured in + */ +#if 1 +#define LIBXML_DOCB_ENABLED +#endif + +/** + * LIBXML_XPATH_ENABLED: + * + * Whether XPath is configured in + */ +#if 1 +#define LIBXML_XPATH_ENABLED +#endif + +/** + * LIBXML_XPTR_ENABLED: + * + * Whether XPointer is configured in + */ +#if 1 +#define LIBXML_XPTR_ENABLED +#endif + +/** + * LIBXML_XINCLUDE_ENABLED: + * + * Whether XInclude is configured in + */ +#if 1 +#define LIBXML_XINCLUDE_ENABLED +#endif + +/** + * LIBXML_ICONV_ENABLED: + * + * Whether iconv support is available + */ +#if 1 +#define LIBXML_ICONV_ENABLED +#endif + +/** + * LIBXML_ISO8859X_ENABLED: + * + * Whether ISO-8859-* support is made available in case iconv is not + */ +#if 1 +#define LIBXML_ISO8859X_ENABLED +#endif + +/** + * LIBXML_DEBUG_ENABLED: + * + * Whether Debugging module is configured in + */ +#if 1 +#define LIBXML_DEBUG_ENABLED +#endif + +/** + * DEBUG_MEMORY_LOCATION: + * + * Whether the memory debugging is configured in + */ +#if 0 +#define DEBUG_MEMORY_LOCATION +#endif + +/** + * LIBXML_DEBUG_RUNTIME: + * + * Whether the runtime debugging is configured in + */ +#if 0 +#define LIBXML_DEBUG_RUNTIME +#endif + +/** + * LIBXML_UNICODE_ENABLED: + * + * Whether the Unicode related interfaces are compiled in + */ +#if 1 +#define LIBXML_UNICODE_ENABLED +#endif + +/** + * LIBXML_REGEXP_ENABLED: + * + * Whether the regular expressions interfaces are compiled in + */ +#if 1 +#define LIBXML_REGEXP_ENABLED +#endif + +/** + * LIBXML_AUTOMATA_ENABLED: + * + * Whether the automata interfaces are compiled in + */ +#if 1 +#define LIBXML_AUTOMATA_ENABLED +#endif + +/** + * LIBXML_SCHEMAS_ENABLED: + * + * Whether the Schemas validation interfaces are compiled in + */ +#if 1 +#define LIBXML_SCHEMAS_ENABLED +#endif + +/** + * LIBXML_MODULES_ENABLED: + * + * Whether the module interfaces are compiled in + */ +#if 1 +#define LIBXML_MODULES_ENABLED +#define LIBXML_MODULE_EXTENSION ".so" +#endif + +/** + * ATTRIBUTE_UNUSED: + * + * Macro used to signal to GCC unused function parameters + */ +#ifdef __GNUC__ +#ifdef HAVE_ANSIDECL_H +#include +#endif +#ifndef ATTRIBUTE_UNUSED +#define ATTRIBUTE_UNUSED __attribute__((unused)) +#endif +#else +#define ATTRIBUTE_UNUSED +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif + + diff --git a/include/libxml/xmlversion.h.in b/include/libxml/xmlversion.h.in new file mode 100644 index 0000000..47a28b9 --- /dev/null +++ b/include/libxml/xmlversion.h.in @@ -0,0 +1,373 @@ +/* + * Summary: compile-time version informations + * Description: compile-time version informations for the XML library + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_VERSION_H__ +#define __XML_VERSION_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * use those to be sure nothing nasty will happen if + * your library and includes mismatch + */ +#ifndef LIBXML2_COMPILING_MSCCDEF +XMLPUBFUN void XMLCALL xmlCheckVersion(int version); +#endif /* LIBXML2_COMPILING_MSCCDEF */ + +/** + * LIBXML_DOTTED_VERSION: + * + * the version string like "1.2.3" + */ +#define LIBXML_DOTTED_VERSION "@VERSION@" + +/** + * LIBXML_VERSION: + * + * the version number: 1.2.3 value is 1002003 + */ +#define LIBXML_VERSION @LIBXML_VERSION_NUMBER@ + +/** + * LIBXML_VERSION_STRING: + * + * the version number string, 1.2.3 value is "1002003" + */ +#define LIBXML_VERSION_STRING "@LIBXML_VERSION_NUMBER@" + +/** + * LIBXML_VERSION_EXTRA: + * + * extra version information, used to show a CVS compilation + */ +#define LIBXML_VERSION_EXTRA "@LIBXML_VERSION_EXTRA@" + +/** + * LIBXML_TEST_VERSION: + * + * Macro to check that the libxml version in use is compatible with + * the version the software has been compiled against + */ +#define LIBXML_TEST_VERSION xmlCheckVersion(@LIBXML_VERSION_NUMBER@); + +#ifndef VMS +#if @WITH_TRIO@ +/** + * WITH_TRIO: + * + * defined if the trio support need to be configured in + */ +#define WITH_TRIO +#else +/** + * WITHOUT_TRIO: + * + * defined if the trio support should not be configured in + */ +#define WITHOUT_TRIO +#endif +#else /* VMS */ +/** + * WITH_TRIO: + * + * defined if the trio support need to be configured in + */ +#define WITH_TRIO 1 +#endif /* VMS */ + +/** + * LIBXML_THREAD_ENABLED: + * + * Whether the thread support is configured in + */ +#if @WITH_THREADS@ +#if defined(_REENTRANT) || defined(__MT__) || (_POSIX_C_SOURCE - 0 >= 199506L) +#define LIBXML_THREAD_ENABLED +#endif +#endif + +/** + * LIBXML_TREE_ENABLED: + * + * Whether the DOM like tree manipulation API support is configured in + */ +#if @WITH_TREE@ +#define LIBXML_TREE_ENABLED +#endif + +/** + * LIBXML_OUTPUT_ENABLED: + * + * Whether the serialization/saving support is configured in + */ +#if @WITH_OUTPUT@ +#define LIBXML_OUTPUT_ENABLED +#endif + +/** + * LIBXML_PUSH_ENABLED: + * + * Whether the push parsing interfaces are configured in + */ +#if @WITH_PUSH@ +#define LIBXML_PUSH_ENABLED +#endif + +/** + * LIBXML_READER_ENABLED: + * + * Whether the xmlReader parsing interface is configured in + */ +#if @WITH_READER@ +#define LIBXML_READER_ENABLED +#endif + +/** + * LIBXML_PATTERN_ENABLED: + * + * Whether the xmlPattern node selection interface is configured in + */ +#if @WITH_PATTERN@ +#define LIBXML_PATTERN_ENABLED +#endif + +/** + * LIBXML_WRITER_ENABLED: + * + * Whether the xmlWriter saving interface is configured in + */ +#if @WITH_WRITER@ +#define LIBXML_WRITER_ENABLED +#endif + +/** + * LIBXML_SAX1_ENABLED: + * + * Whether the older SAX1 interface is configured in + */ +#if @WITH_SAX1@ +#define LIBXML_SAX1_ENABLED +#endif + +/** + * LIBXML_FTP_ENABLED: + * + * Whether the FTP support is configured in + */ +#if @WITH_FTP@ +#define LIBXML_FTP_ENABLED +#endif + +/** + * LIBXML_HTTP_ENABLED: + * + * Whether the HTTP support is configured in + */ +#if @WITH_HTTP@ +#define LIBXML_HTTP_ENABLED +#endif + +/** + * LIBXML_VALID_ENABLED: + * + * Whether the DTD validation support is configured in + */ +#if @WITH_VALID@ +#define LIBXML_VALID_ENABLED +#endif + +/** + * LIBXML_HTML_ENABLED: + * + * Whether the HTML support is configured in + */ +#if @WITH_HTML@ +#define LIBXML_HTML_ENABLED +#endif + +/** + * LIBXML_LEGACY_ENABLED: + * + * Whether the deprecated APIs are compiled in for compatibility + */ +#if @WITH_LEGACY@ +#define LIBXML_LEGACY_ENABLED +#endif + +/** + * LIBXML_C14N_ENABLED: + * + * Whether the Canonicalization support is configured in + */ +#if @WITH_C14N@ +#define LIBXML_C14N_ENABLED +#endif + +/** + * LIBXML_CATALOG_ENABLED: + * + * Whether the Catalog support is configured in + */ +#if @WITH_CATALOG@ +#define LIBXML_CATALOG_ENABLED +#endif + +/** + * LIBXML_DOCB_ENABLED: + * + * Whether the SGML Docbook support is configured in + */ +#if @WITH_DOCB@ +#define LIBXML_DOCB_ENABLED +#endif + +/** + * LIBXML_XPATH_ENABLED: + * + * Whether XPath is configured in + */ +#if @WITH_XPATH@ +#define LIBXML_XPATH_ENABLED +#endif + +/** + * LIBXML_XPTR_ENABLED: + * + * Whether XPointer is configured in + */ +#if @WITH_XPTR@ +#define LIBXML_XPTR_ENABLED +#endif + +/** + * LIBXML_XINCLUDE_ENABLED: + * + * Whether XInclude is configured in + */ +#if @WITH_XINCLUDE@ +#define LIBXML_XINCLUDE_ENABLED +#endif + +/** + * LIBXML_ICONV_ENABLED: + * + * Whether iconv support is available + */ +#if @WITH_ICONV@ +#define LIBXML_ICONV_ENABLED +#endif + +/** + * LIBXML_ISO8859X_ENABLED: + * + * Whether ISO-8859-* support is made available in case iconv is not + */ +#if @WITH_ISO8859X@ +#define LIBXML_ISO8859X_ENABLED +#endif + +/** + * LIBXML_DEBUG_ENABLED: + * + * Whether Debugging module is configured in + */ +#if @WITH_DEBUG@ +#define LIBXML_DEBUG_ENABLED +#endif + +/** + * DEBUG_MEMORY_LOCATION: + * + * Whether the memory debugging is configured in + */ +#if @WITH_MEM_DEBUG@ +#define DEBUG_MEMORY_LOCATION +#endif + +/** + * LIBXML_DEBUG_RUNTIME: + * + * Whether the runtime debugging is configured in + */ +#if @WITH_MEM_DEBUG@ +#define LIBXML_DEBUG_RUNTIME +#endif + +/** + * LIBXML_UNICODE_ENABLED: + * + * Whether the Unicode related interfaces are compiled in + */ +#if @WITH_REGEXPS@ +#define LIBXML_UNICODE_ENABLED +#endif + +/** + * LIBXML_REGEXP_ENABLED: + * + * Whether the regular expressions interfaces are compiled in + */ +#if @WITH_REGEXPS@ +#define LIBXML_REGEXP_ENABLED +#endif + +/** + * LIBXML_AUTOMATA_ENABLED: + * + * Whether the automata interfaces are compiled in + */ +#if @WITH_REGEXPS@ +#define LIBXML_AUTOMATA_ENABLED +#endif + +/** + * LIBXML_SCHEMAS_ENABLED: + * + * Whether the Schemas validation interfaces are compiled in + */ +#if @WITH_SCHEMAS@ +#define LIBXML_SCHEMAS_ENABLED +#endif + +/** + * LIBXML_MODULES_ENABLED: + * + * Whether the module interfaces are compiled in + */ +#if @WITH_MODULES@ +#define LIBXML_MODULES_ENABLED +#define LIBXML_MODULE_EXTENSION "@MODULE_EXTENSION@" +#endif + +/** + * ATTRIBUTE_UNUSED: + * + * Macro used to signal to GCC unused function parameters + */ +#ifdef __GNUC__ +#ifdef HAVE_ANSIDECL_H +#include +#endif +#ifndef ATTRIBUTE_UNUSED +#define ATTRIBUTE_UNUSED __attribute__((unused)) +#endif +#else +#define ATTRIBUTE_UNUSED +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif + + diff --git a/include/libxml/xmlwriter.h b/include/libxml/xmlwriter.h new file mode 100644 index 0000000..31ceb5f --- /dev/null +++ b/include/libxml/xmlwriter.h @@ -0,0 +1,459 @@ + +/* + * Summary: text writing API for XML + * Description: text writing API for XML + * + * Copy: See Copyright for the status of this software. + * + * Author: Alfred Mickautsch + */ + +#ifndef __XML_XMLWRITER_H__ +#define __XML_XMLWRITER_H__ + +#include + +#ifdef LIBXML_WRITER_ENABLED + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + typedef struct _xmlTextWriter xmlTextWriter; + typedef xmlTextWriter *xmlTextWriterPtr; + +/* + * Constructors & Destructor + */ + XMLPUBFUN xmlTextWriterPtr XMLCALL + xmlNewTextWriter(xmlOutputBufferPtr out); + XMLPUBFUN xmlTextWriterPtr XMLCALL + xmlNewTextWriterFilename(const char *uri, int compression); + XMLPUBFUN xmlTextWriterPtr XMLCALL + xmlNewTextWriterMemory(xmlBufferPtr buf, int compression); + XMLPUBFUN xmlTextWriterPtr XMLCALL + xmlNewTextWriterPushParser(xmlParserCtxtPtr ctxt, int compression); + XMLPUBFUN xmlTextWriterPtr XMLCALL + xmlNewTextWriterDoc(xmlDocPtr * doc, int compression); + XMLPUBFUN xmlTextWriterPtr XMLCALL + xmlNewTextWriterTree(xmlDocPtr doc, xmlNodePtr node, + int compression); + XMLPUBFUN void XMLCALL xmlFreeTextWriter(xmlTextWriterPtr writer); + +/* + * Functions + */ + + +/* + * Document + */ + XMLPUBFUN int XMLCALL + xmlTextWriterStartDocument(xmlTextWriterPtr writer, + const char *version, + const char *encoding, + const char *standalone); + XMLPUBFUN int XMLCALL xmlTextWriterEndDocument(xmlTextWriterPtr + writer); + +/* + * Comments + */ + XMLPUBFUN int XMLCALL xmlTextWriterStartComment(xmlTextWriterPtr + writer); + XMLPUBFUN int XMLCALL xmlTextWriterEndComment(xmlTextWriterPtr writer); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatComment(xmlTextWriterPtr writer, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatComment(xmlTextWriterPtr writer, + const char *format, + va_list argptr); + XMLPUBFUN int XMLCALL xmlTextWriterWriteComment(xmlTextWriterPtr + writer, + const xmlChar * + content); + +/* + * Elements + */ + XMLPUBFUN int XMLCALL + xmlTextWriterStartElement(xmlTextWriterPtr writer, + const xmlChar * name); + XMLPUBFUN int XMLCALL xmlTextWriterStartElementNS(xmlTextWriterPtr + writer, + const xmlChar * + prefix, + const xmlChar * name, + const xmlChar * + namespaceURI); + XMLPUBFUN int XMLCALL xmlTextWriterEndElement(xmlTextWriterPtr writer); + XMLPUBFUN int XMLCALL xmlTextWriterFullEndElement(xmlTextWriterPtr + writer); + +/* + * Elements conveniency functions + */ + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer, + const xmlChar * name, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer, + const xmlChar * name, + const char *format, + va_list argptr); + XMLPUBFUN int XMLCALL xmlTextWriterWriteElement(xmlTextWriterPtr + writer, + const xmlChar * name, + const xmlChar * + content); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer, + const xmlChar * prefix, + const xmlChar * name, + const xmlChar * namespaceURI, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer, + const xmlChar * prefix, + const xmlChar * name, + const xmlChar * namespaceURI, + const char *format, + va_list argptr); + XMLPUBFUN int XMLCALL xmlTextWriterWriteElementNS(xmlTextWriterPtr + writer, + const xmlChar * + prefix, + const xmlChar * name, + const xmlChar * + namespaceURI, + const xmlChar * + content); + +/* + * Text + */ + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatRaw(xmlTextWriterPtr writer, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatRaw(xmlTextWriterPtr writer, + const char *format, va_list argptr); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteRawLen(xmlTextWriterPtr writer, + const xmlChar * content, int len); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteRaw(xmlTextWriterPtr writer, + const xmlChar * content); + XMLPUBFUN int XMLCALL xmlTextWriterWriteFormatString(xmlTextWriterPtr + writer, + const char + *format, ...); + XMLPUBFUN int XMLCALL xmlTextWriterWriteVFormatString(xmlTextWriterPtr + writer, + const char + *format, + va_list argptr); + XMLPUBFUN int XMLCALL xmlTextWriterWriteString(xmlTextWriterPtr writer, + const xmlChar * + content); + XMLPUBFUN int XMLCALL xmlTextWriterWriteBase64(xmlTextWriterPtr writer, + const char *data, + int start, int len); + XMLPUBFUN int XMLCALL xmlTextWriterWriteBinHex(xmlTextWriterPtr writer, + const char *data, + int start, int len); + +/* + * Attributes + */ + XMLPUBFUN int XMLCALL + xmlTextWriterStartAttribute(xmlTextWriterPtr writer, + const xmlChar * name); + XMLPUBFUN int XMLCALL xmlTextWriterStartAttributeNS(xmlTextWriterPtr + writer, + const xmlChar * + prefix, + const xmlChar * + name, + const xmlChar * + namespaceURI); + XMLPUBFUN int XMLCALL xmlTextWriterEndAttribute(xmlTextWriterPtr + writer); + +/* + * Attributes conveniency functions + */ + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer, + const xmlChar * name, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer, + const xmlChar * name, + const char *format, + va_list argptr); + XMLPUBFUN int XMLCALL xmlTextWriterWriteAttribute(xmlTextWriterPtr + writer, + const xmlChar * name, + const xmlChar * + content); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer, + const xmlChar * prefix, + const xmlChar * name, + const xmlChar * namespaceURI, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer, + const xmlChar * prefix, + const xmlChar * name, + const xmlChar * namespaceURI, + const char *format, + va_list argptr); + XMLPUBFUN int XMLCALL xmlTextWriterWriteAttributeNS(xmlTextWriterPtr + writer, + const xmlChar * + prefix, + const xmlChar * + name, + const xmlChar * + namespaceURI, + const xmlChar * + content); + +/* + * PI's + */ + XMLPUBFUN int XMLCALL + xmlTextWriterStartPI(xmlTextWriterPtr writer, + const xmlChar * target); + XMLPUBFUN int XMLCALL xmlTextWriterEndPI(xmlTextWriterPtr writer); + +/* + * PI conveniency functions + */ + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer, + const xmlChar * target, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer, + const xmlChar * target, + const char *format, va_list argptr); + XMLPUBFUN int XMLCALL + xmlTextWriterWritePI(xmlTextWriterPtr writer, + const xmlChar * target, + const xmlChar * content); + +/** + * xmlTextWriterWriteProcessingInstruction: + * + * This macro maps to xmlTextWriterWritePI + */ +#define xmlTextWriterWriteProcessingInstruction xmlTextWriterWritePI + +/* + * CDATA + */ + XMLPUBFUN int XMLCALL xmlTextWriterStartCDATA(xmlTextWriterPtr writer); + XMLPUBFUN int XMLCALL xmlTextWriterEndCDATA(xmlTextWriterPtr writer); + +/* + * CDATA conveniency functions + */ + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer, + const char *format, va_list argptr); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteCDATA(xmlTextWriterPtr writer, + const xmlChar * content); + +/* + * DTD + */ + XMLPUBFUN int XMLCALL + xmlTextWriterStartDTD(xmlTextWriterPtr writer, + const xmlChar * name, + const xmlChar * pubid, + const xmlChar * sysid); + XMLPUBFUN int XMLCALL xmlTextWriterEndDTD(xmlTextWriterPtr writer); + +/* + * DTD conveniency functions + */ + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer, + const xmlChar * name, + const xmlChar * pubid, + const xmlChar * sysid, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer, + const xmlChar * name, + const xmlChar * pubid, + const xmlChar * sysid, + const char *format, va_list argptr); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteDTD(xmlTextWriterPtr writer, + const xmlChar * name, + const xmlChar * pubid, + const xmlChar * sysid, + const xmlChar * subset); + +/** + * xmlTextWriterWriteDocType: + * + * this macro maps to xmlTextWriterWriteDTD + */ +#define xmlTextWriterWriteDocType xmlTextWriterWriteDTD + +/* + * DTD element definition + */ + XMLPUBFUN int XMLCALL + xmlTextWriterStartDTDElement(xmlTextWriterPtr writer, + const xmlChar * name); + XMLPUBFUN int XMLCALL xmlTextWriterEndDTDElement(xmlTextWriterPtr + writer); + +/* + * DTD element definition conveniency functions + */ + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer, + const xmlChar * name, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer, + const xmlChar * name, + const char *format, + va_list argptr); + XMLPUBFUN int XMLCALL xmlTextWriterWriteDTDElement(xmlTextWriterPtr + writer, + const xmlChar * + name, + const xmlChar * + content); + +/* + * DTD attribute list definition + */ + XMLPUBFUN int XMLCALL + xmlTextWriterStartDTDAttlist(xmlTextWriterPtr writer, + const xmlChar * name); + XMLPUBFUN int XMLCALL xmlTextWriterEndDTDAttlist(xmlTextWriterPtr + writer); + +/* + * DTD attribute list definition conveniency functions + */ + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer, + const xmlChar * name, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer, + const xmlChar * name, + const char *format, + va_list argptr); + XMLPUBFUN int XMLCALL xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr + writer, + const xmlChar * + name, + const xmlChar * + content); + +/* + * DTD entity definition + */ + XMLPUBFUN int XMLCALL + xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer, + int pe, const xmlChar * name); + XMLPUBFUN int XMLCALL xmlTextWriterEndDTDEntity(xmlTextWriterPtr + writer); + +/* + * DTD entity definition conveniency functions + */ + XMLPUBFUN int XMLCALL + xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer, + int pe, + const xmlChar * name, + const char *format, ...); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer, + int pe, + const xmlChar * name, + const char *format, + va_list argptr); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer, + int pe, + const xmlChar * name, + const xmlChar * content); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer, + int pe, + const xmlChar * name, + const xmlChar * pubid, + const xmlChar * sysid, + const xmlChar * ndataid); + XMLPUBFUN int XMLCALL + xmlTextWriterWriteDTDExternalEntityContents(xmlTextWriterPtr + writer, + const xmlChar * pubid, + const xmlChar * sysid, + const xmlChar * + ndataid); + XMLPUBFUN int XMLCALL xmlTextWriterWriteDTDEntity(xmlTextWriterPtr + writer, int pe, + const xmlChar * name, + const xmlChar * + pubid, + const xmlChar * + sysid, + const xmlChar * + ndataid, + const xmlChar * + content); + +/* + * DTD notation definition + */ + XMLPUBFUN int XMLCALL + xmlTextWriterWriteDTDNotation(xmlTextWriterPtr writer, + const xmlChar * name, + const xmlChar * pubid, + const xmlChar * sysid); + +/* + * Indentation + */ + XMLPUBFUN int XMLCALL + xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent); + XMLPUBFUN int XMLCALL + xmlTextWriterSetIndentString(xmlTextWriterPtr writer, + const xmlChar * str); + +/* + * misc + */ + XMLPUBFUN int XMLCALL xmlTextWriterFlush(xmlTextWriterPtr writer); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_WRITER_ENABLED */ + +#endif /* __XML_XMLWRITER_H__ */ diff --git a/include/libxml/xpath.h b/include/libxml/xpath.h new file mode 100644 index 0000000..eee2630 --- /dev/null +++ b/include/libxml/xpath.h @@ -0,0 +1,513 @@ +/* + * Summary: XML Path Language implementation + * Description: API for the XML Path Language implementation + * + * XML Path Language implementation + * XPath is a language for addressing parts of an XML document, + * designed to be used by both XSLT and XPointer + * http://www.w3.org/TR/xpath + * + * Implements + * W3C Recommendation 16 November 1999 + * http://www.w3.org/TR/1999/REC-xpath-19991116 + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_XPATH_H__ +#define __XML_XPATH_H__ + +#include + +#ifdef LIBXML_XPATH_ENABLED + +#include +#include +#include +#endif /* LIBXML_XPATH_ENABLED */ + +#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +#ifdef __cplusplus +extern "C" { +#endif +#endif /* LIBXML_XPATH_ENABLED or LIBXML_SCHEMAS_ENABLED */ + +#ifdef LIBXML_XPATH_ENABLED +typedef struct _xmlXPathContext xmlXPathContext; +typedef xmlXPathContext *xmlXPathContextPtr; +typedef struct _xmlXPathParserContext xmlXPathParserContext; +typedef xmlXPathParserContext *xmlXPathParserContextPtr; + +/** + * The set of XPath error codes. + */ + +typedef enum { + XPATH_EXPRESSION_OK = 0, + XPATH_NUMBER_ERROR, + XPATH_UNFINISHED_LITERAL_ERROR, + XPATH_START_LITERAL_ERROR, + XPATH_VARIABLE_REF_ERROR, + XPATH_UNDEF_VARIABLE_ERROR, + XPATH_INVALID_PREDICATE_ERROR, + XPATH_EXPR_ERROR, + XPATH_UNCLOSED_ERROR, + XPATH_UNKNOWN_FUNC_ERROR, + XPATH_INVALID_OPERAND, + XPATH_INVALID_TYPE, + XPATH_INVALID_ARITY, + XPATH_INVALID_CTXT_SIZE, + XPATH_INVALID_CTXT_POSITION, + XPATH_MEMORY_ERROR, + XPTR_SYNTAX_ERROR, + XPTR_RESOURCE_ERROR, + XPTR_SUB_RESOURCE_ERROR, + XPATH_UNDEF_PREFIX_ERROR, + XPATH_ENCODING_ERROR, + XPATH_INVALID_CHAR_ERROR, + XPATH_INVALID_CTXT +} xmlXPathError; + +/* + * A node-set (an unordered collection of nodes without duplicates). + */ +typedef struct _xmlNodeSet xmlNodeSet; +typedef xmlNodeSet *xmlNodeSetPtr; +struct _xmlNodeSet { + int nodeNr; /* number of nodes in the set */ + int nodeMax; /* size of the array as allocated */ + xmlNodePtr *nodeTab; /* array of nodes in no particular order */ + /* @@ with_ns to check wether namespace nodes should be looked at @@ */ +}; + +/* + * An expression is evaluated to yield an object, which + * has one of the following four basic types: + * - node-set + * - boolean + * - number + * - string + * + * @@ XPointer will add more types ! + */ + +typedef enum { + XPATH_UNDEFINED = 0, + XPATH_NODESET = 1, + XPATH_BOOLEAN = 2, + XPATH_NUMBER = 3, + XPATH_STRING = 4, + XPATH_POINT = 5, + XPATH_RANGE = 6, + XPATH_LOCATIONSET = 7, + XPATH_USERS = 8, + XPATH_XSLT_TREE = 9 /* An XSLT value tree, non modifiable */ +} xmlXPathObjectType; + +typedef struct _xmlXPathObject xmlXPathObject; +typedef xmlXPathObject *xmlXPathObjectPtr; +struct _xmlXPathObject { + xmlXPathObjectType type; + xmlNodeSetPtr nodesetval; + int boolval; + double floatval; + xmlChar *stringval; + void *user; + int index; + void *user2; + int index2; +}; + +/** + * xmlXPathConvertFunc: + * @obj: an XPath object + * @type: the number of the target type + * + * A conversion function is associated to a type and used to cast + * the new type to primitive values. + * + * Returns -1 in case of error, 0 otherwise + */ +typedef int (*xmlXPathConvertFunc) (xmlXPathObjectPtr obj, int type); + +/* + * Extra type: a name and a conversion function. + */ + +typedef struct _xmlXPathType xmlXPathType; +typedef xmlXPathType *xmlXPathTypePtr; +struct _xmlXPathType { + const xmlChar *name; /* the type name */ + xmlXPathConvertFunc func; /* the conversion function */ +}; + +/* + * Extra variable: a name and a value. + */ + +typedef struct _xmlXPathVariable xmlXPathVariable; +typedef xmlXPathVariable *xmlXPathVariablePtr; +struct _xmlXPathVariable { + const xmlChar *name; /* the variable name */ + xmlXPathObjectPtr value; /* the value */ +}; + +/** + * xmlXPathEvalFunc: + * @ctxt: an XPath parser context + * @nargs: the number of arguments passed to the function + * + * An XPath evaluation function, the parameters are on the XPath context stack. + */ + +typedef void (*xmlXPathEvalFunc)(xmlXPathParserContextPtr ctxt, + int nargs); + +/* + * Extra function: a name and a evaluation function. + */ + +typedef struct _xmlXPathFunct xmlXPathFunct; +typedef xmlXPathFunct *xmlXPathFuncPtr; +struct _xmlXPathFunct { + const xmlChar *name; /* the function name */ + xmlXPathEvalFunc func; /* the evaluation function */ +}; + +/** + * xmlXPathAxisFunc: + * @ctxt: the XPath interpreter context + * @cur: the previous node being explored on that axis + * + * An axis traversal function. To traverse an axis, the engine calls + * the first time with cur == NULL and repeat until the function returns + * NULL indicating the end of the axis traversal. + * + * Returns the next node in that axis or NULL if at the end of the axis. + */ + +typedef xmlXPathObjectPtr (*xmlXPathAxisFunc) (xmlXPathParserContextPtr ctxt, + xmlXPathObjectPtr cur); + +/* + * Extra axis: a name and an axis function. + */ + +typedef struct _xmlXPathAxis xmlXPathAxis; +typedef xmlXPathAxis *xmlXPathAxisPtr; +struct _xmlXPathAxis { + const xmlChar *name; /* the axis name */ + xmlXPathAxisFunc func; /* the search function */ +}; + +/** + * xmlXPathFunction: + * @ctxt: the XPath interprestation context + * @nargs: the number of arguments + * + * An XPath function. + * The arguments (if any) are popped out from the context stack + * and the result is pushed on the stack. + */ + +typedef void (*xmlXPathFunction) (xmlXPathParserContextPtr ctxt, int nargs); + +/* + * Function and Variable Lookup. + */ + +/** + * xmlXPathVariableLookupFunc: + * @ctxt: an XPath context + * @name: name of the variable + * @ns_uri: the namespace name hosting this variable + * + * Prototype for callbacks used to plug variable lookup in the XPath + * engine. + * + * Returns the XPath object value or NULL if not found. + */ +typedef xmlXPathObjectPtr (*xmlXPathVariableLookupFunc) (void *ctxt, + const xmlChar *name, + const xmlChar *ns_uri); + +/** + * xmlXPathFuncLookupFunc: + * @ctxt: an XPath context + * @name: name of the function + * @ns_uri: the namespace name hosting this function + * + * Prototype for callbacks used to plug function lookup in the XPath + * engine. + * + * Returns the XPath function or NULL if not found. + */ +typedef xmlXPathFunction (*xmlXPathFuncLookupFunc) (void *ctxt, + const xmlChar *name, + const xmlChar *ns_uri); + +/** + * xmlXPathContext: + * + * Expression evaluation occurs with respect to a context. + * he context consists of: + * - a node (the context node) + * - a node list (the context node list) + * - a set of variable bindings + * - a function library + * - the set of namespace declarations in scope for the expression + * Following the switch to hash tables, this need to be trimmed up at + * the next binary incompatible release. + */ + +struct _xmlXPathContext { + xmlDocPtr doc; /* The current document */ + xmlNodePtr node; /* The current node */ + + int nb_variables_unused; /* unused (hash table) */ + int max_variables_unused; /* unused (hash table) */ + xmlHashTablePtr varHash; /* Hash table of defined variables */ + + int nb_types; /* number of defined types */ + int max_types; /* max number of types */ + xmlXPathTypePtr types; /* Array of defined types */ + + int nb_funcs_unused; /* unused (hash table) */ + int max_funcs_unused; /* unused (hash table) */ + xmlHashTablePtr funcHash; /* Hash table of defined funcs */ + + int nb_axis; /* number of defined axis */ + int max_axis; /* max number of axis */ + xmlXPathAxisPtr axis; /* Array of defined axis */ + + /* the namespace nodes of the context node */ + xmlNsPtr *namespaces; /* Array of namespaces */ + int nsNr; /* number of namespace in scope */ + void *user; /* function to free */ + + /* extra variables */ + int contextSize; /* the context size */ + int proximityPosition; /* the proximity position */ + + /* extra stuff for XPointer */ + int xptr; /* it this an XPointer context */ + xmlNodePtr here; /* for here() */ + xmlNodePtr origin; /* for origin() */ + + /* the set of namespace declarations in scope for the expression */ + xmlHashTablePtr nsHash; /* The namespaces hash table */ + xmlXPathVariableLookupFunc varLookupFunc;/* variable lookup func */ + void *varLookupData; /* variable lookup data */ + + /* Possibility to link in an extra item */ + void *extra; /* needed for XSLT */ + + /* The function name and URI when calling a function */ + const xmlChar *function; + const xmlChar *functionURI; + + /* function lookup function and data */ + xmlXPathFuncLookupFunc funcLookupFunc;/* function lookup func */ + void *funcLookupData; /* function lookup data */ + + /* temporary namespace lists kept for walking the namespace axis */ + xmlNsPtr *tmpNsList; /* Array of namespaces */ + int tmpNsNr; /* number of namespace in scope */ + + /* error reporting mechanism */ + void *userData; /* user specific data block */ + xmlStructuredErrorFunc error; /* the callback in case of errors */ + xmlError lastError; /* the last error */ + xmlNodePtr debugNode; /* the source node XSLT */ + + /* dictionnary */ + xmlDictPtr dict; /* dictionnary if any */ +}; + +/* + * The structure of a compiled expression form is not public. + */ + +typedef struct _xmlXPathCompExpr xmlXPathCompExpr; +typedef xmlXPathCompExpr *xmlXPathCompExprPtr; + +/** + * xmlXPathParserContext: + * + * An XPath parser context. It contains pure parsing informations, + * an xmlXPathContext, and the stack of objects. + */ +struct _xmlXPathParserContext { + const xmlChar *cur; /* the current char being parsed */ + const xmlChar *base; /* the full expression */ + + int error; /* error code */ + + xmlXPathContextPtr context; /* the evaluation context */ + xmlXPathObjectPtr value; /* the current value */ + int valueNr; /* number of values stacked */ + int valueMax; /* max number of values stacked */ + xmlXPathObjectPtr *valueTab; /* stack of values */ + + xmlXPathCompExprPtr comp; /* the precompiled expression */ + int xptr; /* it this an XPointer expression */ + xmlNodePtr ancestor; /* used for walking preceding axis */ +}; + +/************************************************************************ + * * + * Public API * + * * + ************************************************************************/ + +/** + * Objects and Nodesets handling + */ + +XMLPUBVAR double xmlXPathNAN; +XMLPUBVAR double xmlXPathPINF; +XMLPUBVAR double xmlXPathNINF; + +/* These macros may later turn into functions */ +/** + * xmlXPathNodeSetGetLength: + * @ns: a node-set + * + * Implement a functionality similar to the DOM NodeList.length. + * + * Returns the number of nodes in the node-set. + */ +#define xmlXPathNodeSetGetLength(ns) ((ns) ? (ns)->nodeNr : 0) +/** + * xmlXPathNodeSetItem: + * @ns: a node-set + * @index: index of a node in the set + * + * Implements a functionality similar to the DOM NodeList.item(). + * + * Returns the xmlNodePtr at the given @index in @ns or NULL if + * @index is out of range (0 to length-1) + */ +#define xmlXPathNodeSetItem(ns, index) \ + ((((ns) != NULL) && \ + ((index) >= 0) && ((index) < (ns)->nodeNr)) ? \ + (ns)->nodeTab[(index)] \ + : NULL) +/** + * xmlXPathNodeSetIsEmpty: + * @ns: a node-set + * + * Checks whether @ns is empty or not. + * + * Returns %TRUE if @ns is an empty node-set. + */ +#define xmlXPathNodeSetIsEmpty(ns) \ + (((ns) == NULL) || ((ns)->nodeNr == 0) || ((ns)->nodeTab == NULL)) + + +XMLPUBFUN void XMLCALL + xmlXPathFreeObject (xmlXPathObjectPtr obj); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathNodeSetCreate (xmlNodePtr val); +XMLPUBFUN void XMLCALL + xmlXPathFreeNodeSetList (xmlXPathObjectPtr obj); +XMLPUBFUN void XMLCALL + xmlXPathFreeNodeSet (xmlNodeSetPtr obj); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathObjectCopy (xmlXPathObjectPtr val); +XMLPUBFUN int XMLCALL + xmlXPathCmpNodes (xmlNodePtr node1, + xmlNodePtr node2); +/** + * Conversion functions to basic types. + */ +XMLPUBFUN int XMLCALL + xmlXPathCastNumberToBoolean (double val); +XMLPUBFUN int XMLCALL + xmlXPathCastStringToBoolean (const xmlChar * val); +XMLPUBFUN int XMLCALL + xmlXPathCastNodeSetToBoolean(xmlNodeSetPtr ns); +XMLPUBFUN int XMLCALL + xmlXPathCastToBoolean (xmlXPathObjectPtr val); + +XMLPUBFUN double XMLCALL + xmlXPathCastBooleanToNumber (int val); +XMLPUBFUN double XMLCALL + xmlXPathCastStringToNumber (const xmlChar * val); +XMLPUBFUN double XMLCALL + xmlXPathCastNodeToNumber (xmlNodePtr node); +XMLPUBFUN double XMLCALL + xmlXPathCastNodeSetToNumber (xmlNodeSetPtr ns); +XMLPUBFUN double XMLCALL + xmlXPathCastToNumber (xmlXPathObjectPtr val); + +XMLPUBFUN xmlChar * XMLCALL + xmlXPathCastBooleanToString (int val); +XMLPUBFUN xmlChar * XMLCALL + xmlXPathCastNumberToString (double val); +XMLPUBFUN xmlChar * XMLCALL + xmlXPathCastNodeToString (xmlNodePtr node); +XMLPUBFUN xmlChar * XMLCALL + xmlXPathCastNodeSetToString (xmlNodeSetPtr ns); +XMLPUBFUN xmlChar * XMLCALL + xmlXPathCastToString (xmlXPathObjectPtr val); + +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathConvertBoolean (xmlXPathObjectPtr val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathConvertNumber (xmlXPathObjectPtr val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathConvertString (xmlXPathObjectPtr val); + +/** + * Context handling. + */ +XMLPUBFUN xmlXPathContextPtr XMLCALL + xmlXPathNewContext (xmlDocPtr doc); +XMLPUBFUN void XMLCALL + xmlXPathFreeContext (xmlXPathContextPtr ctxt); + +/** + * Evaluation functions. + */ +XMLPUBFUN long XMLCALL + xmlXPathOrderDocElems (xmlDocPtr doc); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathEval (const xmlChar *str, + xmlXPathContextPtr ctx); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathEvalExpression (const xmlChar *str, + xmlXPathContextPtr ctxt); +XMLPUBFUN int XMLCALL + xmlXPathEvalPredicate (xmlXPathContextPtr ctxt, + xmlXPathObjectPtr res); +/** + * Separate compilation/evaluation entry points. + */ +XMLPUBFUN xmlXPathCompExprPtr XMLCALL + xmlXPathCompile (const xmlChar *str); +XMLPUBFUN xmlXPathCompExprPtr XMLCALL + xmlXPathCtxtCompile (xmlXPathContextPtr ctxt, + const xmlChar *str); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathCompiledEval (xmlXPathCompExprPtr comp, + xmlXPathContextPtr ctx); +XMLPUBFUN void XMLCALL + xmlXPathFreeCompExpr (xmlXPathCompExprPtr comp); +#endif /* LIBXML_XPATH_ENABLED */ +#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) +XMLPUBFUN void XMLCALL + xmlXPathInit (void); +XMLPUBFUN int XMLCALL + xmlXPathIsNaN (double val); +XMLPUBFUN int XMLCALL + xmlXPathIsInf (double val); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_XPATH_ENABLED or LIBXML_SCHEMAS_ENABLED*/ +#endif /* ! __XML_XPATH_H__ */ diff --git a/include/libxml/xpathInternals.h b/include/libxml/xpathInternals.h new file mode 100644 index 0000000..dcd5243 --- /dev/null +++ b/include/libxml/xpathInternals.h @@ -0,0 +1,630 @@ +/* + * Summary: internal interfaces for XML Path Language implementation + * Description: internal interfaces for XML Path Language implementation + * used to build new modules on top of XPath like XPointer and + * XSLT + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_XPATH_INTERNALS_H__ +#define __XML_XPATH_INTERNALS_H__ + +#include +#include + +#ifdef LIBXML_XPATH_ENABLED + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************ + * * + * Helpers * + * * + ************************************************************************/ + +/* + * Many of these macros may later turn into functions. They + * shouldn't be used in #ifdef's preprocessor instructions. + */ +/** + * xmlXPathSetError: + * @ctxt: an XPath parser context + * @err: an xmlXPathError code + * + * Raises an error. + */ +#define xmlXPathSetError(ctxt, err) \ + { xmlXPatherror((ctxt), __FILE__, __LINE__, (err)); \ + if ((ctxt) != NULL) (ctxt)->error = (err); } + +/** + * xmlXPathSetArityError: + * @ctxt: an XPath parser context + * + * Raises an XPATH_INVALID_ARITY error. + */ +#define xmlXPathSetArityError(ctxt) \ + xmlXPathSetError((ctxt), XPATH_INVALID_ARITY) + +/** + * xmlXPathSetTypeError: + * @ctxt: an XPath parser context + * + * Raises an XPATH_INVALID_TYPE error. + */ +#define xmlXPathSetTypeError(ctxt) \ + xmlXPathSetError((ctxt), XPATH_INVALID_TYPE) + +/** + * xmlXPathGetError: + * @ctxt: an XPath parser context + * + * Get the error code of an XPath context. + * + * Returns the context error. + */ +#define xmlXPathGetError(ctxt) ((ctxt)->error) + +/** + * xmlXPathCheckError: + * @ctxt: an XPath parser context + * + * Check if an XPath error was raised. + * + * Returns true if an error has been raised, false otherwise. + */ +#define xmlXPathCheckError(ctxt) ((ctxt)->error != XPATH_EXPRESSION_OK) + +/** + * xmlXPathGetDocument: + * @ctxt: an XPath parser context + * + * Get the document of an XPath context. + * + * Returns the context document. + */ +#define xmlXPathGetDocument(ctxt) ((ctxt)->context->doc) + +/** + * xmlXPathGetContextNode: + * @ctxt: an XPath parser context + * + * Get the context node of an XPath context. + * + * Returns the context node. + */ +#define xmlXPathGetContextNode(ctxt) ((ctxt)->context->node) + +XMLPUBFUN int XMLCALL + xmlXPathPopBoolean (xmlXPathParserContextPtr ctxt); +XMLPUBFUN double XMLCALL + xmlXPathPopNumber (xmlXPathParserContextPtr ctxt); +XMLPUBFUN xmlChar * XMLCALL + xmlXPathPopString (xmlXPathParserContextPtr ctxt); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathPopNodeSet (xmlXPathParserContextPtr ctxt); +XMLPUBFUN void * XMLCALL + xmlXPathPopExternal (xmlXPathParserContextPtr ctxt); + +/** + * xmlXPathReturnBoolean: + * @ctxt: an XPath parser context + * @val: a boolean + * + * Pushes the boolean @val on the context stack. + */ +#define xmlXPathReturnBoolean(ctxt, val) \ + valuePush((ctxt), xmlXPathNewBoolean(val)) + +/** + * xmlXPathReturnTrue: + * @ctxt: an XPath parser context + * + * Pushes true on the context stack. + */ +#define xmlXPathReturnTrue(ctxt) xmlXPathReturnBoolean((ctxt), 1) + +/** + * xmlXPathReturnFalse: + * @ctxt: an XPath parser context + * + * Pushes false on the context stack. + */ +#define xmlXPathReturnFalse(ctxt) xmlXPathReturnBoolean((ctxt), 0) + +/** + * xmlXPathReturnNumber: + * @ctxt: an XPath parser context + * @val: a double + * + * Pushes the double @val on the context stack. + */ +#define xmlXPathReturnNumber(ctxt, val) \ + valuePush((ctxt), xmlXPathNewFloat(val)) + +/** + * xmlXPathReturnString: + * @ctxt: an XPath parser context + * @str: a string + * + * Pushes the string @str on the context stack. + */ +#define xmlXPathReturnString(ctxt, str) \ + valuePush((ctxt), xmlXPathWrapString(str)) + +/** + * xmlXPathReturnEmptyString: + * @ctxt: an XPath parser context + * + * Pushes an empty string on the stack. + */ +#define xmlXPathReturnEmptyString(ctxt) \ + valuePush((ctxt), xmlXPathNewCString("")) + +/** + * xmlXPathReturnNodeSet: + * @ctxt: an XPath parser context + * @ns: a node-set + * + * Pushes the node-set @ns on the context stack. + */ +#define xmlXPathReturnNodeSet(ctxt, ns) \ + valuePush((ctxt), xmlXPathWrapNodeSet(ns)) + +/** + * xmlXPathReturnEmptyNodeSet: + * @ctxt: an XPath parser context + * + * Pushes an empty node-set on the context stack. + */ +#define xmlXPathReturnEmptyNodeSet(ctxt) \ + valuePush((ctxt), xmlXPathNewNodeSet(NULL)) + +/** + * xmlXPathReturnExternal: + * @ctxt: an XPath parser context + * @val: user data + * + * Pushes user data on the context stack. + */ +#define xmlXPathReturnExternal(ctxt, val) \ + valuePush((ctxt), xmlXPathWrapExternal(val)) + +/** + * xmlXPathStackIsNodeSet: + * @ctxt: an XPath parser context + * + * Check if the current value on the XPath stack is a node set or + * an XSLT value tree. + * + * Returns true if the current object on the stack is a node-set. + */ +#define xmlXPathStackIsNodeSet(ctxt) \ + (((ctxt)->value != NULL) \ + && (((ctxt)->value->type == XPATH_NODESET) \ + || ((ctxt)->value->type == XPATH_XSLT_TREE))) + +/** + * xmlXPathStackIsExternal: + * @ctxt: an XPath parser context + * + * Checks if the current value on the XPath stack is an external + * object. + * + * Returns true if the current object on the stack is an external + * object. + */ +#define xmlXPathStackIsExternal(ctxt) \ + ((ctxt->value != NULL) && (ctxt->value->type == XPATH_USERS)) + +/** + * xmlXPathEmptyNodeSet: + * @ns: a node-set + * + * Empties a node-set. + */ +#define xmlXPathEmptyNodeSet(ns) \ + { while ((ns)->nodeNr > 0) (ns)->nodeTab[(ns)->nodeNr--] = NULL; } + +/** + * CHECK_ERROR: + * + * Macro to return from the function if an XPath error was detected. + */ +#define CHECK_ERROR \ + if (ctxt->error != XPATH_EXPRESSION_OK) return + +/** + * CHECK_ERROR0: + * + * Macro to return 0 from the function if an XPath error was detected. + */ +#define CHECK_ERROR0 \ + if (ctxt->error != XPATH_EXPRESSION_OK) return(0) + +/** + * XP_ERROR: + * @X: the error code + * + * Macro to raise an XPath error and return. + */ +#define XP_ERROR(X) \ + { xmlXPathErr(ctxt, X); return; } + +/** + * XP_ERROR0: + * @X: the error code + * + * Macro to raise an XPath error and return 0. + */ +#define XP_ERROR0(X) \ + { xmlXPathErr(ctxt, X); return(0); } + +/** + * CHECK_TYPE: + * @typeval: the XPath type + * + * Macro to check that the value on top of the XPath stack is of a given + * type. + */ +#define CHECK_TYPE(typeval) \ + if ((ctxt->value == NULL) || (ctxt->value->type != typeval)) \ + XP_ERROR(XPATH_INVALID_TYPE) + +/** + * CHECK_TYPE0: + * @typeval: the XPath type + * + * Macro to check that the value on top of the XPath stack is of a given + * type. Return(0) in case of failure + */ +#define CHECK_TYPE0(typeval) \ + if ((ctxt->value == NULL) || (ctxt->value->type != typeval)) \ + XP_ERROR0(XPATH_INVALID_TYPE) + +/** + * CHECK_ARITY: + * @x: the number of expected args + * + * Macro to check that the number of args passed to an XPath function matches. + */ +#define CHECK_ARITY(x) \ + if (ctxt == NULL) return; \ + if (nargs != (x)) \ + XP_ERROR(XPATH_INVALID_ARITY); + +/** + * CAST_TO_STRING: + * + * Macro to try to cast the value on the top of the XPath stack to a string. + */ +#define CAST_TO_STRING \ + if ((ctxt->value != NULL) && (ctxt->value->type != XPATH_STRING)) \ + xmlXPathStringFunction(ctxt, 1); + +/** + * CAST_TO_NUMBER: + * + * Macro to try to cast the value on the top of the XPath stack to a number. + */ +#define CAST_TO_NUMBER \ + if ((ctxt->value != NULL) && (ctxt->value->type != XPATH_NUMBER)) \ + xmlXPathNumberFunction(ctxt, 1); + +/** + * CAST_TO_BOOLEAN: + * + * Macro to try to cast the value on the top of the XPath stack to a boolean. + */ +#define CAST_TO_BOOLEAN \ + if ((ctxt->value != NULL) && (ctxt->value->type != XPATH_BOOLEAN)) \ + xmlXPathBooleanFunction(ctxt, 1); + +/* + * Variable Lookup forwarding. + */ + +XMLPUBFUN void XMLCALL + xmlXPathRegisterVariableLookup (xmlXPathContextPtr ctxt, + xmlXPathVariableLookupFunc f, + void *data); + +/* + * Function Lookup forwarding. + */ + +XMLPUBFUN void XMLCALL + xmlXPathRegisterFuncLookup (xmlXPathContextPtr ctxt, + xmlXPathFuncLookupFunc f, + void *funcCtxt); + +/* + * Error reporting. + */ +XMLPUBFUN void XMLCALL + xmlXPatherror (xmlXPathParserContextPtr ctxt, + const char *file, + int line, + int no); + +XMLPUBFUN void XMLCALL + xmlXPathErr (xmlXPathParserContextPtr ctxt, + int error); + +#ifdef LIBXML_DEBUG_ENABLED +XMLPUBFUN void XMLCALL + xmlXPathDebugDumpObject (FILE *output, + xmlXPathObjectPtr cur, + int depth); +XMLPUBFUN void XMLCALL + xmlXPathDebugDumpCompExpr(FILE *output, + xmlXPathCompExprPtr comp, + int depth); +#endif +/** + * NodeSet handling. + */ +XMLPUBFUN int XMLCALL + xmlXPathNodeSetContains (xmlNodeSetPtr cur, + xmlNodePtr val); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathDifference (xmlNodeSetPtr nodes1, + xmlNodeSetPtr nodes2); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathIntersection (xmlNodeSetPtr nodes1, + xmlNodeSetPtr nodes2); + +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathDistinctSorted (xmlNodeSetPtr nodes); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathDistinct (xmlNodeSetPtr nodes); + +XMLPUBFUN int XMLCALL + xmlXPathHasSameNodes (xmlNodeSetPtr nodes1, + xmlNodeSetPtr nodes2); + +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathNodeLeadingSorted (xmlNodeSetPtr nodes, + xmlNodePtr node); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathLeadingSorted (xmlNodeSetPtr nodes1, + xmlNodeSetPtr nodes2); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathNodeLeading (xmlNodeSetPtr nodes, + xmlNodePtr node); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathLeading (xmlNodeSetPtr nodes1, + xmlNodeSetPtr nodes2); + +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathNodeTrailingSorted (xmlNodeSetPtr nodes, + xmlNodePtr node); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathTrailingSorted (xmlNodeSetPtr nodes1, + xmlNodeSetPtr nodes2); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathNodeTrailing (xmlNodeSetPtr nodes, + xmlNodePtr node); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathTrailing (xmlNodeSetPtr nodes1, + xmlNodeSetPtr nodes2); + + +/** + * Extending a context. + */ + +XMLPUBFUN int XMLCALL + xmlXPathRegisterNs (xmlXPathContextPtr ctxt, + const xmlChar *prefix, + const xmlChar *ns_uri); +XMLPUBFUN const xmlChar * XMLCALL + xmlXPathNsLookup (xmlXPathContextPtr ctxt, + const xmlChar *prefix); +XMLPUBFUN void XMLCALL + xmlXPathRegisteredNsCleanup (xmlXPathContextPtr ctxt); + +XMLPUBFUN int XMLCALL + xmlXPathRegisterFunc (xmlXPathContextPtr ctxt, + const xmlChar *name, + xmlXPathFunction f); +XMLPUBFUN int XMLCALL + xmlXPathRegisterFuncNS (xmlXPathContextPtr ctxt, + const xmlChar *name, + const xmlChar *ns_uri, + xmlXPathFunction f); +XMLPUBFUN int XMLCALL + xmlXPathRegisterVariable (xmlXPathContextPtr ctxt, + const xmlChar *name, + xmlXPathObjectPtr value); +XMLPUBFUN int XMLCALL + xmlXPathRegisterVariableNS (xmlXPathContextPtr ctxt, + const xmlChar *name, + const xmlChar *ns_uri, + xmlXPathObjectPtr value); +XMLPUBFUN xmlXPathFunction XMLCALL + xmlXPathFunctionLookup (xmlXPathContextPtr ctxt, + const xmlChar *name); +XMLPUBFUN xmlXPathFunction XMLCALL + xmlXPathFunctionLookupNS (xmlXPathContextPtr ctxt, + const xmlChar *name, + const xmlChar *ns_uri); +XMLPUBFUN void XMLCALL + xmlXPathRegisteredFuncsCleanup (xmlXPathContextPtr ctxt); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathVariableLookup (xmlXPathContextPtr ctxt, + const xmlChar *name); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathVariableLookupNS (xmlXPathContextPtr ctxt, + const xmlChar *name, + const xmlChar *ns_uri); +XMLPUBFUN void XMLCALL + xmlXPathRegisteredVariablesCleanup(xmlXPathContextPtr ctxt); + +/** + * Utilities to extend XPath. + */ +XMLPUBFUN xmlXPathParserContextPtr XMLCALL + xmlXPathNewParserContext (const xmlChar *str, + xmlXPathContextPtr ctxt); +XMLPUBFUN void XMLCALL + xmlXPathFreeParserContext (xmlXPathParserContextPtr ctxt); + +/* TODO: remap to xmlXPathValuePop and Push. */ +XMLPUBFUN xmlXPathObjectPtr XMLCALL + valuePop (xmlXPathParserContextPtr ctxt); +XMLPUBFUN int XMLCALL + valuePush (xmlXPathParserContextPtr ctxt, + xmlXPathObjectPtr value); + +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathNewString (const xmlChar *val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathNewCString (const char *val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathWrapString (xmlChar *val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathWrapCString (char * val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathNewFloat (double val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathNewBoolean (int val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathNewNodeSet (xmlNodePtr val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathNewValueTree (xmlNodePtr val); +XMLPUBFUN void XMLCALL + xmlXPathNodeSetAdd (xmlNodeSetPtr cur, + xmlNodePtr val); +XMLPUBFUN void XMLCALL + xmlXPathNodeSetAddUnique (xmlNodeSetPtr cur, + xmlNodePtr val); +XMLPUBFUN void XMLCALL + xmlXPathNodeSetAddNs (xmlNodeSetPtr cur, + xmlNodePtr node, + xmlNsPtr ns); +XMLPUBFUN void XMLCALL + xmlXPathNodeSetSort (xmlNodeSetPtr set); + +XMLPUBFUN void XMLCALL + xmlXPathRoot (xmlXPathParserContextPtr ctxt); +XMLPUBFUN void XMLCALL + xmlXPathEvalExpr (xmlXPathParserContextPtr ctxt); +XMLPUBFUN xmlChar * XMLCALL + xmlXPathParseName (xmlXPathParserContextPtr ctxt); +XMLPUBFUN xmlChar * XMLCALL + xmlXPathParseNCName (xmlXPathParserContextPtr ctxt); + +/* + * Existing functions. + */ +XMLPUBFUN double XMLCALL + xmlXPathStringEvalNumber (const xmlChar *str); +XMLPUBFUN int XMLCALL + xmlXPathEvaluatePredicateResult (xmlXPathParserContextPtr ctxt, + xmlXPathObjectPtr res); +XMLPUBFUN void XMLCALL + xmlXPathRegisterAllFunctions (xmlXPathContextPtr ctxt); +XMLPUBFUN xmlNodeSetPtr XMLCALL + xmlXPathNodeSetMerge (xmlNodeSetPtr val1, + xmlNodeSetPtr val2); +XMLPUBFUN void XMLCALL + xmlXPathNodeSetDel (xmlNodeSetPtr cur, + xmlNodePtr val); +XMLPUBFUN void XMLCALL + xmlXPathNodeSetRemove (xmlNodeSetPtr cur, + int val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathNewNodeSetList (xmlNodeSetPtr val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathWrapNodeSet (xmlNodeSetPtr val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPathWrapExternal (void *val); + +XMLPUBFUN int XMLCALL xmlXPathEqualValues(xmlXPathParserContextPtr ctxt); +XMLPUBFUN int XMLCALL xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt); +XMLPUBFUN int XMLCALL xmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict); +XMLPUBFUN void XMLCALL xmlXPathValueFlipSign(xmlXPathParserContextPtr ctxt); +XMLPUBFUN void XMLCALL xmlXPathAddValues(xmlXPathParserContextPtr ctxt); +XMLPUBFUN void XMLCALL xmlXPathSubValues(xmlXPathParserContextPtr ctxt); +XMLPUBFUN void XMLCALL xmlXPathMultValues(xmlXPathParserContextPtr ctxt); +XMLPUBFUN void XMLCALL xmlXPathDivValues(xmlXPathParserContextPtr ctxt); +XMLPUBFUN void XMLCALL xmlXPathModValues(xmlXPathParserContextPtr ctxt); + +XMLPUBFUN int XMLCALL xmlXPathIsNodeType(const xmlChar *name); + +/* + * Some of the axis navigation routines. + */ +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextSelf(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextChild(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextDescendantOrSelf(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextParent(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextAncestorOrSelf(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextFollowingSibling(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextAttribute(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextPrecedingSibling(xmlXPathParserContextPtr ctxt, + xmlNodePtr cur); +/* + * The official core of XPath functions. + */ +XMLPUBFUN void XMLCALL xmlXPathLastFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathCountFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathIdFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathConcatFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathContainsFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathStartsWithFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathNotFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathTrueFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathFalseFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathLangFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs); + +/** + * Really internal functions + */ +XMLPUBFUN void XMLCALL xmlXPathNodeSetFreeNs(xmlNsPtr ns); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_XPATH_ENABLED */ +#endif /* ! __XML_XPATH_INTERNALS_H__ */ diff --git a/include/libxml/xpointer.h b/include/libxml/xpointer.h new file mode 100644 index 0000000..dde1dfb --- /dev/null +++ b/include/libxml/xpointer.h @@ -0,0 +1,114 @@ +/* + * Summary: API to handle XML Pointers + * Description: API to handle XML Pointers + * Base implementation was made accordingly to + * W3C Candidate Recommendation 7 June 2000 + * http://www.w3.org/TR/2000/CR-xptr-20000607 + * + * Added support for the element() scheme described in: + * W3C Proposed Recommendation 13 November 2002 + * http://www.w3.org/TR/2002/PR-xptr-element-20021113/ + * + * Copy: See Copyright for the status of this software. + * + * Author: Daniel Veillard + */ + +#ifndef __XML_XPTR_H__ +#define __XML_XPTR_H__ + +#include + +#ifdef LIBXML_XPTR_ENABLED + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * A Location Set + */ +typedef struct _xmlLocationSet xmlLocationSet; +typedef xmlLocationSet *xmlLocationSetPtr; +struct _xmlLocationSet { + int locNr; /* number of locations in the set */ + int locMax; /* size of the array as allocated */ + xmlXPathObjectPtr *locTab;/* array of locations */ +}; + +/* + * Handling of location sets. + */ + +XMLPUBFUN xmlLocationSetPtr XMLCALL + xmlXPtrLocationSetCreate (xmlXPathObjectPtr val); +XMLPUBFUN void XMLCALL + xmlXPtrFreeLocationSet (xmlLocationSetPtr obj); +XMLPUBFUN xmlLocationSetPtr XMLCALL + xmlXPtrLocationSetMerge (xmlLocationSetPtr val1, + xmlLocationSetPtr val2); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPtrNewRange (xmlNodePtr start, + int startindex, + xmlNodePtr end, + int endindex); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPtrNewRangePoints (xmlXPathObjectPtr start, + xmlXPathObjectPtr end); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPtrNewRangeNodePoint (xmlNodePtr start, + xmlXPathObjectPtr end); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPtrNewRangePointNode (xmlXPathObjectPtr start, + xmlNodePtr end); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPtrNewRangeNodes (xmlNodePtr start, + xmlNodePtr end); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPtrNewLocationSetNodes (xmlNodePtr start, + xmlNodePtr end); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPtrNewLocationSetNodeSet(xmlNodeSetPtr set); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPtrNewRangeNodeObject (xmlNodePtr start, + xmlXPathObjectPtr end); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPtrNewCollapsedRange (xmlNodePtr start); +XMLPUBFUN void XMLCALL + xmlXPtrLocationSetAdd (xmlLocationSetPtr cur, + xmlXPathObjectPtr val); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPtrWrapLocationSet (xmlLocationSetPtr val); +XMLPUBFUN void XMLCALL + xmlXPtrLocationSetDel (xmlLocationSetPtr cur, + xmlXPathObjectPtr val); +XMLPUBFUN void XMLCALL + xmlXPtrLocationSetRemove (xmlLocationSetPtr cur, + int val); + +/* + * Functions. + */ +XMLPUBFUN xmlXPathContextPtr XMLCALL + xmlXPtrNewContext (xmlDocPtr doc, + xmlNodePtr here, + xmlNodePtr origin); +XMLPUBFUN xmlXPathObjectPtr XMLCALL + xmlXPtrEval (const xmlChar *str, + xmlXPathContextPtr ctx); +XMLPUBFUN void XMLCALL + xmlXPtrRangeToFunction (xmlXPathParserContextPtr ctxt, + int nargs); +XMLPUBFUN xmlNodePtr XMLCALL + xmlXPtrBuildNodeList (xmlXPathObjectPtr obj); +XMLPUBFUN void XMLCALL + xmlXPtrEvalRangePredicate (xmlXPathParserContextPtr ctxt); +#ifdef __cplusplus +} +#endif + +#endif /* LIBXML_XPTR_ENABLED */ +#endif /* __XML_XPTR_H__ */ diff --git a/include/r5-only/BePodder_R5.h b/include/r5-only/BePodder_R5.h new file mode 100644 index 0000000..4a963f9 --- /dev/null +++ b/include/r5-only/BePodder_R5.h @@ -0,0 +1,14 @@ +struct pair { + const char* key; + const char* data; +}; + +#define NUMBER 5 + +const pair r5languge[NUMBER]={ + {"alert1","\nYou are going to remove the selected item.\n\nAre you sure?\n(you will lost the enclosure file if any)"}, + {"alert2a","\nYou are going to remove the channel:\n\n"}, + {"alert2b","\n\nWould you like just to archive this channel (keeping all the files and enclosures downloaded so far) or do you want to DELETE the whole channel from you computer?"}, + {"alert3","\nParsing archive.."}, + {"not down","not downloaded"} +}; \ No newline at end of file diff --git a/include/r5-only/ObjectList.h b/include/r5-only/ObjectList.h new file mode 100644 index 0000000..bfa1832 --- /dev/null +++ b/include/r5-only/ObjectList.h @@ -0,0 +1,866 @@ +/* +Open Tracker License + +Terms and Conditions + +Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice applies to all licensees +and shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Be Incorporated shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from Be Incorporated. + +Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks +of Be Incorporated in the United States and other countries. Other brand product +names are registered trademarks or trademarks of their respective holders. +All rights reserved. +*/ + +/**************************************************************************** +** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ** +** ** +** DANGER, WILL ROBINSON! ** +** ** +** The interfaces contained here are part of BeOS's ** +** ** +** >> PRIVATE NOT FOR PUBLIC USE << ** +** ** +** implementation. ** +** ** +** These interfaces WILL CHANGE in future releases. ** +** If you use them, your app WILL BREAK at some future time. ** +** ** +** (And yes, this does mean that binaries built from OpenTracker will not ** +** be compatible with some future releases of the OS. When that happens, ** +** we will provide an updated version of this file to keep compatibility.) ** +** ** +** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ** +****************************************************************************/ + +// +// ObjectList is a wrapper around BList that adds type safety, +// optional object ownership, search, insert operations, etc. +// + +#ifndef __OBJECT_LIST__ +#define __OBJECT_LIST__ + +#ifndef _BE_H +#include +#endif + +#include + + +template class BObjectList; + +template +struct UnaryPredicate { + + virtual int operator()(const T *) const + // virtual could be avoided here if FindBinaryInsertionIndex, + // etc. were member template functions + { return 0; } + +private: + static int _unary_predicate_glue(const void *item, void *context); + +friend class BObjectList; +}; + +template +int +UnaryPredicate::_unary_predicate_glue(const void *item, void *context) +{ + return ((UnaryPredicate *)context)->operator()((const T *)item); +} + + +class _PointerList_ : public BList { +public: + _PointerList_(const _PointerList_ &list); + _PointerList_(int32 itemsPerBlock = 20, bool owning = false); + ~_PointerList_(); + + typedef void *(* GenericEachFunction)(void *, void *); + typedef int (* GenericCompareFunction)(const void *, const void *); + typedef int (* GenericCompareFunctionWithState)(const void *, const void *, + void *); + typedef int (* UnaryPredicateGlue)(const void *, void *); + + void *EachElement(GenericEachFunction, void *); + void SortItems(GenericCompareFunction); + void SortItems(GenericCompareFunctionWithState, void *state); + void HSortItems(GenericCompareFunction); + void HSortItems(GenericCompareFunctionWithState, void *state); + + void *BinarySearch(const void *, GenericCompareFunction) const; + void *BinarySearch(const void *, GenericCompareFunctionWithState, void *state) const; + + int32 BinarySearchIndex(const void *, GenericCompareFunction) const; + int32 BinarySearchIndex(const void *, GenericCompareFunctionWithState, void *state) const; + int32 BinarySearchIndexByPredicate(const void *, UnaryPredicateGlue) const; + + bool Owning() const; + bool ReplaceItem(int32, void *); + +protected: + bool owning; + +}; + +template +class BObjectList : private _PointerList_ { +public: + + // iteration and sorting + typedef T *(* EachFunction)(T *, void *); + typedef const T *(* ConstEachFunction)(const T *, void *); + typedef int (* CompareFunction)(const T *, const T *); + typedef int (* CompareFunctionWithState)(const T *, const T *, void *state); + + BObjectList(int32 itemsPerBlock = 20, bool owning = false); + BObjectList(const BObjectList &list); + // clones list; if list is owning, makes copies of all + // the items + + virtual ~BObjectList(); + + BObjectList &operator=(const BObjectList &list); + // clones list; if list is owning, makes copies of all + // the items + + // adding and removing + // ToDo: + // change Add calls to return const item + bool AddItem(T *); + bool AddItem(T *, int32); + bool AddList(BObjectList *); + bool AddList(BObjectList *, int32); + + bool RemoveItem(T *, bool deleteIfOwning = true); + // if owning, deletes the removed item + T *RemoveItemAt(int32); + // returns the removed item + + void MakeEmpty(bool deleteIfOwning = true); + + // item access + T *ItemAt(int32) const; + + bool ReplaceItem(int32 index, T *); + // if list is owning, deletes the item at first + T *SwapWithItem(int32 index, T *newItem); + // same as ReplaceItem, except does not delete old item at , + // returns it instead + + T *FirstItem() const; + T *LastItem() const; + + // misc. getters + int32 IndexOf(const T *) const; + bool HasItem(const T *) const; + bool IsEmpty() const; + int32 CountItems() const; + + T *EachElement(EachFunction, void *); + const T *EachElement(ConstEachFunction, void *) const; + + void SortItems(CompareFunction); + void SortItems(CompareFunctionWithState, void *state); + void HSortItems(CompareFunction); + void HSortItems(CompareFunctionWithState, void *state); + + // linear search, returns first item that matches predicate + const T *FindIf(const UnaryPredicate &) const; + T *FindIf(const UnaryPredicate &); + + // list must be sorted with CompareFunction for these to work + T *BinarySearch(const T &, CompareFunction) const; + T *BinarySearch(const T &, CompareFunctionWithState, void *state) const; + + template + T *BinarySearchByKey(const Key &key, int (*compare)(const Key *, const T *)) + const; + + template + T *BinarySearchByKey(const Key &key, + int (*compare)(const Key *, const T *, void *), void *state) const; + + int32 BinarySearchIndex(const T &item, CompareFunction compare) const; + int32 BinarySearchIndex(const T &item, CompareFunctionWithState compare, + void *state) const; + + template + int32 BinarySearchIndexByKey(const Key &key, + int (*compare)(const Key *, const T *)) const; + + // Binary insertion - list must be sorted with CompareFunction for + // these to work + + // simple insert + bool BinaryInsert(T *, CompareFunction); + bool BinaryInsert(T *, CompareFunctionWithState, void *state); + bool BinaryInsert(T *, const UnaryPredicate &); + + // unique insert, returns false if item already in list + bool BinaryInsertUnique(T *, CompareFunction); + bool BinaryInsertUnique(T *, CompareFunctionWithState, void *state); + bool BinaryInsertUnique(T *, const UnaryPredicate &); + + // insert a copy of the item, returns new inserted item + T *BinaryInsertCopy(const T ©This, CompareFunction); + T *BinaryInsertCopy(const T ©This, CompareFunctionWithState, void *state); + + // insert a copy of the item if not in list already + // returns new inserted item or existing item in case of a conflict + T *BinaryInsertCopyUnique(const T ©This, CompareFunction); + T *BinaryInsertCopyUnique(const T ©This, CompareFunctionWithState, void *state); + + int32 FindBinaryInsertionIndex(const UnaryPredicate &, bool *alreadyInList = 0) const; + // returns either the index into which a new item should be inserted + // or index of an existing item that matches the predicate + + // deprecated API, will go away + BList *AsBList() + { return this; } + const BList *AsBList() const + { return this; } +private: + void SetItem(int32, T *); +}; + +template +Result +WhileEachListItem(BObjectList *list, Result (Item::*func)(Param1), Param1 p1) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (list->ItemAt(index)->*func)(p1)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (*func)(Item *, Param1), Param1 p1) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (*func)(list->ItemAt(index), p1)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (Item::*func)(Param1, Param2), + Param1 p1, Param2 p2) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (list->ItemAt(index)->*func)(p1, p2)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (*func)(Item *, Param1, Param2), + Param1 p1, Param2 p2) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (*func)(list->ItemAt(index), p1, p2)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (*func)(Item *, Param1, Param2, + Param3, Param4), Param1 p1, Param2 p2, Param3 p3, Param4 p4) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (*func)(list->ItemAt(index), p1, p2, p3, p4)) != 0) + break; + + return result; +} + +template +void +EachListItemIgnoreResult(BObjectList *list, Result (Item::*func)()) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (list->ItemAt(index)->*func)(); +} + +template +void +EachListItem(BObjectList *list, void (*func)(Item *, Param1), Param1 p1) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1); +} + +template +void +EachListItem(BObjectList *list, void (Item::*func)(Param1, Param2), + Param1 p1, Param2 p2) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (list->ItemAt(index)->*func)(p1, p2); +} + +template +void +EachListItem(BObjectList *list, void (*func)(Item *,Param1, Param2), + Param1 p1, Param2 p2) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1, p2); +} + +template +void +EachListItem(BObjectList *list, void (*func)(Item *,Param1, Param2, + Param3), Param1 p1, Param2 p2, Param3 p3) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1, p2, p3); +} + + +template +void +EachListItem(BObjectList *list, void (*func)(Item *,Param1, Param2, + Param3, Param4), Param1 p1, Param2 p2, Param3 p3, Param4 p4) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1, p2, p3, p4); +} + +// inline code + +inline bool +_PointerList_::Owning() const +{ + return owning; +} + +template +BObjectList::BObjectList(int32 itemsPerBlock, bool owning) + : _PointerList_(itemsPerBlock, owning) +{ +} + +template +BObjectList::BObjectList(const BObjectList &list) + : _PointerList_(list) +{ + owning = list.owning; + if (owning) { + // make our own copies in an owning list + int32 count = list.CountItems(); + for (int32 index = 0; index < count; index++) { + T *item = list.ItemAt(index); + if (item) + item = new T(*item); + SetItem(index, item); + } + } +} + +template +BObjectList::~BObjectList() +{ + if (Owning()) + // have to nuke elements first + MakeEmpty(); +} + +template +BObjectList & +BObjectList::operator=(const BObjectList &list) +{ + owning = list.owning; + BObjectList &result = (BObjectList &)_PointerList_::operator=(list); + if (owning) { + // make our own copies in an owning list + int32 count = list.CountItems(); + for (int32 index = 0; index < count; index++) { + T *item = list.ItemAt(index); + if (item) + item = new T(*item); + SetItem(index, item); + } + } + return result; +} + +template +bool +BObjectList::AddItem(T *item) +{ + // need to cast to void * to make T work for const pointers + return _PointerList_::AddItem((void *)item); +} + +template +bool +BObjectList::AddItem(T *item, int32 atIndex) +{ + return _PointerList_::AddItem((void *)item, atIndex); +} + +template +bool +BObjectList::AddList(BObjectList *newItems) +{ + return _PointerList_::AddList(newItems); +} + +template +bool +BObjectList::AddList(BObjectList *newItems, int32 atIndex) +{ + return _PointerList_::AddList(newItems, atIndex); +} + + +template +bool +BObjectList::RemoveItem(T *item, bool deleteIfOwning) +{ + bool result = _PointerList_::RemoveItem((void *)item); + + if (result && Owning() && deleteIfOwning) + delete item; + + return result; +} + +template +T * +BObjectList::RemoveItemAt(int32 index) +{ + return (T *)_PointerList_::RemoveItem(index); +} + +template +inline T * +BObjectList::ItemAt(int32 index) const +{ + return (T *)_PointerList_::ItemAt(index); +} + +template +bool +BObjectList::ReplaceItem(int32 index, T *item) +{ + if (owning) + delete ItemAt(index); + return _PointerList_::ReplaceItem(index, (void *)item); +} + +template +T * +BObjectList::SwapWithItem(int32 index, T *newItem) +{ + T *result = ItemAt(index); + _PointerList_::ReplaceItem(index, (void *)newItem); + return result; +} + +template +void +BObjectList::SetItem(int32 index, T *newItem) +{ + _PointerList_::ReplaceItem(index, (void *)newItem); +} + +template +int32 +BObjectList::IndexOf(const T *item) const +{ + return _PointerList_::IndexOf((void *)item); +} + +template +T * +BObjectList::FirstItem() const +{ + return (T *)_PointerList_::FirstItem(); +} + +template +T * +BObjectList::LastItem() const +{ + return (T *)_PointerList_::LastItem(); +} + +template +bool +BObjectList::HasItem(const T *item) const +{ + return _PointerList_::HasItem((void *)item); +} + +template +bool +BObjectList::IsEmpty() const +{ + return _PointerList_::IsEmpty(); +} + +template +int32 +BObjectList::CountItems() const +{ + return _PointerList_::CountItems(); +} + +template +void +BObjectList::MakeEmpty(bool deleteIfOwning) +{ + if (owning && deleteIfOwning) { + int32 count = CountItems(); + for (int32 index = 0; index < count; index++) + delete ItemAt(index); + } + _PointerList_::MakeEmpty(); +} + +template +T * +BObjectList::EachElement(EachFunction func, void *params) +{ + return (T *)_PointerList_::EachElement((GenericEachFunction)func, params); +} + + +template +const T * +BObjectList::EachElement(ConstEachFunction func, void *params) const +{ + return (const T *) + const_cast *>(this)->_PointerList_::EachElement( + (GenericEachFunction)func, params); +} + +template +const T * +BObjectList::FindIf(const UnaryPredicate &predicate) const +{ + int32 count = CountItems(); + for (int32 index = 0; index < count; index++) + if (predicate.operator()(ItemAt(index)) == 0) + return ItemAt(index); + return 0; +} + +template +T * +BObjectList::FindIf(const UnaryPredicate &predicate) +{ + int32 count = CountItems(); + for (int32 index = 0; index < count; index++) + if (predicate.operator()(ItemAt(index)) == 0) + return ItemAt(index); + return 0; +} + + +template +void +BObjectList::SortItems(CompareFunction function) +{ + _PointerList_::SortItems((GenericCompareFunction)function); +} + +template +void +BObjectList::SortItems(CompareFunctionWithState function, void *state) +{ + _PointerList_::SortItems((GenericCompareFunctionWithState)function, state); +} + +template +void +BObjectList::HSortItems(CompareFunction function) +{ + _PointerList_::HSortItems((GenericCompareFunction)function); +} + +template +void +BObjectList::HSortItems(CompareFunctionWithState function, void *state) +{ + _PointerList_::HSortItems((GenericCompareFunctionWithState)function, state); +} + +template +T * +BObjectList::BinarySearch(const T &key, CompareFunction func) const +{ + return (T*)_PointerList_::BinarySearch(&key, + (GenericCompareFunction)func); +} + +template +T * +BObjectList::BinarySearch(const T &key, CompareFunctionWithState func, void *state) const +{ + return (T*)_PointerList_::BinarySearch(&key, + (GenericCompareFunctionWithState)func, state); +} + + +template +template +T * +BObjectList::BinarySearchByKey(const Key &key, + int (*compare)(const Key *, const T *)) const +{ + return (T*)_PointerList_::BinarySearch(&key, + (GenericCompareFunction)compare); +} + + +template +template +T * +BObjectList::BinarySearchByKey(const Key &key, + int (*compare)(const Key *, const T *, void *), void *state) const +{ + return (T*)_PointerList_::BinarySearch(&key, + (GenericCompareFunctionWithState)compare, state); +} + + +template +int32 +BObjectList::BinarySearchIndex(const T &item, CompareFunction compare) const +{ + return _PointerList_::BinarySearchIndex(&item, + (GenericCompareFunction)compare); +} + + +template +int32 +BObjectList::BinarySearchIndex(const T &item, + CompareFunctionWithState compare, void *state) const +{ + return _PointerList_::BinarySearchIndex(&item, + (GenericCompareFunctionWithState)compare, state); +} + + +template +template +int32 +BObjectList::BinarySearchIndexByKey(const Key &key, + int (*compare)(const Key *, const T *)) const +{ + return _PointerList_::BinarySearchIndex(&key, + (GenericCompareFunction)compare); +} + + +template +bool +BObjectList::BinaryInsert(T *item, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunction)func); + if (index >= 0) { + // already in list, add after existing + return AddItem(item, index + 1); + } + + return AddItem(item, -index - 1); +} + +template +bool +BObjectList::BinaryInsert(T *item, CompareFunctionWithState func, void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunctionWithState)func, state); + if (index >= 0) { + // already in list, add after existing + return AddItem(item, index + 1); + } + + return AddItem(item, -index - 1); +} + +template +bool +BObjectList::BinaryInsertUnique(T *item, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunction)func); + if (index >= 0) + return false; + + return AddItem(item, -index - 1); +} + +template +bool +BObjectList::BinaryInsertUnique(T *item, CompareFunctionWithState func, void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunctionWithState)func, state); + if (index >= 0) + return false; + + return AddItem(item, -index - 1); +} + + +template +T * +BObjectList::BinaryInsertCopy(const T ©This, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunction)func); + + if (index >= 0) + index++; + else + index = -index - 1; + + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +T * +BObjectList::BinaryInsertCopy(const T ©This, CompareFunctionWithState func, void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunctionWithState)func, state); + + if (index >= 0) + index++; + else + index = -index - 1; + + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +T * +BObjectList::BinaryInsertCopyUnique(const T ©This, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunction)func); + if (index >= 0) + return ItemAt(index); + + index = -index - 1; + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +T * +BObjectList::BinaryInsertCopyUnique(const T ©This, CompareFunctionWithState func, + void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunctionWithState)func, state); + if (index >= 0) + return ItemAt(index); + + index = -index - 1; + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +int32 +BObjectList::FindBinaryInsertionIndex(const UnaryPredicate &pred, bool *alreadyInList) + const +{ + int32 index = _PointerList_::BinarySearchIndexByPredicate(&pred, + (UnaryPredicateGlue)&UnaryPredicate::_unary_predicate_glue); + + if (alreadyInList) + *alreadyInList = index >= 0; + + if (index < 0) + index = -index - 1; + + return index; +} + +template +bool +BObjectList::BinaryInsert(T *item, const UnaryPredicate &pred) +{ + return AddItem(item, FindBinaryInsertionIndex(pred)); +} + +template +bool +BObjectList::BinaryInsertUnique(T *item, const UnaryPredicate &pred) +{ + bool alreadyInList; + int32 index = FindBinaryInsertionIndex(pred, &alreadyInList); + if (alreadyInList) + return false; + + AddItem(item, index); + return true; +} + +#endif /* __OBJECT_LIST__ */ diff --git a/include/r5-only/R5Locale.h b/include/r5-only/R5Locale.h new file mode 100644 index 0000000..c74b13e --- /dev/null +++ b/include/r5-only/R5Locale.h @@ -0,0 +1,9 @@ +#ifndef _R5Locale_H +#define _R5Locale_H + +#include "String.h" + +const char* +findKey(const char*); + +#endif \ No newline at end of file diff --git a/include/r5-only/iconv.h b/include/r5-only/iconv.h new file mode 100644 index 0000000..a59a6f3 --- /dev/null +++ b/include/r5-only/iconv.h @@ -0,0 +1,120 @@ +/* Copyright (C) 1999-2002 Free Software Foundation, Inc. + This file is part of the GNU LIBICONV Library. + + The GNU LIBICONV Library is free software; you can redistribute it + and/or modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + The GNU LIBICONV Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU LIBICONV Library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, Inc., 59 Temple Place - + Suite 330, Boston, MA 02111-1307, USA. */ + +/* When installed, this file is called "iconv.h". */ + +#ifndef _LIBICONV_H +#define _LIBICONV_H + +#define _LIBICONV_VERSION 0x0108 /* version number: (major<<8) + minor */ +extern int _libiconv_version; /* Likewise */ + +/* We would like to #include any system header file which could define + iconv_t, 1. in order to eliminate the risk that the user gets compilation + errors because some other system header file includes /usr/include/iconv.h + which defines iconv_t or declares iconv after this file, 2. when compiling + for LIBICONV_PLUG, we need the proper iconv_t type in order to produce + binary compatible code. + But gcc's #include_next is not portable. Thus, once libiconv's iconv.h + has been installed in /usr/local/include, there is no way any more to + include the original /usr/include/iconv.h. We simply have to get away + without it. + Ad 1. The risk that a system header file does + #include "iconv.h" or #include_next "iconv.h" + is small. They all do #include . + Ad 2. The iconv_t type is a pointer type in all cases I have seen. (It + has to be a scalar type because (iconv_t)(-1) is a possible return value + from iconv_open().) */ + +/* Define iconv_t ourselves. */ +#undef iconv_t +#define iconv_t libiconv_t +typedef void* iconv_t; + +/* Get size_t declaration. */ +#include + +/* Get errno declaration and values. */ +#include +/* Some systems, like SunOS 4, don't have EILSEQ. Some systems, like BSD/OS, + have EILSEQ in a different header. On these systems, define EILSEQ + ourselves. */ +#ifndef EILSEQ +#define EILSEQ +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Allocates descriptor for code conversion from encoding `fromcode' to + encoding `tocode'. */ +#ifndef LIBICONV_PLUG +#define iconv_open libiconv_open +#endif +extern iconv_t iconv_open (const char* tocode, const char* fromcode); + +/* Converts, using conversion descriptor `cd', at most `*inbytesleft' bytes + starting at `*inbuf', writing at most `*outbytesleft' bytes starting at + `*outbuf'. + Decrements `*inbytesleft' and increments `*inbuf' by the same amount. + Decrements `*outbytesleft' and increments `*outbuf' by the same amount. */ +#ifndef LIBICONV_PLUG +#define iconv libiconv +#endif +extern size_t iconv (iconv_t cd, const char* * inbuf, size_t *inbytesleft, char* * outbuf, size_t *outbytesleft); + +/* Frees resources allocated for conversion descriptor `cd'. */ +#ifndef LIBICONV_PLUG +#define iconv_close libiconv_close +#endif +extern int iconv_close (iconv_t cd); + + +#ifndef LIBICONV_PLUG + +/* Nonstandard extensions. */ + +/* Control of attributes. */ +#define iconvctl libiconvctl +extern int iconvctl (iconv_t cd, int request, void* argument); + +/* Requests for iconvctl. */ +#define ICONV_TRIVIALP 0 /* int *argument */ +#define ICONV_GET_TRANSLITERATE 1 /* int *argument */ +#define ICONV_SET_TRANSLITERATE 2 /* const int *argument */ +#define ICONV_GET_DISCARD_ILSEQ 3 /* int *argument */ +#define ICONV_SET_DISCARD_ILSEQ 4 /* const int *argument */ + +/* Listing of locale independent encodings. */ +#define iconvlist libiconvlist +extern void iconvlist (int (*do_one) (unsigned int namescount, + const char * const * names, + void* data), + void* data); +#endif + + +#ifdef __cplusplus +} +#endif + + +#endif /* _LIBICONV_H */ diff --git a/include/runview/RVAction.h b/include/runview/RVAction.h new file mode 100644 index 0000000..4bbeebb --- /dev/null +++ b/include/runview/RVAction.h @@ -0,0 +1,15 @@ +#ifndef _RVAction_h_ +#define _RVAction_h_ + +class RVAction +{ + public: + + virtual ~RVAction(){}; + + virtual status_t Perform(BString param) = 0; + virtual BString GetDescription() = 0; + +}; + +#endif diff --git a/include/runview/RunView.h b/include/runview/RunView.h new file mode 100644 index 0000000..8cb55d6 --- /dev/null +++ b/include/runview/RunView.h @@ -0,0 +1,249 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Vision. + * + * The Initial Developer of the Original Code is The Vision Team. + * Portions created by The Vision Team are + * Copyright (C) 1999, 2000, 2001 The Vision Team. All Rights + * Reserved. + * + * Contributor(s): Rene Gollent + * Todd Lair + */ + +#ifndef RUNVIEW_H_ +#define RUNVIEW_H_ + +#define LINE_COUNT 1000 + +#include + + +//#include "main.h" + +struct Line; +class RVAction; //by xeD +class Theme; +class RunView; +class BScrollView; +class BCursor; +class BMessageRunner; +class BPopUpMenu; + + +const uint32 kResizeMessage = 'irsz'; +const uint32 M_LOOKUP_WEBSTER = 'rvlw'; +const uint32 M_LOOKUP_GOOGLE = 'rvlg'; +const uint32 M_LOOKUP_ACRONYM = 'rvla'; +const uint32 M_CLEAR = 'rvcl'; + +const uint32 M_OFFVIEW_SELECTION = 'rvos'; +const uint32 M_THEME_FOREGROUND_CHANGE = 'rvtf'; +const uint32 M_THEME_BACKGROUND_CHANGE = 'rvtb'; +const uint32 M_THEME_FONT_CHANGE = 'rvto'; + +#define C_URL 0 +#define C_TIMESTAMP 1 +#define C_TEXT 2 +#define C_OWNNICK 3 +#define C_OTHERNICK 4 +#define C_ACTION 5 +#define C_SELECTION 6 +#define C_TIMESTAMP_DUMMY 7 // Needed to fake a TS +#define MAX_COLORS 8 + +/* +#define F_URL 0 +#define F_TEXT 1 +#define F_TIMESTAMP 2 +#define F_ACTION 3 +#define F_EMOTICON 4 // new style by xeD ;) +#define F_STYLE_0 4 // new style by xeD ;) +#define F_TIMESTAMP_DUMMY 5 // Needed to fake TS +#define MAX_FONTS 6 +*/ + +enum { + F_URL = 0, + F_TEXT, + F_TIMESTAMP, + F_ACTION, + F_EMOTICON, + F_STYLE_0, + F_STYLE_1, + F_STYLE_2, + F_TIMESTAMP_DUMMY, //DON'T TOUCH NOT USE + MAX_FONTS //DON'T TOUCH NOT USE +}; + +class SelectPos +{ + public: + + int16 fLine; + int16 fOffset; + + SelectPos ( + int16 selLine = 0, + int16 selOffset = 0) + : fLine (selLine), + fOffset (selOffset) + { } + + SelectPos (const SelectPos &pos) + : fLine (pos.fLine), + fOffset (pos.fOffset) + { } + + ~SelectPos (void) + { } + + SelectPos &operator = (const SelectPos &pos) + { + fLine = pos.fLine; + fOffset = pos.fOffset; + + return *this; + } + + inline int operator == (const SelectPos &rhs) const + { + return ((fLine == rhs.fLine) && (fOffset == rhs.fOffset)); + } + + inline int operator != (const SelectPos &rhs) const + { + return (!(*this == rhs)); + } + + +}; + +class RunView : public BView +{ + BScrollView *fScroller; + BCursor *fURLCursor; + Theme *fTheme; + + Line *fWorking; + Line *fLines[LINE_COUNT]; + int16 fLine_count, + fClickCount; + + char *fStamp_format; + char *fClipping_name; + + SelectPos fSp_start, fSp_end; + + int32 fTracking; + SelectPos fTrack_offset; + BMessageRunner *fOff_view_runner; + bigtime_t fOff_view_time; + + bool fResizedirty; + bool fFontsdirty; + BPopUpMenu *fMyPopUp; + BPoint fLastClick; + bigtime_t fLastClickTime; + + BMessage urls; //by xeD + BMessage actions; //by xeD + + bool fIndent; //by xeD + + RVAction* fDefaultURLAction; //by xeD + + RVAction* FindAction(const char* symbolicName); //by xeD + void InvokeAction(BString mangledName); //by xeD + + bool RecalcScrollBar (bool constrain); + void ResizeRecalc (void); + void FontChangeRecalc (void); + void ExtendTrackingSelect (BPoint); + void ShiftTrackingSelect (BPoint, bool, bigtime_t); + void CheckURLCursor (BPoint); + bool CheckURL(BPoint); //by xeD + BString GetURL(BPoint); + + void BuildPopUp (BPoint point); + + bool CheckClickBounds (const SelectPos &, const BPoint &) const; + void LoadURL(const char *url); + + public: + + RunView ( + BRect, + const char *, + Theme *, + uint32 = B_FOLLOW_LEFT | B_FOLLOW_TOP, + uint32 = 0UL); + virtual ~RunView (void); + + virtual void AttachedToWindow (void); + virtual void DetachedFromWindow (void); + virtual void FrameResized (float, float); + + virtual void TextResized(BRect /*r*/){}; //by xeD Callback when text bounds changed. + virtual float ExtraTextSize(){ return 0;}; //by xeD does we use more Vert space than the text? + + virtual void TargetedByScrollView (BScrollView *); + virtual void Show (); + virtual void Draw (BRect); + virtual void MessageReceived (BMessage *); + + virtual void SetViewColor (rgb_color); + void SetViewColor (uchar red, uchar green, uchar blue, uchar alpha = 255) + { rgb_color color = {red, green, blue, alpha}; SetViewColor (color); } + + + virtual void MouseDown (BPoint); + virtual void MouseMoved (BPoint, uint32, const BMessage *); + virtual void MouseUp (BPoint); + + //by xeD + void SetIndentWrappedLine(bool val){ fIndent = val;} + + void Append (const char *, int32, int16, int16, int16); + void Append (const char *, int16, int16, int16); + void AppendURL(const char *,const char *,int16 font); + void AppendURL(const char *,const char *,int16 back,int16 font); + + void ClearActions(); //by xeD + void AddAction(const char* symbolicName,RVAction*); //by xeD + void SetDefaultOpenURLAction(RVAction*); //by xeD + + void Clear (void); + + int16 LineCount (void) const; + const char *LineAt (int16) const; + + void SetTimeStampFormat (const char *); + void SetTheme (Theme *); + + SelectPos PositionAt (BPoint) const; + BPoint PointAt (SelectPos) const; + + BRect GetTextFrame (const SelectPos &, const SelectPos &) const; + bool IntersectSelection (const SelectPos &, const SelectPos &) const; + void GetSelectionText (BString &) const; + void Select (const SelectPos &, const SelectPos &); + void SelectAll (void); + void SetClippingName (const char *); + bool FindText(const char *); + + void ScrollToBottom(void); + void ScrollToSelection(void); + +}; + +#endif diff --git a/include/runview/TextRender.h b/include/runview/TextRender.h new file mode 100644 index 0000000..700fcc3 --- /dev/null +++ b/include/runview/TextRender.h @@ -0,0 +1,25 @@ +#ifndef _TextRender_H_ +#define _TextRender_H_ + +class TextRender +{ + public: + TextRender(){}; + virtual ~TextRender() {}; + + virtual void Render(BView *target,const char*,int16 num,BPoint pos,BRect drawRect) = 0; + + virtual void GetHeight(font_height *height) = 0; + virtual void GetEscapements(const char charArray[], int32 numChars,float escapementArray[])=0; + virtual float Size(float maxwidth) = 0; + + virtual void MarginAfterTheText(BView *target,rgb_color view_color, BRect rect){ + // Margin after fText + target->SetDrawingMode (B_OP_COPY); + target->SetLowColor (view_color); + target->FillRect (rect, B_SOLID_LOW); + } + // + +}; +#endif diff --git a/include/runview/Theme.h b/include/runview/Theme.h new file mode 100644 index 0000000..762be7d --- /dev/null +++ b/include/runview/Theme.h @@ -0,0 +1,109 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Vision. + * + * The Initial Developer of the Original Code is The Vision Team. + * Portions created by The Vision Team are + * Copyright (C) 1999, 2000, 2001 The Vision Team. All Rights + * Reserved. + * + * Contributor(s): Rene Gollent + * Todd Lair + */ + +#ifndef THEME_H_ +#define THEME_H_ + +#include +#include +#include + +#include "TextRender.h" + +class BView; +class NormalTextRender; + +class Theme +{ + char *name; + rgb_color *fores; + rgb_color *backs; + //BFont *fonts; + TextRender **text_renders; //FIX!! + + int16 fore_count; + int16 back_count; + int16 render_count; + + BList list; + sem_id sid; + + public: + + static int16 TimestampFore; + static int16 TimestampBack; + static int16 TimestampFont; + static int16 TimespaceFore; + static int16 TimespaceBack; + static int16 TimespaceFont; + static int16 NormalFore; + static int16 NormalBack; + static int16 NormalFont; + static int16 SelectionBack; + + Theme ( + const char *, + int16, + int16, + int16); + virtual ~Theme (void); + + const char *Name (void) const + { return name; } + + void ReadLock (void); + void ReadUnlock (void); + void WriteLock (void); + void WriteUnlock (void); + + int16 CountForegrounds (void) const; + int16 CountBackgrounds (void) const; +// int16 CountFonts (void) const; + int16 CountTextRenders (void) const; + + const rgb_color ForegroundAt (int16) const; + const rgb_color BackgroundAt (int16) const; + + //const BFont &FontAt (int16) const; + + TextRender* TextRenderAt(int16); + + bool SetForeground (int16, const rgb_color); + bool SetForeground (int16 w, uchar r, uchar g, uchar b, uchar a = 255) + { rgb_color color = {r, g, b, a}; return SetForeground (w, color); } + bool SetBackground (int16, const rgb_color); + bool SetBackground (int16 w, uchar r, uchar g, uchar b, uchar a = 255) + { rgb_color color = {r, g, b, a}; return SetBackground (w, color); } + + //bool SetFont (int16, const BFont &); + bool SetTextRender(int16, TextRender *); + + + + + void AddView (BView *); + void RemoveView (BView *); + + NormalTextRender *normal_textrender; +}; + +#endif diff --git a/library/Jamfile b/library/Jamfile new file mode 100644 index 0000000..2fd4553 --- /dev/null +++ b/library/Jamfile @@ -0,0 +1,8 @@ +SubDir TOP ; +SubInclude TOP libfunky ; +SubInclude TOP libclv ; +SubInclude TOP libfish ; +SubInclude TOP librunview ; +MakeDistro distro ; + + diff --git a/library/Jamrules b/library/Jamrules new file mode 100644 index 0000000..089a2cb --- /dev/null +++ b/library/Jamrules @@ -0,0 +1,67 @@ + +# The directories used by the build. +BUILD_DIR = [ FDirName $(TOP) build ] ; +GENERATED_DIR = [ FDirName $(TOP) generated ] ; +DISTRO_DIR = [ FDirName $(TOP) generated distro ] ; + +include [ FDirName $(BUILD_DIR) HelperRules ] ; +include [ FDirName $(BUILD_DIR) ConfigRules ] ; +include [ FDirName $(BUILD_DIR) OverriddenJamRules ] ; +include [ FDirName $(BUILD_DIR) MainBuildRules ] ; +include [ FDirName $(BUILD_DIR) BuildSettings ] ; + +# Include UserBuildConfig. +{ + local userBuildConfig = [ GLOB $(BUILD_DIR) : UserBuildConfig ] ; + if $(userBuildConfig) + { + LOCATE on UserBuildConfig = $(BUILD_DIR) ; + include UserBuildConfig ; + } +} + +# default to strip generated apps if not specified otherwise: +STRIP_APPS ?= 1 ; + +# Cache files for header scanning and jamfile caching. +HCACHEFILE = header_cache ; +JCACHEFILE = jamfile_cache ; +LOCATE on $(HCACHEFILE) $(JCACHEFILE) = $(GENERATED_DIR) ; + + +rule MakeDistro +{ + # MakeDistro + + local target = $1 ; + + NotFile $(target) ; + Always $(target) ; +} + +actions MakeDistro +{ + echo "making distro $(DISTRO_DIR)" ; + + jam + + ln -sf ../library/librunview/include ../include/runview + ln -sf ../library/libclv/include ../include/libclv + ln -sf ../library/libfish/include ../include/libfish + ln -sf ../library/libfunky/include ../include/libfunky + + cp $(DISTRO_DIR)/libclv.a ../libs/libclv.a + + if [ $(DEFINES)="ZETA" ] + then + echo "zeta" + cp $(DISTRO_DIR)/libfish.a ../libs/libfish.a + cp $(DISTRO_DIR)/librunview.a ../libs/librunview.a + cp $(DISTRO_DIR)/libfunky.a ../libs/libfunky.a + else + echo "beos" + cp $(DISTRO_DIR)/libfish.a ../libs/libfish.r5.a + cp $(DISTRO_DIR)/librunview.a ../libs/librunview.r5.a + cp $(DISTRO_DIR)/libfunky.a ../libs/libfunky.r5.a + fi +} diff --git a/library/build/BuildSettings b/library/build/BuildSettings new file mode 100644 index 0000000..bb9332d --- /dev/null +++ b/library/build/BuildSettings @@ -0,0 +1,127 @@ +# BuildSettings +# +# Setup global variables. + +# C and C++ flags +if $(OSPLAT) = PPC { + # filter out -nosyspath + CFLAGS = [ FFilter $(CFLAGS) : -nosyspath ] ; + C++FLAGS = [ FFilter $(C++FLAGS) : -nosyspath ] ; + LINKFLAGS += -warn -export pragma ; + + # set file containing preprocessed headers: + PREFIX_FILE ?= [ FDirName $(LOCATE_TARGET) pe.headers ] ; +} + +if $(OSPLAT) = X86 { + # check for BONE... + local haveBone = [ GLOB /boot/develop/headers/be/bone/arpa : inet.h ] ; + if $(haveBone) { + CCFLAGS += -DBONE_BUILD ; + C++FLAGS += -DBONE_BUILD ; + SYSHDRS += /boot/develop/headers/be/bone /boot/develop/headers/be/bone/sys ; + LINKLIBS += -lsocket -lbind ; + } else { + LINKLIBS += -lnet ; + } + # check for Zeta... + local haveZeta = [ GLOB /boot/beos/system/lib : libzeta.so ] ; + if $(haveZeta) { + LINKLIBS += -lzeta ; + DEFINES += ZETA ; + } +} + +# Use copyattr for copying. +CP = copyattr --data ; + +# Default paths for bison and flex: +BISON = bison ; +LEX = flex ; + +# mkdir shall not fail, if the directory already exists. +MKDIR = mkdir -p ; + +# Modify the main target dirs for languages and extensions. +SetConfigVar LOCATE_MAIN_TARGET : TOP Languages + : [ FDirName $(DISTRO_DIR) Languages ] ; +SetConfigVar LOCATE_MAIN_TARGET : TOP Extensions + : [ FDirName $(DISTRO_DIR) Extensions ] ; + +rule SetUpSubDirBuildSettings { + # SetUpSubDirBuildSettings