1diff -ruN a/b/rhino1.7.7.2/build.properties a/b/rhino1.7.7.2/build.properties 2--- a/b/rhino1.7.7.2/build.properties 2026-10-31 20:42:49.489534187 -0500 3+++ a/b/rhino1.7.7.2/build.properties 2026-10-31 20:42:49.840321657 -0500 4@@ -23,4 +23,4 @@ 5 source-level: 1.6 6 7 # jar generation settings 8-jar-compression: true 9+jar-compression: true 10\ No newline at end of file 11diff -ruN a/b/rhino1.7.7.2/build.xml a/b/rhino1.7.7.2/build.xml 12--- a/b/rhino1.7.7.2/build.xml 1969-12-31 19:00:00.000000000 -0500 13+++ b/b/rhino1.7.7.2/build.xml 2026-11-03 00:00:00.000000000 -0500 14@@ -0,0 +1,87 @@ 15+<?xml version="1.0" encoding="UTF-8"?> 16+<!-- This Source Code Form is subject to the terms of the Mozilla Public 17+ - License, v. 2.0. If a copy of the MPL was not distributed with this 18+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> 19+ 20+<project name="rhino" default="jar" basedir="."> 21+ 22+ <target name="init"> 23+ <property file="build.properties"/> 24+ <property name="src.dir" value="src"/> 25+ <property name="build.dir" value="${build.dir}"/> 26+ <property name="classes.dir" value="${classes}"/> 27+ <property name="rhino.jar" value="${rhino.jar}"/> 28+ <property name="small-rhino.jar" value="${small-rhino.jar}"/> 29+ <property name="dist.dir" value="${dist.dir}"/> 30+ <property name="dist.name" value="${dist.name}"/> 31+ 32+ <mkdir dir="${classes.dir}"/> 33+ <mkdir dir="${build.dir}"/> 34+ <mkdir dir="${dist.dir}"/> 35+ </target> 36+ 37+ <target name="compile" depends="init"> 38+ <javac srcdir="${src.dir}" 39+ destdir="${classes.dir}" 40+ debug="${debug}" 41+ target="${target-jvm}" 42+ source="${source-level}" 43+ includeantruntime="false" 44+ encoding="UTF-8"> 45+ <compilerarg value="-Xlint:-options"/> 46+ </javac> 47+ </target> 48+ 49+ <target name="jar" depends="compile"> 50+ <jar destfile="${build.dir}/${rhino.jar}" 51+ compress="${jar-compression}"> 52+ <manifest> 53+ <attribute name="Manifest-Version" value="1.0"/> 54+ <attribute name="Implementation-Title" value="Rhino"/> 55+ <attribute name="Implementation-Version" value="1.7.7.2"/> 56+ </manifest> 57+ <fileset dir="${classes.dir}"/> 58+ <fileset dir="${basedir}/src" includes="**/*.properties"/> 59+ </jar> 60+ </target> 61+ 62+ <target name="small-jar" depends="compile"> 63+ <jar destfile="${build.dir}/${small-rhino.jar}" 64+ compress="${jar-compression}"> 65+ <manifest> 66+ <attribute name="Manifest-Version" value="1.0"/> 67+ <attribute name="Implementation-Title" value="Rhino"/> 68+ <attribute name="Implementation-Version" value="1.7.7.2"/> 69+ </manifest> 70+ <fileset dir="${classes.dir}"> 71+ <exclude name="**/tools/**"/> 72+ <exclude name="**/debugger/**"/> 73+ <exclude name="**/shell/**"/> 74+ <exclude name="**/jsc/**"/> 75+ <exclude name="**/idswitch/**"/> 76+ <exclude name="**/classfile/**"/> 77+ </fileset> 78+ <fileset dir="${basedir}/src" includes="**/*.properties"/> 79+ </jar> 80+ </target> 81+ 82+ <target name="dist" depends="jar, small-jar"> 83+ <mkdir dir="${dist.dir}/${dist.name}/lib"/> 84+ <copy file="${build.dir}/${rhino.jar}" 85+ tofile="${dist.dir}/${dist.name}/lib/${rhino.jar}"/> 86+ <copy file="${build.dir}/${small-rhino.jar}" 87+ tofile="${dist.dir}/${dist.name}/lib/${small-rhino.jar}"/> 88+ <copy file="LICENSE.txt" 89+ todir="${dist.dir}/${dist.name}"/> 90+ <copy file="README.md" 91+ todir="${dist.dir}/${dist.name}"/> 92+ <copy file="RELEASE-NOTES.md" 93+ todir="${dist.dir}/${dist.name}"/> 94+ </target> 95+ 96+ <target name="clean"> 97+ <delete dir="${build.dir}"/> 98+ <delete dir="${dist.dir}"/> 99+ </target> 100+ 101+</project> 102+ 103+</project> 104\ No newline at end of file 105diff -ruN a/b/rhino1.7.7.2/src/org/mozilla/javascript/DefiningClassLoader.java a/b/rhino1.7.7.2/src/org/mozilla/javascript/DefiningClassLoader.java 106--- a/b/rhino1.7.7.2/src/org/mozilla/javascript/DefiningClassLoader.java 2026-10-31 20:42:49.607742394 -0500 107+++ a/b/rhino1.7.7.2/src/org/mozilla/javascript/DefiningClassLoader.java 2026-10-31 20:42:49.766998760 -0500 108@@ -4,6 +4,9 @@ 109 110 package org.mozilla.javascript; 111 112+import java.lang.reflect.Method; 113+import java.lang.reflect.InvocationTargetException; 114+ 115 /** 116 * Load generated classes. 117 * 118@@ -14,10 +17,30 @@ 119 { 120 public DefiningClassLoader() { 121 this.parentLoader = getClass().getClassLoader(); 122+ init(); 123 } 124 125 public DefiningClassLoader(ClassLoader parentLoader) { 126 this.parentLoader = parentLoader; 127+ init(); 128+ } 129+ 130+ private void init() { 131+ this.contextLoader = null; 132+ if (method_getContextClassLoader != null) { 133+ try { 134+ this.contextLoader = (ClassLoader) 135+ method_getContextClassLoader.invoke( 136+ Thread.currentThread(), 137+ ScriptRuntime.emptyArgs); 138+ } catch (IllegalAccessException ex) { 139+ } catch (InvocationTargetException ex) { 140+ } catch (SecurityException ex) { 141+ } 142+ if (this.contextLoader == this.parentLoader) { 143+ this.contextLoader = null; 144+ } 145+ } 146 } 147 148 public Class<?> defineClass(String name, byte[] data) { 149@@ -38,10 +61,14 @@ 150 { 151 Class<?> cl = findLoadedClass(name); 152 if (cl == null) { 153- if (parentLoader != null) { 154- cl = parentLoader.loadClass(name); 155+ if (contextLoader == null) { 156+ cl = loadFromParent(name); 157 } else { 158- cl = findSystemClass(name); 159+ try { 160+ cl = loadFromParent(name); 161+ } catch (ClassNotFoundException ex) { 162+ cl = contextLoader.loadClass(name); 163+ } 164 } 165 } 166 if (resolve) { 167@@ -50,5 +77,36 @@ 168 return cl; 169 } 170 171+ private Class loadFromParent(String name) 172+ throws ClassNotFoundException 173+ { 174+ if (parentLoader != null) { 175+ return parentLoader.loadClass(name); 176+ } else { 177+ return findSystemClass(name); 178+ } 179+ } 180+ 181 private final ClassLoader parentLoader; 182+ 183+ private ClassLoader contextLoader; 184+ 185+ // We'd like to use "Thread.getContextClassLoader", but 186+ // that's only available on Java2. 187+ private static Method method_getContextClassLoader; 188+ 189+ static { 190+ try { 191+ // Don't use "Thread.class": that performs the lookup 192+ // in the class initializer, which doesn't allow us to 193+ // catch possible security exceptions. 194+ Class threadClass = Class.forName("java.lang.Thread"); 195+ method_getContextClassLoader = 196+ threadClass.getDeclaredMethod("getContextClassLoader", 197+ new Class[0]); 198+ } catch (ClassNotFoundException e) { 199+ } catch (NoSuchMethodException e) { 200+ } catch (SecurityException e) { 201+ } 202+ } 203 } 204diff -ruN a/b/rhino1.7.7.2/src/org/mozilla/javascript/tools/debugger/Dim.java a/b/rhino1.7.7.2/src/org/mozilla/javascript/tools/debugger/Dim.java 205--- a/b/rhino1.7.7.2/src/org/mozilla/javascript/tools/debugger/Dim.java 2026-10-31 20:42:49.648044642 -0500 206+++ a/b/rhino1.7.7.2/src/org/mozilla/javascript/tools/debugger/Dim.java 2026-10-31 20:42:49.791085088 -0500 207@@ -34,6 +34,7 @@ 208 private static final int IPROXY_OBJECT_TO_STRING = 5; 209 private static final int IPROXY_OBJECT_PROPERTY = 6; 210 private static final int IPROXY_OBJECT_IDS = 7; 211+ private static final int IPROXY_EVAL_SCRIPT_WITH_RETURN = 8; 212 213 /** 214 * Interface to the debugger GUI. 215@@ -398,7 +399,7 @@ 216 */ 217 private String getNormalizedUrl(DebuggableScript fnOrScript) { 218 String url = fnOrScript.getSourceName(); 219- if (url == null) { url = "<stdin>"; } 220+ if (url == null) { url = "document"; } 221 else { 222 // Not to produce window for eval from different lines, 223 // strip line numbers, i.e. replace all #[0-9]+\(eval\) by 224@@ -587,6 +588,17 @@ 225 } 226 227 /** 228+ * Evaluates the given script with scope and return value. 229+ */ 230+ public Object evalScriptWithReturn(final String url, final String text, Scriptable scope) { 231+ DimIProxy action = new DimIProxy(this, IPROXY_EVAL_SCRIPT_WITH_RETURN); 232+ action.url = url; 233+ action.text = text; 234+ action.scope = scope; 235+ return contextFactory.call(action); 236+ } 237+ 238+ /** 239 * Converts the given script object to a string. 240 */ 241 public String objectToString(Object object) { 242@@ -931,6 +943,11 @@ 243 private Object[] objectArrayResult; 244 245 /** 246+ * The Scriptable as arguments. 247+ */ 248+ private Scriptable scope; 249+ 250+ /** 251 * Creates a new DimIProxy. 252 */ 253 private DimIProxy(Dim dim, int type) { 254@@ -962,6 +979,20 @@ 255 } 256 break; 257 258+ case IPROXY_EVAL_SCRIPT_WITH_RETURN: 259+ if (this.scope != null) { 260+ return cx.evaluateString(this.scope, text, url, 1, null); 261+ } else { 262+ Scriptable sc = null; 263+ if (dim.scopeProvider != null) { 264+ sc = dim.scopeProvider.getScope(); 265+ } 266+ if (sc == null) { 267+ sc = new ImporterTopLevel(cx); 268+ } 269+ return cx.evaluateString(sc, text, url, 1, null); 270+ } 271+ 272 case IPROXY_STRING_IS_COMPILABLE: 273 booleanResult = cx.stringIsCompilableUnit(text); 274 break; 275diff -ruN a/b/rhino1.7.7.2/src/org/mozilla/javascript/tools/debugger/GuiCallback.java a/b/rhino1.7.7.2/src/org/mozilla/javascript/tools/debugger/GuiCallback.java 276--- a/b/rhino1.7.7.2/src/org/mozilla/javascript/tools/debugger/GuiCallback.java 2026-10-31 20:42:49.649184458 -0500 277+++ a/b/rhino1.7.7.2/src/org/mozilla/javascript/tools/debugger/GuiCallback.java 2026-10-31 20:42:49.791267690 -0500 278@@ -23,6 +23,11 @@ 279 String threadTitle, 280 String alertMessage); 281 282+ /** 283+ * Called when the interrupt loop has been exited. 284+ */ 285+ void exitInterrupt(); 286+ 287 /** 288 * Returns whether the current thread is the GUI's event thread. 289 * This information is required to avoid blocking the event thread 290@@ -35,4 +40,4 @@ 291 * is necessary when the GUI event thread itself has been stopped. 292 */ 293 void dispatchNextGuiEvent() throws InterruptedException; 294-} 295+} 296\ No newline at end of file 297diff -ruN a/b/rhino1.7.7.2/src/org/mozilla/javascript/tools/debugger/Main.java a/b/rhino1.7.7.2/src/org/mozilla/javascript/tools/debugger/Main.java 298--- a/b/rhino1.7.7.2/src/org/mozilla/javascript/tools/debugger/Main.java 2026-10-31 20:42:49.648814653 -0500 299+++ a/b/rhino1.7.7.2/src/org/mozilla/javascript/tools/debugger/Main.java 2026-10-31 20:42:49.791202989 -0500 300@@ -8,6 +8,7 @@ 301 302 import java.io.InputStream; 303 import java.io.PrintStream; 304+import java.net.URL; 305 306 import javax.swing.JFrame; 307 308@@ -126,7 +127,7 @@ 309 * Console window. 310 */ 311 public InputStream getIn() { 312- return debugGui.getConsole().getIn(); 313+ return null;//return debugGui.getConsole().getIn(); 314 } 315 316 /** 317@@ -134,7 +135,7 @@ 318 * Console window. 319 */ 320 public PrintStream getOut() { 321- return debugGui.getConsole().getOut(); 322+ return null;//return debugGui.getConsole().getOut(); 323 } 324 325 /** 326@@ -142,7 +143,7 @@ 327 * Console window. 328 */ 329 public PrintStream getErr() { 330- return debugGui.getConsole().getErr(); 331+ return null;//return debugGui.getConsole().getErr(); 332 } 333 334 /** 335@@ -349,6 +350,41 @@ 336 { 337 throw new IllegalStateException(); 338 } 339+ 340+ // shortcut methods 341+ 342+ public void addWindowListener(java.awt.event.WindowListener l) { 343+ debugGui.addWindowListener(l); 344+ } 345+ 346+ public void highlighLineInScriptWindow(URL url, int lineNum) { 347+ debugGui.highlighLineInScriptWindow(url, lineNum); 348+ } 349+ 350+ public Object runScriptWindow(URL scriptUrl) throws Exception 351+ { 352+ return debugGui.runScriptWindow(scriptUrl); 353+ } 354+ 355+ public void openFile(URL scriptUrl, Scriptable scope, Runnable closeCallback) { 356+ debugGui.openFile(scriptUrl, scope, closeCallback); 357+ } 358+ 359+ public void toFront() { 360+ debugGui.toFront(); 361+ } 362+ 363+ public void showScriptWindow(URL url) { 364+ debugGui.showScriptWindow(url); 365+ } 366+ 367+ public boolean isModified(URL url) { 368+ return debugGui.isModified(url); 369+ } 370+ 371+ public String getText(URL url) { 372+ return debugGui.getText(url); 373+ } 374 375 /** 376 * Class to consolidate all internal implementations of interfaces 377@@ -408,4 +444,4 @@ 378 return scope; 379 } 380 } 381-} 382+} 383\ No newline at end of file 384diff -ruN a/b/rhino1.7.7.2/src/org/mozilla/javascript/tools/debugger/OfficeScriptInfo.java a/b/rhino1.7.7.2/src/org/mozilla/javascript/tools/debugger/OfficeScriptInfo.java 385--- a/b/rhino1.7.7.2/src/org/mozilla/javascript/tools/debugger/OfficeScriptInfo.java 1969-12-31 19:00:00.000000000 -0500 386+++ a/b/rhino1.7.7.2/src/org/mozilla/javascript/tools/debugger/OfficeScriptInfo.java 2026-10-31 20:42:49.792418706 -0500 387@@ -0,0 +1,122 @@ 388+/************************************************************** 389+ * 390+ * Licensed to the Apache Software Foundation (ASF) under one 391+ * or more contributor license agreements. See the NOTICE file 392+ * distributed with this work for additional information 393+ * regarding copyright ownership. The ASF licenses this file 394+ * to you under the Apache License, Version 2.0 (the 395+ * "License"); you may not use this file except in compliance 396+ * with the License. You may obtain a copy of the License at 397+ * 398+ * http://www.apache.org/licenses/LICENSE-2.0 399+ * 400+ * Unless required by applicable law or agreed to in writing, 401+ * software distributed under the License is distributed on an 402+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 403+ * KIND, either express or implied. See the License for the 404+ * specific language governing permissions and limitations 405+ * under the License. 406+ * 407+ *************************************************************/ 408+ 409+ 410+package org.mozilla.javascript.tools.debugger; 411+import java.net.URL; 412+import java.util.Hashtable; 413+import org.mozilla.javascript.Scriptable; 414+ 415+public class OfficeScriptInfo 416+{ 417+ private Hashtable<String, SFScriptInfo> loadedSFScripts = new Hashtable<String, SFScriptInfo>(); 418+ 419+ public void addScript( URL url, Scriptable scope, Runnable closeCallback ) 420+ { 421+ addScript( url.toString(), url, scope, closeCallback ); 422+ } 423+ 424+ public void addScript( String key, URL url, Scriptable scope, Runnable closeCallback ) 425+ { 426+ SFScriptInfo si = (SFScriptInfo)loadedSFScripts.get( key ); 427+ if ( si == null ) 428+ { 429+ si = new SFScriptInfo(); 430+ si.url = url; 431+ si.scope = scope; 432+ si.closeCallback = closeCallback; 433+ loadedSFScripts.put( key, si ); 434+ } 435+ } 436+ 437+ public void deleteScript( String key ) 438+ { 439+ SFScriptInfo info = (SFScriptInfo)loadedSFScripts.remove( key ); 440+ if ( info != null ) 441+ { 442+ if ( info.closeCallback != null ) 443+ { 444+ System.out.println("** In removeSFScriptInfo have callback for " + key ); 445+ info.closeCallback.run(); 446+ } 447+ } 448+ } 449+ 450+ public Scriptable getScriptScope( String key ) 451+ { 452+ Scriptable result = null; 453+ SFScriptInfo info = (SFScriptInfo)loadedSFScripts.get( key ); 454+ if ( info != null ) 455+ { 456+ result = info.scope; 457+ } 458+ return result; 459+ } 460+ 461+ public URL getScriptUrl( String key ) 462+ { 463+ URL result = null; 464+ SFScriptInfo info = (SFScriptInfo)loadedSFScripts.get( key ); 465+ if ( info != null ) 466+ { 467+ result = info.url; 468+ } 469+ return result; 470+ } 471+ public boolean hasScript( String key ) 472+ { 473+ boolean result = true; 474+ SFScriptInfo info = (SFScriptInfo)loadedSFScripts.get( key ); 475+ if ( info == null ) 476+ { 477+ result = false; 478+ } 479+ return result; 480+ } 481+ 482+ public void setScriptRunning( String key, boolean running ) 483+ { 484+ SFScriptInfo info = (SFScriptInfo)loadedSFScripts.get( key ); 485+ if ( info != null ) 486+ { 487+ info.isExecuting = running; 488+ } 489+ } 490+ 491+ public boolean isScriptRunning( String key ) 492+ { 493+ boolean result = false; 494+ SFScriptInfo info = (SFScriptInfo)loadedSFScripts.get( key ); 495+ if ( info != null ) 496+ { 497+ result = info.isExecuting; 498+ } 499+ return result; 500+ } 501+ 502+ class SFScriptInfo 503+ { 504+ Scriptable scope; 505+ boolean isExecuting; 506+ URL url; 507+ Runnable closeCallback; 508+ } 509+} 510diff -ruN a/b/rhino1.7.7.2/src/org/mozilla/javascript/tools/debugger/SwingGui.java a/b/rhino1.7.7.2/src/org/mozilla/javascript/tools/debugger/SwingGui.java 511--- a/b/rhino1.7.7.2/src/org/mozilla/javascript/tools/debugger/SwingGui.java 2026-10-31 20:42:49.648303446 -0500 512+++ a/b/rhino1.7.7.2/src/org/mozilla/javascript/tools/debugger/SwingGui.java 2026-10-31 20:42:49.792500007 -0500 513@@ -32,6 +32,8 @@ 514 import java.awt.Toolkit; 515 import java.awt.event.*; 516 517+import java.net.URL; 518+ 519 import java.util.List; 520 import java.util.ArrayList; 521 import java.util.Arrays; 522@@ -47,6 +49,7 @@ 523 import java.lang.reflect.Method; 524 525 import org.mozilla.javascript.Kit; 526+import org.mozilla.javascript.Scriptable; 527 import org.mozilla.javascript.SecurityUtilities; 528 529 import org.mozilla.javascript.tools.shell.ConsoleTextArea; 530@@ -59,6 +62,138 @@ 531 * GUI for the Rhino debugger. 532 */ 533 public class SwingGui extends JFrame implements GuiCallback { 534+ private boolean sourceEditingEnabled = true; 535+ 536+ public boolean isSourceEditingEnabled() { 537+ return sourceEditingEnabled; 538+ } 539+ 540+ public void setSourceEditingEnabled(boolean b) { 541+ sourceEditingEnabled = b; 542+ } 543+ 544+ public void exitInterrupt() { 545+ setSourceEditingEnabled(true); 546+ } 547+ 548+ // patched Office specific interface 549+ OfficeScriptInfo officeScripts = new OfficeScriptInfo(); 550+ 551+ void removeScript(String url) { 552+ officeScripts.deleteScript(url); 553+ } 554+ 555+ private String getFileName(URL url) { 556+ if (url.getProtocol().startsWith("vnd.sun.star.")) 557+ return url.toString(); 558+ // Preserve full identity (protocol, host, query) for non-UNO URLs. 559+ return url.toString(); 560+ } 561+ 562+ public void openFile(URL scriptUrl, Scriptable scope, Runnable closeCallback) { 563+ if (scope == null) { 564+ javax.swing.JOptionPane.showMessageDialog(this, 565+ "Can't compile scripts: no scope available", 566+ "Open", javax.swing.JOptionPane.ERROR_MESSAGE); 567+ } else if (scriptUrl != null) { 568+ String fileName = getFileName(scriptUrl); 569+ // Avoid duplicating an already-open editor window. 570+ if (getFileWindow(fileName) != null) { 571+ showScriptWindow(scriptUrl); 572+ return; 573+ } 574+ String text; 575+ try (java.io.InputStreamReader reader = new java.io.InputStreamReader(scriptUrl.openStream())) { 576+ text = org.mozilla.javascript.Kit.readReader(reader); 577+ } catch (java.io.IOException e) { 578+ javax.swing.JOptionPane.showMessageDialog(this, 579+ "Can't open stream for script: " + e.toString(), 580+ "Open", javax.swing.JOptionPane.ERROR_MESSAGE); 581+ return; 582+ } 583+ officeScripts.addScript(fileName, scriptUrl, scope, closeCallback); 584+ // Register/compile the source with the debugger using Rhino's OPEN_FILE mechanism. 585+ RunProxy proxy = new RunProxy(this, RunProxy.OPEN_FILE); 586+ proxy.fileName = fileName; 587+ proxy.text = text; 588+ new Thread(proxy).start(); 589+ } 590+ } 591+ 592+ public void showScriptWindow(URL url) { 593+ String key = getFileName(url); 594+ FileWindow w = (FileWindow) getFileWindow(key); 595+ if (w != null) 596+ { 597+ desk.getDesktopManager().deiconifyFrame(w); 598+ desk.getDesktopManager().activateFrame(w); 599+ w.show(); 600+ w.toFront(); 601+ } 602+ } 603+ 604+ public void highlighLineInScriptWindow(URL url, int lineNum) { 605+ String key = getFileName(url); 606+ FileWindow w = (FileWindow) getFileWindow(key); 607+ if (w != null) 608+ { 609+ showFileWindow(key, lineNum); 610+ } 611+ } 612+ 613+ public Object runScriptWindow(URL scriptUrl) throws Exception 614+ { 615+ String key = getFileName(scriptUrl); 616+ FileWindow w = (FileWindow) getFileWindow(key); 617+ Object result = null; 618+ if (w != null) 619+ { 620+ w.toFront(); 621+ Scriptable scope = officeScripts.getScriptScope(key); 622+ if (scope == null) 623+ { 624+ javax.swing.JOptionPane.showMessageDialog(this, "Can't load scripts: no scope available", "Run", javax.swing.JOptionPane.ERROR_MESSAGE); 625+ } 626+ else 627+ { 628+ String url = w.getUrl(); 629+ if (url != null) 630+ { 631+ if (officeScripts.isScriptRunning(key)) 632+ { 633+ return result; 634+ } 635+ officeScripts.setScriptRunning(key, true); 636+ try { 637+ result = dim.evalScriptWithReturn(url, w.getText(), scope); 638+ } catch (Exception exc) { 639+ exc.printStackTrace(); 640+ throw exc; 641+ } finally { 642+ officeScripts.setScriptRunning(key, false); 643+ } 644+ } 645+ } 646+ } 647+ return result; 648+ } 649+ 650+ public boolean isModified(URL url) { 651+ String key = getFileName(url); 652+ FileWindow w = (FileWindow) getFileWindow(key); 653+ if (w != null) 654+ return w.isModified(); 655+ return false; 656+ } 657+ 658+ public String getText(URL url) { 659+ String key = getFileName(url); 660+ FileWindow w = (FileWindow) getFileWindow(key); 661+ if (w != null) 662+ return w.getText(); 663+ return null; 664+ } 665+ 666 667 /** 668 * Serializable magic number. 669@@ -2052,7 +2187,7 @@ 670 /** 671 * An internal frame for script files. 672 */ 673-class FileWindow extends JInternalFrame implements ActionListener { 674+class FileWindow extends JInternalFrame implements ActionListener, javax.swing.event.DocumentListener { 675 676 /** 677 * Serializable magic number. 678@@ -2089,6 +2224,83 @@ 679 */ 680 int currentPos; 681 682+ boolean isModified = false; 683+ 684+ public void insertUpdate(javax.swing.event.DocumentEvent e) { 685+ doChanged(e); 686+ } 687+ 688+ public void removeUpdate(javax.swing.event.DocumentEvent e) { 689+ doChanged(e); 690+ } 691+ 692+ public void changedUpdate(javax.swing.event.DocumentEvent e) { 693+ doChanged(e); 694+ } 695+ 696+ public void doChanged(javax.swing.event.DocumentEvent e) { 697+ this.isModified = true; 698+ } 699+ 700+ public boolean isModified() { 701+ return this.isModified; 702+ } 703+ 704+ public String getText() { 705+ return textArea.getText(); 706+ } 707+ 708+ void save() { 709+ String url = getUrl(); 710+ if (url != null) { 711+ java.io.OutputStream os = null; 712+ try { 713+ if (url.startsWith("vnd.sun.star")) 714+ { 715+ URL scriptUrl = debugGui.officeScripts.getScriptUrl(url); 716+ if ( scriptUrl == null ) 717+ { 718+ throw new java.io.IOException("Can't obtain stream for " + url); 719+ } 720+ os = scriptUrl.openConnection().getOutputStream(); 721+ } 722+ else 723+ { 724+ os = new java.io.FileOutputStream(url); 725+ } 726+ String txt = textArea.getText(); 727+ byte[] data = txt.getBytes(java.nio.charset.StandardCharsets.UTF_8); 728+ os.write(data, 0, data.length); 729+ 730+ this.isModified = false; 731+ } catch (java.io.IOException ioe) { 732+ javax.swing.JOptionPane.showMessageDialog(this, 733+ "Error saving file: " + ioe.getMessage(), 734+ "Error", javax.swing.JOptionPane.ERROR_MESSAGE); 735+ } 736+ finally 737+ { 738+ if ( os != null ) 739+ { 740+ try 741+ { 742+ os.close(); 743+ os = null; 744+ } 745+ catch( java.io.IOException ioe ) 746+ { 747+ System.err.println("Error closing stream: " + ioe.getMessage() ); 748+ ioe.printStackTrace(); 749+ } 750+ } 751+ } 752+ } 753+ } 754+ 755+ public boolean isEditable() { 756+ return debugGui.isSourceEditingEnabled(); 757+ } 758+ 759 /** 760 * Loads the file. 761 */ 762@@ -3546,4 +3758,5 @@ 763 764 } 765 } 766+ 767 } 768