aboutsummaryrefslogtreecommitdiffstats
path: root/cgi-bin
diff options
context:
space:
mode:
authorArne Georg Gleditsch <argggh@lxr.linpro.no>2007-07-05 00:51:08 +0200
committerArne Georg Gleditsch <argggh@lxr.linpro.no>2007-07-05 00:51:08 +0200
commite9fa4c98bb5f084739d3418ade3f0c51e34a0aa1 (patch)
treefec1d635625e031cde7cba1b0a1d95ee92ac760b /cgi-bin
Rebase tree.
Diffstat (limited to 'cgi-bin')
-rw-r--r--cgi-bin/.htaccess8
-rw-r--r--cgi-bin/css/lxrng.css278
-rw-r--r--cgi-bin/gfx/Makefile10
-rw-r--r--cgi-bin/gfx/close.pngbin0 -> 802 bytes
-rw-r--r--cgi-bin/gfx/close.svg102
-rw-r--r--cgi-bin/gfx/diff.pngbin0 -> 605 bytes
-rw-r--r--cgi-bin/gfx/diff.svg129
-rw-r--r--cgi-bin/gfx/left.pngbin0 -> 585 bytes
-rw-r--r--cgi-bin/gfx/left.svg102
-rw-r--r--cgi-bin/gfx/print.pngbin0 -> 355 bytes
-rw-r--r--cgi-bin/gfx/print.svg149
-rw-r--r--cgi-bin/gfx/right.pngbin0 -> 586 bytes
-rw-r--r--cgi-bin/gfx/right.svg102
-rw-r--r--cgi-bin/gfx/rolldown.pngbin0 -> 536 bytes
-rw-r--r--cgi-bin/gfx/rolldown.svg102
-rw-r--r--cgi-bin/js/lxrng-funcs.js293
-rwxr-xr-xcgi-bin/lxr659
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
new file mode 100644
index 0000000..cd4178f
--- /dev/null
+++ b/cgi-bin/gfx/close.png
Binary files differ
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
new file mode 100644
index 0000000..73edeca
--- /dev/null
+++ b/cgi-bin/gfx/diff.png
Binary files differ
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
new file mode 100644
index 0000000..b01b78c
--- /dev/null
+++ b/cgi-bin/gfx/left.png
Binary files differ
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
new file mode 100644
index 0000000..4e56c0e
--- /dev/null
+++ b/cgi-bin/gfx/print.png
Binary files differ
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
new file mode 100644
index 0000000..439fe13
--- /dev/null
+++ b/cgi-bin/gfx/right.png
Binary files differ
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
new file mode 100644
index 0000000..a2a15ca
--- /dev/null
+++ b/cgi-bin/gfx/rolldown.png
Binary files differ
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;