/*
Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
и других спецификаций для функционирования компактных приложений на языке
Java (мидлетов) в среде программного обеспечения Малик Эмулятор.
Copyright © 2016–2017, 2019–2023 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package javax.microedition.lcdui;
import java.io.*;
import javax.microedition.midlet.*;
import javax.microedition.rms.*;
import malik.emulator.application.*;
import malik.emulator.media.graphics.*;
import malik.emulator.microedition.*;
import malik.emulator.util.*;
public class Display extends VisibleElement implements Rectangle
{
static abstract class OneShotAction extends Object implements Runnable
{
private static final int FREED = 0;
private static final int REQUESTED = 1;
private static final int EXECUTING = 2;
private static final int REPEATED = 3;
private int state;
private Object service;
protected final Object monitor;
protected OneShotAction() {
this.monitor = new Object();
}
protected OneShotAction(Object monitor) {
this.monitor = monitor == null ? new Object() : monitor;
}
public final void run() {
boolean exec = false;
Object monitor;
synchronized(monitor = this.monitor)
{
if(state == REQUESTED)
{
state = EXECUTING;
exec = true;
}
}
if(exec) serviceExecute(monitor);
}
public final void service() {
boolean exec = false;
Object monitor;
synchronized(monitor = this.monitor)
{
if(Thread.currentThread() == service)
{
if(state == REQUESTED)
{
state = EXECUTING;
exec = true;
}
} else
{
while(state != FREED)
{
try
{
monitor.wait();
}
catch(InterruptedException e)
{
e.printRealStackTrace();
}
}
}
}
if(exec) serviceExecute(monitor);
}
public final void request(Display parent) {
boolean exec;
if(parent == null)
{
throw new NullPointerException("OneShotAction.request: аргумент parent равен нулевой ссылке.");
}
exec = false;
synchronized(monitor)
{
label0:
{
switch(state)
{
default:
break label0;
case FREED:
state = REQUESTED;
break;
case EXECUTING:
state = REPEATED;
break;
}
service = parent.serviceThread;
exec = true;
}
}
if(exec) parent.callSerially(this);
}
protected abstract void execute();
private void serviceExecute(Object monitor) {
try
{
execute();
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
synchronized(monitor)
{
state &= 1;
monitor.notifyAll();
}
}
}
private static final class ApplicationTermination extends Object implements Runnable
{
private final Requestable stream;
private final MIDletDispatcher dispatcher;
public ApplicationTermination(Requestable stream, MIDletDispatcher dispatcher) {
this.stream = stream;
this.dispatcher = dispatcher;
}
public void run() {
dispatcher.stop();
stream.terminate();
}
}
public static final int LIST_ELEMENT = 1;
public static final int CHOICE_GROUP_ELEMENT = 2;
public static final int ALERT = 3;
public static final int COLOR_BACKGROUND = 0;
public static final int COLOR_FOREGROUND = 1;
public static final int COLOR_HIGHLIGHTED_BACKGROUND = 2;
public static final int COLOR_HIGHLIGHTED_FOREGROUND = 3;
public static final int COLOR_BORDER = 4;
public static final int COLOR_HIGHLIGHTED_BORDER = 5;
private static long lastUpdated;
private static ApplicationThread[] appThreads;
private static final Clip screenClip;
private static final Object screenMonitor;
static {
appThreads = new ApplicationThread[7];
screenClip = new Clip(RasterCanvas.MAX_SCREEN_WIDTH, RasterCanvas.MAX_SCREEN_HEIGHT);
screenMonitor = new Object();
}
public static void registerApplication(MIDlet application) {
Thread current;
if(!((current = Thread.currentThread()) instanceof ApplicationThread) || !((ApplicationThread) current).setApplication(application))
{
throw new SecurityException("MIDlet: невозможно создать новый мидлет.");
}
}
public static Display getDisplay(MIDlet application) {
ApplicationThread[] appthreads;
if(application == null)
{
throw new NullPointerException("Display.getDisplay: аргумент application равен нулевой ссылке.");
}
for(int i = (appthreads = appThreads).length; i-- > 0; )
{
ApplicationThread current;
if((current = appthreads[i]) != null && current.getApplication() == application) return current.parentDisplay();
}
return DeviceManager.getInstance().getMainDisplay();
}
private static void addAppThread(ApplicationThread appthread) {
synchronized(screenMonitor)
{
int len;
ApplicationThread[] appthreads;
if(Array.findf(appthreads = appThreads, 0, appthread) >= (len = appthreads.length))
{
int index;
if((index = Array.findf(appthreads, 0, null)) >= len)
{
Array.copy(appthreads, 0, appthreads = new ApplicationThread[(len << 1) + 1], 0, len);
appThreads = appthreads;
}
appthreads[index] = appthread;
}
}
}
private static void removeAppThread(Thread appthread) {
synchronized(screenMonitor)
{
int index;
ApplicationThread[] appthreads;
if((index = Array.findb(appthreads = appThreads, appthreads.length - 1, appthread)) >= 0) appthreads[index] = null;
}
}
private class ActionStream extends Requestable implements Runnable
{
private final class DelayedAction extends Scheduler.Task
{
private final Runnable action;
public DelayedAction(Runnable action) {
this.action = action;
}
public void run() {
((Requestable) ActionStream.this).request(action, 0L);
}
}
private final int capacity;
private final RequestableQueue queue;
public ActionStream(int initialCapacity, int historyCapacity) {
this.capacity = historyCapacity;
this.queue = new RequestableQueue(initialCapacity);
}
public synchronized void request(int action, int param1, int param2, int param3) {
queue.addTailElement(null, (long) (action & 0xffff) | (long) (param1 & 0xffff) << 0x10 | (long) (param2 & 0xffff) << 0x20 | (long) (param3 & 0xffff) << 0x30);
notify();
}
public void request(Runnable action, long delay) {
if(delay > 0L)
{
if(action != null) Scheduler.schedule(this.new DelayedAction(action), delay, Scheduler.MONOPOLY);
return;
}
synchronized(this)
{
queue.addTailElement(action, -1L);
notify();
}
}
public synchronized void terminate() {
super.terminate();
notify();
}
public void run() {
int historyCapacity = capacity;
int[] ids = InputDevice.getIDs();
RequestableQueue queue = this.queue;
KeyboardEvent kbdevent = new KeyboardEvent(historyCapacity);
PointerEvent ptrevent = new PointerEvent(historyCapacity);
InputDevice keyboard = null;
InputDevice pointing = null;
InputDevice device;
for(int len = ids.length, i = 0; i < len; i++) if(!(device = InputDevice.get(ids[i])).isVirtual())
{
if(device.sourceSupported(InputDevice.SOURCE_CLASS_BUTTON) && device.getKeyboardType() != InputDevice.KEYBOARD_TYPE_NONE)
{
keyboard = device;
}
else if(device.sourceSupported(InputDevice.SOURCE_CLASS_POINTER))
{
pointing = device;
}
}
historyCapacity = 0;
ids = null;
device = null;
for(Display parent = Display.this; ; )
{
long fromUser;
Runnable fromApp;
Displayable background;
Displayable foreground;
waitAction();
if(super.terminated()) break;
synchronized(this)
{
if(queue.isEmpty())
{
fromUser = -1L;
fromApp = null;
} else
{
fromUser = queue.peekHeadLong();
fromApp = queue.peekHeadRunnable();
((Queue) queue).removeHeadElement();
}
}
if(fromApp != null)
{
try
{
fromApp.run();
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
continue;
}
if(fromUser != -1L && (foreground = parent.getActiveForeground()) != null)
{
int action = (short) fromUser;
int param1 = (short) (fromUser >> 0x10);
int param2 = (short) (fromUser >> 0x20);
int param3 = (short) (fromUser >> 0x30);
switch(action)
{
case ACTION_WINDOW_SHOW:
if((background = parent.getActiveBackground()) != null && background != foreground) background.eventShow(parent);
foreground.eventShow(parent);
foreground.requestPaintAll();
break;
case ACTION_WINDOW_HIDE:
foreground.eventHide();
if((background = parent.getActiveBackground()) != null && background != foreground) background.eventHide();
break;
case ACTION_KEY_REPEATED:
case ACTION_KEY_PRESSED:
kbdevent.addStory(action, param1, param2 & 0xffff | param3 << 0x10, keyboard, InputDevice.SOURCE_KEYBOARD, 0L);
foreground.eventKeyboard(kbdevent);
break;
case ACTION_KEY_RELEASED:
kbdevent.addStory(action, param1, 0, keyboard, InputDevice.SOURCE_KEYBOARD, 0L);
foreground.eventKeyboard(kbdevent);
break;
case ACTION_POINTER_DRAGGED:
ptrevent.addStory(action, 0, param2, param3, pointing, InputDevice.SOURCE_MOUSE, 0L);
ptrevent.translateReset();
foreground.eventPointer(ptrevent);
break;
case ACTION_POINTER_PRESSED:
case ACTION_POINTER_RELEASED:
case ACTION_BUTTON_PRESSED:
case ACTION_BUTTON_RELEASED:
ptrevent.addStory(action, param1, param2, param3, pointing, InputDevice.SOURCE_MOUSE, 0L);
ptrevent.translateReset();
foreground.eventPointer(ptrevent);
break;
}
}
}
}
private synchronized void waitAction() {
for(; ; )
{
try
{
wait();
break;
}
catch(InterruptedException e)
{
e.printRealStackTrace();
}
}
}
}
private final class ApplicationThread extends Thread
{
private MIDlet application;
public ApplicationThread(ActionStream target) {
super(target, "Поток исполнения, обслуживающий события мидлета");
}
public boolean setApplication(MIDlet application) {
if(this.application == null)
{
this.application = application;
return true;
}
return false;
}
public MIDlet getApplication() {
return application;
}
public Display parentDisplay() {
return Display.this;
}
}
private final class ApplicationExecution extends ActionStream
{
private final String typeName;
private final MIDletDispatcher dispatcher;
public ApplicationExecution(int initialCapacity, int historyCapacity, String typeName, MIDletDispatcher dispatcher) {
super(initialCapacity, historyCapacity);
this.typeName = typeName;
this.dispatcher = dispatcher;
}
public void run() {
int status;
Display parent = Display.this;
PrintStream printer = System.out;
String typeName = this.typeName;
MIDletDispatcher dispatcher = this.dispatcher;
/* вывод сообщений о запуске мидлета */
printer.println("Запуск приложения… Класс мидлета: ".concat(typeName));
/* запуск мидлета */
status = dispatcher.start();
parent.notifyStarted();
if(status != MIDletDispatcher.OK)
{
/* вывод сообщений о неудачной попытке запуска */
printer.println("Не удалось запустить – приложение завершает работу. Класс мидлета: ".concat(typeName));
/* остановка мидлета */
if(status == MIDletDispatcher.MUST_STOPPED) dispatcher.stop();
parent.notifyStopped();
return;
}
/* вывод сообщений об удачной попытке запуска */
printer.println("Приложение запущено и работает. Класс мидлета: ".concat(typeName));
/* обработка событий мидлета */
super.run();
/* вывод сообщений о завершении мидлета */
printer.println("Приложение завершило работу. Класс мидлета: ".concat(typeName));
/* остановка мидлета */
RecordStore.closeAllRecordStores();
parent.notifyStopped();
}
}
private int left;
private int top;
private final int width;
private final int height;
private final RasterBuffer screenBuffer;
private final ScreenGraphics screenGraphics;
private MIDletDispatcher serviceDispatcher;
private Requestable serviceStream;
Thread serviceThread;
private final Runnable serviceStarted;
private final Runnable serviceStopped;
Displayable currentBackground;
SurfaceScreen currentForeground;
Displayable activeBackground;
SurfaceScreen activeForeground;
private final OneShotAction activeChanged;
private final Object monitor;
Display(boolean system, boolean visibility, int left, int top, int width, int height) {
super(visibility);
RasterBuffer buffer;
if(width < RasterCanvas.MIN_SCREEN_WIDTH || width > RasterCanvas.MAX_SCREEN_WIDTH)
{
throw new IllegalArgumentException("Display: аргумент width выходит из диапазона.");
}
if(height < RasterCanvas.MIN_SCREEN_HEIGHT || height > RasterCanvas.MAX_SCREEN_HEIGHT)
{
throw new IllegalArgumentException("Display: аргумент height выходит из диапазона.");
}
this.left = left;
this.top = top;
this.width = width;
this.height = height;
this.screenBuffer = buffer = RasterBuffer.create(width, height, 0xffffff, true);
this.screenGraphics = new ScreenGraphics(buffer);
this.serviceStream = system ? Run.instance : null;
this.serviceThread = system ? Thread.currentThread() : null;
this.serviceStarted = new Runnable() {
public void run() {
DeviceManager.getInstance().applicationStarted(Display.this);
}
};
this.serviceStopped = new Runnable() {
public void run() {
DeviceManager.getInstance().applicationStopped(Display.this);
}
};
this.activeChanged = new OneShotAction() {
public void execute() {
Display parent = Display.this;
Displayable oldForeground = parent.activeForeground;
Displayable oldBackground = parent.activeBackground;
Displayable newBackground = parent.currentBackground;
SurfaceScreen newForeground = parent.currentForeground;
parent.activeBackground = newBackground;
parent.activeForeground = newForeground;
if(!parent.visibility) return;
if(oldBackground == newBackground && oldForeground != newForeground)
{
if(oldForeground != null) oldForeground.eventHide();
if(newForeground != null)
{
newForeground.eventShow(parent);
newForeground.requestPaintAll();
return;
}
if(oldBackground != null) oldBackground.requestPaintAll();
return;
}
if(oldBackground != newBackground && oldForeground == newForeground)
{
if(oldForeground != null)
{
if(oldBackground != null) oldBackground.eventHide();
if(newBackground != null) newBackground.eventShow(parent);
oldForeground.requestPaintAll();
return;
}
if(oldBackground != null) oldBackground.eventHide();
if(newBackground != null)
{
newBackground.eventShow(parent);
newBackground.requestPaintAll();
}
return;
}
if(oldBackground != newBackground && oldForeground != newForeground)
{
if(oldForeground != null) oldForeground.eventHide();
if(oldBackground != null) oldBackground.eventHide();
if(newBackground != null) newBackground.eventShow(parent);
if(newForeground != null)
{
newForeground.eventShow(parent);
newForeground.requestPaintAll();
return;
}
if(newBackground != null) newBackground.requestPaintAll();
}
}
};
this.monitor = new Object();
}
public void handleKeyboardEvent(KeyboardEvent event) {
Requestable stream;
if(event == null)
{
throw new NullPointerException("Display.handleKeyboardEvent: аргумент event равен нулевой ссылке.");
}
if(Thread.currentThread() == serviceThread)
{
Displayable foreground;
if(visibility && (foreground = getActiveForeground()) != null) foreground.eventKeyboard(event);
return;
}
if((stream = serviceStream) != null)
{
int action;
switch(action = event.getAction())
{
case KeyboardEvent.ACTION_KEY_REPEATED:
case KeyboardEvent.ACTION_KEY_PRESSED:
if(visibility) stream.requestKeyboardEvent(action, event.getKey(), event.getCharCode());
break;
case KeyboardEvent.ACTION_KEY_RELEASED:
if(visibility) stream.requestKeyboardEvent(action, event.getKey(), 0);
break;
}
}
}
public void handlePointerEvent(PointerEvent event) {
Requestable stream;
if(event == null)
{
throw new NullPointerException("Display.handlePointerEvent: аргумент event равен нулевой ссылке.");
}
if(Thread.currentThread() == serviceThread)
{
Displayable foreground;
if(visibility && (foreground = getActiveForeground()) != null) foreground.eventPointer(event);
return;
}
if((stream = serviceStream) != null)
{
int action;
switch(action = event.getAction())
{
case PointerEvent.ACTION_POINTER_DRAGGED:
if(visibility) stream.requestPointerEvent(action, 0, event.getX(), event.getY());
break;
case PointerEvent.ACTION_POINTER_PRESSED:
case PointerEvent.ACTION_POINTER_RELEASED:
case PointerEvent.ACTION_BUTTON_PRESSED:
case PointerEvent.ACTION_BUTTON_RELEASED:
if(visibility) stream.requestPointerEvent(action, event.getButton(), event.getX(), event.getY());
break;
}
}
}
public void callSerially(Runnable action) {
Requestable stream;
if(action != null && (stream = serviceStream) != null) stream.request(action, 0L);
}
public void callSerially(Runnable action, long delay) {
Requestable stream;
if(action != null && (stream = serviceStream) != null) stream.request(action, delay);
}
public void setCurrent(Displayable screen) {
if(screen == null) return;
if(screen instanceof SurfaceScreen)
{
currentForeground = (SurfaceScreen) screen;
} else
{
currentBackground = screen;
currentForeground = null;
}
activeChanged.request(this);
}
public void setCurrent(Alert foreground, Displayable background) {
if(foreground == null)
{
throw new NullPointerException("Display.setCurrent: аргумент foreground равен нулевой ссылке.");
}
if(background == null)
{
throw new NullPointerException("Display.setCurrent: аргумент background равен нулевой ссылке.");
}
if(background instanceof SurfaceScreen)
{
throw new IllegalArgumentException("Display.setCurrent: аргумент background не может иметь тип SurfaceScreen.");
}
currentBackground = background;
currentForeground = foreground;
activeChanged.request(this);
}
public void setCurrent(SurfaceScreen foreground, Displayable background) {
if(foreground == null)
{
throw new NullPointerException("Display.setCurrent: аргумент foreground равен нулевой ссылке.");
}
if(background == null)
{
throw new NullPointerException("Display.setCurrent: аргумент background равен нулевой ссылке.");
}
if(background instanceof SurfaceScreen)
{
throw new IllegalArgumentException("Display.setCurrent: аргумент background не может иметь тип SurfaceScreen.");
}
currentBackground = background;
currentForeground = foreground;
activeChanged.request(this);
}
public void setCurrentItem(Item item) {
Screen screen;
if(item == null)
{
throw new NullPointerException("Display.setCurrentItem: аргумент item равен нулевой ссылке.");
}
if((screen = item.owner) == null)
{
throw new IllegalStateException("Display.setCurrentItem: элемент не принадлежит какому-либо экрану.");
}
currentBackground = screen;
currentForeground = null;
activeChanged.request(this);
screen.setFocus(item, this);
}
public void hideForeground() {
currentForeground = null;
activeChanged.request(this);
}
public boolean flashBacklight(int duration) {
if(duration < 0)
{
throw new IllegalArgumentException("Display.flashBacklight: аргумент duration не может быть отрицательным.");
}
if(visibility)
{
DeviceManager.getInstance().getBacklight().start((long) duration);
return true;
}
return false;
}
public boolean vibrate(int duration) {
if(duration < 0)
{
throw new IllegalArgumentException("Display.vibrate: аргумент duration не может быть отрицательным.");
}
if(visibility)
{
DeviceManager.getInstance().getVibrator().start((long) duration);
return true;
}
return false;
}
public boolean isColor() {
return true;
}
public int numColors() {
return 0x01000000;
}
public int numAlphaLevels() {
return 0x00000100;
}
public int getBestImageWidth(int type) {
switch(type)
{
case CHOICE_GROUP_ELEMENT:
return ChoiceGroup.ICON_WIDTH;
case LIST_ELEMENT:
return List.ICON_WIDTH;
case ALERT:
return Alert.ICON_WIDTH;
default:
throw new IllegalArgumentException("Display.getBestImageWidth: аргумент type имеет недопустимое значение.");
}
}
public int getBestImageHeight(int type) {
switch(type)
{
case CHOICE_GROUP_ELEMENT:
return ChoiceGroup.ICON_HEIGHT;
case LIST_ELEMENT:
return List.ICON_HEIGHT;
case ALERT:
return Alert.ICON_HEIGHT;
default:
throw new IllegalArgumentException("Display.getBestImageHeight: аргумент type имеет недопустимое значение.");
}
}
public int getBorderStyle(boolean highlighted) {
return Graphics.SOLID;
}
public int getColor(int colorSpecifier) {
switch(colorSpecifier)
{
case COLOR_FOREGROUND:
return RasterCanvas.getSystemColor(0x20);
case COLOR_HIGHLIGHTED_BACKGROUND:
return RasterCanvas.getSystemColor(0x19);
case COLOR_HIGHLIGHTED_FOREGROUND:
return RasterCanvas.getSystemColor(0x21);
case COLOR_BACKGROUND:
case COLOR_BORDER:
case COLOR_HIGHLIGHTED_BORDER:
return RasterCanvas.getSystemColor(0x05);
default:
throw new IllegalArgumentException("Display.getColor: аргумент colorSpecifier имеет недопустимое значение.");
}
}
public Displayable getCurrent() {
SurfaceScreen result;
return (result = currentForeground) != null && (result instanceof Alert) ? result : currentBackground;
}
public Displayable getBackground() {
return currentBackground;
}
public Displayable getForeground() {
Displayable result;
return (result = currentForeground) != null ? result : currentBackground;
}
public final void show() {
if(!visibility) showDisplay();
}
public final void hide() {
if(visibility) hideDisplay();
}
public final void setVisibility(boolean visibility) {
boolean current = this.visibility;
if(visibility && !current)
{
showDisplay();
return;
}
if(!visibility && current)
{
hideDisplay();
}
}
public final boolean isVisible() {
return visibility;
}
public final int getLeft() {
return left;
}
public final int getTop() {
return top;
}
public final int getWidth() {
return width;
}
public final int getHeight() {
return height;
}
public final void setPosition(int left, int top) {
boolean needRepaint = false;
Displayable foreground;
synchronized(screenClip)
{
if(this.left != left || this.top != top)
{
needRepaint = true;
this.left = left;
this.top = top;
}
}
if(needRepaint && visibility && (foreground = getActiveForeground()) != null) foreground.requestPaintAll();
}
public final Displayable getActiveBackground() {
return activeBackground;
}
public final Displayable getActiveForeground() {
Displayable result;
return (result = activeForeground) != null ? result : activeBackground;
}
final void update() {
int behavior;
long period;
long milliseconds;
RasterCanvas screen;
DeviceManager manager;
if(!visibility) return;
behavior = 0;
milliseconds = 0L;
period = (long) (manager = DeviceManager.getInstance()).getSettings().getMinimumPeriod();
synchronized(screenMonitor)
{
long last = lastUpdated;
long curr = System.currentTimeMillis();
long prev = last - period;
long next = last + period;
if(curr >= prev && curr < last)
{
milliseconds = last - curr;
behavior = 1;
}
else if(curr >= last && curr < next)
{
lastUpdated = next;
milliseconds = next - curr;
behavior = 2;
}
else
{
lastUpdated = curr;
behavior = 3;
}
}
try
{
switch(behavior)
{
case 1:
Thread.sleep(milliseconds);
break;
case 2:
Thread.sleep(milliseconds);
/* fall through */
case 3:
synchronized(screenClip)
{
if(manager.isVisibleDisplay(this))
{
(screen = RasterCanvas.screen).drawPixels(screenBuffer, RasterCanvas.TRANSFORM_NONE, this, screenClip);
screen.updateScreen();
}
}
}
}
catch(InterruptedException e)
{
e.printRealStackTrace();
}
}
final void notifyStarted() {
Run.instance.request(serviceStarted);
}
final void notifyStopped() {
removeAppThread(serviceThread);
serviceDispatcher = null;
serviceStream = null;
serviceThread = null;
currentBackground = null;
currentForeground = null;
activeBackground = null;
activeForeground = null;
Run.instance.request(serviceStopped);
}
final int start(String applicationTypeName) {
int error = 0;
ApplicationThread appthread = null;
synchronized(monitor)
{
label0:
{
Requestable stream;
ActionStream execution;
MIDletDispatcher dispatcher;
if((stream = serviceStream) == Run.instance)
{
error = 1;
break label0;
}
if(stream != null)
{
error = 2;
break label0;
}
if(applicationTypeName == null)
{
error = 3;
break label0;
}
this.serviceDispatcher = dispatcher = new MIDletDispatcher(applicationTypeName);
this.serviceStream = execution = this.new ApplicationExecution(0x10, 0x10, applicationTypeName, dispatcher);
this.serviceThread = appthread = this.new ApplicationThread(execution);
}
}
if(error != 0) return error;
addAppThread(appthread);
((Thread) appthread).start();
return 0;
}
final int stop(boolean destroyAppInvoke) {
int error = 0;
synchronized(monitor)
{
label0:
{
Requestable stream;
if((stream = serviceStream) == Run.instance)
{
error = 1;
break label0;
}
if(stream == null)
{
error = 2;
break label0;
}
if(destroyAppInvoke)
{
stream.request(new ApplicationTermination(stream, serviceDispatcher));
break label0;
}
stream.terminate();
}
}
return error;
}
final MIDlet application() {
Thread thread;
return (thread = serviceThread) instanceof ApplicationThread ? ((ApplicationThread) thread).getApplication() : null;
}
final ScreenGraphics graphics() {
return screenGraphics;
}
private void showDisplay() {
Displayable background;
Displayable foreground;
Requestable stream;
visibility = true;
if(Thread.currentThread() == serviceThread)
{
if((foreground = getActiveForeground()) != null)
{
if((background = getActiveBackground()) != null && background != foreground) background.eventShow(this);
foreground.eventShow(this);
foreground.requestPaintAll();
}
return;
}
update();
if((stream = serviceStream) != null) stream.requestWindowShow();
}
private void hideDisplay() {
Displayable background;
Displayable foreground;
Requestable stream;
visibility = false;
if(Thread.currentThread() == serviceThread)
{
if((foreground = getActiveForeground()) != null)
{
foreground.eventHide();
if((background = getActiveBackground()) != null && background != foreground) background.eventHide();
}
return;
}
if((stream = serviceStream) != null) stream.requestWindowHide();
}
}