mirror of
https://github.com/esp8266/Arduino.git
synced 2025-07-30 16:24:09 +03:00
Libraries now support syntax coloring and are built on IDE startup.
This commit is contained in:
482
app/Library.java
482
app/Library.java
@ -19,6 +19,8 @@
|
||||
|
||||
package processing.app;
|
||||
|
||||
import processing.app.syntax.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.zip.*;
|
||||
@ -35,6 +37,7 @@ import javax.swing.event.*;
|
||||
public class Library implements MessageConsumer{
|
||||
|
||||
private File libFolder;
|
||||
private File utilityFolder;
|
||||
private LibraryManager libManager;
|
||||
RunnerException exception;
|
||||
|
||||
@ -48,10 +51,13 @@ public class Library implements MessageConsumer{
|
||||
{
|
||||
libFolder = folder;
|
||||
libManager = manager;
|
||||
utilityFolder = getUtilityFolder();
|
||||
|
||||
/* for debug output
|
||||
// for debug output
|
||||
/*
|
||||
System.out.println("library: " + getName());
|
||||
System.out.println("folder: " + getFolder());
|
||||
System.out.println("utility: " + utilityFolder);
|
||||
System.out.println("built: " + isBuilt());
|
||||
System.out.println("buildable: " + isBuildable());
|
||||
System.out.println("o files: " + getObjectFiles().length);
|
||||
@ -85,12 +91,7 @@ public class Library implements MessageConsumer{
|
||||
*/
|
||||
public boolean isBuilt()
|
||||
{
|
||||
FileFilter onlyObjectFiles = new FileFilter() {
|
||||
public boolean accept(File file) {
|
||||
return file.getName().endsWith(".o");
|
||||
}
|
||||
};
|
||||
if(0 < (libFolder.listFiles(onlyObjectFiles)).length){
|
||||
if(getObjectFiles().length >= (getCSourceFiles().length + getCPPSourceFiles().length)){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -98,16 +99,11 @@ public class Library implements MessageConsumer{
|
||||
|
||||
/*
|
||||
* Tests if library is buildable
|
||||
* @return True if library has .cpp files, false otherwise
|
||||
* @return True if library has source files, false otherwise
|
||||
*/
|
||||
public boolean isBuildable()
|
||||
{
|
||||
FileFilter onlySourceFiles = new FileFilter() {
|
||||
public boolean accept(File file) {
|
||||
return (file.getName()).endsWith(".cpp");
|
||||
}
|
||||
};
|
||||
if(0 < (libFolder.listFiles(onlySourceFiles)).length){
|
||||
if(0 < (getCSourceFiles().length + getCPPSourceFiles().length)){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -127,6 +123,29 @@ public class Library implements MessageConsumer{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scans for library "utility" folder
|
||||
* @return File object of library's "utility" folder, or null
|
||||
*/
|
||||
private File getUtilityFolder()
|
||||
{
|
||||
FileFilter filter = new FileFilter() {
|
||||
public boolean accept(File file) {
|
||||
if(file.isDirectory()){
|
||||
if((file.getName()).equalsIgnoreCase("utility")){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
File[] files = libFolder.listFiles(filter);
|
||||
if(files.length > 0){
|
||||
return files[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds examples folder
|
||||
* @return "examples" folder as file object or null
|
||||
@ -195,21 +214,33 @@ public class Library implements MessageConsumer{
|
||||
|
||||
/*
|
||||
* List of object files for linking
|
||||
* @return Array of library's object files as File objects
|
||||
* @return Array of object files as File objects
|
||||
*/
|
||||
public File[] getObjectFiles()
|
||||
private File[] getObjectFiles(File folder)
|
||||
{
|
||||
FileFilter onlyObjectFiles = new FileFilter() {
|
||||
public boolean accept(File file) {
|
||||
return (file.getName()).endsWith(".o");
|
||||
}
|
||||
};
|
||||
return libFolder.listFiles(onlyObjectFiles);
|
||||
return folder.listFiles(onlyObjectFiles);
|
||||
}
|
||||
public File[] getObjectFiles()
|
||||
{
|
||||
if(null == utilityFolder){
|
||||
return getObjectFiles(libFolder);
|
||||
}
|
||||
File[] libraryObjects = getObjectFiles(libFolder);
|
||||
File[] utilityObjects = getObjectFiles(utilityFolder);
|
||||
File[] objects = new File[libraryObjects.length + utilityObjects.length];
|
||||
System.arraycopy(libraryObjects, 0, objects, 0, libraryObjects.length);
|
||||
System.arraycopy(utilityObjects, 0, objects, libraryObjects.length, utilityObjects.length);
|
||||
return objects;
|
||||
}
|
||||
|
||||
/*
|
||||
* List of header source files for inclusion
|
||||
* @return Array of library's header source files as File objects
|
||||
* @return Array of header source files as File objects
|
||||
*/
|
||||
public File[] getHeaderFiles()
|
||||
{
|
||||
@ -222,31 +253,55 @@ public class Library implements MessageConsumer{
|
||||
}
|
||||
|
||||
/*
|
||||
* List of C source files for compiling
|
||||
* @return Array of library's C source files as File objects
|
||||
* List of library's C source files for compiling
|
||||
* @return Array of C source files as File objects
|
||||
*/
|
||||
private File[] getCSourceFiles()
|
||||
private File[] getCSourceFiles(File folder)
|
||||
{
|
||||
FileFilter onlyCFiles = new FileFilter() {
|
||||
public boolean accept(File file) {
|
||||
return (file.getName()).endsWith(".c");
|
||||
}
|
||||
};
|
||||
return libFolder.listFiles(onlyCFiles);
|
||||
return folder.listFiles(onlyCFiles);
|
||||
}
|
||||
private File[] getCSourceFiles()
|
||||
{
|
||||
if(null == utilityFolder){
|
||||
return getCSourceFiles(libFolder);
|
||||
}
|
||||
File[] librarySources = getCSourceFiles(libFolder);
|
||||
File[] utilitySources = getCSourceFiles(utilityFolder);
|
||||
File[] sources = new File[librarySources.length + utilitySources.length];
|
||||
System.arraycopy(librarySources, 0, sources, 0, librarySources.length);
|
||||
System.arraycopy(utilitySources, 0, sources, librarySources.length, utilitySources.length);
|
||||
return sources;
|
||||
}
|
||||
|
||||
/*
|
||||
* List of C++ source files for compiling
|
||||
* @return Array of library's C++ source files as File objects
|
||||
* @return Array of C++ source files as File objects
|
||||
*/
|
||||
private File[] getCPPSourceFiles()
|
||||
private File[] getCPPSourceFiles(File folder)
|
||||
{
|
||||
FileFilter onlyCPPFiles = new FileFilter() {
|
||||
public boolean accept(File file) {
|
||||
return (file.getName()).endsWith(".cpp");
|
||||
}
|
||||
};
|
||||
return libFolder.listFiles(onlyCPPFiles);
|
||||
return folder.listFiles(onlyCPPFiles);
|
||||
}
|
||||
private File[] getCPPSourceFiles()
|
||||
{
|
||||
if(null == utilityFolder){
|
||||
return getCPPSourceFiles(libFolder);
|
||||
}
|
||||
File[] librarySources = getCPPSourceFiles(libFolder);
|
||||
File[] utilitySources = getCPPSourceFiles(utilityFolder);
|
||||
File[] sources = new File[librarySources.length + utilitySources.length];
|
||||
System.arraycopy(librarySources, 0, sources, 0, librarySources.length);
|
||||
System.arraycopy(utilitySources, 0, sources, librarySources.length, utilitySources.length);
|
||||
return sources;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -255,157 +310,170 @@ public class Library implements MessageConsumer{
|
||||
*/
|
||||
public boolean build() throws RunnerException
|
||||
{
|
||||
if(isBuildable()){
|
||||
String userDir = System.getProperty("user.dir") + File.separator;
|
||||
|
||||
String[] baseCompileCommandC = new String[] {
|
||||
((!Base.isMacOS()) ? "tools/avr/bin/avr-gcc" : userDir + "tools/avr/bin/avr-gcc"),
|
||||
"-c",
|
||||
"-g",
|
||||
"-Os",
|
||||
"-Wall",
|
||||
"-mmcu=" + Preferences.get("build.mcu"),
|
||||
"-DF_CPU=" + Preferences.get("build.f_cpu"),
|
||||
"-I" + libManager.getTarget().getPath(),
|
||||
"-I" + getFolder(),
|
||||
};
|
||||
|
||||
String[] baseCompileCommandCPP = new String[] {
|
||||
((!Base.isMacOS()) ? "tools/avr/bin/avr-g++" : userDir + "tools/avr/bin/avr-g++"),
|
||||
"-c",
|
||||
"-g",
|
||||
"-Os",
|
||||
"-Wall",
|
||||
"-fno-exceptions",
|
||||
"-mmcu=" + Preferences.get("build.mcu"),
|
||||
"-DF_CPU=" + Preferences.get("build.f_cpu"),
|
||||
"-I" + libManager.getTarget().getPath(),
|
||||
"-I" + getFolder(),
|
||||
};
|
||||
|
||||
// use built lib directories in include paths when searching for headers
|
||||
// this allows libs to use other libs easily
|
||||
String[] libDirs = libManager.getFolderPaths();
|
||||
String[] compileCommandC = new String[baseCompileCommandC.length + libDirs.length + 2];
|
||||
String[] compileCommandCPP = new String[baseCompileCommandCPP.length + libDirs.length + 2];
|
||||
System.arraycopy(baseCompileCommandC, 0, compileCommandC, 0, baseCompileCommandC.length);
|
||||
System.arraycopy(baseCompileCommandCPP, 0, compileCommandCPP, 0, baseCompileCommandCPP.length);
|
||||
for (int i = 0; i < libDirs.length; ++i) {
|
||||
compileCommandC[baseCompileCommandC.length + i] = "-I" + libDirs[i];
|
||||
compileCommandCPP[baseCompileCommandCPP.length + i] = "-I" + libDirs[i];
|
||||
}
|
||||
|
||||
File[] sourcesC = getCSourceFiles();
|
||||
File[] sourcesCPP = getCPPSourceFiles();
|
||||
|
||||
// execute the compiler, and create threads to deal
|
||||
// with the input and error streams
|
||||
//
|
||||
int result = 0;
|
||||
try {
|
||||
String nameSansExtension;
|
||||
Process process;
|
||||
boolean compiling = true;
|
||||
|
||||
// compile c sources
|
||||
for(int i = 0; i < sourcesC.length; ++i) {
|
||||
nameSansExtension = sourcesC[i].getName();
|
||||
nameSansExtension = nameSansExtension.substring(0, nameSansExtension.length() - 2); // -2 because ".c"
|
||||
|
||||
compileCommandC[compileCommandC.length - 2] = sourcesC[i].getPath();
|
||||
compileCommandC[compileCommandC.length - 1] = "-o" + getFolder() + File.separator + nameSansExtension + ".o";
|
||||
|
||||
process = Runtime.getRuntime().exec(compileCommandC);
|
||||
new MessageSiphon(process.getInputStream(), this);
|
||||
new MessageSiphon(process.getErrorStream(), this);
|
||||
|
||||
// wait for the process to finish. if interrupted
|
||||
// before waitFor returns, continue waiting
|
||||
//
|
||||
compiling = true;
|
||||
while (compiling) {
|
||||
try {
|
||||
result = process.waitFor();
|
||||
//System.out.println("result is " + result);
|
||||
compiling = false;
|
||||
} catch (InterruptedException ignored) { }
|
||||
}
|
||||
if (exception != null) {
|
||||
exception.hideStackTrace = true;
|
||||
throw exception;
|
||||
}
|
||||
if(result != 0){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// compile c++ sources
|
||||
for(int i = 0; i < sourcesCPP.length; ++i) {
|
||||
nameSansExtension = sourcesCPP[i].getName();
|
||||
nameSansExtension = nameSansExtension.substring(0, nameSansExtension.length() - 4); // -4 because ".cpp"
|
||||
|
||||
compileCommandCPP[compileCommandCPP.length - 2] = sourcesCPP[i].getPath();
|
||||
compileCommandCPP[compileCommandCPP.length - 1] = "-o" + getFolder() + File.separator + nameSansExtension + ".o";
|
||||
|
||||
process = Runtime.getRuntime().exec(compileCommandCPP);
|
||||
new MessageSiphon(process.getInputStream(), this);
|
||||
new MessageSiphon(process.getErrorStream(), this);
|
||||
|
||||
// wait for the process to finish. if interrupted
|
||||
// before waitFor returns, continue waiting
|
||||
//
|
||||
compiling = true;
|
||||
while (compiling) {
|
||||
try {
|
||||
result = process.waitFor();
|
||||
//System.out.println("result is " + result);
|
||||
compiling = false;
|
||||
} catch (InterruptedException ignored) { }
|
||||
}
|
||||
if (exception != null) {
|
||||
exception.hideStackTrace = true;
|
||||
throw exception;
|
||||
}
|
||||
if(result != 0){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
String msg = e.getMessage();
|
||||
if ((msg != null) && (msg.indexOf("avr-gcc: not found") != -1)) {
|
||||
Base.showWarning("Compiler error",
|
||||
"Could not find the compiler.\n" +
|
||||
"avr-gcc is missing from your PATH,\n" +
|
||||
"see readme.txt for help.", null);
|
||||
return false;
|
||||
|
||||
} else if ((msg != null) && (msg.indexOf("avr-g++: not found") != -1)) {
|
||||
Base.showWarning("Compiler error",
|
||||
"Could not find the compiler.\n" +
|
||||
"avr-g++ is missing from your PATH,\n" +
|
||||
"see readme.txt for help.", null);
|
||||
return false;
|
||||
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// an error was queued up by message()
|
||||
if (exception != null) {
|
||||
throw exception;
|
||||
}
|
||||
|
||||
if (result != 0 && result != 1 ) {
|
||||
Base.openURL(BUGS_URL);
|
||||
throw new RunnerException(SUPER_BADNESS);
|
||||
}
|
||||
|
||||
// success would mean that 'result' is set to zero
|
||||
return (result == 0); // ? true : false;
|
||||
// fail if library is not buildable (contains no sources)
|
||||
if(!isBuildable()){
|
||||
return false;
|
||||
}
|
||||
return false; // library is not buildable (contains no sources)
|
||||
|
||||
String userDir = System.getProperty("user.dir") + File.separator;
|
||||
|
||||
String[] baseCompileCommandC = new String[] {
|
||||
((!Base.isMacOS()) ? "tools/avr/bin/avr-gcc" : userDir + "tools/avr/bin/avr-gcc"),
|
||||
"-c",
|
||||
"-g",
|
||||
"-Os",
|
||||
"-Wall",
|
||||
"-mmcu=" + Preferences.get("build.mcu"),
|
||||
"-DF_CPU=" + Preferences.get("build.f_cpu"),
|
||||
"-I" + libManager.getTarget().getPath(),
|
||||
"-I" + getFolder(),
|
||||
};
|
||||
|
||||
String[] baseCompileCommandCPP = new String[] {
|
||||
((!Base.isMacOS()) ? "tools/avr/bin/avr-g++" : userDir + "tools/avr/bin/avr-g++"),
|
||||
"-c",
|
||||
"-g",
|
||||
"-Os",
|
||||
"-Wall",
|
||||
"-fno-exceptions",
|
||||
"-mmcu=" + Preferences.get("build.mcu"),
|
||||
"-DF_CPU=" + Preferences.get("build.f_cpu"),
|
||||
"-I" + libManager.getTarget().getPath(),
|
||||
"-I" + getFolder(),
|
||||
};
|
||||
|
||||
// use built lib directories in include paths when searching for headers
|
||||
// this allows libs to use other libs easily
|
||||
int extraSpots = 2; // two spots for file path and -o portions
|
||||
utilityFolder = getUtilityFolder(); // refresh status of utility folder
|
||||
if(null != utilityFolder){
|
||||
extraSpots = 3; // an extra spot for utility folder as include
|
||||
}
|
||||
String[] libDirs = libManager.getFolderPaths();
|
||||
String[] compileCommandC = new String[baseCompileCommandC.length + libDirs.length + extraSpots];
|
||||
String[] compileCommandCPP = new String[baseCompileCommandCPP.length + libDirs.length + extraSpots];
|
||||
System.arraycopy(baseCompileCommandC, 0, compileCommandC, 0, baseCompileCommandC.length);
|
||||
System.arraycopy(baseCompileCommandCPP, 0, compileCommandCPP, 0, baseCompileCommandCPP.length);
|
||||
for (int i = 0; i < libDirs.length; ++i) {
|
||||
compileCommandC[baseCompileCommandC.length + i] = "-I" + libDirs[i];
|
||||
compileCommandCPP[baseCompileCommandCPP.length + i] = "-I" + libDirs[i];
|
||||
}
|
||||
|
||||
// add this library's "utility" folder to inclusion paths
|
||||
if(null != utilityFolder){
|
||||
compileCommandC[compileCommandC.length - 3] = "-I" + utilityFolder.getPath();
|
||||
compileCommandCPP[compileCommandCPP.length - 3] = "-I" + utilityFolder.getPath();
|
||||
}
|
||||
|
||||
File[] sourcesC = getCSourceFiles();
|
||||
File[] sourcesCPP = getCPPSourceFiles();
|
||||
|
||||
// execute the compiler, and create threads to deal
|
||||
// with the input and error streams
|
||||
//
|
||||
int result = 0;
|
||||
try {
|
||||
String pathSansExtension;
|
||||
Process process;
|
||||
boolean compiling = true;
|
||||
|
||||
// compile c sources
|
||||
for(int i = 0; i < sourcesC.length; ++i) {
|
||||
pathSansExtension = sourcesC[i].getPath();
|
||||
pathSansExtension = pathSansExtension.substring(0, pathSansExtension.length() - 2); // -2 because ".c"
|
||||
|
||||
compileCommandC[compileCommandC.length - 2] = sourcesC[i].getPath();
|
||||
compileCommandC[compileCommandC.length - 1] = "-o" + pathSansExtension + ".o";
|
||||
|
||||
process = Runtime.getRuntime().exec(compileCommandC);
|
||||
new MessageSiphon(process.getInputStream(), this);
|
||||
new MessageSiphon(process.getErrorStream(), this);
|
||||
|
||||
// wait for the process to finish. if interrupted
|
||||
// before waitFor returns, continue waiting
|
||||
//
|
||||
compiling = true;
|
||||
while (compiling) {
|
||||
try {
|
||||
result = process.waitFor();
|
||||
//System.out.println("result is " + result);
|
||||
compiling = false;
|
||||
} catch (InterruptedException ignored) { }
|
||||
}
|
||||
if (exception != null) {
|
||||
exception.hideStackTrace = true;
|
||||
throw exception;
|
||||
}
|
||||
if(result != 0){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// compile c++ sources
|
||||
for(int i = 0; i < sourcesCPP.length; ++i) {
|
||||
pathSansExtension = sourcesCPP[i].getPath();
|
||||
pathSansExtension = pathSansExtension.substring(0, pathSansExtension.length() - 4); // -4 because ".cpp"
|
||||
|
||||
compileCommandCPP[compileCommandCPP.length - 2] = sourcesCPP[i].getPath();
|
||||
compileCommandCPP[compileCommandCPP.length - 1] = "-o" + pathSansExtension + ".o";
|
||||
|
||||
process = Runtime.getRuntime().exec(compileCommandCPP);
|
||||
new MessageSiphon(process.getInputStream(), this);
|
||||
new MessageSiphon(process.getErrorStream(), this);
|
||||
|
||||
// wait for the process to finish. if interrupted
|
||||
// before waitFor returns, continue waiting
|
||||
//
|
||||
compiling = true;
|
||||
while (compiling) {
|
||||
try {
|
||||
result = process.waitFor();
|
||||
//System.out.println("result is " + result);
|
||||
compiling = false;
|
||||
} catch (InterruptedException ignored) { }
|
||||
}
|
||||
if (exception != null) {
|
||||
exception.hideStackTrace = true;
|
||||
throw exception;
|
||||
}
|
||||
if(result != 0){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
String msg = e.getMessage();
|
||||
if ((msg != null) && (msg.indexOf("avr-gcc: not found") != -1)) {
|
||||
Base.showWarning("Compiler error",
|
||||
"Could not find the compiler.\n" +
|
||||
"avr-gcc is missing from your PATH,\n" +
|
||||
"see readme.txt for help.", null);
|
||||
return false;
|
||||
|
||||
} else if ((msg != null) && (msg.indexOf("avr-g++: not found") != -1)) {
|
||||
Base.showWarning("Compiler error",
|
||||
"Could not find the compiler.\n" +
|
||||
"avr-g++ is missing from your PATH,\n" +
|
||||
"see readme.txt for help.", null);
|
||||
return false;
|
||||
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// an error was queued up by message()
|
||||
if (exception != null) {
|
||||
throw exception;
|
||||
}
|
||||
|
||||
if (result != 0 && result != 1 ) {
|
||||
Base.openURL(BUGS_URL);
|
||||
throw new RunnerException(SUPER_BADNESS);
|
||||
}
|
||||
|
||||
// success would mean that 'result' is set to zero
|
||||
return (result == 0); // ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -440,5 +508,69 @@ public class Library implements MessageConsumer{
|
||||
exception = new RunnerException("Error building library \"" + getName() + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles loading of keywords file.
|
||||
* It is recommended that a # sign be used for comments
|
||||
* inside keywords.txt.
|
||||
*/
|
||||
public void addSyntaxColors(PdeKeywords keywords) {
|
||||
File keywordsFile = new File(libFolder.getPath() + File.separator + "keywords.txt");
|
||||
|
||||
// do not bother if no keywords file to read
|
||||
// should reprimand negligent library writers?!
|
||||
if(!keywordsFile.exists() || !keywordsFile.canRead()){
|
||||
return;
|
||||
}
|
||||
|
||||
try{
|
||||
// open file stream in the verbose java way
|
||||
InputStream input = new FileInputStream(keywordsFile);
|
||||
InputStreamReader isr = new InputStreamReader(input);
|
||||
BufferedReader reader = new BufferedReader(isr);
|
||||
|
||||
String line = null;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
|
||||
// skip empty and whitespace lines
|
||||
if (line.trim().length() == 0){
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip lines without tabs
|
||||
if (line.indexOf('\t') == -1){
|
||||
continue;
|
||||
}
|
||||
|
||||
String pieces[] = Base.split(line, '\t');
|
||||
|
||||
if (pieces.length >= 2) {
|
||||
String keyword = pieces[0].trim();
|
||||
String coloring = pieces[1].trim();
|
||||
|
||||
if (coloring.length() > 0) {
|
||||
// text will be KEYWORD or LITERAL
|
||||
boolean isKey = (coloring.charAt(0) == 'K');
|
||||
|
||||
// KEYWORD1 -> 0, KEYWORD2 -> 1, etc
|
||||
int num = coloring.charAt(coloring.length() - 1) - '1';
|
||||
|
||||
byte id = (byte)((isKey ? Token.KEYWORD1 : Token.LITERAL1) + num);
|
||||
|
||||
//System.out.println("got " + (isKey ? "keyword" : "literal") + (num+1) + " for " + keyword);
|
||||
|
||||
PdeKeywords.getKeywordColoring().add(keyword, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// close file stream
|
||||
reader.close();
|
||||
} catch (Exception e) {
|
||||
Base.showError("Problem Loading Keywords",
|
||||
"Could not load or interpret 'keywords.txt' in " + getName() + " library.\n" +
|
||||
"This must be corrected before distributing.", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user