2021-10-01 01:17:12 -05:00
|
|
|
package noppes.npcs.client.gui.util;
|
|
|
|
|
|
2023-07-30 01:26:36 -05:00
|
|
|
import noppes.npcs.client.ClientProxy;
|
2023-01-12 21:33:06 -05:00
|
|
|
|
2021-10-01 01:17:12 -05:00
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.regex.Matcher;
|
|
|
|
|
import java.util.regex.Pattern;
|
|
|
|
|
|
|
|
|
|
public class TextContainer {
|
2023-07-30 01:26:36 -05:00
|
|
|
private final static char colorChar = '\u00A7';
|
|
|
|
|
|
|
|
|
|
//public final Pattern regexString = Pattern.compile("\"(?:[^\"\\\\]|\\\\.)*?(\"|$)|'(?:[^'\\\\]|\\\\.)*?('|$)");
|
|
|
|
|
//public final Pattern regexString = Pattern.compile("\"(.*?(?<![\\\\])(\\s)*?)*?\"");
|
|
|
|
|
public final Pattern regexString = Pattern.compile("([\"'])(?:(?=(\\\\?))\\2.)*?\\1", Pattern.MULTILINE);
|
2021-10-01 01:17:12 -05:00
|
|
|
public final Pattern regexFunction = Pattern.compile("\\b(if|else|switch|with|for|while|in|var|const|let|throw|then|function|continue|break|foreach|return|try|catch|finally|do|this|typeof|instanceof|new)(?=[^\\w])");
|
2023-07-30 01:48:19 -05:00
|
|
|
public final Pattern regexType = Pattern.compile("\\b(Array|Date|eval|hasOwnProperty|Infinity|isFinite|isNaN|isPrototypeOf|Math|NaN|Number|Object|prototype|String|toString|undefined|valueOf|parseInt|parseFloat|print)(?=[^\\w])");
|
2021-10-01 01:17:12 -05:00
|
|
|
public final Pattern regexWord = Pattern.compile("[\\p{L}-]+|\\n|$");
|
|
|
|
|
public final Pattern regexNumber = Pattern.compile("\\b-?(?:0[xX][\\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+|\\d*\\.?\\d+(?:[Ee][+-]?\\d+)?(?:[fFbBdDlLsS])?|NaN|null|Infinity|unidentified|true|false)\\b");
|
|
|
|
|
public final Pattern regexComment = Pattern.compile("\\/\\*[\\s\\S]*?(?:\\*\\/|$)|\\/\\/.*|#.*");
|
2023-07-30 01:26:36 -05:00
|
|
|
|
2021-10-01 01:17:12 -05:00
|
|
|
public String text;
|
2023-07-30 01:26:36 -05:00
|
|
|
|
|
|
|
|
public List<MarkUp> makeup = new ArrayList<MarkUp>();
|
|
|
|
|
public List<LineData> lines = new ArrayList<LineData>();
|
|
|
|
|
|
2021-10-01 01:17:12 -05:00
|
|
|
public int lineHeight;
|
|
|
|
|
public int totalHeight;
|
|
|
|
|
public int visibleLines = 1;
|
|
|
|
|
public int linesCount;
|
|
|
|
|
|
2023-07-30 01:26:36 -05:00
|
|
|
|
|
|
|
|
public TextContainer(String text){
|
2021-10-01 01:17:12 -05:00
|
|
|
this.text = text;
|
|
|
|
|
text.replaceAll("\\r?\\n|\\r", "\n");
|
2023-07-30 01:26:36 -05:00
|
|
|
double l = 1d;
|
2021-10-01 01:17:12 -05:00
|
|
|
}
|
|
|
|
|
|
2023-07-30 01:26:36 -05:00
|
|
|
public void init(int width, int height){
|
|
|
|
|
lineHeight = ClientProxy.Font.height();
|
|
|
|
|
if(lineHeight == 0)
|
|
|
|
|
lineHeight = 12;
|
|
|
|
|
String[] split = text.split("\n");
|
2021-10-01 01:17:12 -05:00
|
|
|
|
|
|
|
|
int totalChars = 0;
|
2023-07-30 01:26:36 -05:00
|
|
|
for(String l : split){
|
2021-10-01 01:17:12 -05:00
|
|
|
StringBuilder line = new StringBuilder();
|
2023-07-30 01:26:36 -05:00
|
|
|
Matcher m = regexWord.matcher(l);
|
|
|
|
|
int i = 0;
|
|
|
|
|
while(m.find()){
|
2021-10-01 01:17:12 -05:00
|
|
|
String word = l.substring(i, m.start());
|
2023-07-30 01:26:36 -05:00
|
|
|
if(ClientProxy.Font.width(line + word) > width - 10){
|
|
|
|
|
lines.add(new LineData(line.toString(), totalChars, totalChars + line.length()));
|
2021-10-01 01:17:12 -05:00
|
|
|
totalChars += line.length();
|
|
|
|
|
line = new StringBuilder();
|
|
|
|
|
}
|
|
|
|
|
line.append(word);
|
2023-07-30 01:26:36 -05:00
|
|
|
i = m.start();
|
2021-10-01 01:17:12 -05:00
|
|
|
}
|
2023-07-30 01:26:36 -05:00
|
|
|
lines.add(new LineData(line.toString(), totalChars, totalChars + line.length() + 1));
|
2021-10-01 01:17:12 -05:00
|
|
|
|
|
|
|
|
totalChars += line.length() + 1;
|
|
|
|
|
}
|
2023-07-30 01:26:36 -05:00
|
|
|
linesCount = lines.size();
|
|
|
|
|
totalHeight = linesCount * lineHeight;
|
|
|
|
|
visibleLines = Math.max(height / lineHeight, 1);
|
2021-10-01 01:17:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void formatCodeText() {
|
2023-07-30 01:26:36 -05:00
|
|
|
MarkUp markup = null;
|
|
|
|
|
int start = 0;
|
|
|
|
|
while((markup = getNextMatching(start)) != null) {
|
|
|
|
|
makeup.add(markup);
|
|
|
|
|
start = markup.end;
|
2021-10-01 01:17:12 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-30 01:26:36 -05:00
|
|
|
private MarkUp getNextMatching(int start) {
|
|
|
|
|
MarkUp markup = null;
|
|
|
|
|
String s = text.substring(start);
|
|
|
|
|
Matcher matcher = regexNumber.matcher(s);
|
2021-10-01 01:17:12 -05:00
|
|
|
if(matcher.find()) {
|
2023-07-30 01:26:36 -05:00
|
|
|
markup = new MarkUp(matcher.start(), matcher.end(), '6', 0);
|
2021-10-01 01:17:12 -05:00
|
|
|
}
|
2023-07-30 01:26:36 -05:00
|
|
|
matcher = regexFunction.matcher(s);
|
|
|
|
|
if(matcher.find()){
|
|
|
|
|
MarkUp markup2 = new MarkUp(matcher.start(), matcher.end(), '2', 0);
|
|
|
|
|
if(compareMarkUps(markup, markup2)) {
|
2021-10-01 01:17:12 -05:00
|
|
|
markup = markup2;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-07-30 01:42:34 -05:00
|
|
|
matcher = regexType.matcher(s);
|
|
|
|
|
if(matcher.find()){
|
|
|
|
|
MarkUp markup2 = new MarkUp(matcher.start(), matcher.end(), '3', 0);
|
|
|
|
|
if(compareMarkUps(markup, markup2)) {
|
|
|
|
|
markup = markup2;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-07-30 01:26:36 -05:00
|
|
|
matcher = regexString.matcher(s);
|
|
|
|
|
if(matcher.find()){
|
|
|
|
|
MarkUp markup2 = new MarkUp(matcher.start(), matcher.end(), '4', 7);
|
|
|
|
|
if(compareMarkUps(markup, markup2)) {
|
2021-10-01 01:17:12 -05:00
|
|
|
markup = markup2;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-07-30 01:26:36 -05:00
|
|
|
matcher = regexComment.matcher(s);
|
|
|
|
|
if(matcher.find()){
|
|
|
|
|
MarkUp markup2 = new MarkUp(matcher.start(), matcher.end(), '8', 7);
|
|
|
|
|
if(compareMarkUps(markup, markup2)) {
|
2021-10-01 01:17:12 -05:00
|
|
|
markup = markup2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(markup != null) {
|
|
|
|
|
markup.start += start;
|
|
|
|
|
markup.end += start;
|
|
|
|
|
}
|
|
|
|
|
return markup;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-30 01:26:36 -05:00
|
|
|
public boolean compareMarkUps(MarkUp mu1, MarkUp mu2) {
|
|
|
|
|
if(mu1 == null)
|
|
|
|
|
return true;
|
|
|
|
|
return mu1.start > mu2.start;
|
2021-10-01 01:17:12 -05:00
|
|
|
}
|
|
|
|
|
|
2023-07-30 01:26:36 -05:00
|
|
|
public void addMakeUp(int start, int end, char c, int level){
|
|
|
|
|
if(!removeConflictingMarkUp(start, end, level))
|
|
|
|
|
return;
|
|
|
|
|
makeup.add(new MarkUp(start, end, c, level));
|
2021-10-01 01:17:12 -05:00
|
|
|
}
|
|
|
|
|
|
2023-07-30 01:26:36 -05:00
|
|
|
private boolean removeConflictingMarkUp(int start, int end, int level){
|
|
|
|
|
List<MarkUp> conflicting = new ArrayList<MarkUp>();
|
|
|
|
|
for(MarkUp m : makeup){
|
|
|
|
|
if(start >= m.start && start <= m.end || end >= m.start && end <= m.end || start < m.start && end > m.start){
|
|
|
|
|
if(level < m.level || level == m.level && m.start <= start)
|
|
|
|
|
return false;
|
|
|
|
|
conflicting.add(m);
|
2021-10-01 01:17:12 -05:00
|
|
|
}
|
|
|
|
|
}
|
2023-07-30 01:26:36 -05:00
|
|
|
makeup.removeAll(conflicting);
|
|
|
|
|
return true;
|
2021-10-01 01:17:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class LineData {
|
|
|
|
|
public String text;
|
2023-07-30 01:26:36 -05:00
|
|
|
public int start, end;
|
2021-10-01 01:17:12 -05:00
|
|
|
|
2023-07-30 01:26:36 -05:00
|
|
|
public LineData(String text, int start, int end){
|
2021-10-01 01:17:12 -05:00
|
|
|
this.text = text;
|
|
|
|
|
this.start = start;
|
|
|
|
|
this.end = end;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-30 01:26:36 -05:00
|
|
|
public void drawString(int x, int y, int color) {
|
|
|
|
|
ClientProxy.Font.drawString(this.getFormattedString(), x, y, color);
|
|
|
|
|
}
|
2021-10-01 01:17:12 -05:00
|
|
|
|
2023-07-30 01:26:36 -05:00
|
|
|
public String getFormattedString(){
|
|
|
|
|
StringBuilder builder = new StringBuilder(text);
|
|
|
|
|
int found = 0;
|
|
|
|
|
for(MarkUp entry : makeup){
|
|
|
|
|
if(entry.start >= start && entry.start < end){
|
|
|
|
|
builder.insert(entry.start - start + found * 2, Character.toString(colorChar) + Character.toString(entry.c));
|
|
|
|
|
found++;
|
2021-10-01 01:17:12 -05:00
|
|
|
}
|
2023-07-30 01:26:36 -05:00
|
|
|
if(entry.start < start && entry.end > start){
|
|
|
|
|
builder.insert(0, Character.toString(colorChar) + Character.toString(entry.c));
|
|
|
|
|
found++;
|
2021-10-01 01:17:12 -05:00
|
|
|
}
|
2023-07-30 01:26:36 -05:00
|
|
|
if(entry.end >= start && entry.end < end){
|
|
|
|
|
builder.insert(entry.end - start + found * 2, Character.toString(colorChar) + Character.toString('r'));
|
|
|
|
|
found++;
|
2021-10-01 01:17:12 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return builder.toString();
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-07-30 01:26:36 -05:00
|
|
|
|
|
|
|
|
class MarkUp {
|
|
|
|
|
public int start, end, level;
|
|
|
|
|
public char c;
|
|
|
|
|
|
|
|
|
|
public MarkUp(int start, int end, char c, int level){
|
|
|
|
|
this.start = start;
|
|
|
|
|
this.end = end;
|
|
|
|
|
this.c = c;
|
|
|
|
|
this.level = level;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-10-01 01:17:12 -05:00
|
|
|
}
|