Revision 7a16363389b0026609141d50b71c40a298b11939 authored by chou86_e on 10 January 2008, 03:22:31 UTC, committed by chou86_e on 10 January 2008, 03:22:31 UTC
Yield() is used for window manager to put events on the queue so logoEventManager->ProcessAnEvent() can handle it. git-svn-id: https://svn.code.sf.net/p/ucblogo/code@50 fc4ef4ee-df3e-0410-84de-fb01f5d6c4f7
1 parent 7938cdc
wxMain.cpp
#include <iostream>
#include <wx/wx.h>
#include "LogoFrame.h"
#include <stdio.h>
#include <wx/thread.h>
#include <wx/app.h>
#include "stdio.h"
#include "wxTurtleGraphics.h"
#include "wxGlobals.h"
#ifdef __WXMAC__
#include <CoreServices/CoreServices.h>
#endif
#include <string>
#include "wxTerminal.h" /* must come after wxTurtleGraphics.h */
std::string pathString;
#include <wx/stdpaths.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
int wx_Debugging = 0;
/* The thread for Logo */
class AppThread : public wxThread {
public:
AppThread(int , char **);
virtual void * Entry();
virtual void doExit(int code);
virtual void OnExit();
private:
int argc;
char ** argv;
};
// start the application
IMPLEMENT_APP(LogoApplication)
// ----------------------------------------------------------------------------
// Globals
// ----------------------------------------------------------------------------
// externs from the logo interpreter
extern "C" int start (int , char **);
extern "C" void redraw_graphics();
// need to redraw turtle graphics
int needToRefresh = 0;
// need to load
int load_flag = 0;
// need to save
int save_flag = 0;
// alreadyAlerted indicated there is a pending message from logo to the GUI
int alreadyAlerted = 0;
// IO buffer handling
char nameBuffer [NAME_BUFFER_SIZE];
int nameBufferSize = 0;
int MAXOUTBUFF = MAXOUTBUFF_;
char out_buff1[MAXOUTBUFF_];
char out_buff2[MAXOUTBUFF_];
int out_buff_index_public = 0;
int out_buff_index_private = 0;
char * out_buff_public = out_buff1;
char * out_buff_private = out_buff2;
#ifdef MULTITHREAD
// mutexes for the buffers
wxMutex out_mut;
wxMutex * init_m;
wxMutex buff_full_m;
wxCondition buff_full_cond(out_mut);
// used for sleeping
wxMutex sleepMut;
wxCondition sleepCond(sleepMut);
// the buffer from the GUI to the interpreter
char buff[1024];
int buff_index = 0;
wxMutex in_mut;
wxCondition read_buff (in_mut);
#else
char buff[1024];
int buff_index = 0;
#endif
// ----------------------------------------------------------------------------
// AppThread
// ----------------------------------------------------------------------------
// this class corresponds to the logo interpereter thread that is started when
// UCBLogo starts up
#ifdef MULTITHREAD
void * AppThread::Entry()
{
#ifndef __WXMAC__ /* needed for wxWidgets 2.6 */
wxSetWorkingDirectory(wxStandardPaths::Get().GetDocumentsDir());
#endif
// fix the working directory in mac
#ifdef __WXMAC__
char path[1024];
CFBundleRef mainBundle = CFBundleGetMainBundle();
assert( mainBundle );
CFURLRef mainBundleURL = CFBundleCopyBundleURL( mainBundle);
assert( mainBundleURL);
CFStringRef cfStringRef = CFURLCopyFileSystemPath( mainBundleURL, kCFURLPOSIXPathStyle);
assert( cfStringRef);
CFStringGetCString( cfStringRef, path, 1024, kCFStringEncodingASCII);
CFRelease( mainBundleURL);
CFRelease( cfStringRef);
//std::string pathString(path);
pathString = path;
pathString+="/Contents/Resources/";
// chdir(pathString.c_str());
#endif
/*wxTerminal::terminal->x_coord=0;
wxTerminal::terminal->y_coord=0;
wxTerminal::terminal->x_max=80;
wxTerminal::terminal->y_max=24;*/
start(argc, argv);
return 0;
}
void AppThread::doExit(int code) {
this->Exit((ExitCode)code);
}
void AppThread::OnExit()
{
turtleGraphics->exitApplication();
while (1) {
this->Sleep(1000);
}
}
AppThread:: AppThread(int c, char ** v)
: wxThread(wxTHREAD_DETACHED)
{
argc = c;
argv = v;
}
#endif
// ----------------------------------------------------------------------------
// misc functions
// ----------------------------------------------------------------------------
extern "C" void wxLogoExit(int code) {
#ifdef MULTITHREAD
AppThread * thisThread = (AppThread *)AppThread::This();
thisThread->doExit(code);
#else
logoEventManager->LogoExit();
#endif
}
#ifdef MULTITHREAD
// start the interpreter thread
void init_Logo_Interpreter ( int argc, char ** argv) {
AppThread * a = new AppThread(argc, argv);
if (a->Create() != wxTHREAD_NO_ERROR) {
wxdprintf("There was an error during create");
}
if (a->Run() != wxTHREAD_NO_ERROR) {
wxdprintf("There was an error during run");
}
}
#endif
#define LINEPAUSE 25
// flush the output
extern "C" void flushFile(FILE * stream, int justPost) {
static int numLines = 0;
int doPost = 0;
char * temp;
if (!justPost) {
#ifdef MULTITHREAD
out_mut.Lock();
#endif
while (out_buff_index_public != 0) {
#ifdef MULTITHREAD
buff_full_cond.Wait();
#else
logoEventManager->ProcessAnEvent();
wxMilliSleep(10);
#endif
}
if (numLines >= LINEPAUSE) {
// this is to give the user a chance to pause
#ifdef MULTITHREAD
buff_full_cond.WaitTimeout(1);
#else
wxMilliSleep(1);
numLines = 0;
#endif
}
else
numLines++;
temp = out_buff_public;
out_buff_public = out_buff_private;
out_buff_private = temp;
out_buff_index_public = out_buff_index_private;
out_buff_index_private = 0;
if (alreadyAlerted == 0)
doPost = 1;
#ifdef MULTITHREAD
out_mut.Unlock();
#endif
}
if (doPost || justPost) {
if (!doPost) {
// This is so that I don't have to grab the lock twice
if (numLines >= LINEPAUSE) {
#ifdef MULTITHREAD
out_mut.Lock();
buff_full_cond.WaitTimeout(1);
out_mut.Unlock();
#else
wxMilliSleep(1);
#endif
numLines = 0;
}
else
numLines++;
}
haveInputEvent->SetClientData(NULL);
#ifdef MULTITHREAD
wxPostEvent(wxTerminal::terminal, *(haveInputEvent));
#else
wxTerminal::terminal->ProcessEvent(*haveInputEvent);
#endif
}
}
// have the interpreter go to sleep
extern "C" void wxLogoSleep(unsigned int milli) {
flushFile(stdout, 0);
#ifdef MULTITHREAD
if(needToRefresh){
redraw_graphics();
// to make sure we always get an entire refresh
if(needToRefresh == 1)
needToRefresh = 0;
else needToRefresh = 1;
}
sleepMut.Lock();
sleepCond.WaitTimeout(milli);
sleepMut.Unlock();
#else
wxMilliSleep(milli);
#endif
}
// have the interpreter wake up
#ifdef MULTITHREAD
void wxLogoWakeup() {
sleepMut.Lock();
sleepCond.Broadcast();
sleepMut.Unlock();
in_mut.Lock();
read_buff.Broadcast();
in_mut.Unlock();
}
#endif
/* Called by the logo thread to display a character onto the terminal screen */
extern "C" void printToScreen(char c, FILE * stream)
{
if (stream != stdout) {
putc(c, stream);
return;
}
if(TurtleFrame::in_graphics_mode && !TurtleFrame::in_splitscreen)
// we are in fullscreen mode
wxSplitScreen();
if (out_buff_index_private >= (MAXOUTBUFF - 1)) {
flushFile(stdout, 0);
}
if (c == '\n') {
out_buff_private[out_buff_index_private++] = 10;
out_buff_private[out_buff_index_private++] = 13;
flushFile(stdout, 1);
}
else {
out_buff_private[out_buff_index_private++] = c;
}
}
extern "C" char getFromWX_2(FILE * f) ;
extern "C" char getFromWX()
{
return getFromWX_2(stdin);
}
extern "C" char getFromWX_2(FILE * f)
{
int putReturn = 0;
if (f != stdin) {
return getc(f);
}
#ifdef MULTITHREAD
in_mut.Lock();
#endif
while (buff_index == 0 && !putReturn) {
if(needToRefresh){
#ifdef MULTITHREAD
in_mut.Unlock();
#endif
redraw_graphics();
wxdprintf("wxMain after calling redraw graphics\n");
#ifdef MULTITHREAD
in_mut.Lock();
#endif
needToRefresh = 0;
turtleGraphics->Refresh();
wxdprintf("after wxMain calling refresh()");
}
if (load_flag) {
load_flag = 0;
int i;
buff[buff_index++] = '\n';
for (i = 0; i < nameBufferSize; i++) {
buff[buff_index++] = nameBuffer[nameBufferSize - i - 1];
}
buff[buff_index++] = '"'; buff[buff_index++] = ' '; buff[buff_index++] = 'd'; buff[buff_index++] = 'a'; buff[buff_index++] = 'o'; buff[buff_index++] = 'l';
}
if (save_flag) {
save_flag = 0;
int i;
buff[buff_index++] = '\n';
for (i = 0; i < nameBufferSize; i++) {
buff[buff_index++] = nameBuffer[nameBufferSize - i - 1];
}
buff[buff_index++] = '"'; buff[buff_index++] = ' '; buff[buff_index++] = 'e'; buff[buff_index++] = 'v'; buff[buff_index++] = 'a'; buff[buff_index++] = 's';
}
#ifdef MULTITHREAD
in_mut.Unlock();
#endif
// Do this while the lock is released just in case the longjump occurs
if (check_wx_stop()) {
putReturn = 1;
}
flushFile(stdout, 0);
#ifdef MULTITHREAD
in_mut.Lock();
#endif
if (buff_index == 0 && !putReturn)
#ifdef MULTITHREAD
read_buff.WaitTimeout(1000);
#else
wxMilliSleep(1); // don't wait too long now...
#endif
}
char c;
if (putReturn)
c = '\n';
else
c= buff[--buff_index];
#ifdef MULTITHREAD
in_mut.Unlock();
#endif
return c;
}
extern "C" int wxKeyp() {
int ret = 0;
#ifdef MULTITHREAD
in_mut.Lock();
#endif
if (buff_index != 0)
ret = 1;
#ifdef MULTITHREAD
in_mut.Unlock();
#endif
return ret;
}
extern "C" int wxUnget_c(int c, FILE * f) {
if (f != stdin)
return ungetc(c, f);
else {
#ifdef MULTITHREAD
in_mut.Lock();
#endif
buff[++buff_index] = (char)c;
#ifdef MULTITHREAD
in_mut.Unlock();
#endif
return c;
}
}
extern "C" char* wx_fgets(char* s, int n, FILE* stream) {
if (stream != stdin) {
return fgets(s, n, stream);
}
char c;
char * orig = s;
n --;
c = ' ';
while (c != '\n' && n != 0) {
c = getFromWX_2(stream);
s[0] = c;
s++;
n--;
}
return orig;
}
void doLoad(char * name, int length) {
int i = 0;
#ifdef MULTITHREAD
in_mut.Lock();
#endif
while (i < length && i < NAME_BUFFER_SIZE) {
nameBuffer[i] = name[i];
i++;
}
nameBufferSize = (length >= NAME_BUFFER_SIZE? NAME_BUFFER_SIZE : length);
load_flag = 1;
#ifdef MULTITHREAD
read_buff.Broadcast();
in_mut.Unlock();
#endif
}
void doSave(char * name, int length) {
int i = 0;
#ifdef MULTITHREAD
in_mut.Lock();
#endif
while (i < length && i < NAME_BUFFER_SIZE) {
nameBuffer[i] = name[i];
i++;
}
nameBufferSize = (length >= NAME_BUFFER_SIZE? NAME_BUFFER_SIZE : length);
save_flag = 1;
#ifdef MULTITHREAD
read_buff.Broadcast();
in_mut.Unlock();
#endif
}
extern "C" const char* wxMacGetLibloc(){
#ifdef __WXMAC__
static std::string libloc;
libloc=pathString;
libloc+="logolib";
return libloc.c_str();
#endif
return 0;
}
extern "C" const char* wxMacGetCslsloc(){
#ifdef __WXMAC__
static std::string cslsloc;
cslsloc=pathString;
cslsloc+="csls";
return cslsloc.c_str();
#endif
return 0;
}
extern "C" const char* wxMacGetHelploc(){
#ifdef __WXMAC__
static std::string helploc;
helploc=pathString;
helploc+="helpfiles";
return helploc.c_str();
#endif
return 0;
}
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...