diff options
author | Arne Georg Gleditsch <argggh@lxr.linpro.no> | 2007-07-05 00:51:08 +0200 |
---|---|---|
committer | Arne Georg Gleditsch <argggh@lxr.linpro.no> | 2007-07-05 00:51:08 +0200 |
commit | e9fa4c98bb5f084739d3418ade3f0c51e34a0aa1 (patch) | |
tree | fec1d635625e031cde7cba1b0a1d95ee92ac760b /cgi-bin |
Rebase tree.
Diffstat (limited to 'cgi-bin')
-rw-r--r-- | cgi-bin/.htaccess | 8 | ||||
-rw-r--r-- | cgi-bin/css/lxrng.css | 278 | ||||
-rw-r--r-- | cgi-bin/gfx/Makefile | 10 | ||||
-rw-r--r-- | cgi-bin/gfx/close.png | bin | 0 -> 802 bytes | |||
-rw-r--r-- | cgi-bin/gfx/close.svg | 102 | ||||
-rw-r--r-- | cgi-bin/gfx/diff.png | bin | 0 -> 605 bytes | |||
-rw-r--r-- | cgi-bin/gfx/diff.svg | 129 | ||||
-rw-r--r-- | cgi-bin/gfx/left.png | bin | 0 -> 585 bytes | |||
-rw-r--r-- | cgi-bin/gfx/left.svg | 102 | ||||
-rw-r--r-- | cgi-bin/gfx/print.png | bin | 0 -> 355 bytes | |||
-rw-r--r-- | cgi-bin/gfx/print.svg | 149 | ||||
-rw-r--r-- | cgi-bin/gfx/right.png | bin | 0 -> 586 bytes | |||
-rw-r--r-- | cgi-bin/gfx/right.svg | 102 | ||||
-rw-r--r-- | cgi-bin/gfx/rolldown.png | bin | 0 -> 536 bytes | |||
-rw-r--r-- | cgi-bin/gfx/rolldown.svg | 102 | ||||
-rw-r--r-- | cgi-bin/js/lxrng-funcs.js | 293 | ||||
-rwxr-xr-x | cgi-bin/lxr | 659 |
17 files changed, 1934 insertions, 0 deletions
diff --git a/cgi-bin/.htaccess b/cgi-bin/.htaccess new file mode 100644 index 0000000..06615a1 --- /dev/null +++ b/cgi-bin/.htaccess @@ -0,0 +1,8 @@ +Options ExecCGI +<Files lxr> +SetHandler cgi-script +</Files> + +<Files prefs> +SetHandler cgi-script +</Files> diff --git a/cgi-bin/css/lxrng.css b/cgi-bin/css/lxrng.css new file mode 100644 index 0000000..9a47d80 --- /dev/null +++ b/cgi-bin/css/lxrng.css @@ -0,0 +1,278 @@ +/* http://devnull.tagsoup.com/fixed/horizontal.html */ + +span.lxr_l { + text-transform: uppercase; + margin-left: 5px; + font-weight: normal; +} + +span.lxr_x { + text-transform: uppercase; + font-weight: normal; +} + +span.lxr_r { + text-transform: uppercase; + font-weight: normal; + padding-right: 5px; + border-right: solid; + border-width: 1px; +} + +span.lxr_title { + float: left; +} + +span.lxr_menu { +/* float: right; */ +} +div.lxr_menu { + float: right; +} + +span.lxr_search { + font-weight: normal; + margin-left: 5px; + padding-left: 5px; + margin-right: 5px; +/* border-left: solid; + border-width: 1px; */ +} +span.lxr_prefs { + font-weight: normal; + margin-left: 5px; + padding-left: 5px; + margin-right: 5px; + border-left: solid; + border-width: 1px; +} + +span.lxr_version { + font-weight: normal; + padding-left: 5px; +/* border-left: solid; + border-width: 1px; */ +} + +body.full div.search_results { + background: #F0F0F0; + z-index: 3; + position: fixed; + right: 3px; + top: 35px; + width: 35%; + height: 70%; + border: solid; + border-width: 1px; + display: none; + overflow: auto; + padding: 3px; +} + +body.popup div.search_results { + background: #F0F0F0; + border: solid; + border-width: 1px; + padding: 3px; + margin: 1px; +} + +div.query_desc { + font-weight: bold; +} + +span.close-button { + float: right; + margin-top: 3px; + margin-right: 3px; +} + +a.line:before { + content: attr(id); +} + +a.line { + position: absolute; + top: auto; + left: 0px; + width: 4.5ex; + text-align: right; + background: #e0e0e0; + + border: solid; + border-width: 1px; + border-color: #000000; + margin-left: 3px; + padding-right: 5px; +} + +body { + margin-top: 3px; + margin-left: 3px; + margin-right: 3px; + overflow: scroll; +} + +pre { + margin-left: 6ex; +} + +div.headingtop { +} + +div.headingbottom { + clear: both; +} + +div.heading { + background: #F0F0F0; + margin-right: 0px; + margin-left: 0px; + font-weight: bold; + font-size: 120%; + border: solid; + border-width: 1px; + text-align: right; +} + +div.heading img { + vertical-align: middle; +} + +div.searchbox { + background: #F0F0F0; + border: solid; + margin-top: 3px; + border-width: 1px; + margin-right: 0px; + margin-left: 0px; + width: 30ex; + float: right; +} + + +button.print { + border: 0; + background: #F0F0F0; +} + + +table.query { + width: 100%; +} + +table.params { + width: 100%; +} + +table.directory { + width: 100%; +} + +table.directory td.name { + width: 30ex; +} + +table.directory td.size { + width: 10ex; + text-align: right; + padding-right: 1ex; +} + +table.directory td.time { + width: 30ex; +} + +div.footerbox { + left: 3px; + right: 3px; + bottom: 3px; + border: solid; + border-width: 1px; + background: #F0F0F0; +} + +div.footerfill { + height: 3px; +} + +div.content { + background: white; +} + + +span.comment { + font-weight: bold; + font-style: italic; +} + +span.string { + font-style: italic; + color: red; +} + +div.find { + padding: 3px; +} + +div.find div.find_input { + width: 100%; +} + +div.find div.find_code { + width: 33%; + float: left; + text-align: left; +} + +div.find div.find_text { + width: 33%; + float: left; + text-align: center; +} + +div.find div.find_file { + width: 33%; + float: right; + text-align: right; +} + +div.vars { + clear: both; + padding: 3px; +} + +div.vars div.var_title { + clear: both; + width: 50%; + float: left; + text-align: left; +} + +div.vars div.var_select { + width: 50%; + float: right; + text-align: right; +} + +div.vars div.do_update { + clear: both; + width: 50%; + float: left; + text-align: left; +} + +div.vars div.do_hide { + width: 50%; + float: right; + text-align: right; +} + +div.progress { + font-weight: bold; + font-style: italic; +} + +form { + display: inline; +} diff --git a/cgi-bin/gfx/Makefile b/cgi-bin/gfx/Makefile new file mode 100644 index 0000000..bef9f65 --- /dev/null +++ b/cgi-bin/gfx/Makefile @@ -0,0 +1,10 @@ +SVGFILES=$(wildcard *.svg) +PNGFILES=$(subst svg,png,${SVGFILES}) + +all: ${PNGFILES} + +clean: + rm -f ${PNGFILES} + +%.png: %.svg + inkscape -e $@ -w 16 -h 16 $< diff --git a/cgi-bin/gfx/close.png b/cgi-bin/gfx/close.png Binary files differnew file mode 100644 index 0000000..cd4178f --- /dev/null +++ b/cgi-bin/gfx/close.png diff --git a/cgi-bin/gfx/close.svg b/cgi-bin/gfx/close.svg new file mode 100644 index 0000000..2207f0f --- /dev/null +++ b/cgi-bin/gfx/close.svg @@ -0,0 +1,102 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="32px" + height="32px" + id="svg2160" + sodipodi:version="0.32" + inkscape:version="0.45" + sodipodi:modified="TRUE" + inkscape:export-filename="foo" + inkscape:export-xdpi="67.5" + inkscape:export-ydpi="67.5"> + <defs + id="defs2162"> + <linearGradient + id="linearGradient3207"> + <stop + style="stop-color:#f19257;stop-opacity:0.31632653;" + offset="0" + id="stop3209" /> + <stop + style="stop-color:#e25213;stop-opacity:1;" + offset="1" + id="stop3211" /> + </linearGradient> + <linearGradient + id="linearGradient3185"> + <stop + style="stop-color:#ed2929;stop-opacity:1;" + offset="1" + id="stop3187" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3207" + id="radialGradient3217" + cx="16" + cy="16" + fx="16" + fy="16" + r="15" + gradientUnits="userSpaceOnUse" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="11.197802" + inkscape:cx="16" + inkscape:cy="16" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="822" + inkscape:window-height="596" + inkscape:window-x="427" + inkscape:window-y="289" /> + <metadata + id="metadata2165"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <rect + style="opacity:1;fill:url(#radialGradient3217);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:16.69999886;stroke-dasharray:none;stroke-opacity:1" + id="rect2168" + width="30" + height="30" + x="1" + y="1" /> + <path + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#dfdfdf;stroke-width:5;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" + d="M 27,27 L 5,5" + id="path2170" /> + <path + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#dfdfdf;stroke-width:5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 4.92738,27.193327 L 27.04318,5.1040233" + id="path3219" + sodipodi:nodetypes="cc" /> + </g> +</svg> diff --git a/cgi-bin/gfx/diff.png b/cgi-bin/gfx/diff.png Binary files differnew file mode 100644 index 0000000..73edeca --- /dev/null +++ b/cgi-bin/gfx/diff.png diff --git a/cgi-bin/gfx/diff.svg b/cgi-bin/gfx/diff.svg new file mode 100644 index 0000000..46290d3 --- /dev/null +++ b/cgi-bin/gfx/diff.svg @@ -0,0 +1,129 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="32px" + height="32px" + id="svg2160" + sodipodi:version="0.32" + inkscape:version="0.45" + inkscape:export-filename="foo" + inkscape:export-xdpi="67.5" + inkscape:export-ydpi="67.5" + sodipodi:docbase="/home/argggh/privat/tshirt-art" + sodipodi:docname="diff.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + sodipodi:modified="true"> + <defs + id="defs2162"> + <linearGradient + id="linearGradient3207"> + <stop + style="stop-color:#e8ef1f;stop-opacity:0.3137255;" + offset="0" + id="stop3209" /> + <stop + style="stop-color:#e8ef1f;stop-opacity:1;" + offset="1" + id="stop3211" /> + </linearGradient> + <linearGradient + id="linearGradient3185"> + <stop + style="stop-color:#ed2929;stop-opacity:1;" + offset="1" + id="stop3187" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3207" + id="radialGradient3217" + cx="16" + cy="16" + fx="16" + fy="16" + r="15" + gradientUnits="userSpaceOnUse" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3207" + id="radialGradient3246" + gradientUnits="userSpaceOnUse" + cx="23.32336" + cy="10.578739" + fx="23.32336" + fy="10.578739" + r="15" + gradientTransform="matrix(-0.740049,-0.6725529,0.6904064,-0.7596943,32.018907,33.65448)" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3207" + id="radialGradient3250" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.740049,-0.6725529,-0.6904064,-0.7596943,-1.8907e-2,45.65448)" + cx="23.32336" + cy="10.578739" + fx="23.32336" + fy="10.578739" + r="15" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="15.836083" + inkscape:cx="16.28893" + inkscape:cy="16.801809" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="false" + inkscape:document-units="px" + inkscape:window-width="822" + inkscape:window-height="1025" + inkscape:window-x="280" + inkscape:window-y="96" + objecttolerance="50" + guidetolerance="50" + inkscape:object-nodes="false" + inkscape:object-points="false" + inkscape:object-bbox="false" + inkscape:guide-bbox="false" + inkscape:grid-points="true" + inkscape:object-paths="false" /> + <metadata + id="metadata2165"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <path + style="fill:url(#radialGradient3246);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:16.69999886;stroke-opacity:1" + d="M 31,11 L 21,1 L 21,6 L 14,6 L 14,14 L 21,14 L 21,19 L 31,11 z " + id="rect2168" + sodipodi:nodetypes="cccccccc" /> + <path + style="fill:url(#radialGradient3250);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:16.69999886;stroke-opacity:1" + d="M 1,21 L 11,12 L 11,17 L 18,17 L 18,25 L 11,25 L 11,30 L 1,21 z " + id="path3248" + sodipodi:nodetypes="cccccccc" /> + </g> +</svg> diff --git a/cgi-bin/gfx/left.png b/cgi-bin/gfx/left.png Binary files differnew file mode 100644 index 0000000..b01b78c --- /dev/null +++ b/cgi-bin/gfx/left.png diff --git a/cgi-bin/gfx/left.svg b/cgi-bin/gfx/left.svg new file mode 100644 index 0000000..4a3b1df --- /dev/null +++ b/cgi-bin/gfx/left.svg @@ -0,0 +1,102 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="32px" + height="32px" + id="svg2160" + sodipodi:version="0.32" + inkscape:version="0.45" + inkscape:export-filename="foo" + inkscape:export-xdpi="67.5" + inkscape:export-ydpi="67.5" + sodipodi:docbase="/home/argggh/privat/tshirt-art" + sodipodi:docname="left.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + sodipodi:modified="true"> + <defs + id="defs2162"> + <linearGradient + id="linearGradient3207"> + <stop + style="stop-color:#288b0a;stop-opacity:0.3137255;" + offset="0" + id="stop3209" /> + <stop + style="stop-color:#298b0a;stop-opacity:1;" + offset="1" + id="stop3211" /> + </linearGradient> + <linearGradient + id="linearGradient3185"> + <stop + style="stop-color:#ed2929;stop-opacity:1;" + offset="1" + id="stop3187" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3207" + id="radialGradient3217" + cx="16" + cy="16" + fx="16" + fy="16" + r="15" + gradientUnits="userSpaceOnUse" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="15.836083" + inkscape:cx="16" + inkscape:cy="16.801809" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="false" + inkscape:document-units="px" + inkscape:window-width="822" + inkscape:window-height="1025" + inkscape:window-x="280" + inkscape:window-y="96" + objecttolerance="50" + guidetolerance="50" + inkscape:object-nodes="false" + inkscape:object-points="false" + inkscape:object-bbox="false" + inkscape:guide-bbox="false" + inkscape:grid-points="true" + inkscape:object-paths="false" /> + <metadata + id="metadata2165"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <path + style="fill:url(#radialGradient3217);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:16.69999886;stroke-opacity:1" + d="M 1,16 L 20,1 L 20,9 L 31,9 L 31,23 L 20,23 L 20,31 L 1,16 z " + id="rect2168" + sodipodi:nodetypes="cccccccc" /> + </g> +</svg> diff --git a/cgi-bin/gfx/print.png b/cgi-bin/gfx/print.png Binary files differnew file mode 100644 index 0000000..4e56c0e --- /dev/null +++ b/cgi-bin/gfx/print.png diff --git a/cgi-bin/gfx/print.svg b/cgi-bin/gfx/print.svg new file mode 100644 index 0000000..b981609 --- /dev/null +++ b/cgi-bin/gfx/print.svg @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="32px" + height="32px" + id="svg2160" + sodipodi:version="0.32" + inkscape:version="0.45" + inkscape:export-filename="foo" + inkscape:export-xdpi="67.5" + inkscape:export-ydpi="67.5" + sodipodi:docbase="/home/argggh/projects/lxrng/cgi-bin/gfx" + sodipodi:docname="print.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + sodipodi:modified="true"> + <defs + id="defs2162"> + <linearGradient + id="linearGradient3207"> + <stop + style="stop-color:#288b0a;stop-opacity:0.3137255;" + offset="0" + id="stop3209" /> + <stop + style="stop-color:#298b0a;stop-opacity:1;" + offset="1" + id="stop3211" /> + </linearGradient> + <linearGradient + id="linearGradient3185"> + <stop + style="stop-color:#ed2929;stop-opacity:1;" + offset="1" + id="stop3187" /> + </linearGradient> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="15.836083" + inkscape:cx="16" + inkscape:cy="16.801809" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="false" + inkscape:document-units="px" + inkscape:window-width="822" + inkscape:window-height="1025" + inkscape:window-x="605" + inkscape:window-y="34" + objecttolerance="50" + guidetolerance="50" + inkscape:object-nodes="false" + inkscape:object-points="false" + inkscape:object-bbox="false" + inkscape:guide-bbox="false" + inkscape:grid-points="true" + inkscape:object-paths="false" /> + <metadata + id="metadata2165"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer" + style="display:inline"> + <path + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:16.69999886;stroke-opacity:1" + d="M 7,2 L 31,2 L 31,30 L 7,30 L 7,2 z " + id="rect2168" + sodipodi:nodetypes="ccccc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#979797;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 10,6 L 25,6" + id="path3134" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#979797;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 10,10 L 18,10" + id="path3136" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#979797;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 10,14 L 23,14" + id="path3138" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#979797;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 10,18 L 15,18" + id="path3140" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#979797;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 10,24 L 25,24" + id="path3142" /> + </g> + <g + inkscape:groupmode="layer" + id="layer2" + inkscape:label="PDF" + style="display:inline"> + <rect + style="fill:#ff0901;fill-opacity:1;stroke:#ff0901;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect3145" + width="24" + height="10" + x="3" + y="7" + ry="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 5,15 L 5,9 L 9,9 L 9,13 L 5,13" + id="path3147" + sodipodi:nodetypes="ccccc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#fefefe;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 13,9 L 13,15 L 16,15 L 17,14 L 17,10 L 16,9 L 13,9 z " + id="path3149" + sodipodi:nodetypes="ccccccc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 21,15 L 21,9 L 25,9" + id="path3151" + sodipodi:nodetypes="ccc" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:2;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 21,13 L 23,13" + id="path3153" + sodipodi:nodetypes="cc" /> + </g> +</svg> diff --git a/cgi-bin/gfx/right.png b/cgi-bin/gfx/right.png Binary files differnew file mode 100644 index 0000000..439fe13 --- /dev/null +++ b/cgi-bin/gfx/right.png diff --git a/cgi-bin/gfx/right.svg b/cgi-bin/gfx/right.svg new file mode 100644 index 0000000..07e8941 --- /dev/null +++ b/cgi-bin/gfx/right.svg @@ -0,0 +1,102 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="32px" + height="32px" + id="svg2160" + sodipodi:version="0.32" + inkscape:version="0.45" + inkscape:export-filename="foo" + inkscape:export-xdpi="67.5" + inkscape:export-ydpi="67.5" + sodipodi:docbase="/home/argggh/privat/tshirt-art" + sodipodi:docname="right.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + sodipodi:modified="true"> + <defs + id="defs2162"> + <linearGradient + id="linearGradient3207"> + <stop + style="stop-color:#288b0a;stop-opacity:0.3137255;" + offset="0" + id="stop3209" /> + <stop + style="stop-color:#298b0a;stop-opacity:1;" + offset="1" + id="stop3211" /> + </linearGradient> + <linearGradient + id="linearGradient3185"> + <stop + style="stop-color:#ed2929;stop-opacity:1;" + offset="1" + id="stop3187" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3207" + id="radialGradient3217" + cx="16" + cy="16" + fx="16" + fy="16" + r="15" + gradientUnits="userSpaceOnUse" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="15.836083" + inkscape:cx="16.28893" + inkscape:cy="16.801809" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="false" + inkscape:document-units="px" + inkscape:window-width="822" + inkscape:window-height="1025" + inkscape:window-x="280" + inkscape:window-y="96" + objecttolerance="50" + guidetolerance="50" + inkscape:object-nodes="false" + inkscape:object-points="false" + inkscape:object-bbox="false" + inkscape:guide-bbox="false" + inkscape:grid-points="true" + inkscape:object-paths="false" /> + <metadata + id="metadata2165"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <path + style="fill:url(#radialGradient3217);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:16.69999886;stroke-opacity:1" + d="M 31,16 L 12,1 L 12,9 L 1,9 L 1,23 L 12,23 L 12,31 L 31,16 z " + id="rect2168" + sodipodi:nodetypes="cccccccc" /> + </g> +</svg> diff --git a/cgi-bin/gfx/rolldown.png b/cgi-bin/gfx/rolldown.png Binary files differnew file mode 100644 index 0000000..a2a15ca --- /dev/null +++ b/cgi-bin/gfx/rolldown.png diff --git a/cgi-bin/gfx/rolldown.svg b/cgi-bin/gfx/rolldown.svg new file mode 100644 index 0000000..85697fb --- /dev/null +++ b/cgi-bin/gfx/rolldown.svg @@ -0,0 +1,102 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="32px" + height="32px" + id="svg2160" + sodipodi:version="0.32" + inkscape:version="0.45" + inkscape:export-filename="foo" + inkscape:export-xdpi="67.5" + inkscape:export-ydpi="67.5" + sodipodi:docbase="/home/argggh/privat/tshirt-art" + sodipodi:docname="rolldown.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + sodipodi:modified="true"> + <defs + id="defs2162"> + <linearGradient + id="linearGradient3207"> + <stop + style="stop-color:#0b718b;stop-opacity:0.3137255;" + offset="0" + id="stop3209" /> + <stop + style="stop-color:#0b718b;stop-opacity:1;" + offset="1" + id="stop3211" /> + </linearGradient> + <linearGradient + id="linearGradient3185"> + <stop + style="stop-color:#ed2929;stop-opacity:1;" + offset="1" + id="stop3187" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3207" + id="radialGradient3217" + cx="16" + cy="16" + fx="16" + fy="16" + r="15" + gradientUnits="userSpaceOnUse" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="15.836083" + inkscape:cx="16" + inkscape:cy="16.801809" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="false" + inkscape:document-units="px" + inkscape:window-width="822" + inkscape:window-height="1025" + inkscape:window-x="280" + inkscape:window-y="96" + objecttolerance="50" + guidetolerance="50" + inkscape:object-nodes="false" + inkscape:object-points="false" + inkscape:object-bbox="false" + inkscape:guide-bbox="false" + inkscape:grid-points="true" + inkscape:object-paths="false" /> + <metadata + id="metadata2165"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <path + style="fill:url(#radialGradient3217);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:16.69999886;stroke-opacity:1" + d="M 1,7 L 31,7 L 16.444972,27 L 1,7 z " + id="rect2168" + sodipodi:nodetypes="cccc" /> + </g> +</svg> diff --git a/cgi-bin/js/lxrng-funcs.js b/cgi-bin/js/lxrng-funcs.js new file mode 100644 index 0000000..d7c9be8 --- /dev/null +++ b/cgi-bin/js/lxrng-funcs.js @@ -0,0 +1,293 @@ +function popup_search(searchform) { + searchform = document.getElementById(searchform); + searchform.target = window.name + '-popup'; + searchform.navtarget.value = window.name; + window.open('', window.name + '-popup', + 'width=400,height=600,menubar=yes,status=yes,scrollbars=yes'); + return true; +} + +function popup_anchor() { + var anchor = this; + window.open('', window.name + '-popup', + 'width=400,height=600,menubar=yes,status=yes,scrollbars=yes'); + anchor.target = window.name + '-popup'; + + if (anchor.href.indexOf("navtarget=") >= 0) + return true; + + if (anchor.href.indexOf("?") >= 0) { + anchor.href = anchor.href + ';navtarget=' + window.name; + } + else { + anchor.href = anchor.href + '?navtarget=' + window.name; + } + return true; +} + +function navigate_here(searchform) { + searchform = document.getElementById(searchform); + searchform.target = window.name; + return true; +} + +function window_unique(serial) { + if (!window.name) + window.name = 'lxr-source-' + serial; +} + +function do_search(form) { + if (use_ajax_navigation) { + var res = document.getElementById('search_results'); + res.style.display = 'block'; + res.innerHTML = '<div class="progress">Searching...</div>'; + + pjx_search(['type__search', + 'search', 'v', 'tree__' + loaded_tree], + ['search_results']); + return false; + } + else if (use_popup_navigation) { + form.target = window.name + '-popup'; + form.navtarget.value = window.name; + reswin = window.open('', window.name + '-popup', + 'width=400,height=600,menubar=yes,status=yes,scrollbars=yes'); + } + return true; +} + +function hide_search() { + var res = document.getElementById('search_results'); + res.style.display = 'none'; + return false; +} + +var loaded_hash; +var loaded_tree; +var loaded_file; +var loaded_ver; +var loaded_line; + +var pending_tree; +var pending_file; +var pending_ver; +var pending_line; + +function ajax_nav() { + var file = this.href.replace(/^(http:.*?lxr\/[+]ajax\/|)/, ''); + // alert(loaded_file + ' - ' + file); + load_file(loaded_tree, file, loaded_ver, ''); + return false; +} + +function ajax_prefs() { + if (use_ajax_navigation) { + var full_path = location.href.split(/#/)[0]; + full_path = full_path + '/' + loaded_tree; + if (loaded_ver) { + full_path = full_path + '+' + loaded_ver; + } + full_path = full_path + '/+prefs?return=' + loaded_file.replace(/^\/?$/, '.'); + location = full_path; + return false; + } + else { + return true; + } +} + +var hash_check; +function check_hash_navigation() { + if (location.hash != loaded_hash) { + if (location.hash.replace(/\#L\d+$/, '') == + loaded_hash.replace(/\#L\d+$/, '')) + { + var l = location.hash.replace(/.*(\#L\d+)$/, '$1'); + var a = document.getElementById(l); + if (l && a) { + a.name = location.hash; + location.hash = a.name; + } + } + else { + // alert(location.hash + ' / ' + loaded_hash); + load_content(); + } + } + else { + hash_check = setTimeout('check_hash_navigation()', 50); + } +} + +function load_file(tree, file, ver, line) { + if (!use_ajax_navigation) { + return true; + } + + if (hash_check) { + clearTimeout(hash_check); + } + + var res = document.getElementById('content'); + + // TODO: check if file already loaded and perform only line + // location update. + res.innerHTML = '<div class="progress">Loading...</div>'; + pending_line = line; + pending_tree = tree; + pending_file = file; + if (ver) { + pending_ver = ver; + } + else { + pending_ver = ''; + } + + pjx_load_file(['tree__' + tree, 'file__' + file, 'v__' + ver, 'line__' + line], + [load_file_finalize]); + return false; +} + +function load_file_finalize(content) { + var res = document.getElementById('content'); + res.innerHTML = content; + var head = document.getElementById('current_path'); + head.innerHTML = '<a class=\"fref\" href=\".\">' + pending_tree + '</a>'; + var path_walked = ''; + var elems = pending_file.split(/\//); + for (var i=0; i<elems.length; i++) { + if (elems[i] != '') { + head.innerHTML = head.innerHTML + '/' + + '<a class=\"fref\" href=\"' + path_walked + elems[i] + + '\">' + elems[i] + '</a>'; + path_walked = path_walked + elems[i] + '/'; + } + } + document.title = 'LXR ' + pending_tree + '/' + pending_file; + + var full_path = pending_tree; + if (pending_ver) { + full_path = full_path + '+' + pending_ver; + } + full_path = full_path + '/' + pending_file.replace(/^\/?/, ''); + + var pre = document.getElementById('file_contents'); + if (pre && pre.className == 'partial') { + pjx_load_file(['tree__' + pending_tree, 'file__' + pending_file, + 'v__' + pending_ver, 'full__1'], + [load_file_finalize]); + } + + if (pending_line) { + var anchor = document.getElementById('L' + pending_line); + if (anchor) { + anchor.name = full_path + '#L' + pending_line; + location.hash = full_path + '#L' + pending_line; + } + else { + location.hash = full_path; + } + loaded_line = pending_line; + } + else { + location.hash = full_path; + loaded_line = 0; + } + loaded_hash = location.hash; + loaded_tree = pending_tree; + loaded_file = pending_file; + loaded_ver = pending_ver; + if (hash_check) { + clearTimeout(hash_check); + } + hash_check = setTimeout('check_hash_navigation()', 50); + + var i; + for (i = 0; i < document.links.length; i++) { + if (document.links[i].className == 'fref' || + document.links[i].className == 'line') + { + document.links[i].onclick = ajax_nav; + } + else if (document.links[i].className == 'sref' || + document.links[i].className == 'falt') + { + document.links[i].onclick = ajax_lookup_anchor; + } + + } +} + +function load_content() { + var tree = location.hash.split('/', 1); + tree = tree[0].split(/[+]/); + var ver = tree[1] || ''; + tree = tree[0].replace(/^#/, ''); + var file = location.hash.replace(/^[^\/]*\/?/, ''); + var line = file.replace(/.*\#L(\d+)/, '$1'); + file = file.replace(/\#L\d+$/, ''); + + load_file(tree, file, ver, line); + + pjx_releases(['tree__' + tree], + [load_content_finalize]); +} + +function load_content_finalize(content) { + var res = document.getElementById('ver_select'); + res.innerHTML = content; + var verlist = document.getElementById('ver_list'); + verlist.value = pending_ver; +} + +function update_version(verlist, base_url, tree, defversion, path) { + if (use_ajax_navigation) { + var file = location.hash.replace(/^[^\/]*\//, ''); + + load_file(loaded_tree, file, verlist.value, ''); + return false; + } + else { + var newurl = base_url.replace(/[^\/]*\/?$/, ''); + if (verlist.value == defversion) { + newurl = newurl + tree; + } + else { + newurl = newurl + tree + '+' + verlist.value; + } + newurl = newurl + '/' + path.replace(/^\//, ''); + document.location = newurl; + } +} + +function popup_prepare(serial) { + window_unique(serial); + var i; + for (i = 0; i < document.links.length; i++) { + if (document.links[i].className == 'sref' || + document.links[i].className == 'falt') + { + document.links[i].onclick = popup_anchor; + } + } +} + +function ajax_lookup_anchor(event, anchor) { + if (!use_ajax_navigation) + return true; + + if (!anchor) + anchor = this; + + lookup = anchor.href.replace(/^(http:.*?lxr\/[+]ajax\/|)/, ''); + var lvar = document.getElementById('ajax_lookup'); + lvar.value = lookup; + + var res = document.getElementById('search_results'); + res.style.display = 'block'; + res.innerHTML = '<div class="progress">Searching...</div>'; + + pjx_search(['ajax_lookup', 'v', 'tree__' + loaded_tree], + ['search_results']); + return false; +} diff --git a/cgi-bin/lxr b/cgi-bin/lxr new file mode 100755 index 0000000..cda9179 --- /dev/null +++ b/cgi-bin/lxr @@ -0,0 +1,659 @@ +#!/usr/bin/perl + +use strict; + +use FindBin; +use lib "$FindBin::Bin/../lib"; +use lib '/home/argggh/www/lxrng/_deps/share/perl/5.8.4'; + +use CGI::Carp qw(fatalsToBrowser); +use IO::Handle; + +use LXRng ROOT => "$FindBin::Bin/.."; +use LXRng::Context; +use LXRng::Lang qw(C); +use LXRng::Parse::Simple; +use LXRng::Markup::File; +use LXRng::Markup::Dir; +use Subst::Complex; + +use Template; +use Digest::SHA1 qw(sha1_hex); +use CGI::Ajax; +use CGI::Simple qw(-newstyle_urls); +use File::Temp qw(tempdir tempfile); +use POSIX qw(waitpid); + +use constant PDF_LINELEN => 95; +use constant PDF_CHARPTS => 6.6; + +use vars qw($has_gzip_io); +eval { require PerlIO::gzip; $has_gzip_io = 1; }; + + +# Return 1 if gzip compression of html is desired. + +sub do_compress_response { + my ($query) = @_; + + my @enc = split(",", $query->http('Accept-Encoding')); + return $has_gzip_io && grep { $_ eq 'gzip' } @enc; +} + + +# Progressive output of marked-up file. If the file in question +# exists in cache, and this is the initial load of an ajax-requested +# file, return only the lines the user wants to see (with a minimum of +# context) as a first approximation. + +sub print_markedup_file { + my ($context, $template, $node) = @_; + + autoflush STDOUT 1; + + if ($node->isa('LXRng::Repo::Directory')) { + my $markup = LXRng::Markup::Dir->new('context' => $context, + 'node' => $node); + $template->process('content_dir.tt2', + {'context' => $context, + 'dir_listing' => $markup->listing}) + or die $template->error(); + } + else { + # Grmble. We assume the identifiers to markup are identical + # from one version to another, but if the same revision of a + # file exists both in an indexed and un-indexed release, one + # of them will have its identifiers highlighted and the other + # not. So we can't share a cache slot across releases without + # adding some extra logic here. Bummer. + # TODO: Resolve by caching only accesses to releases that are + # is_indexed. + my $shaid = sha1_hex(join("\0", $node->name, $node->revision, + $context->release)); + my $cfile; + $cfile = $context->config->{'cache'}.'/'.$shaid + if exists $context->config->{'cache'}; + + if ($cfile and -e $cfile) { + open(my $cache, '<', $cfile); + + my $focus = $context->param('line') || 0; + $focus = 0 if $context->param('full'); + my $class = $focus ? 'partial' : 'full'; + print("<pre id=\"file_contents\" class=\"$class\">"); + while (<$cache>) { + next if $focus and $. < $focus - 5; + print($_); + last if $focus and $. > $focus + 70; + } + print("</pre>"); + close($cache); + } + else { + my $cache; + open($cache, '>', $cfile) if $cfile; + my $handle = $node->handle(); + my $lang = LXRng::Lang->new($node); + my $parse = LXRng::Parse::Simple->new($handle, 8, + @{$lang->parsespec}); + my $markup = LXRng::Markup::File->new('context' => $context); + my $subst = $lang->markuphandlers($context, $node, $markup); + + # Possible optimization: store cached file also as .gz, + # and pass that on if the client accepts gzip-encoded + # data. Saves us from compressing the cached file each + # time it's needed, but requires a bit of fiddling with + # perlio and the streams to get right. Also messes up + # partial transfers. + print("<pre id=\"file_contents\" class=\"full\">"); + while (1) { + my @frags = $markup->markupfile($subst, $parse); + last unless @frags; + print(@frags); + print($cache @frags) if $cache; + } + print("</pre>\n"); + } + } +} + +sub print_release_list { + my ($context, $template) = @_; + + $template->process('release_select.tt2', + {'context' => $context}) + or die $template->error(); +} + +sub source { + my ($context, $template, $query) = @_; + + my $pjx = CGI::Ajax->new('pjx_search' => 'lxr', + 'pjx_load_file' => 'lxr', + 'pjx_releases' => 'lxr'); + $pjx->js_encode_function('escape'); + + if ($context->prefs and $context->prefs->{'navmethod'} eq 'ajax') { + my $path = $query->path_info; + $path =~ s,^/[+ ],,; + if ($path ne '') { + $path =~ s,^/+,,; + print($query->redirect($query->url(-full => 1). + '#'.$path)); + } + else { + print($query->header(-type => 'text/html', + -charset => 'utf-8')); + + my $base = $query->url(-full => 1); + $template->process('main.tt2', + {'context' => $context, + 'base_url' => $base.'/+ajax/', + 'javascript' => $pjx->show_javascript(), + 'is_ajax' => 1}) + or die $template->error(); + } + return; + } + + my $gzip = do_compress_response($query); + + # history cookie + + print($query->header(-type => 'text/html', + -charset => 'utf-8', + $gzip ? (-content_encoding => 'gzip') : ())); + + binmode(\*STDOUT, ":gzip") if $gzip; + + my $ver = $context->release; + my $rep = $context->config->{'repository'}; + my $node = $rep->node($context->path, $ver); + + die "Node not found: ".$context->path." ($ver)" unless $node; + + my %template_args = ('context' => $context, + 'tree' => $context->tree, + 'node' => $node, + 'base_url' => $context->base_url, + 'javascript' => $pjx->show_javascript()); + + + if ($context->prefs and $context->prefs->{'navmethod'} eq 'popup') { + $template_args{'is_popup'} = 1; + $template_args{'popup_serial'} = int(rand(1000000)); + } + + if ($node->isa('LXRng::Repo::Directory')) { + my $markup = LXRng::Markup::Dir->new('context' => $context, + 'node' => $node); + $template->process('main.tt2', + {%template_args, + 'dir_listing' => $markup->listing, + 'is_dir' => 1}) + or die $template->error(); + } + else { + my $html = ''; + $template->process('main.tt2', + {%template_args, + 'file_content' => '<!--FILE_CONTENT-->', + 'is_dir' => 0}, + \$html) + or die $template->error(); + + # Template directives in processed template. Sigh. TT2 sadly + # can't do progressive rendering of its templates, so we cheat... + my ($pre, $post) = split('<!--FILE_CONTENT-->', $html); + print($pre); + print_markedup_file($context, $template, $node); + print($post); + } + + # TODO: This is potentially useful, in that it resets the stream + # to uncompressed mode. However, under Perl 5.8.8+PerlIO::gzip + # 0.18, this seems to truncate the stream. Not strictly needed + # for CGI, reexamine when adapting to mod_perl. + ## binmode(\*STDOUT, ":pop") if $gzip; +} + +#sub ident { +# my ($self) = @_; + +# my $index = $self->context->config->{'index'}; +# my $view = LXRng::View->new('context' => $self->context);; + +# my $ident = $self->context->value('ident'); +# my $target = $self->context->value('navtarget'); +# $target ||= 'source'; + +# my $rel_id = $index->release_id($self->tree, $self->context->value('v')); +# my ($symname, $symid, $ident, $refs) = +# $index->get_identifier_info($ident, $rel_id); + +# $$ident[1] = $LXRng::Lang::deftypes{$$ident[1]}; +# $$ident[5] &&= $LXRng::Lang::deftypes{$$ident[5]}; + +# return $view->identifier_info($symname, $symid, $ident, $refs, $target); +#} + + +# Perform various search operations. Return results as html suitable +# both as a response to an ajax request and inclusion in a more +# general html document. + +sub search { + my ($context, $template, $type, $find) = @_; + + my $ver = $context->release; + $find ||= $context->param('search'); + + my $index = $context->config->{'index'}; + my $rel_id = $index->release_id($context->tree, $ver); + my %template_args = ('context' => $context); + + $template_args{'navtarget'} = 'target='.$context->param('navtarget') + if $context->param('navtarget'); + + + if ($find =~ /\S/) { + if ($type eq 'file' or $type eq 'search') { + # $template_args{'file_res'} = {'query' => $find, + # 'files' => \@args,} + } + if ($type eq 'text' or $type eq 'search') { + my $hash = $context->config->{'search'}; + my ($total, $res) = $hash->search($rel_id, $find); + + $template_args{'text_res'} = {'query' => $find, + 'total' => $total, + 'files' => $res}; + } + if ($type eq 'code' or $type eq 'search') { + my $result = $index->symbols_by_name($context->tree, $ver, $find); + my @cooked = (map { $$_[1] = $LXRng::Lang::deftypes{$$_[1]}; + $$_[5] &&= $LXRng::Lang::deftypes{$$_[5]}; + $_ } + sort { $LXRng::Lang::defweight{$$a[1]} cmp + $LXRng::Lang::defweight{$$b[1]} } + @$result); + $template_args{'code_res'} = {'query' => $find, + 'idents' => \@cooked}; + } + if ($type eq 'ident') { + my ($symname, $symid, $ident, $refs) = + $index->get_identifier_info($find, $rel_id); + + $$ident[1] = $LXRng::Lang::deftypes{$$ident[1]}; + $$ident[5] &&= $LXRng::Lang::deftypes{$$ident[5]}; + + use Data::Dumper; + warn Dumper($symname, $symid, $ident, $refs); + $template_args{'ident_res'} = {'query' => $symname, + 'ident' => $ident, + 'refs' => $refs}; + } + if ($type eq 'ambig') { + my $rep = $context->config->{'repository'}; + my @args = grep { + $rep->node($_, $context->release) + } split(/\|/, $find); + $template_args{'ambig_res'} = {'query' => $find, + 'files' => \@args,} + } + } + else { + die "No query string given"; + } + my $html = ''; + $template_args{'tree'} = $context->tree; + $template->process('search_result.tt2', + \%template_args, + \$html) + or die $template->error(); + return $html; +} + + +# Display search results for plain and popup navigation methods. +# (Ajax methods call "search" directly.) + +sub search_result { + my ($context, $template, $query, $result) = @_; + + my %template_args = ('context' => $context, + 'tree' => $context->tree, + 'search_res' => $result, + 'base_url' => $context->base_url); + + my $gzip = do_compress_response($query); + + print($query->header(-type => 'text/html', + -charset => 'utf-8', + $gzip ? (-content_encoding => 'gzip') : ())); + + binmode(\*STDOUT, ":gzip") if $gzip; + + if ($context->prefs and $context->prefs->{'navmethod'} eq 'popup') { + $template->process('popup_main.tt2', + {%template_args, + 'is_popup' => 1}) + or die $template->error(); + } + else { + $template->process('main.tt2', + {%template_args, + 'file_content' => '', + 'is_dir' => 0}) + or die $template->error(); + } +} + + +# Callback to perform the ajax-available functions. + +sub handle_ajax_request { + my ($query, $context, $template) = @_; + my $gzip = do_compress_response($query); + + print($query->header(-type => 'text/html', + -charset => 'utf-8', + $gzip ? (-content_encoding => 'gzip') : ())); + + binmode(\*STDOUT, ":gzip") if $gzip; + + if ($context->param('fname') eq 'pjx_load_file') { + my $rep = $context->config->{'repository'}; + my $node = $rep->node($context->param('file'), $context->release); + print_markedup_file($context, $template, $node); + + } + elsif ($context->param('fname') eq 'pjx_search') { + if ($context->param('ajax_lookup') =~ + /^[+ ](code|ident|file|text|ambig)=(.*)/) + { + print(search($context, $template, $1, $2)); + } + else { + print(search($context, $template, 'search', + $context->param('search'))); + } + } + elsif ($context->param('fname') eq 'pjx_releases') { + print_release_list($context, $template); + } + + # binmode(\*STDOUT, ":pop") if $gzip; +} + + +# Stuff user preferences in cookie. + +sub handle_preferences { + my ($query, $context, $template) = @_; + + if ($context->param('resultloc')) { + my @prefs; + if ($context->param('resultloc') =~ /^(replace|popup|ajax)$/) { + push(@prefs, 'navmethod='.$1); + } + my $lxr_prefs = $query->cookie(-name => 'lxr_prefs', + -values => \@prefs, + -expires => '+1y'); + print($query->header(-type => 'text/html', + -charset => 'utf-8', + -cookie => $lxr_prefs)); + + my %template_args; + if (defined($context->param('return')) and $context->config) { + $template_args{'return'} = + $context->base_url.$query->param('return'); + } + else { + my $url = $query->url(-full => 1, -path => 1); + $url =~ s,/[+ ]prefs\b.*,/,; + $template_args{'return'} = $url; + } + + $template->process('prefs_set.tt2', + \%template_args) + or die $template->error(); + } + else { + print($query->header(-type => 'text/html', + -charset => 'utf-8')); + + $template->process('prefs.tt2', + {'return' => $query->param('return')}) + or die $template->error(); + } +} + + +# Generate pdf listing of given file. Much if the following lifted +# from the script "texify". Proof of concept, code quality could be +# better. + +sub generate_pdf { + my ($query, $context, $template, $path) = @_; + + my $tempdir = tempdir(CLEANUP => 1); + + my %tspecials = ( + '$' => '\$', '*' => "\$\\ast\$", + '&' => '\&', '%' => '\%', + '#' => '\#', '_' => '\_', + '^' => '\^{}', '{' => '\{', + '}' => '\}', '|' => "\$|\$", + '[' => '{[}', ']' => '{]}', + "'" => "{'}", "\"" => "\\string\"", + '~' => '\~{}', '<' => "\$<\$", + '>' => "\$>\$", "\\" => "\$\\backslash\$", + '-' => '\dash{}', + "\242" => '?', "\244" => '?', + "\245" => '?', "\246" => '?', + "\252" => "\$\252\$", "\254" => "\$\254\$", + "\255" => "\\dash{}", "\260" => "\$\260\$", + "\261" => "\$\261\$", "\262" => "\$\262\$", + "\263" => "\$\263\$", "\265" => "\$\265\$", + "\271" => "\$\271\$", "\272" => "\$\272\$", + "\327" => "\$\327\$", "\367" => "\$\367\$"); + + my $tspecials = join('', map { quotemeta($_) } keys(%tspecials)); + + my $ver = $context->release; + my $rep = $context->config->{'repository'}; + my $node = $rep->node($path, $ver); + + die "No such file" unless $node; + + my $handle = $node->handle(); + my $lang = LXRng::Lang->new($node); + my $parse = LXRng::Parse::Simple->new($handle, 8, + @{$lang->parsespec}); + my $res = $lang->reserved(); + my $resre; + if (%$res) { + $resre = '(?:(?<=[\s\W])|^)('. + join('|', map { my $c = $_; $c =~ s/\#/\\\#/g; quotemeta($c) } + sort { length($b) <=> length($a) } + keys %$res).')(?=$|[\s\W])'; + } + + my @lines; + my $row = 1; + my $col = 0; + my $line = '\\lxrln{1}'; + + while (1) { + my ($btype, $frag) = $parse->nextfrag; + + last unless defined $frag; + + $btype ||= 'code'; + my @parts = split(/(\n)/, $frag); + + while (@parts) { + my $part = shift(@parts); + my $align = 0; + my $cont = 0; + + if ($part eq "\n") { + push(@lines, $line); + + $col = 0; + $row++; + if ($row % 5 == 0) { + $line = "\\lxrln{$row}"; + } + else { + $line = ''; + } + next; + } + + if ($part =~ /^(.*? +)(.*)/) { + unshift(@parts, $2); + $part = $1; + $align = 1; + } + + $col += length($part); + + if ($col > PDF_LINELEN) { + unshift(@parts, + substr($part, PDF_LINELEN - $col, length($part), '')); + if ($part =~ s/([^\s_,\(\)\{\}\/\=\-\+\*\<\>\[\]\.]+)$//) { + if (length($1) < 20) { + unshift(@parts, $1); + } + else { + $part .= $1; + } + } + $align = 0; + $cont = 1; + } + + $part =~ s/([$tspecials])/$tspecials{$1}/ge; + + if ($btype eq 'code') { + $part =~ s/$resre/\\textbf{$1}/g if $resre; + } + elsif ($btype eq 'include') { + $part =~ s/$resre/\\textbf{$1}/ if $resre; + } + elsif ($btype eq 'comment') { + $part = '\textit{'.$part.'}'; + } + elsif ($btype eq 'string') { + $part = '\texttt{'.$part.'}'; + } + + # Common fixed-width "ascii-art" characters. + $part =~ s/(\$\\ast\$|=)/'\\makebox['.PDF_CHARPTS."pt][c]{$1}"/ge; + $line .= $part; + if ($align) { + $line = '\\makebox['.int($col * PDF_CHARPTS). + 'pt][l]{'.$line.'}'; + } + if ($cont) { + push(@lines, "$line\\raisebox{-2pt}{\\ArrowBoldRightStrobe}"); + $line = '\\raisebox{-2pt}{\\ArrowBoldDownRight} '; + $col = 3; + } + } + } + + if ($line ne '') { + push(@lines, $line); + } + else { + $row--; + } + + if (@lines and $row % 5 != 0) { + $lines[$#lines] =~ s/^/\\lxrln{$row}/; + } + + my $pathdesc = $context->tree."/$path ($ver)"; + $pathdesc =~ s/([$tspecials])/$tspecials{$1}/ge; + + my ($texh, $texname) = tempfile(DIR => $tempdir, SUFFIX => '.tex'); + + $template->process('print_pdf.tt2', + {'pathdesc' => $pathdesc, + 'lines' => \@lines}, + $texh) + or die $template->error(); + my $pid = fork(); + die $! unless defined($pid); + if ($pid == 0) { + close(STDOUT); + open(STDOUT, "> $texname.output"); + close(STDERR); + open(STDERR, ">&STDOUT"); + chdir($tempdir); + exec("pdflatex", "$texname"); + kill(9, $$); + } + waitpid($pid, 0); + my $pdfname = $texname; + $pdfname =~ s/[.]tex$/.pdf/; + if (-e $pdfname) { + open(my $pdfh, "< $pdfname") or die $!; + + print($query->header(-type => 'application/pdf', + -content_disposition => + "inline; filename=$path.pdf")); + my $buf = ''; + while (sysread($pdfh, $buf, 65536) > 0) { + print($buf); + } + close($pdfh); + } + elsif (-e "$texname.output") { + open(my $errh, "< $texname.output") or die $!; + my @err = <$errh>; + close($errh); + @err = splice(@err, -15) if @err > 15; + die "PDF generation failed: ".join("\n", @err); + } + else { + die "PDF generation failed"; + } +} + + +# Initial request dispatch. + +my $query = CGI::Simple->new(); +my $context = LXRng::Context->new('query' => $query); +my $template = Template->new({'INCLUDE_PATH' => $LXRng::ROOT.'/tmpl/'}); + + +if ($context->param('fname')) { + handle_ajax_request($query, $context, $template); +} +else { + if ($context->path =~ /^[+ ]prefs$/) { + handle_preferences($query, $context, $template); + } + elsif ($context->path =~ /^[+ ]print=(.*)/) { + generate_pdf($query, $context, $template, $1); + } + else { + if ($context->path =~ + /^[+ ](search|code|ident|file|text|ambig)(?:=(.*)|)/) + { + search_result($context, $template, $query, + search($context, $template, $1, $2)); + $context->path(''); + } + else { + source($context, $template, $query); + } + } +} + +1; |