kopia lustrzana https://github.com/maccasoft/z80-tools
2831 wiersze
93 KiB
Java
2831 wiersze
93 KiB
Java
/*
|
|
* Copyright (c) 2018-19 Marco Maccaferri and others.
|
|
* All rights reserved.
|
|
*
|
|
* This program and the accompanying materials are made available under
|
|
* the terms of the Eclipse Public License v1.0 which accompanies this
|
|
* distribution, and is available at
|
|
* http://www.eclipse.org/legal/epl-v10.html
|
|
*/
|
|
|
|
package com.maccasoft.tools;
|
|
|
|
import java.beans.PropertyChangeEvent;
|
|
import java.beans.PropertyChangeListener;
|
|
import java.io.BufferedReader;
|
|
import java.io.File;
|
|
import java.io.FileOutputStream;
|
|
import java.io.FileReader;
|
|
import java.io.IOException;
|
|
import java.io.LineNumberReader;
|
|
import java.io.OutputStream;
|
|
import java.io.OutputStreamWriter;
|
|
import java.io.PrintStream;
|
|
import java.io.Reader;
|
|
import java.io.StringReader;
|
|
import java.io.Writer;
|
|
import java.text.SimpleDateFormat;
|
|
import java.util.ArrayList;
|
|
import java.util.Date;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.concurrent.atomic.AtomicReference;
|
|
|
|
import org.eclipse.core.databinding.observable.Realm;
|
|
import org.eclipse.core.databinding.observable.value.IValueChangeListener;
|
|
import org.eclipse.core.databinding.observable.value.ValueChangeEvent;
|
|
import org.eclipse.core.databinding.observable.value.WritableValue;
|
|
import org.eclipse.core.runtime.IProgressMonitor;
|
|
import org.eclipse.jface.databinding.swt.DisplayRealm;
|
|
import org.eclipse.jface.dialogs.IDialogConstants;
|
|
import org.eclipse.jface.dialogs.MessageDialog;
|
|
import org.eclipse.jface.viewers.IOpenListener;
|
|
import org.eclipse.jface.viewers.ISelectionChangedListener;
|
|
import org.eclipse.jface.viewers.IStructuredSelection;
|
|
import org.eclipse.jface.viewers.OpenEvent;
|
|
import org.eclipse.jface.viewers.SelectionChangedEvent;
|
|
import org.eclipse.swt.SWT;
|
|
import org.eclipse.swt.custom.CTabFolder;
|
|
import org.eclipse.swt.custom.CTabFolder2Adapter;
|
|
import org.eclipse.swt.custom.CTabFolderEvent;
|
|
import org.eclipse.swt.custom.CTabItem;
|
|
import org.eclipse.swt.custom.CaretEvent;
|
|
import org.eclipse.swt.custom.CaretListener;
|
|
import org.eclipse.swt.custom.SashForm;
|
|
import org.eclipse.swt.custom.StackLayout;
|
|
import org.eclipse.swt.custom.StyledText;
|
|
import org.eclipse.swt.dnd.Clipboard;
|
|
import org.eclipse.swt.dnd.TextTransfer;
|
|
import org.eclipse.swt.dnd.Transfer;
|
|
import org.eclipse.swt.events.DisposeEvent;
|
|
import org.eclipse.swt.events.DisposeListener;
|
|
import org.eclipse.swt.events.MenuEvent;
|
|
import org.eclipse.swt.events.MenuListener;
|
|
import org.eclipse.swt.events.MouseAdapter;
|
|
import org.eclipse.swt.events.MouseEvent;
|
|
import org.eclipse.swt.events.SelectionAdapter;
|
|
import org.eclipse.swt.events.SelectionEvent;
|
|
import org.eclipse.swt.events.TraverseEvent;
|
|
import org.eclipse.swt.events.TraverseListener;
|
|
import org.eclipse.swt.graphics.FontMetrics;
|
|
import org.eclipse.swt.graphics.GC;
|
|
import org.eclipse.swt.graphics.Image;
|
|
import org.eclipse.swt.graphics.Point;
|
|
import org.eclipse.swt.graphics.Rectangle;
|
|
import org.eclipse.swt.layout.GridData;
|
|
import org.eclipse.swt.layout.GridLayout;
|
|
import org.eclipse.swt.widgets.Composite;
|
|
import org.eclipse.swt.widgets.Control;
|
|
import org.eclipse.swt.widgets.Display;
|
|
import org.eclipse.swt.widgets.Event;
|
|
import org.eclipse.swt.widgets.FileDialog;
|
|
import org.eclipse.swt.widgets.Label;
|
|
import org.eclipse.swt.widgets.Listener;
|
|
import org.eclipse.swt.widgets.Menu;
|
|
import org.eclipse.swt.widgets.MenuItem;
|
|
import org.eclipse.swt.widgets.Shell;
|
|
import org.eclipse.swt.widgets.ToolBar;
|
|
import org.eclipse.swt.widgets.ToolItem;
|
|
|
|
import com.maccasoft.tools.SourceMap.LineEntry;
|
|
import com.maccasoft.tools.editor.Z80TokenMarker;
|
|
import com.maccasoft.tools.internal.BusyIndicator;
|
|
import com.maccasoft.tools.internal.ImageRegistry;
|
|
|
|
import jssc.SerialPort;
|
|
import nl.grauw.glass.AssemblyException;
|
|
import nl.grauw.glass.Line;
|
|
import nl.grauw.glass.Source;
|
|
import nl.grauw.glass.SourceBuilder;
|
|
import nl.grauw.glass.directives.Directive;
|
|
import nl.grauw.glass.directives.Include;
|
|
|
|
public class Application {
|
|
|
|
public static final String APP_TITLE = "Z80 Tools";
|
|
public static final String APP_VERSION = "1.2.0";
|
|
|
|
Display display;
|
|
Shell shell;
|
|
|
|
Composite stack;
|
|
StackLayout stackLayout;
|
|
|
|
SashForm sashForm1;
|
|
FileBrowser browser;
|
|
SashForm sashForm2;
|
|
CTabFolder tabFolder;
|
|
Console console;
|
|
|
|
Memory memory;
|
|
SourceViewer viewer;
|
|
Registers registers;
|
|
Label consolePlaceHolder;
|
|
|
|
StatusLine statusLine;
|
|
|
|
SerialTerminal terminal;
|
|
DebugTerminal debugTerminal;
|
|
Emulator emulator;
|
|
|
|
DebugTMS9918 debugTMS9918;
|
|
|
|
Debugger debugger;
|
|
Thread debuggerThread;
|
|
|
|
Preferences preferences;
|
|
|
|
WritableValue tabFolderSelection;
|
|
|
|
final CaretListener caretListener = new CaretListener() {
|
|
|
|
@Override
|
|
public void caretMoved(CaretEvent event) {
|
|
StyledText text = (StyledText) event.widget;
|
|
int offset = text.getCaretOffset();
|
|
int y = text.getLineAtOffset(offset);
|
|
int x = offset - text.getOffsetAtLine(y);
|
|
statusLine.setCaretPosition(String.format("%d : %d ", y + 1, x + 1));
|
|
}
|
|
};
|
|
|
|
final PropertyChangeListener preferencesChangeListner = new PropertyChangeListener() {
|
|
|
|
@Override
|
|
public void propertyChange(PropertyChangeEvent evt) {
|
|
if (Preferences.PROP_ROOTS.equals(evt.getPropertyName())) {
|
|
String[] roots = preferences.getRoots();
|
|
if (roots == null || roots.length == 0) {
|
|
roots = new String[] {
|
|
new File(System.getProperty("user.home")).getAbsolutePath()
|
|
};
|
|
}
|
|
browser.setRoots(roots);
|
|
}
|
|
else if (Preferences.PROP_EDITOR_FONT.equals(evt.getPropertyName())) {
|
|
CTabItem[] tabItem = tabFolder.getItems();
|
|
for (int i = 0; i < tabItem.length; i++) {
|
|
SourceEditorTab tab = (SourceEditorTab) tabItem[i].getData();
|
|
tab.getEditor().setFont((String) evt.getNewValue());
|
|
}
|
|
}
|
|
else if (Preferences.PROP_SHOW_LINE_NUMBERS.equals(evt.getPropertyName())) {
|
|
CTabItem[] tabItem = tabFolder.getItems();
|
|
for (int i = 0; i < tabItem.length; i++) {
|
|
SourceEditorTab tab = (SourceEditorTab) tabItem[i].getData();
|
|
tab.getEditor().setShowLineNumbers(((Boolean) evt.getNewValue()).booleanValue());
|
|
}
|
|
}
|
|
else if (Preferences.PROP_TABWIDTH.equals(evt.getPropertyName())) {
|
|
CTabItem[] tabItem = tabFolder.getItems();
|
|
for (int i = 0; i < tabItem.length; i++) {
|
|
SourceEditorTab tab = (SourceEditorTab) tabItem[i].getData();
|
|
tab.getEditor().setTabWidth(((Integer) evt.getNewValue()).intValue());
|
|
}
|
|
}
|
|
else if (Preferences.PROP_USE_TABSTOPS.equals(evt.getPropertyName())) {
|
|
CTabItem[] tabItem = tabFolder.getItems();
|
|
for (int i = 0; i < tabItem.length; i++) {
|
|
SourceEditorTab tab = (SourceEditorTab) tabItem[i].getData();
|
|
tab.getEditor().setUseTabstops(((Boolean) evt.getNewValue()).booleanValue());
|
|
}
|
|
}
|
|
else if (Preferences.PROP_MNEMONIC_COLUMN.equals(evt.getPropertyName()) || Preferences.PROP_ARGUMENT_COLUMN.equals(evt.getPropertyName())
|
|
|| Preferences.PROP_COMMENT_COLUMN.equals(evt.getPropertyName())) {
|
|
CTabItem[] tabItem = tabFolder.getItems();
|
|
for (int i = 0; i < tabItem.length; i++) {
|
|
SourceEditorTab tab = (SourceEditorTab) tabItem[i].getData();
|
|
tab.getEditor().setTabStops(new int[] {
|
|
preferences.getMnemonicColumn(),
|
|
preferences.getArgumentColumn(),
|
|
preferences.getCommentColumn()
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
public Application() {
|
|
|
|
}
|
|
|
|
public void open() {
|
|
display = Display.getDefault();
|
|
preferences = Preferences.getInstance();
|
|
|
|
shell = new Shell(display);
|
|
shell.setText(APP_TITLE);
|
|
|
|
Image[] images = new Image[] {
|
|
ImageRegistry.getImageFromResources("app128.png"),
|
|
ImageRegistry.getImageFromResources("app64.png"),
|
|
ImageRegistry.getImageFromResources("app48.png"),
|
|
ImageRegistry.getImageFromResources("app32.png"),
|
|
ImageRegistry.getImageFromResources("app16.png"),
|
|
};
|
|
shell.setImages(images);
|
|
|
|
Menu menu = new Menu(shell, SWT.BAR);
|
|
createFileMenu(menu);
|
|
createEditMenu(menu);
|
|
createToolsMenu(menu);
|
|
createHelpMenu(menu);
|
|
shell.setMenuBar(menu);
|
|
|
|
GridLayout layout = new GridLayout(1, false);
|
|
layout.marginWidth = layout.marginHeight = 5;
|
|
shell.setLayout(layout);
|
|
|
|
Control control = createToolbar(shell);
|
|
control.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
|
|
|
|
control = createContents(shell);
|
|
control.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
|
|
|
statusLine = new StatusLine(shell);
|
|
statusLine.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
|
|
|
|
Rectangle screen = display.getClientArea();
|
|
|
|
Rectangle rect = new Rectangle(0, 0, (int) ((float) screen.width / (float) screen.height * 800), 900);
|
|
rect.x = (screen.width - rect.width) / 2;
|
|
rect.y = (screen.height - rect.height) / 2;
|
|
if (rect.y < 0) {
|
|
rect.height += rect.y * 2;
|
|
rect.y = 0;
|
|
}
|
|
|
|
shell.setLocation(rect.x, rect.y);
|
|
shell.setSize(rect.width, rect.height);
|
|
if (rect.width > screen.width || rect.height > screen.height) {
|
|
shell.setMaximized(true);
|
|
}
|
|
|
|
shell.open();
|
|
|
|
preferences.addPropertyChangeListener(preferencesChangeListner);
|
|
|
|
shell.addListener(SWT.Close, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event event) {
|
|
event.doit = handleUnsavedContent();
|
|
}
|
|
});
|
|
shell.addDisposeListener(new DisposeListener() {
|
|
|
|
@Override
|
|
public void widgetDisposed(DisposeEvent e) {
|
|
if (debugger != null) {
|
|
debugger.doStop();
|
|
}
|
|
if (terminal != null) {
|
|
terminal.dispose();
|
|
terminal = null;
|
|
}
|
|
if (debugTerminal != null) {
|
|
debugTerminal.dispose();
|
|
debugTerminal = null;
|
|
}
|
|
if (debugTMS9918 != null) {
|
|
debugTMS9918.dispose();
|
|
debugTMS9918 = null;
|
|
}
|
|
try {
|
|
preferences.removePropertyChangeListener(preferencesChangeListner);
|
|
|
|
List<String> openTabs = new ArrayList<String>();
|
|
for (int i = 0; i < tabFolder.getItemCount(); i++) {
|
|
SourceEditorTab tab = (SourceEditorTab) tabFolder.getItem(i).getData();
|
|
if (tab.getFile() != null) {
|
|
openTabs.add(tab.getFile().getAbsolutePath());
|
|
}
|
|
}
|
|
preferences.setOpenTabs(openTabs.toArray(new String[openTabs.size()]));
|
|
|
|
if (tabFolder.getSelection() != null) {
|
|
SourceEditorTab tab = (SourceEditorTab) tabFolder.getSelection().getData();
|
|
preferences.setSelectedTab(tab.getFile().getAbsolutePath());
|
|
}
|
|
|
|
preferences.save();
|
|
} catch (IOException e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
ImageRegistry.dispose();
|
|
}
|
|
});
|
|
|
|
BusyIndicator.showWhile(display, new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
String line;
|
|
|
|
final String[] openTabs = preferences.getOpenTabs();
|
|
if (openTabs == null || openTabs.length == 0 || !preferences.isReloadOpenTabs()) {
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < openTabs.length; i++) {
|
|
File file = new File(openTabs[i]);
|
|
StringBuilder sb = new StringBuilder();
|
|
try {
|
|
if (!file.exists() || file.isDirectory()) {
|
|
continue;
|
|
}
|
|
|
|
BufferedReader reader = new BufferedReader(new FileReader(file));
|
|
while ((line = reader.readLine()) != null) {
|
|
sb.append(line);
|
|
sb.append("\n");
|
|
}
|
|
reader.close();
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
display.asyncExec(new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
SourceEditorTab tab = new SourceEditorTab(tabFolder, sb.toString());
|
|
tab.setText(file.getName());
|
|
tab.setToolTipText(file.getAbsolutePath());
|
|
tab.setFile(file);
|
|
applyEditoTabPreferences(tab);
|
|
}
|
|
});
|
|
}
|
|
|
|
display.asyncExec(new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
if (tabFolder.getItemCount() == 0) {
|
|
return;
|
|
}
|
|
|
|
SourceEditorTab tab = (SourceEditorTab) tabFolder.getItem(0).getData();
|
|
|
|
String s = preferences.getSelectedTab();
|
|
if (s != null) {
|
|
File selectedFile = new File(s);
|
|
for (int i = 0; i < tabFolder.getItemCount(); i++) {
|
|
SourceEditorTab editorTab = (SourceEditorTab) tabFolder.getItem(i).getData();
|
|
if (selectedFile.equals(editorTab.getFile())) {
|
|
tab = editorTab;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
tabFolder.setSelection(tab.getTabItem());
|
|
tab.setFocus();
|
|
}
|
|
});
|
|
}
|
|
}, true);
|
|
}
|
|
|
|
void createFileMenu(Menu parent) {
|
|
final Menu menu = new Menu(parent.getParent(), SWT.DROP_DOWN);
|
|
|
|
MenuItem item = new MenuItem(parent, SWT.CASCADE);
|
|
item.setText("&File");
|
|
item.setMenu(menu);
|
|
|
|
item = new MenuItem(menu, SWT.CASCADE);
|
|
item.setText("New\tCtrl+N");
|
|
item.setAccelerator(SWT.MOD1 + 'N');
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleFileNew();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Open...\tCtrl+O");
|
|
item.setAccelerator(SWT.MOD1 + 'O');
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleFileOpen();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
new MenuItem(menu, SWT.SEPARATOR);
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Close");
|
|
item.setAccelerator(SWT.MOD1 + 'O');
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleFileClose();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Close All");
|
|
item.setAccelerator(SWT.MOD1 + 'O');
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleFileCloseAll();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
new MenuItem(menu, SWT.SEPARATOR);
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Save\tCtrl+S");
|
|
item.setAccelerator(SWT.MOD1 + 'S');
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleFileSave();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Save As...");
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleFileSaveAs();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Save All\tCtrl+Shift+S");
|
|
item.setAccelerator(SWT.MOD1 + SWT.MOD2 + 'S');
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleFileSaveAll();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
item = getSystemMenuItem(SWT.ID_PREFERENCES);
|
|
if (item == null) {
|
|
new MenuItem(menu, SWT.SEPARATOR);
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Preferences");
|
|
}
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
PreferencesDialog dlg = new PreferencesDialog(shell);
|
|
dlg.open();
|
|
}
|
|
});
|
|
|
|
new MenuItem(menu, SWT.SEPARATOR);
|
|
|
|
final int lruItemIndex = menu.getItemCount();
|
|
menu.addMenuListener(new MenuListener() {
|
|
|
|
MenuItem[] lruItems;
|
|
|
|
@Override
|
|
public void menuShown(MenuEvent e) {
|
|
if (lruItems != null) {
|
|
for (int i = 0; i < lruItems.length; i++) {
|
|
lruItems[i].dispose();
|
|
}
|
|
}
|
|
lruItems = populateLruFiles(menu, lruItemIndex);
|
|
}
|
|
|
|
@Override
|
|
public void menuHidden(MenuEvent e) {
|
|
|
|
}
|
|
});
|
|
|
|
item = getSystemMenuItem(SWT.ID_QUIT);
|
|
if (item == null) {
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Exit");
|
|
}
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
shell.dispose();
|
|
}
|
|
});
|
|
}
|
|
|
|
MenuItem[] populateLruFiles(Menu menu, int itemIndex) {
|
|
int index = 0;
|
|
List<MenuItem> list = new ArrayList<MenuItem>();
|
|
|
|
Iterator<String> iter = preferences.getLru().iterator();
|
|
while (iter.hasNext() && index < 4) {
|
|
final File fileToOpen = new File(iter.next());
|
|
MenuItem item = new MenuItem(menu, SWT.PUSH, itemIndex++);
|
|
item.setText(String.format("%d %s", index + 1, fileToOpen.getName()));
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
if (!fileToOpen.exists()) {
|
|
preferences.removeLru(fileToOpen);
|
|
return;
|
|
}
|
|
openSourceTab(fileToOpen);
|
|
preferences.addLru(fileToOpen);
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
list.add(item);
|
|
index++;
|
|
}
|
|
|
|
if (index > 0) {
|
|
list.add(new MenuItem(menu, SWT.SEPARATOR, itemIndex));
|
|
}
|
|
|
|
return list.toArray(new MenuItem[list.size()]);
|
|
}
|
|
|
|
void createEditMenu(Menu parent) {
|
|
Menu menu = new Menu(parent.getParent(), SWT.DROP_DOWN);
|
|
|
|
MenuItem item = new MenuItem(parent, SWT.CASCADE);
|
|
item.setText("&Edit");
|
|
item.setMenu(menu);
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Undo\tCtrl+Z");
|
|
item.setAccelerator(SWT.MOD1 + 'Z');
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
CTabItem tabItem = tabFolder.getSelection();
|
|
if (tabItem == null) {
|
|
return;
|
|
}
|
|
((SourceEditorTab) tabItem.getData()).getEditor().undo();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Redo\tCtrl+Shift+Z");
|
|
item.setAccelerator(SWT.MOD1 + SWT.MOD2 + 'Z');
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
CTabItem tabItem = tabFolder.getSelection();
|
|
if (tabItem == null) {
|
|
return;
|
|
}
|
|
((SourceEditorTab) tabItem.getData()).getEditor().redo();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
new MenuItem(menu, SWT.SEPARATOR);
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Cut\tCtrl+X");
|
|
item.setAccelerator(SWT.MOD1 + 'X');
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
CTabItem tabItem = tabFolder.getSelection();
|
|
if (tabItem == null) {
|
|
return;
|
|
}
|
|
((SourceEditorTab) tabItem.getData()).getEditor().cut();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Copy\tCtrl+C");
|
|
item.setAccelerator(SWT.MOD1 + 'C');
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
CTabItem tabItem = tabFolder.getSelection();
|
|
if (tabItem == null) {
|
|
return;
|
|
}
|
|
((SourceEditorTab) tabItem.getData()).getEditor().copy();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Copy Packed CP/M Binary");
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleCompileAndCopyBinaryToClipboard();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Copy Intel HEX");
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleCompileAndCopyIntelHexToClipboard();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Paste\tCtrl+V");
|
|
item.setAccelerator(SWT.MOD1 + 'V');
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
CTabItem tabItem = tabFolder.getSelection();
|
|
if (tabItem == null) {
|
|
return;
|
|
}
|
|
((SourceEditorTab) tabItem.getData()).getEditor().paste();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
new MenuItem(menu, SWT.SEPARATOR);
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Select All\tCtrl+A");
|
|
item.setAccelerator(SWT.MOD1 + 'A');
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
CTabItem tabItem = tabFolder.getSelection();
|
|
if (tabItem == null) {
|
|
return;
|
|
}
|
|
((SourceEditorTab) tabItem.getData()).getEditor().selectAll();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
new MenuItem(menu, SWT.SEPARATOR);
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Next Source\tCtrl+Tab");
|
|
item.setAccelerator(SWT.MOD1 + SWT.TAB);
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleNextTab();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Previous Source\tCtrl+Shift+Tab");
|
|
item.setAccelerator(SWT.MOD1 + SWT.MOD2 + SWT.TAB);
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handlePreviousTab();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void createToolsMenu(Menu parent) {
|
|
Menu menu = new Menu(parent.getParent(), SWT.DROP_DOWN);
|
|
|
|
MenuItem item = new MenuItem(parent, SWT.CASCADE);
|
|
item.setText("&Tools");
|
|
item.setMenu(menu);
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Format source\tCtrl+Shift+F");
|
|
item.setAccelerator(SWT.MOD1 + +SWT.MOD2 + 'F');
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
CTabItem tabItem = tabFolder.getSelection();
|
|
if (tabItem == null) {
|
|
return;
|
|
}
|
|
SourceEditorTab tab = (SourceEditorTab) tabItem.getData();
|
|
|
|
StringReader reader = new StringReader(tab.getEditor().getText());
|
|
SourceBuilder builder = new SourceBuilder(new ArrayList<File>()) {
|
|
|
|
@Override
|
|
public Directive getDirective(Line line, LineNumberReader reader, File sourceFile) {
|
|
if (line.getMnemonic() != null) {
|
|
switch (line.getMnemonic()) {
|
|
case "include":
|
|
case "INCLUDE":
|
|
case ".include":
|
|
case ".INCLUDE":
|
|
return new Include();
|
|
}
|
|
}
|
|
return super.getDirective(line, reader, sourceFile);
|
|
}
|
|
|
|
};
|
|
|
|
SourceFormatter formatter = new SourceFormatter(builder.parse(reader, new File("")));
|
|
formatter.setMnemonicColumn(preferences.getMnemonicColumn());
|
|
formatter.setArgumentColumn(preferences.getArgumentColumn());
|
|
formatter.setCommentColumn(preferences.getCommentColumn());
|
|
formatter.setLabelCase(preferences.getLabelCase());
|
|
formatter.setMnemonicCase(preferences.getMnemonicCase());
|
|
formatter.setDirectivePrefix(preferences.getDirectivePrefix());
|
|
|
|
tab.getEditor().replaceText(formatter.format());
|
|
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
new MenuItem(menu, SWT.SEPARATOR);
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Verify / Compile\tCtrl+R");
|
|
item.setAccelerator(SWT.MOD1 + 'R');
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleCompile();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Upload Intel HEX");
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleCompileAndUploadIntelHex();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
new MenuItem(menu, SWT.SEPARATOR);
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Upload Packed CP/M binary");
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleCompileAndUploadBinary();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Upload XModem binary");
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleCompileAndUploadXModem();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
new MenuItem(menu, SWT.SEPARATOR);
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Emulator\tCtrl+Shift+E");
|
|
item.setAccelerator(SWT.MOD1 + SWT.MOD2 + 'E');
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleOpenEmulator();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Serial Terminal\tCtrl+Shift+T");
|
|
item.setAccelerator(SWT.MOD1 + SWT.MOD2 + 'T');
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleOpenTerminal();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void createDebugMenu(Menu parent, int index) {
|
|
Menu menu = new Menu(parent.getParent(), SWT.DROP_DOWN);
|
|
|
|
MenuItem menuItem = new MenuItem(parent, SWT.CASCADE, index);
|
|
menuItem.setText("&Debug");
|
|
menuItem.setMenu(menu);
|
|
|
|
MenuItem item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Run\tF5");
|
|
item.setAccelerator(SWT.F5);
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleRun();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Stop");
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleStop();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
new MenuItem(menu, SWT.SEPARATOR);
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Step into\tF8");
|
|
item.setAccelerator(SWT.F8);
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleStep();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Step over\tF7");
|
|
item.setAccelerator(SWT.F7);
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleStepOver();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Run to line");
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleRunToLine();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
new MenuItem(menu, SWT.SEPARATOR);
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Toggle breakpoint\tCtrl+Shift+B");
|
|
item.setAccelerator(SWT.MOD1 + SWT.MOD2 + 'B');
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleToggleBreakpoint();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Clear all breakpoints");
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleClearBreakpoints();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
new MenuItem(menu, SWT.SEPARATOR);
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Open terminal window");
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleOpenDebugTerminal();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Open TMS9918 window");
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleOpenTMS9918Window();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
new MenuItem(menu, SWT.SEPARATOR);
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("Reset\tF5");
|
|
item.setAccelerator(SWT.F5);
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
try {
|
|
handleReset();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void createHelpMenu(Menu parent) {
|
|
MenuItem item = getSystemMenuItem(SWT.ID_PREFERENCES);
|
|
if (item == null) {
|
|
Menu menu = new Menu(parent.getParent(), SWT.DROP_DOWN);
|
|
|
|
item = new MenuItem(parent, SWT.CASCADE);
|
|
item.setText("&Help");
|
|
item.setMenu(menu);
|
|
|
|
item = new MenuItem(menu, SWT.PUSH);
|
|
item.setText("About " + APP_TITLE);
|
|
}
|
|
item.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event e) {
|
|
AboutDialog dlg = new AboutDialog(shell);
|
|
dlg.open();
|
|
}
|
|
});
|
|
}
|
|
|
|
private MenuItem getSystemMenuItem(int id) {
|
|
Menu menu = display.getSystemMenu();
|
|
if (menu != null) {
|
|
for (MenuItem item : menu.getItems()) {
|
|
if (item.getID() == id) {
|
|
return item;
|
|
}
|
|
}
|
|
}
|
|
|
|
menu = display.getMenuBar();
|
|
if (menu != null) {
|
|
for (MenuItem item : menu.getItems()) {
|
|
if (item.getID() == id) {
|
|
return item;
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
ToolBar createToolbar(Composite parent) {
|
|
ToolBar toolBar = new ToolBar(parent, SWT.FLAT);
|
|
|
|
ToolItem toolItem = new ToolItem(toolBar, SWT.PUSH);
|
|
toolItem.setImage(ImageRegistry.getImageFromResources("application_verify.png"));
|
|
toolItem.setToolTipText("Verify / Compile");
|
|
toolItem.addSelectionListener(new SelectionAdapter() {
|
|
|
|
@Override
|
|
public void widgetSelected(SelectionEvent e) {
|
|
try {
|
|
handleCompile();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
createUploadToolItem(toolBar);
|
|
|
|
new ToolItem(toolBar, SWT.SEPARATOR);
|
|
|
|
toolItem = new ToolItem(toolBar, SWT.PUSH);
|
|
toolItem.setImage(ImageRegistry.getImageFromResources("application_xp_terminal.png"));
|
|
toolItem.setToolTipText("Serial Terminal");
|
|
toolItem.addSelectionListener(new SelectionAdapter() {
|
|
|
|
@Override
|
|
public void widgetSelected(SelectionEvent e) {
|
|
try {
|
|
handleOpenTerminal();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
new ToolItem(toolBar, SWT.SEPARATOR);
|
|
|
|
toolItem = new ToolItem(toolBar, SWT.PUSH);
|
|
toolItem.setImage(ImageRegistry.getImageFromResources("application_add.png"));
|
|
toolItem.setToolTipText("New");
|
|
toolItem.addSelectionListener(new SelectionAdapter() {
|
|
|
|
@Override
|
|
public void widgetSelected(SelectionEvent e) {
|
|
try {
|
|
handleFileNew();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
toolItem = new ToolItem(toolBar, SWT.PUSH);
|
|
toolItem.setImage(ImageRegistry.getImageFromResources("application_get.png"));
|
|
toolItem.setToolTipText("Open");
|
|
toolItem.addSelectionListener(new SelectionAdapter() {
|
|
|
|
@Override
|
|
public void widgetSelected(SelectionEvent e) {
|
|
try {
|
|
handleFileOpen();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
toolItem = new ToolItem(toolBar, SWT.PUSH);
|
|
toolItem.setImage(ImageRegistry.getImageFromResources("application_put.png"));
|
|
toolItem.setToolTipText("Save");
|
|
toolItem.addSelectionListener(new SelectionAdapter() {
|
|
|
|
@Override
|
|
public void widgetSelected(SelectionEvent e) {
|
|
try {
|
|
handleFileSave();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
new ToolItem(toolBar, SWT.SEPARATOR);
|
|
|
|
toolItem = new ToolItem(toolBar, SWT.CHECK);
|
|
toolItem.setImage(ImageRegistry.getImageFromResources("bug.png"));
|
|
toolItem.setToolTipText("Debug");
|
|
toolItem.addSelectionListener(new SelectionAdapter() {
|
|
|
|
@Override
|
|
public void widgetSelected(SelectionEvent e) {
|
|
boolean selection = ((ToolItem) e.widget).getSelection();
|
|
try {
|
|
if (selection) {
|
|
handleCompileAndDebug();
|
|
}
|
|
else {
|
|
handleSwitchToEditor();
|
|
}
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
toolItem = new ToolItem(toolBar, SWT.PUSH);
|
|
toolItem.setImage(ImageRegistry.getImageFromResources("application_xp_terminal.png"));
|
|
toolItem.setToolTipText("Debug Terminal");
|
|
toolItem.addSelectionListener(new SelectionAdapter() {
|
|
|
|
@Override
|
|
public void widgetSelected(SelectionEvent e) {
|
|
try {
|
|
handleOpenDebugTerminal();
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
return toolBar;
|
|
}
|
|
|
|
void createUploadToolItem(ToolBar toolBar) {
|
|
final ToolItem toolItem = new ToolItem(toolBar, SWT.DROP_DOWN);
|
|
toolItem.setImage(ImageRegistry.getImageFromResources("application_go.png"));
|
|
|
|
final Menu menu = new Menu(shell, SWT.POP_UP);
|
|
|
|
MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
|
|
menuItem.setText("Upload Intel HEX");
|
|
menuItem.addSelectionListener(new SelectionAdapter() {
|
|
|
|
@Override
|
|
public void widgetSelected(SelectionEvent e) {
|
|
try {
|
|
if (((MenuItem) e.widget).getSelection()) {
|
|
toolItem.setToolTipText(((MenuItem) e.widget).getText());
|
|
preferences.setLastUploadType(menu.indexOf((MenuItem) e.widget));
|
|
handleCompileAndUploadIntelHex();
|
|
}
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
menuItem = new MenuItem(menu, SWT.RADIO);
|
|
menuItem.setText("Upload Packed CP/M binary");
|
|
menuItem.addSelectionListener(new SelectionAdapter() {
|
|
|
|
@Override
|
|
public void widgetSelected(SelectionEvent e) {
|
|
try {
|
|
if (((MenuItem) e.widget).getSelection()) {
|
|
toolItem.setToolTipText(((MenuItem) e.widget).getText());
|
|
preferences.setLastUploadType(menu.indexOf((MenuItem) e.widget));
|
|
handleCompileAndUploadBinary();
|
|
}
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
menuItem = new MenuItem(menu, SWT.RADIO);
|
|
menuItem.setText("Upload XModem binary");
|
|
menuItem.addSelectionListener(new SelectionAdapter() {
|
|
|
|
@Override
|
|
public void widgetSelected(SelectionEvent e) {
|
|
try {
|
|
if (((MenuItem) e.widget).getSelection()) {
|
|
toolItem.setToolTipText(((MenuItem) e.widget).getText());
|
|
preferences.setLastUploadType(menu.indexOf((MenuItem) e.widget));
|
|
handleCompileAndUploadXModem();
|
|
}
|
|
} catch (Exception e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
int selection = preferences.getLastUploadType();
|
|
if (selection < 0 || selection >= menu.getItemCount()) {
|
|
selection = 0;
|
|
}
|
|
menu.getItem(selection).setSelection(true);
|
|
|
|
toolItem.setToolTipText(menu.getItem(selection).getText());
|
|
|
|
toolItem.addListener(SWT.Selection, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event event) {
|
|
if (event.detail == SWT.ARROW) {
|
|
Rectangle rect = toolItem.getBounds();
|
|
Point pt = new Point(rect.x, rect.y + rect.height);
|
|
pt = toolBar.toDisplay(pt);
|
|
menu.setLocation(pt.x, pt.y);
|
|
menu.setVisible(true);
|
|
}
|
|
else {
|
|
MenuItem[] menuItem = menu.getItems();
|
|
for (int i = 0; i < menuItem.length; i++) {
|
|
if (menuItem[i].getSelection()) {
|
|
menuItem[i].notifyListeners(SWT.Selection, new Event());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
protected Control createContents(Composite parent) {
|
|
stack = new Composite(parent, SWT.NONE);
|
|
stackLayout = new StackLayout();
|
|
stackLayout.marginWidth = stackLayout.marginHeight = 0;
|
|
stack.setLayout(stackLayout);
|
|
|
|
createEditorContents(stack);
|
|
createDebuggerContents(stack);
|
|
|
|
stackLayout.topControl = stack.getChildren()[0];
|
|
|
|
return stack;
|
|
}
|
|
|
|
protected Control createEditorContents(Composite parent) {
|
|
GC gc = new GC(parent);
|
|
FontMetrics fontMetrics = gc.getFontMetrics();
|
|
gc.dispose();
|
|
|
|
sashForm1 = new SashForm(parent, SWT.HORIZONTAL);
|
|
sashForm1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
|
|
|
browser = new FileBrowser(sashForm1);
|
|
|
|
sashForm2 = new SashForm(sashForm1, SWT.VERTICAL);
|
|
sashForm2.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
|
|
|
tabFolder = new CTabFolder(sashForm2, SWT.BORDER) {
|
|
|
|
@Override
|
|
public void setSelection(int index) {
|
|
super.setSelection(index);
|
|
CTabItem tabItem = tabFolder.getSelection();
|
|
tabFolderSelection.setValue(tabItem != null ? tabItem.getData() : null);
|
|
}
|
|
|
|
};
|
|
tabFolder.setTabHeight((int) (fontMetrics.getHeight() * 1.5));
|
|
tabFolder.addCTabFolder2Listener(new CTabFolder2Adapter() {
|
|
|
|
@Override
|
|
public void close(CTabFolderEvent event) {
|
|
SourceEditorTab tab = (SourceEditorTab) event.item.getData();
|
|
event.doit = canCloseSourceTab(tab);
|
|
}
|
|
});
|
|
|
|
tabFolderSelection = new WritableValue();
|
|
tabFolderSelection.addValueChangeListener(new IValueChangeListener() {
|
|
|
|
@Override
|
|
public void handleValueChange(ValueChangeEvent event) {
|
|
SourceEditorTab tab = (SourceEditorTab) event.diff.getOldValue();
|
|
if (tab != null) {
|
|
tab.getEditor().removeCaretListener(caretListener);
|
|
}
|
|
tab = (SourceEditorTab) event.diff.getNewValue();
|
|
if (tab != null) {
|
|
StyledText text = tab.getEditor().getStyledText();
|
|
int offset = text.getCaretOffset();
|
|
int y = text.getLineAtOffset(offset);
|
|
int x = offset - text.getOffsetAtLine(y);
|
|
statusLine.setCaretPosition(String.format("%d : %d ", y + 1, x + 1));
|
|
tab.getEditor().addCaretListener(caretListener);
|
|
}
|
|
else {
|
|
statusLine.setCaretPosition("");
|
|
}
|
|
}
|
|
});
|
|
|
|
tabFolder.addTraverseListener(new TraverseListener() {
|
|
|
|
@Override
|
|
public void keyTraversed(TraverseEvent e) {
|
|
if (e.character == SWT.TAB) {
|
|
if ((e.stateMask & SWT.MODIFIER_MASK) == SWT.MOD1) {
|
|
handleNextTab();
|
|
e.doit = false;
|
|
}
|
|
else if ((e.stateMask & SWT.MODIFIER_MASK) == (SWT.MOD1 | SWT.MOD2)) {
|
|
handlePreviousTab();
|
|
e.doit = false;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
console = new Console(sashForm2);
|
|
console.getStyledText().addListener(SWT.MouseDown, new Listener() {
|
|
|
|
@Override
|
|
public void handleEvent(Event event) {
|
|
try {
|
|
StyledText control = (StyledText) event.widget;
|
|
int offset = control.getOffsetAtLocation(new Point(event.x, event.y));
|
|
String line = control.getLine(control.getLineAtOffset(offset));
|
|
if (line.toLowerCase().contains(" error : ")) {
|
|
int s = 0;
|
|
int e = line.indexOf(')');
|
|
if (e != -1) {
|
|
line = line.substring(s, e + 1);
|
|
|
|
s = 0;
|
|
e = line.indexOf('(');
|
|
String name = line.substring(s, e);
|
|
s = e + 1;
|
|
if ((e = line.indexOf(':', s)) == -1) {
|
|
e = line.indexOf(',', s);
|
|
}
|
|
int row = Integer.parseInt(line.substring(s, e)) - 1;
|
|
if (row < 0) {
|
|
row = 0;
|
|
}
|
|
s = e + 1;
|
|
e = line.indexOf(')', s);
|
|
int column = Integer.parseInt(line.substring(s, e)) - 1;
|
|
if (column < 0) {
|
|
column = 0;
|
|
}
|
|
switchToEditor(name, row, column);
|
|
}
|
|
}
|
|
else if (line.toLowerCase().contains(" error: ") || line.toLowerCase().contains(" warning: ")) {
|
|
int e = line.indexOf(':');
|
|
String name = line.substring(0, e);
|
|
int s = e + 1;
|
|
e = line.indexOf(':', s);
|
|
int row = Integer.parseInt(line.substring(s, e)) - 1;
|
|
s = e + 1;
|
|
int column = 0;
|
|
if (line.charAt(s) != ' ') {
|
|
e = line.indexOf(':', s);
|
|
column = Integer.parseInt(line.substring(s, e)) - 1;
|
|
}
|
|
switchToEditor(name, row, column);
|
|
}
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
void switchToEditor(String name, int line, int column) {
|
|
CTabItem[] tabItem = tabFolder.getItems();
|
|
for (int i = 0; i < tabItem.length; i++) {
|
|
SourceEditorTab tab = (SourceEditorTab) tabItem[i].getData();
|
|
if (name.equalsIgnoreCase(tab.getText())) {
|
|
tab.getEditor().gotToLineColumn(line, column);
|
|
tab.setFocus();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
sashForm1.setWeights(new int[] {
|
|
20, 80
|
|
});
|
|
sashForm2.setWeights(new int[] {
|
|
80, 20
|
|
});
|
|
|
|
String[] roots = preferences.getRoots();
|
|
if (roots == null || roots.length == 0) {
|
|
roots = new String[] {
|
|
new File(System.getProperty("user.home")).getAbsolutePath()
|
|
};
|
|
}
|
|
browser.setRoots(roots);
|
|
|
|
String lastPath = preferences.getLastPath();
|
|
if (lastPath == null) {
|
|
lastPath = new File("").getAbsolutePath();
|
|
}
|
|
File file = new File(lastPath).getAbsoluteFile();
|
|
if (!file.isDirectory()) {
|
|
file = file.getParentFile();
|
|
}
|
|
browser.setSelection(file);
|
|
browser.addSelectionChangedListener(new ISelectionChangedListener() {
|
|
|
|
@Override
|
|
public void selectionChanged(SelectionChangedEvent event) {
|
|
if (event.getSelection().isEmpty()) {
|
|
preferences.setLastPath(null);
|
|
return;
|
|
}
|
|
File file = (File) ((IStructuredSelection) event.getSelection()).getFirstElement();
|
|
if (!file.isDirectory()) {
|
|
file = file.getParentFile();
|
|
}
|
|
if (file != null) {
|
|
preferences.setLastPath(file.getAbsolutePath());
|
|
}
|
|
}
|
|
});
|
|
browser.addOpenListener(new IOpenListener() {
|
|
|
|
@Override
|
|
public void open(OpenEvent event) {
|
|
try {
|
|
IStructuredSelection selection = (IStructuredSelection) event.getSelection();
|
|
if (selection.getFirstElement() instanceof File) {
|
|
File file = (File) selection.getFirstElement();
|
|
if (file.isDirectory()) {
|
|
return;
|
|
}
|
|
openSourceTab(file);
|
|
preferences.addLru(file);
|
|
}
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
|
|
browser.setFocus();
|
|
|
|
return sashForm1;
|
|
}
|
|
|
|
protected Control createDebuggerContents(Composite parent) {
|
|
Composite container = new Composite(parent, SWT.NONE);
|
|
GridLayout gridLayout = new GridLayout(2, false);
|
|
gridLayout.marginWidth = gridLayout.marginHeight = 0;
|
|
container.setLayout(gridLayout);
|
|
|
|
memory = new Memory(container);
|
|
memory.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
|
|
|
|
SashForm sashForm = new SashForm(container, SWT.VERTICAL);
|
|
sashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
|
|
|
Composite composite = new Composite(sashForm, SWT.NONE);
|
|
gridLayout = new GridLayout(2, false);
|
|
gridLayout.marginWidth = gridLayout.marginHeight = 0;
|
|
composite.setLayout(gridLayout);
|
|
|
|
viewer = new SourceViewer(composite, new Z80TokenMarker());
|
|
viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
|
viewer.getStyledText().addMouseListener(new MouseAdapter() {
|
|
|
|
@Override
|
|
public void mouseDoubleClick(MouseEvent e) {
|
|
handleToggleBreakpoint();
|
|
}
|
|
});
|
|
|
|
registers = new Registers(composite);
|
|
registers.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
|
|
|
|
consolePlaceHolder = new Label(sashForm, SWT.NONE);
|
|
consolePlaceHolder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
|
|
|
|
sashForm.setWeights(new int[] {
|
|
80, 20
|
|
});
|
|
|
|
return container;
|
|
}
|
|
|
|
private void handleFileNew() {
|
|
SourceEditorTab tab = new SourceEditorTab(tabFolder, "");
|
|
tab.setText(getDefaultName());
|
|
applyEditoTabPreferences(tab);
|
|
tab.setFocus();
|
|
}
|
|
|
|
String getDefaultName() {
|
|
Date date = new Date();
|
|
SimpleDateFormat df = new SimpleDateFormat("MMMdd");
|
|
|
|
for (char c = 'a'; c <= 'z'; c++) {
|
|
String result = String.format("%s%c.asm", df.format(date), c);
|
|
File file = new File(result);
|
|
if (!file.exists() && !nameExists(result)) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
boolean nameExists(String name) {
|
|
CTabItem[] tabItem = tabFolder.getItems();
|
|
for (int n = 0; n < tabItem.length; n++) {
|
|
if (name.equals(tabItem[n].getText())) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private void handleFileOpen() {
|
|
FileDialog dlg = new FileDialog(shell, SWT.OPEN);
|
|
dlg.setText("Open File");
|
|
String[] filterNames = new String[] {
|
|
"Assembler Files"
|
|
};
|
|
String[] filterExtensions = new String[] {
|
|
"*.ASM;*.asm"
|
|
};
|
|
dlg.setFilterNames(filterNames);
|
|
dlg.setFilterExtensions(filterExtensions);
|
|
|
|
String filterPath = null;
|
|
if (tabFolder.getSelection() != null) {
|
|
SourceEditorTab tab = (SourceEditorTab) tabFolder.getSelection().getData();
|
|
if (tab.getFile() != null) {
|
|
File file = tab.getFile().getAbsoluteFile().getParentFile();
|
|
if (file != null) {
|
|
filterPath = file.getAbsolutePath();
|
|
}
|
|
}
|
|
}
|
|
if (filterPath == null) {
|
|
filterPath = preferences.getLastPath();
|
|
}
|
|
if (filterPath != null) {
|
|
dlg.setFilterPath(filterPath);
|
|
}
|
|
|
|
final String fileName = dlg.open();
|
|
if (fileName != null) {
|
|
File file = new File(fileName);
|
|
try {
|
|
openSourceTab(file);
|
|
preferences.addLru(file);
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
|
|
void openSourceTab(File file) {
|
|
CTabItem[] tabItem = tabFolder.getItems();
|
|
for (int i = 0; i < tabItem.length; i++) {
|
|
SourceEditorTab tab = (SourceEditorTab) tabItem[i].getData();
|
|
if (file.equals(tab.getFile())) {
|
|
tabFolder.setSelection(tab.getTabItem());
|
|
if (tabFolder.getSelection() != null) {
|
|
tabFolder.getSelection().getControl().setFocus();
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
BusyIndicator.showWhile(display, new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
String line;
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
if (file.exists()) {
|
|
try {
|
|
String lineDelimiter = System.getProperty("line.separator");
|
|
BufferedReader reader = new BufferedReader(new FileReader(file));
|
|
while ((line = reader.readLine()) != null) {
|
|
sb.append(line);
|
|
sb.append(lineDelimiter);
|
|
}
|
|
reader.close();
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
display.asyncExec(new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
SourceEditorTab tab = new SourceEditorTab(tabFolder, sb.toString());
|
|
tab.setText(file.getName());
|
|
tab.setToolTipText(file.getAbsolutePath());
|
|
tab.setFile(file);
|
|
applyEditoTabPreferences(tab);
|
|
|
|
tabFolder.setSelection(tab.getTabItem());
|
|
tab.setFocus();
|
|
}
|
|
});
|
|
}
|
|
}, true);
|
|
}
|
|
|
|
void applyEditoTabPreferences(SourceEditorTab tab) {
|
|
tab.getEditor().setShowLineNumbers(preferences.isShowLineNumbers());
|
|
tab.getEditor().setFont(preferences.getEditorFont());
|
|
tab.getEditor().setTabWidth(preferences.getTabWidth());
|
|
tab.getEditor().setTabStops(new int[] {
|
|
preferences.getMnemonicColumn(),
|
|
preferences.getArgumentColumn(),
|
|
preferences.getCommentColumn()
|
|
});
|
|
tab.getEditor().setUseTabstops(preferences.isUseTabstops());
|
|
}
|
|
|
|
private void handleFileSave() throws IOException {
|
|
CTabItem tabItem = tabFolder.getSelection();
|
|
if (tabItem == null) {
|
|
return;
|
|
}
|
|
File file = saveSourceTab((SourceEditorTab) tabItem.getData(), false);
|
|
if (file != null) {
|
|
browser.refresh(file.getAbsoluteFile());
|
|
}
|
|
}
|
|
|
|
private void handleFileSaveAs() throws IOException {
|
|
CTabItem tabItem = tabFolder.getSelection();
|
|
if (tabItem == null) {
|
|
return;
|
|
}
|
|
File file = saveSourceTab((SourceEditorTab) tabItem.getData(), true);
|
|
if (file != null) {
|
|
browser.refresh(file.getAbsoluteFile());
|
|
}
|
|
}
|
|
|
|
private void handleFileSaveAll() {
|
|
CTabItem[] tabItem = tabFolder.getItems();
|
|
for (int i = 0; i < tabItem.length; i++) {
|
|
SourceEditorTab tab = (SourceEditorTab) tabItem[i].getData();
|
|
if (tab.isDirty()) {
|
|
try {
|
|
if (saveSourceTab(tab, false) == null) {
|
|
break;
|
|
}
|
|
tab.clearDirty();
|
|
} catch (IOException e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
browser.refresh();
|
|
}
|
|
|
|
private boolean handleUnsavedContent() {
|
|
boolean dirty = false;
|
|
|
|
CTabItem[] tabItem = tabFolder.getItems();
|
|
for (int i = 0; i < tabItem.length; i++) {
|
|
SourceEditorTab tab = (SourceEditorTab) tabItem[i].getData();
|
|
if (tab.isDirty()) {
|
|
dirty = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (dirty) {
|
|
String msg = "Editor contains unsaved changes. Save before exit?";
|
|
String[] buttons = new String[] {
|
|
IDialogConstants.YES_LABEL,
|
|
IDialogConstants.NO_LABEL,
|
|
IDialogConstants.CANCEL_LABEL
|
|
};
|
|
MessageDialog dlg = new MessageDialog(shell, APP_TITLE, null, msg, MessageDialog.QUESTION, buttons, 0);
|
|
switch (dlg.open()) {
|
|
case 0: // YES
|
|
try {
|
|
for (int i = 0; i < tabItem.length; i++) {
|
|
SourceEditorTab tab = (SourceEditorTab) tabItem[i].getData();
|
|
if (tab.isDirty()) {
|
|
if (saveSourceTab(tab, false) == null) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
dirty = false;
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
break;
|
|
case 1: // NO
|
|
return true;
|
|
case 2: // CANCEL
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return !dirty;
|
|
}
|
|
|
|
File saveSourceTab(SourceEditorTab tab, boolean saveAs) throws IOException {
|
|
File file = tab.getFile();
|
|
|
|
if (saveAs || file == null) {
|
|
FileDialog dlg = new FileDialog(shell, SWT.SAVE);
|
|
dlg.setText("Save File");
|
|
dlg.setFileName(tab.getText());
|
|
|
|
String filterPath = null;
|
|
if (file != null) {
|
|
file = file.getAbsoluteFile().getParentFile();
|
|
if (file != null) {
|
|
filterPath = file.getAbsolutePath();
|
|
}
|
|
}
|
|
if (filterPath == null) {
|
|
filterPath = preferences.getLastPath();
|
|
}
|
|
if (filterPath != null) {
|
|
dlg.setFilterPath(filterPath);
|
|
}
|
|
|
|
String fileName = dlg.open();
|
|
if (fileName == null) {
|
|
return null;
|
|
}
|
|
file = new File(fileName);
|
|
}
|
|
|
|
String text = tab.getEditor().getText();
|
|
switch (preferences.getLineDelimiters()) {
|
|
case 0:
|
|
text = text.replaceAll("(\r\n|\n|\r)", System.getProperty("line.separator"));
|
|
break;
|
|
case 1:
|
|
text = text.replaceAll("(\r\n|\n|\r)", "\r\n");
|
|
break;
|
|
case 2:
|
|
text = text.replaceAll("(\r\n|\n|\r)", "\n");
|
|
break;
|
|
}
|
|
|
|
Writer os = new OutputStreamWriter(new FileOutputStream(file));
|
|
os.write(text);
|
|
os.close();
|
|
|
|
if (saveAs || tab.getFile() == null) {
|
|
tab.setFile(file);
|
|
tab.setText(file.getName());
|
|
tab.setToolTipText(file.getAbsolutePath());
|
|
}
|
|
|
|
tab.clearDirty();
|
|
|
|
return file;
|
|
}
|
|
|
|
private void handleFileClose() {
|
|
CTabItem tabItem = tabFolder.getSelection();
|
|
if (tabItem == null) {
|
|
return;
|
|
}
|
|
SourceEditorTab tab = (SourceEditorTab) tabItem.getData();
|
|
if (canCloseSourceTab(tab)) {
|
|
tabItem.dispose();
|
|
}
|
|
}
|
|
|
|
private void handleFileCloseAll() {
|
|
CTabItem[] tabItem = tabFolder.getItems();
|
|
for (int i = 0; i < tabItem.length; i++) {
|
|
SourceEditorTab tab = (SourceEditorTab) tabItem[i].getData();
|
|
if (!canCloseSourceTab(tab)) {
|
|
return;
|
|
}
|
|
}
|
|
for (int i = 0; i < tabItem.length; i++) {
|
|
tabItem[i].dispose();
|
|
}
|
|
}
|
|
|
|
boolean canCloseSourceTab(SourceEditorTab tab) {
|
|
if (tab.isDirty()) {
|
|
String msg = "Save changes in '" + tab.getText() + "'?";
|
|
String[] buttons = new String[] {
|
|
IDialogConstants.YES_LABEL,
|
|
IDialogConstants.NO_LABEL,
|
|
IDialogConstants.CANCEL_LABEL
|
|
};
|
|
MessageDialog dlg = new MessageDialog(shell, APP_TITLE, null, msg, MessageDialog.QUESTION, buttons, 0);
|
|
switch (dlg.open()) {
|
|
case 0:
|
|
try {
|
|
if (saveSourceTab(tab, false) == null) {
|
|
return false;
|
|
}
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
return false;
|
|
}
|
|
break;
|
|
case 2:
|
|
return false;
|
|
}
|
|
tab.clearDirty();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private void handleCompile() throws Exception {
|
|
CTabItem tabItem = tabFolder.getSelection();
|
|
if (tabItem == null) {
|
|
return;
|
|
}
|
|
SourceEditorTab tab = (SourceEditorTab) tabItem.getData();
|
|
|
|
console.clear();
|
|
|
|
final StringReader reader = new StringReader(tab.getEditor().getText());
|
|
|
|
final String name = tab.getText();
|
|
final File file = tab.getFile();
|
|
|
|
new Thread(new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
IProgressMonitor monitor = statusLine.getProgressMonitor();
|
|
monitor.beginTask("Compile", IProgressMonitor.UNKNOWN);
|
|
|
|
compile(reader, name, file);
|
|
|
|
monitor.done();
|
|
}
|
|
}).start();
|
|
}
|
|
|
|
Source compile(Reader reader, String name, File file) {
|
|
PrintStream out = new PrintStream(console.getOutputStream());
|
|
PrintStream err = new PrintStream(console.getErrorStream());
|
|
|
|
out.print("Compiling " + name + "...");
|
|
|
|
try {
|
|
final List<File> includePaths = new ArrayList<File>();
|
|
if (file != null) {
|
|
includePaths.add(file.getParentFile());
|
|
}
|
|
|
|
String[] includes = preferences.getIncludes();
|
|
if (includes != null) {
|
|
for (int i = 0; i < includes.length; i++) {
|
|
includePaths.add(new File(includes[i]));
|
|
}
|
|
}
|
|
|
|
SourceBuilder builder = new SourceBuilder(includePaths) {
|
|
|
|
@Override
|
|
public Source parse(File sourceFile) {
|
|
final AtomicReference<StringReader> result = new AtomicReference<StringReader>();
|
|
|
|
out.print("\r\nCompiling " + sourceFile.getName() + "...");
|
|
|
|
display.syncExec(new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
CTabItem[] tabItem = tabFolder.getItems();
|
|
for (int i = 0; i < tabItem.length; i++) {
|
|
SourceEditorTab tab = (SourceEditorTab) tabItem[i].getData();
|
|
if (sourceFile.equals(tab.getFile())) {
|
|
StringReader reader = new StringReader(tab.getEditor().getText());
|
|
result.set(reader);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
if (result.get() != null) {
|
|
return parse(result.get(), sourceFile);
|
|
}
|
|
|
|
return super.parse(sourceFile);
|
|
}
|
|
|
|
};
|
|
|
|
Source source = builder.parse(reader, new File(name));
|
|
source.register();
|
|
source.expand();
|
|
source.resolve();
|
|
|
|
if (file != null) {
|
|
String baseName = name;
|
|
if (baseName.indexOf('.') != -1) {
|
|
baseName = baseName.substring(0, baseName.lastIndexOf('.'));
|
|
}
|
|
|
|
if (preferences.isGenerateListing()) {
|
|
OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(new File(file.getParentFile(), baseName + ".LST")));
|
|
os.write(new ListingBuilder(source).build().toString());
|
|
os.close();
|
|
}
|
|
|
|
if (preferences.isGenerateBinary()) {
|
|
OutputStream output = new FileOutputStream(new File(file.getParentFile(), baseName + ".BIN"));
|
|
output.write(new BinaryBuilder(source).build());
|
|
output.close();
|
|
}
|
|
|
|
if (preferences.isGenerateHex()) {
|
|
OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(new File(file.getParentFile(), baseName + ".HEX")));
|
|
os.write(new IntelHexBuilder(source).build().toString());
|
|
os.close();
|
|
}
|
|
}
|
|
|
|
int lower = Integer.MAX_VALUE;
|
|
int higher = Integer.MIN_VALUE;
|
|
for (Line line : source.getLines()) {
|
|
try {
|
|
if (line.getSize() != 0) {
|
|
lower = Math.min(lower, line.getScope().getAddress());
|
|
higher = Math.max(higher, line.getScope().getAddress() + line.getSize() - 1);
|
|
}
|
|
} catch (Exception e) {
|
|
// Ignore, not important
|
|
}
|
|
}
|
|
out.println();
|
|
out.println(String.format("Compiled %d lines from %04XH to %04XH (%d bytes)", source.getLines().size(), lower, higher, higher - lower + 1));
|
|
|
|
return source;
|
|
|
|
} catch (AssemblyException ex) {
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
Iterator<AssemblyException.Context> iter = ex.contexts.iterator();
|
|
if (iter.hasNext()) {
|
|
AssemblyException.Context context = iter.next();
|
|
sb.append(context.file.getName());
|
|
sb.append(":");
|
|
sb.append(context.line + 1);
|
|
if (context.column != -1) {
|
|
sb.append(":");
|
|
sb.append(context.column);
|
|
}
|
|
sb.append(": error: ");
|
|
sb.append(ex.getPlainMessage());
|
|
}
|
|
|
|
out.println();
|
|
err.println(sb.toString());
|
|
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private void handleOpenTerminal() {
|
|
if (terminal == null) {
|
|
terminal = new SerialTerminal();
|
|
terminal.open();
|
|
terminal.getShell().addDisposeListener(new DisposeListener() {
|
|
|
|
@Override
|
|
public void widgetDisposed(DisposeEvent e) {
|
|
terminal = null;
|
|
}
|
|
});
|
|
}
|
|
terminal.setFocus();
|
|
}
|
|
|
|
private void handleCompileAndUploadIntelHex() throws Exception {
|
|
CTabItem tabItem = tabFolder.getSelection();
|
|
if (tabItem == null) {
|
|
return;
|
|
}
|
|
SourceEditorTab tab = (SourceEditorTab) tabItem.getData();
|
|
|
|
console.clear();
|
|
|
|
final StringReader reader = new StringReader(tab.getEditor().getText());
|
|
|
|
final String name = tab.getText();
|
|
final File file = tab.getFile();
|
|
|
|
new Thread(new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
final PrintStream out = new PrintStream(console.getOutputStream());
|
|
|
|
IProgressMonitor monitor = statusLine.getProgressMonitor();
|
|
monitor.beginTask("Compile", IProgressMonitor.UNKNOWN);
|
|
|
|
try {
|
|
Source source = compile(reader, name, file);
|
|
if (source == null) {
|
|
return;
|
|
}
|
|
|
|
display.syncExec(new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
handleOpenTerminal();
|
|
}
|
|
});
|
|
|
|
SerialPort serialPort = terminal.getSerialPort();
|
|
StringBuilder sb = new IntelHexBuilder(source).build();
|
|
|
|
monitor.beginTask("Upload", sb.length());
|
|
out.println("Sending to serial port " + serialPort.getPortName() + " ...");
|
|
|
|
for (int i = 0; i < sb.length(); i++) {
|
|
serialPort.writeInt(sb.charAt(i));
|
|
monitor.worked(1);
|
|
}
|
|
while (serialPort.getOutputBufferBytesCount() > 0) {
|
|
Thread.sleep(1);
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
out.println("Done");
|
|
monitor.done();
|
|
}
|
|
}).start();
|
|
|
|
}
|
|
|
|
private void handleNextTab() {
|
|
int index = tabFolder.getSelectionIndex();
|
|
index++;
|
|
if (index >= tabFolder.getItemCount()) {
|
|
index = 0;
|
|
}
|
|
tabFolder.setSelection(index);
|
|
if (tabFolder.getSelection() != null) {
|
|
tabFolder.getSelection().getControl().setFocus();
|
|
}
|
|
}
|
|
|
|
private void handlePreviousTab() {
|
|
int index = tabFolder.getSelectionIndex();
|
|
index--;
|
|
if (index < 0) {
|
|
index = tabFolder.getItemCount() - 1;
|
|
}
|
|
tabFolder.setSelection(index);
|
|
if (tabFolder.getSelection() != null) {
|
|
tabFolder.getSelection().getControl().setFocus();
|
|
}
|
|
}
|
|
|
|
private void handleCompileAndUploadBinary() throws Exception {
|
|
CTabItem tabItem = tabFolder.getSelection();
|
|
if (tabItem == null) {
|
|
return;
|
|
}
|
|
SourceEditorTab tab = (SourceEditorTab) tabItem.getData();
|
|
|
|
console.clear();
|
|
|
|
final StringReader reader = new StringReader(tab.getEditor().getText());
|
|
|
|
final String name = tab.getText();
|
|
final File file = tab.getFile();
|
|
|
|
new Thread(new Runnable() {
|
|
|
|
PrintStream out;
|
|
IProgressMonitor monitor;
|
|
SerialPort serialPort;
|
|
|
|
@Override
|
|
public void run() {
|
|
out = new PrintStream(console.getOutputStream());
|
|
|
|
monitor = statusLine.getProgressMonitor();
|
|
monitor.beginTask("Compile", IProgressMonitor.UNKNOWN);
|
|
|
|
try {
|
|
String baseName = name;
|
|
if (baseName.indexOf('.') != -1) {
|
|
baseName = baseName.substring(0, baseName.lastIndexOf('.'));
|
|
}
|
|
|
|
Source source = compile(reader, name, file);
|
|
if (source == null) {
|
|
return;
|
|
}
|
|
|
|
display.syncExec(new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
handleOpenTerminal();
|
|
}
|
|
});
|
|
|
|
serialPort = terminal.getSerialPort();
|
|
byte[] data = new BinaryBuilder(source).build();
|
|
|
|
monitor.beginTask("Upload", (data.length + 127) / 128);
|
|
out.println("Sending to serial port " + serialPort.getPortName() + " ...");
|
|
|
|
terminal.uploadPackedBinary(baseName + ".COM", data, monitor);
|
|
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
out.println("Done");
|
|
monitor.done();
|
|
}
|
|
|
|
}).start();
|
|
|
|
}
|
|
|
|
private void handleCompileAndUploadXModem() throws Exception {
|
|
CTabItem tabItem = tabFolder.getSelection();
|
|
if (tabItem == null) {
|
|
return;
|
|
}
|
|
SourceEditorTab tab = (SourceEditorTab) tabItem.getData();
|
|
|
|
console.clear();
|
|
|
|
final StringReader reader = new StringReader(tab.getEditor().getText());
|
|
|
|
final String name = tab.getText();
|
|
final File file = tab.getFile();
|
|
|
|
new Thread(new Runnable() {
|
|
|
|
PrintStream out;
|
|
IProgressMonitor monitor;
|
|
SerialPort serialPort;
|
|
|
|
@Override
|
|
public void run() {
|
|
out = new PrintStream(console.getOutputStream());
|
|
|
|
monitor = statusLine.getProgressMonitor();
|
|
monitor.beginTask("Compile", IProgressMonitor.UNKNOWN);
|
|
|
|
try {
|
|
String baseName = name;
|
|
if (baseName.indexOf('.') != -1) {
|
|
baseName = baseName.substring(0, baseName.lastIndexOf('.'));
|
|
}
|
|
|
|
Source source = compile(reader, name, file);
|
|
if (source == null) {
|
|
return;
|
|
}
|
|
|
|
display.syncExec(new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
handleOpenTerminal();
|
|
}
|
|
});
|
|
|
|
serialPort = terminal.getSerialPort();
|
|
byte[] data = new BinaryBuilder(source).build();
|
|
|
|
monitor.beginTask("Upload", (data.length + 127) / 128);
|
|
out.println("Sending to serial port " + serialPort.getPortName() + " ...");
|
|
|
|
terminal.uploadXModem(baseName + ".COM", data, monitor);
|
|
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
out.println("Done");
|
|
monitor.done();
|
|
}
|
|
|
|
}).start();
|
|
|
|
}
|
|
|
|
private void handleCompileAndDebug() {
|
|
CTabItem tabItem = tabFolder.getSelection();
|
|
if (tabItem == null) {
|
|
return;
|
|
}
|
|
SourceEditorTab tab = (SourceEditorTab) tabItem.getData();
|
|
|
|
console.clear();
|
|
|
|
final StringReader reader = new StringReader(tab.getEditor().getText());
|
|
|
|
final String name = tab.getText();
|
|
final File file = tab.getFile();
|
|
|
|
new Thread(new Runnable() {
|
|
|
|
PrintStream out;
|
|
IProgressMonitor monitor;
|
|
|
|
@Override
|
|
public void run() {
|
|
out = new PrintStream(console.getOutputStream());
|
|
|
|
monitor = statusLine.getProgressMonitor();
|
|
monitor.beginTask("Compile", IProgressMonitor.UNKNOWN);
|
|
|
|
try {
|
|
Source source = compile(reader, name, file);
|
|
if (source == null) {
|
|
return;
|
|
}
|
|
|
|
debugger = new Debugger(out) {
|
|
|
|
@Override
|
|
public void poke8(int address, int value) {
|
|
display.syncExec(new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
memory.poke(address, value);
|
|
}
|
|
});
|
|
super.poke8(address, value);
|
|
}
|
|
|
|
@Override
|
|
protected void doUpdateDebuggerState() {
|
|
super.doUpdateDebuggerState();
|
|
display.syncExec(new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
updateDebuggerState();
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
protected boolean isBreakpoint(int address) {
|
|
return viewer.isBreakpoint(address);
|
|
}
|
|
|
|
};
|
|
|
|
debugger.setDebugTerminal(debugTerminal);
|
|
|
|
debugger.tms9918Ram = preferences.getTms9918Ram();
|
|
debugger.tms9918Reg = preferences.getTms9918Register();
|
|
|
|
display.syncExec(new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
debugger.setSource(source);
|
|
|
|
memory.setData(debugger.getRam());
|
|
memory.setSelection(debugger.proc.getRegPC());
|
|
viewer.setSourceMap(debugger.getSourceMap());
|
|
handleReset();
|
|
|
|
reparentControls();
|
|
|
|
Menu menuBar = shell.getMenuBar();
|
|
createDebugMenu(menuBar, menuBar.getItemCount() - 1);
|
|
|
|
stackLayout.topControl = stack.getChildren()[1];
|
|
stack.layout(true, true);
|
|
|
|
viewer.getControl().setFocus();
|
|
}
|
|
});
|
|
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
out.println("Done");
|
|
monitor.done();
|
|
}
|
|
|
|
}).start();
|
|
|
|
}
|
|
|
|
private void handleSwitchToEditor() {
|
|
Menu menu = shell.getMenuBar();
|
|
menu.getItem(menu.getItemCount() - 2).dispose();
|
|
|
|
reparentControls();
|
|
|
|
stackLayout.topControl = stack.getChildren()[0];
|
|
stack.layout(true, true);
|
|
|
|
CTabItem tabItem = tabFolder.getSelection();
|
|
if (tabItem == null) {
|
|
return;
|
|
}
|
|
tabItem.getControl().setFocus();
|
|
}
|
|
|
|
void reparentControls() {
|
|
Composite parent = consolePlaceHolder.getParent();
|
|
Object layoutData = consolePlaceHolder.getLayoutData();
|
|
|
|
consolePlaceHolder.setParent(console.getControl().getParent());
|
|
consolePlaceHolder.setLayoutData(console.getControl().getLayoutData());
|
|
|
|
console.getControl().setParent(parent);
|
|
console.getControl().setLayoutData(layoutData);
|
|
}
|
|
|
|
private void handleReset() {
|
|
if (debuggerThread != null) {
|
|
return;
|
|
}
|
|
|
|
if (debugTerminal != null) {
|
|
try {
|
|
while (debugTerminal.getInputStream().available() > 0) {
|
|
debugTerminal.getInputStream().read();
|
|
}
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
memory.clearUpdates();
|
|
viewer.getControl().setFocus();
|
|
|
|
debugger.reset();
|
|
|
|
updateDebuggerState();
|
|
}
|
|
|
|
private void handleStep() {
|
|
if (debuggerThread != null) {
|
|
return;
|
|
}
|
|
|
|
memory.clearUpdates();
|
|
viewer.getControl().setFocus();
|
|
viewer.setHighlighCurrentLine(false);
|
|
|
|
debuggerThread = new Thread(new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
debugger.stepInto();
|
|
debuggerThread = null;
|
|
}
|
|
|
|
});
|
|
debuggerThread.start();
|
|
}
|
|
|
|
private void handleStepOver() {
|
|
if (debuggerThread != null) {
|
|
return;
|
|
}
|
|
|
|
memory.clearUpdates();
|
|
viewer.getControl().setFocus();
|
|
viewer.setHighlighCurrentLine(false);
|
|
|
|
debuggerThread = new Thread(new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
debugger.stepOver();
|
|
debuggerThread = null;
|
|
}
|
|
|
|
});
|
|
debuggerThread.start();
|
|
}
|
|
|
|
private void handleRunToLine() {
|
|
if (debuggerThread != null) {
|
|
return;
|
|
}
|
|
|
|
memory.clearUpdates();
|
|
viewer.getControl().setFocus();
|
|
viewer.setHighlighCurrentLine(false);
|
|
|
|
int caretOffset = viewer.getStyledText().getCaretOffset();
|
|
int lineAtOffset = viewer.getStyledText().getLineAtOffset(caretOffset);
|
|
|
|
final LineEntry lineEntry = viewer.getSourceMap().getLines().get(lineAtOffset);
|
|
|
|
debuggerThread = new Thread(new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
debugger.runToAddress(lineEntry.address);
|
|
debuggerThread = null;
|
|
}
|
|
|
|
});
|
|
debuggerThread.start();
|
|
}
|
|
|
|
private void handleStop() {
|
|
debugger.doStop();
|
|
}
|
|
|
|
private void handleToggleBreakpoint() {
|
|
int caretOffset = viewer.getStyledText().getCaretOffset();
|
|
int lineAtOffset = viewer.getStyledText().getLineAtOffset(caretOffset);
|
|
|
|
LineEntry lineEntry = viewer.getSourceMap().getLines().get(lineAtOffset);
|
|
if (lineEntry != null) {
|
|
int address = lineEntry.address;
|
|
viewer.toggleBreakpoint(address);
|
|
}
|
|
}
|
|
|
|
private void handleClearBreakpoints() {
|
|
viewer.resetBreakpoints();
|
|
debugger.resetBreakpoints();
|
|
}
|
|
|
|
private void handleRun() {
|
|
if (debuggerThread != null) {
|
|
return;
|
|
}
|
|
|
|
memory.clearUpdates();
|
|
viewer.getControl().setFocus();
|
|
viewer.setHighlighCurrentLine(false);
|
|
|
|
debuggerThread = new Thread(new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
debugger.run();
|
|
debuggerThread = null;
|
|
}
|
|
|
|
});
|
|
debuggerThread.start();
|
|
}
|
|
|
|
void updateDebuggerState() {
|
|
memory.update();
|
|
registers.updateRegisters(debugger.proc);
|
|
|
|
if (debugTMS9918 != null) {
|
|
debugTMS9918.redraw();
|
|
}
|
|
|
|
LineEntry lineEntry = debugger.getSourceMap().getLineAtAddress(debugger.proc.getRegPC());
|
|
if (lineEntry != null) {
|
|
viewer.gotToLineColumn(lineEntry.lineNumber, 0);
|
|
viewer.setHighlighCurrentLine(true);
|
|
}
|
|
}
|
|
|
|
private void handleOpenDebugTerminal() {
|
|
if (debugTerminal == null) {
|
|
debugTerminal = new DebugTerminal();
|
|
debugTerminal.open();
|
|
debugTerminal.getShell().addDisposeListener(new DisposeListener() {
|
|
|
|
@Override
|
|
public void widgetDisposed(DisposeEvent e) {
|
|
debugTerminal = null;
|
|
if (debugger != null) {
|
|
debugger.setDebugTerminal(debugTerminal);
|
|
}
|
|
}
|
|
});
|
|
if (debugger != null) {
|
|
debugger.setDebugTerminal(debugTerminal);
|
|
}
|
|
}
|
|
debugTerminal.setFocus();
|
|
}
|
|
|
|
private void handleOpenTMS9918Window() {
|
|
if (debugTMS9918 == null) {
|
|
debugTMS9918 = new DebugTMS9918();
|
|
debugTMS9918.setTMS9918(debugger.tms9918);
|
|
debugTMS9918.open();
|
|
debugTMS9918.getShell().addDisposeListener(new DisposeListener() {
|
|
|
|
@Override
|
|
public void widgetDisposed(DisposeEvent e) {
|
|
debugTMS9918 = null;
|
|
}
|
|
});
|
|
}
|
|
debugTMS9918.setFocus();
|
|
}
|
|
|
|
private void handleCompileAndCopyIntelHexToClipboard() throws Exception {
|
|
CTabItem tabItem = tabFolder.getSelection();
|
|
if (tabItem == null) {
|
|
return;
|
|
}
|
|
SourceEditorTab tab = (SourceEditorTab) tabItem.getData();
|
|
|
|
console.clear();
|
|
|
|
final StringReader reader = new StringReader(tab.getEditor().getText());
|
|
|
|
final String name = tab.getText();
|
|
final File file = tab.getFile();
|
|
|
|
new Thread(new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
IProgressMonitor monitor = statusLine.getProgressMonitor();
|
|
monitor.beginTask("Compile", IProgressMonitor.UNKNOWN);
|
|
|
|
try {
|
|
Source source = compile(reader, name, file);
|
|
if (source == null) {
|
|
return;
|
|
}
|
|
|
|
final StringBuilder sb = new IntelHexBuilder(source).build();
|
|
display.syncExec(new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
Clipboard clipboard = new Clipboard(display);
|
|
try {
|
|
clipboard.setContents(new Object[] {
|
|
sb.toString()
|
|
}, new Transfer[] {
|
|
TextTransfer.getInstance()
|
|
});
|
|
} finally {
|
|
clipboard.dispose();
|
|
}
|
|
}
|
|
});
|
|
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
monitor.done();
|
|
}
|
|
}).start();
|
|
|
|
}
|
|
|
|
private void handleCompileAndCopyBinaryToClipboard() throws Exception {
|
|
CTabItem tabItem = tabFolder.getSelection();
|
|
if (tabItem == null) {
|
|
return;
|
|
}
|
|
SourceEditorTab tab = (SourceEditorTab) tabItem.getData();
|
|
|
|
console.clear();
|
|
|
|
final StringReader reader = new StringReader(tab.getEditor().getText());
|
|
|
|
final String name = tab.getText();
|
|
final File file = tab.getFile();
|
|
|
|
new Thread(new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
IProgressMonitor monitor = statusLine.getProgressMonitor();
|
|
monitor.beginTask("Compile", IProgressMonitor.UNKNOWN);
|
|
|
|
try {
|
|
String baseName = name;
|
|
if (baseName.indexOf('.') != -1) {
|
|
baseName = baseName.substring(0, baseName.lastIndexOf('.'));
|
|
}
|
|
|
|
Source source = compile(reader, name, file);
|
|
if (source == null) {
|
|
return;
|
|
}
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
String s = preferences.getDownloadCommand();
|
|
s = s.replace("{0}", baseName + ".COM");
|
|
sb.append(s);
|
|
sb.append("\r");
|
|
|
|
sb.append("U0\r");
|
|
sb.append(":");
|
|
|
|
int checksum = 0;
|
|
byte[] data = new BinaryBuilder(source).build();
|
|
for (int i = 0; i < data.length; i++) {
|
|
sb.append(String.format("%02X", data[i] & 0xFF));
|
|
checksum += data[i] & 0xFF;
|
|
}
|
|
|
|
sb.append(">");
|
|
sb.append(String.format("%02X", data.length & 0xFF));
|
|
sb.append(String.format("%02X", checksum & 0xFF));
|
|
|
|
display.syncExec(new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
Clipboard clipboard = new Clipboard(display);
|
|
try {
|
|
clipboard.setContents(new Object[] {
|
|
sb.toString()
|
|
}, new Transfer[] {
|
|
TextTransfer.getInstance()
|
|
});
|
|
} finally {
|
|
clipboard.dispose();
|
|
}
|
|
}
|
|
});
|
|
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
monitor.done();
|
|
}
|
|
|
|
}).start();
|
|
|
|
}
|
|
|
|
private void handleOpenEmulator() {
|
|
if (emulator == null) {
|
|
emulator = new Emulator();
|
|
emulator.open();
|
|
emulator.getShell().addDisposeListener(new DisposeListener() {
|
|
|
|
@Override
|
|
public void widgetDisposed(DisposeEvent e) {
|
|
emulator = null;
|
|
}
|
|
});
|
|
}
|
|
emulator.setFocus();
|
|
}
|
|
|
|
static {
|
|
Display.setAppName(APP_TITLE);
|
|
Display.setAppVersion(APP_VERSION);
|
|
System.setProperty("SWT_GTK3", "0");
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
final Display display = new Display();
|
|
|
|
Realm.runWithDefault(DisplayRealm.getRealm(display), new Runnable() {
|
|
|
|
@Override
|
|
public void run() {
|
|
try {
|
|
Application app = new Application();
|
|
app.open();
|
|
|
|
while (display.getShells().length != 0) {
|
|
if (!display.readAndDispatch()) {
|
|
display.sleep();
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
return;
|
|
}
|
|
}
|
|
});
|
|
|
|
display.dispose();
|
|
}
|
|
}
|