Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

https://github.com/jrincayc/ucblogo-code
26 January 2024, 08:32:20 UTC
  • Code
  • Branches (8)
  • Releases (24)
  • Visits
Revision 8d03f497146e641d7c3785ab2562b5148584fb3d authored by Joshua Cogliati on 22 November 2020, 22:08:40 UTC, committed by GitHub on 22 November 2020, 22:08:40 UTC
Merge pull request #64 from dmalec/ISSUE-63
ISSUE-63: Exit getFromWX_2 input loop on pause character sequence.
2 parent s a7bd4e1 + 4aa84f2
  • Files
  • Changes
    • Branches
    • Releases
    • HEAD
    • refs/heads/debug_stop
    • refs/heads/fix_39
    • refs/heads/makefile_updates_v2
    • refs/heads/master
    • refs/heads/message_fix
    • refs/heads/release_624_changes
    • refs/heads/utf8_play
    • refs/tags/dev-latest
    • 8d03f497146e641d7c3785ab2562b5148584fb3d
    • version_6.2.5rc1
    • version_6.2.4rc1
    • version_6.2.4
    • version_6.2.3rc1
    • version_6.2.3
    • version_6.2.2
    • version_6.2.1
    • version_6.2
    • version_6.1
    • version_6.0
    • pre_release_6_2_b
    • pre_release_6_2_a
    • pre_release_6_2_2
    • pre_release_6_1_c
    • pre_release_6_1_b
    • pre_release_6_1_a
    • last_svn_version
    • debian/6.2.4-1
    • debian/6.2.3-1
    • debian/6.2.2-3
    • debian/6.2.2-2
    • debian/6.2.2-1
    • debian/6.2.1-2
    • debian/6.2.1-1
  • d96b992
  • /
  • wxTerminal.cpp
Raw File Download
Take a new snapshot of a software origin

If the archived software origin currently browsed is not synchronized with its upstream version (for instance when new commits have been issued), you can explicitly request Software Heritage to take a new snapshot of it.

Use the form below to proceed. Once a request has been submitted and accepted, it will be processed as soon as possible. You can then check its processing state by visiting this dedicated page.
swh spinner

Processing "take a new snapshot" request ...

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • revision
  • directory
  • content
  • snapshot
origin badgerevision badge
swh:1:rev:8d03f497146e641d7c3785ab2562b5148584fb3d
origin badgedirectory badge
swh:1:dir:d96b9928ef893466ad4079ec4316955146303f57
origin badgecontent badge
swh:1:cnt:d516476713c066e1ce06137503c7466ff047f34c
origin badgesnapshot badge
swh:1:snp:6eedb1da19a602bcc290a95dfe80bedb7646053c

This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
Select below a type of object currently browsed in order to generate citations for them.

  • revision
  • directory
  • content
  • snapshot
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Tip revision: 8d03f497146e641d7c3785ab2562b5148584fb3d authored by Joshua Cogliati on 22 November 2020, 22:08:40 UTC
Merge pull request #64 from dmalec/ISSUE-63
Tip revision: 8d03f49
wxTerminal.cpp
/* This file implements the logo frame, which is the main frame that
   contains the terminal, turtle graphics and the editor.

CONTAINED IN #IF 0 BLOCKS:
-- if user types input, presses UP, and then DOWN, it remembers it...
   feature isn't very complete, though...
   to implement, probably need TWO copies of the history buffer

*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <iostream>

#ifdef __GNUG__
    #pragma implementation "wxTerminal.h"
#endif

// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWindows headers
#ifndef WX_PRECOMP
    #include "wx/wx.h"
#endif

#include <wx/timer.h>
extern std::string pathString;
#include <wx/stdpaths.h>
#include <ctype.h>

extern "C" int readingInstruction;

#include <wx/print.h>
#include "LogoFrame.h"
#include "wxGlobals.h"
#include <wx/clipbrd.h>
#include <wx/html/htmprint.h>
#include <wx/print.h>
#include <wx/printdlg.h>
#include <wx/dcbuffer.h>  //buffered_DC
#include "wxTurtleGraphics.h"
#include "TextEditor.h"
#ifndef __WXMSW__
    #include "config.h"
#endif
#ifdef __WXMAC__
    #include "CoreFoundation/CFBundle.h"
#endif
#include "wxTerminal.h"		/* must come after wxTurtleGraphics.h */
#include <wx/fontdlg.h>

// in Visual Studio 6.0, min and max are not defined up this point
#ifndef max
#define max(a,b)    (((a) > (b)) ? (a) : (b))
#endif

#ifndef min
#define min(a,b)    (((a) < (b)) ? (a) : (b))
#endif

using namespace std;

// ----------------------------------------------------------------------------
// Globals
// ----------------------------------------------------------------------------
// This is for the input for terminal-like behavior
char input_buffer [MAXINBUFF+1];
// How far into the input_buffer we are
int input_index = 0;
// Where the cursor is in the input_buffer
int input_current_pos = 0;


//history storage
char *cmdHistory[HIST_MAX] = {0};
char **hist_inptr, **hist_outptr; 

#if 0
//temporary storage of currently typed input
//so that if we retrieve history and then come back, we can see it again
char latest_history_buffer[MAXINBUFF];
int latest_history_stored = 0;
#endif

// if logo is in character mode
int logo_char_mode;
extern "C" int reading_char_now;
// the terminal DC
wxFont old_font;
wxTextAttr old_style;
// when edit is called in logo
TextEditor * editWindow;
// the turtle graphics we are using
TurtleCanvas * turtleGraphics; 
// this contains the previous 3 window
wxBoxSizer *topsizer;
LogoFrame *logoFrame;
LogoEventManager *logoEventManager;

// used to calculate where the cursor should be
int cur_x = 0, cur_y = 0;
int first = 1;
int last_logo_x = 0, last_logo_y = 0;
int last_input_x = 0, last_input_y = 0;
// the menu
wxMenuBar* menuBar;

extern "C" void wxTextScreen();

// This is for stopping logo asynchronously
#ifdef SIG_TAKES_ARG
extern "C" void logo_stop(int);
extern "C" void logo_pause(int);
#else
extern "C" void logo_stop();
extern "C" void logo_pause();
#endif
int logo_stop_flag = 0;
int logo_pause_flag = 0;

// this is a static reference to the main terminal
wxTerminal *wxTerminal::terminal;

// This is a static reference to the working directory
wxString originalWorkingDir;


// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------

enum
{
	
    Menu_File = 200,
	Menu_File_Save,
	Menu_File_Save_As,
	Menu_File_Load,
    Menu_File_Page_Setup,
	Menu_File_Print_Text,
	Menu_File_Print_Text_Prev,
	Menu_File_Print_Turtle,
	Menu_File_Print_Turtle_Prev,
	Menu_File_Quit,
	
	Menu_Edit = 300,
    Menu_Edit_Copy,
	Menu_Edit_Paste,
	
	Menu_Logo = 400,
	Menu_Logo_Stop,
	Menu_Logo_Pause,
	
	Menu_Font = 500,
        Menu_Font_Choose,
	Menu_Font_Inc,
	Menu_Font_Dec,
	
	Menu_Help = 600,
	Menu_Help_Man,
	
	Edit_Menu_File = 700,
	Edit_Menu_File_Close_Accept,
	Edit_Menu_File_Close_Reject,
    Edit_Menu_File_Page_Setup,
    Edit_Menu_File_Print_Text,

	
	Edit_Menu_Edit = 800,
    Edit_Menu_Edit_Copy,
	Edit_Menu_Edit_Paste,
	Edit_Menu_Edit_Cut,
	Edit_Menu_Edit_Find,
	Edit_Menu_Edit_Find_Next
	
};


// ----------------------------------------------------------------------------
// misc functions
// ----------------------------------------------------------------------------

char *new_c_string_from_wx_string(wxString wxStr) {
  char *cStr = (char *)malloc(sizeof(char) * (wxStr.length() + 1));

  strncpy(cStr, (const char*)wxStr.mb_str(), wxStr.length());
  cStr[wxStr.length()] = '\0';

  return cStr;
}


// ----------------------------------------------------------------------------
// LogoApplication class
// ----------------------------------------------------------------------------


bool LogoApplication::OnInit()
{
  // capture the original working directory for any later relative file loads
  originalWorkingDir = wxGetCwd();

  logoFrame = new LogoFrame
    (_T("Berkeley Logo"));

  logoFrame->Show(TRUE);
  SetTopWindow(logoFrame);

#ifndef __WXMAC__
  m_mainLoop = new wxEventLoop();
#endif

  logoEventManager = new LogoEventManager(this);

  return TRUE;	
}

extern "C" int start (int, char **);


int LogoApplication::OnRun()
{
  wxEventLoop::SetActive(m_mainLoop);
  //SetExitOnFrameDelete(true);

  wxSetWorkingDirectory(wxStandardPaths::Get().GetDocumentsDir());

  // 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

  // capture the command line arguments from wxWidgets for the interpreter
  int argc = this->argc;
  char **argv = (char **)malloc(sizeof(char *) * argc);

  for(int i=0; i<argc; i++) {
    argv[i] = new_c_string_from_wx_string(this->argv[i]);
  }

  // pass control to the interpreter
  start(argc, argv);

  // cleanup the captured command line arguments
  for(int i=0; i<argc; i++) {
    free(argv[i]);
  }
  free(argv);

  return 0;
}

int LogoApplication::OnExit() {
  return 0;
}

// ----------------------------------------------------------------------------
// LogoEventManager class
// ----------------------------------------------------------------------------

LogoEventManager::LogoEventManager(LogoApplication *logoApp)
{
  m_logoApp = logoApp;
}

extern "C" void wx_refresh();
void LogoEventManager::ProcessEvents(int force_yield)
{
  static int inside_yield = 0;
  static int yield_delay = 500;  // carefully tuned fudge factor
  static int foo = yield_delay;

  foo--;

  if( m_logoApp->Pending() ) {
    while( m_logoApp->Pending() )
       m_logoApp->Dispatch();
  }
  else {
    if(force_yield || foo == 0) {
      if(!inside_yield) {
        inside_yield++;
        m_logoApp->Yield(TRUE);
        inside_yield--;
      }
    }
  }

  if(foo == 0) {
    wx_refresh();
    foo = yield_delay;
  }
}


// ----------------------------------------------------------------------------
// LogoFrame class
// ----------------------------------------------------------------------------

BEGIN_EVENT_TABLE (LogoFrame, wxFrame)
EVT_MENU(Menu_File_Save,				LogoFrame::OnSave)
EVT_MENU(Menu_File_Save_As,			LogoFrame::OnSaveAs)
EVT_MENU(Menu_File_Load,				LogoFrame::OnLoad)
EVT_MENU(Menu_File_Page_Setup,			TurtleCanvas::OnPageSetup)
EVT_MENU(Menu_File_Print_Text,			LogoFrame::OnPrintText)
EVT_MENU(Menu_File_Print_Text_Prev,		LogoFrame::OnPrintTextPrev)
EVT_MENU(Menu_File_Print_Turtle,	TurtleCanvas::PrintTurtleWindow)
EVT_MENU(Menu_File_Print_Turtle_Prev,   TurtleCanvas::TurtlePrintPreview)
EVT_MENU(Menu_File_Quit,			LogoFrame::OnQuit)
EVT_MENU(Menu_Edit_Copy,			LogoFrame::DoCopy)
EVT_MENU(Menu_Edit_Paste,			LogoFrame::DoPaste)
EVT_MENU(Menu_Logo_Pause,			LogoFrame::DoPause)
EVT_MENU(Menu_Logo_Stop,			LogoFrame::DoStop)
EVT_MENU(Menu_Font_Choose,                      LogoFrame::OnSelectFont)
EVT_MENU(Menu_Font_Inc,				LogoFrame::OnIncreaseFont)
EVT_MENU(Menu_Font_Dec,				LogoFrame::OnDecreaseFont)
EVT_MENU(Edit_Menu_File_Close_Accept,	LogoFrame::OnEditCloseAccept)
EVT_MENU(Edit_Menu_File_Close_Reject,	LogoFrame::OnEditCloseReject)
EVT_MENU(Edit_Menu_File_Page_Setup,		TurtleCanvas::OnPageSetup)
EVT_MENU(Edit_Menu_File_Print_Text,		LogoFrame::OnEditPrint)
EVT_MENU(Edit_Menu_Edit_Copy,			LogoFrame::OnEditCopy)
EVT_MENU(Edit_Menu_Edit_Cut,			LogoFrame::OnEditCut)
EVT_MENU(Edit_Menu_Edit_Paste,			LogoFrame::OnEditPaste)
EVT_MENU(Edit_Menu_Edit_Find,			LogoFrame::OnEditFind)
EVT_MENU(Edit_Menu_Edit_Find_Next,		LogoFrame::OnEditFindNext)
EVT_CLOSE(LogoFrame::OnCloseWindow)
END_EVENT_TABLE()

#include "ucblogo.xpm"

extern "C" void wxSetTextColor(int fg, int bg);

//this should compute the size based on the chosen font!
LogoFrame::LogoFrame (const wxChar *title,
 int xpos, int ypos,
 int width, int height)
  : wxFrame( (wxFrame *) NULL, -1, title,
	     wxPoint(xpos, ypos),
	     wxSize(width, height)) {
  // the topsizer allows different resizeable segments in the main frame (i.e. for 
  // turtle graphics and the terminal displaying simultaneously)
  SetMinSize(wxSize(100, 100));
  SetIcon(wxIcon(ucblogo));
  logoFrame = this;
  topsizer = new wxBoxSizer( wxVERTICAL );
  wxTerminal::terminal = new wxTerminal (this, -1, wxPoint(-1, -1),
			        TERM_COLS, TERM_ROWS,  _T(""));
  turtleGraphics = new TurtleCanvas( this );

  wxFont f(FONT_CFG(wx_font_face, wx_font_size));

  wxTerminal::terminal->SetFont(f);

  AdjustSize();

    wxSetTextColor(7+SPECIAL_COLORS, 0+SPECIAL_COLORS);
  editWindow = new TextEditor( this, -1, _T(""), wxDefaultPosition,
			      wxSize(100,60), wxTE_MULTILINE|wxTE_RICH, f);
  wxTerminal::terminal->isEditFile=0;
  
  topsizer->Add(
		editWindow,
		1,            // make vertically stretchable
		wxEXPAND |    // make horizontally stretchable
		wxALL,        //   and make border all around
		2 );  
 
  topsizer->Add(
		turtleGraphics,
		4,            // make vertically stretchable
		wxEXPAND |    // make horizontally stretchable
		wxALL,        //   and make border all around
		2 );
  topsizer->Add(
		wxTerminal::terminal,
		1,            // make vertically stretchable
		wxEXPAND |    // make horizontally stretchable
		wxALL,        //   and make border all around
		2 ); 
  topsizer->Layout();

  topsizer->Show(wxTerminal::terminal, 1);
  topsizer->Show(turtleGraphics, 0);
  topsizer->Show(editWindow, 0);
  
  SetSizer( topsizer ); 
  
  //SetAutoLayout(true);
  //topsizer->Fit(this);
  //topsizer->SetSizeHints(this);  
  
  wxTerminal::terminal->SetFocus();
  SetUpMenu();
}

extern "C" int wx_leave_mainloop;
void LogoFrame::OnCloseWindow(wxCloseEvent& event)
{
  logo_stop_flag = 1;
  wx_leave_mainloop++;
  Destroy();
}

extern "C" int need_save;

void LogoFrame::OnQuit(wxCommandEvent& event)
{
    if (need_save) {
	wxMessageDialog dialog( NULL, _T("Save workspace before quitting?"),
			       _T("Quit Logo"), wxYES_DEFAULT|wxYES_NO|wxCANCEL);
	switch ( dialog.ShowModal() ) {
	    case wxID_YES:
		LogoFrame::OnSave(event);
	    /* falls through */
	    case wxID_NO:
		Close(TRUE);
	}
    } else Close(TRUE);
}



void LogoFrame::SetUpMenu(){
	int i;
	if(!menuBar)
		menuBar = new wxMenuBar( wxMB_DOCKABLE );
	else
		for(i=menuBar->GetMenuCount()-1;i>=0;i--)
			delete menuBar->Remove(i);

	
	wxMenu *fileMenu = new wxMenu;
	fileMenu->Append( Menu_File_Load, _T("Load Logo Session \tCtrl-O"));
	fileMenu->Append( Menu_File_Save, _T("Save Logo Session \tCtrl-S"));
	fileMenu->Append( Menu_File_Save_As, _T("Save As..."));
	fileMenu->AppendSeparator();
	fileMenu->Append( Menu_File_Page_Setup, _T("Page Setup"));
	fileMenu->Append( Menu_File_Print_Text, _T("Print Text Window"));
	fileMenu->Append( Menu_File_Print_Text_Prev, _T("Print Preview Text Window"));
	fileMenu->Append( Menu_File_Print_Turtle, _T("Print Turtle Graphics"));
	fileMenu->Append( Menu_File_Print_Turtle_Prev, _T("Turtle Graphics Print Preview"));
	fileMenu->AppendSeparator();
	fileMenu->Append(Menu_File_Quit, _T("Quit UCBLogo \tCtrl-Q"));
	
	
	wxMenu *editMenu = new wxMenu;
		
	menuBar->Append(fileMenu, _T("&File"));
	menuBar->Append(editMenu, _T("&Edit"));

	wxMenu *logoMenu = new wxMenu;
// #ifdef __WXMSW__
// 	editMenu->Append(Menu_Edit_Copy, _T("Copy \tCtrl-C"));
// 	editMenu->Append(Menu_Edit_Paste, _T("Paste \tCtrl-V"));
// 
// 	logoMenu->Append(Menu_Logo_Pause, _T("Pause \tCtrl-P"));
// 	logoMenu->Append(Menu_Logo_Stop, _T("Stop \tCtrl-S"));	
// #else
	editMenu->Append(Menu_Edit_Copy, _T("Copy \tCtrl-C"));
	editMenu->Append(Menu_Edit_Paste, _T("Paste \tCtrl-V"));

	logoMenu->Append(Menu_Logo_Pause, _T("Pause \tAlt-P"));
	logoMenu->Append(Menu_Logo_Stop, _T("Stop \tAlt-S"));
// #endif
	menuBar->Append(logoMenu, _T("&Logo"));
	
	wxMenu *fontMenu = new wxMenu;
	fontMenu->Append(Menu_Font_Choose, _T("Select Font..."));
	fontMenu->Append(Menu_Font_Inc, _T("Increase Font Size \tCtrl-+"));
	fontMenu->Append(Menu_Font_Dec, _T("Decrease Font Size \tCtrl--"));
	menuBar->Append(fontMenu, _T("&Font"));
	
	/*wxMenu *helpMenu = new wxMenu;
	helpMenu->Append(Menu_Help_Man, _T("Browse Online Manual"));
	menuBar->Append(helpMenu, _T("&Help"));*/
	
	SetMenuBar(menuBar);
}
void LogoFrame::DoCopy(wxCommandEvent& WXUNUSED(event)){
	wxTerminal::terminal->DoCopy();
}

void LogoFrame::DoPaste(wxCommandEvent& WXUNUSED(event)){
	wxTerminal::terminal->DoPaste();
}

extern "C" void new_line(FILE *);
int firstloadsave = 1;
extern "C" void *save_name;

void doSave(char * name);
void doLoad(char * name);

extern "C" void *cons(void*, void*);
extern "C" void lsave(void*);

void LogoFrame::OnSave(wxCommandEvent& event) {
    if (save_name != NIL) {
	lsave(cons(save_name, NIL));
    } else {
	OnSaveAs(event);
    }
}

void LogoFrame::OnSaveAs(wxCommandEvent& WXUNUSED(event)) {
	wxFileDialog dialog(this,
			    _T("Save Logo Workspace"),
			    (firstloadsave ?
			      wxStandardPaths::Get().GetDocumentsDir() :
			      ""),
			    wxEmptyString,
			    _T("Logo workspaces(*.lg)|*.lg|All files(*)|*"),
//			    "*",
			    wxFD_SAVE|wxFD_OVERWRITE_PROMPT|wxFD_CHANGE_DIR
			    );
	
//	dialog.SetFilterIndex(1);
	if (dialog.ShowModal() == wxID_OK)
	{
	    doSave((char *)dialog.GetPath().char_str(wxConvUTF8));
	    new_line(stdout);
	}
    firstloadsave = 0;
}

void LogoFrame::OnLoad(wxCommandEvent& WXUNUSED(event)){
	wxFileDialog dialog
	(
	 this,
	 _T("Load Logo Workspace"),
	 (firstloadsave ?
	    wxStandardPaths::Get().GetDocumentsDir() :
			  ""),
	 wxEmptyString,
	 _T("Logo workspaces(*.lg)|*.lg|All files(*)|*"),
//	 "*",
	 wxFD_OPEN|wxFD_FILE_MUST_EXIST|wxFD_CHANGE_DIR
	 );
		
	if (dialog.ShowModal() == wxID_OK) {
	    doLoad((char *)dialog.GetPath().char_str(wxConvUTF8));
	    new_line(stdout);
	}
    firstloadsave = 0;
}


void LogoFrame::OnPrintText(wxCommandEvent& WXUNUSED(event)){
	wxHtmlEasyPrinting *htmlPrinter=wxTerminal::terminal->htmlPrinter;
	if(!htmlPrinter){
		htmlPrinter = new wxHtmlEasyPrinting();
		int fontsizes[] = { 6, 8, 12, 14, 16, 20, 24 };
		htmlPrinter->SetFonts(_T("Courier"),_T("Courier"), fontsizes);
	}
	wxString *textString = wxTerminal::terminal->get_text();
	
	
	htmlPrinter->PrintText(*textString);	
	delete textString;
}

void LogoFrame::OnPrintTextPrev(wxCommandEvent& WXUNUSED(event)){
	wxHtmlEasyPrinting *htmlPrinter=wxTerminal::terminal->htmlPrinter;
	if(!htmlPrinter){
		htmlPrinter = new wxHtmlEasyPrinting();
		int fontsizes[] = { 6, 8, 12, 14, 16, 20, 24 };
		htmlPrinter->SetFonts(_T("Courier"),_T("Courier"), fontsizes);
	}
	wxString *textString = wxTerminal::terminal->get_text();
	
	htmlPrinter->PreviewText(*textString,_T(""));
	
}

extern "C" void wxSetFont(char *fm, int sz);

void LogoFrame::OnSelectFont(wxCommandEvent& WXUNUSED(event)) {
    wxFontData data;
    data.SetInitialFont(wxTerminal::terminal->GetFont());

    wxFontDialog dialog(this, data);
    if ( dialog.ShowModal() == wxID_OK )
    {
        wxFontData retData = dialog.GetFontData();
        wxFont font = retData.GetChosenFont();

	wxSetFont((char *)font.GetFaceName().char_str(wxConvUTF8), 
		  font.GetPointSize());	
    }    
}

void LogoFrame::OnIncreaseFont(wxCommandEvent& WXUNUSED(event)){
	int expected;
	
	wxFont font = wxTerminal::terminal->GetFont();
	expected = font.GetPointSize()+1;
	
	// see that we have the font we are trying to use
	// since for some fonts, the next size is +2
	while(font.GetPointSize() != expected && expected <= 24){
		expected++;
		font.SetPointSize(expected);
	}

	wxSetFont(wx_font_face, expected);
	
}

void LogoFrame::OnDecreaseFont(wxCommandEvent& WXUNUSED(event)){
	int expected;

	wxFont font = wxTerminal::terminal->GetFont();
	expected = font.GetPointSize()-1;
	
	// see that we have the font we are trying to use
	while(font.GetPointSize() != expected && expected >= 6){
		expected--;
		font.SetPointSize(expected);
	}	

	wxSetFont(wx_font_face, expected);

}

extern "C" void *Unbound;

extern "C" void *IncreaseFont(void *) {
    wxCommandEvent dummy;
    logoFrame->OnIncreaseFont(dummy);
    return Unbound;
}

extern "C" void *DecreaseFont(void *) {
    wxCommandEvent dummy;
    logoFrame->OnDecreaseFont(dummy);
    return Unbound;
}
 
void LogoFrame::AdjustSize() {
  int char_width, char_height;	
  wxTerminal::terminal->GetCharSize(&char_width, &char_height);
  wxSize sz(char_width * TERM_COLS, char_height * TERM_ROWS + 5 );
  SetClientSize(sz);
  //Layout();
}

void LogoFrame::DoStop(wxCommandEvent& WXUNUSED(event)){
  logo_stop_flag = 1;
}


void LogoFrame::DoPause(wxCommandEvent& WXUNUSED(event)){
  logo_pause_flag = 1;
}

void LogoFrame::OnEditCloseAccept(wxCommandEvent& WXUNUSED(event)){
	editWindow->OnCloseAccept();
}
void LogoFrame::OnEditCloseReject(wxCommandEvent& WXUNUSED(event)){
	editWindow->OnCloseReject();
}
void LogoFrame::OnEditPrint(wxCommandEvent& WXUNUSED(event)){
	editWindow->DoPrint();
}
void LogoFrame::OnEditCopy(wxCommandEvent& WXUNUSED(event)){
	editWindow->DoCopy();
}
void LogoFrame::OnEditCut(wxCommandEvent& WXUNUSED(event)){
	editWindow->DoCut();
}
void LogoFrame::OnEditPaste(wxCommandEvent& WXUNUSED(event)){
	editWindow->Paste();
}
void LogoFrame::OnEditFind(wxCommandEvent& WXUNUSED(event)){
	editWindow->OnFind();
}
void LogoFrame::OnEditFindNext(wxCommandEvent& WXUNUSED(event)){
	editWindow->OnFindNext();
}
void LogoFrame::OnEditSave(wxCommandEvent& WXUNUSED(event)){
	editWindow->OnSave();
}

void LogoFrame::SetUpEditMenu(){
	int i;
	for(i=menuBar->GetMenuCount()-1;i>=0;i--)
		delete menuBar->Remove(i);
	
	wxMenu *fileMenu = new wxMenu;
	fileMenu->Append( Edit_Menu_File_Close_Accept, _T("Close and Accept Changes \tAlt-A"));
	fileMenu->Append( Edit_Menu_File_Close_Reject, _T("Close and Revert Changes \tAlt-R"));
	fileMenu->AppendSeparator();
	fileMenu->Append( Edit_Menu_File_Page_Setup, _T("Page Setup"));
	fileMenu->Append( Edit_Menu_File_Print_Text, _T("Print... \tCtrl-P"));
	
	wxMenu *editMenu = new wxMenu;
	
	menuBar->Append(fileMenu, _T("&File"));
	menuBar->Append(editMenu, _T("&Edit"));
	
	
	editMenu->Append(Edit_Menu_Edit_Cut, _T("Cut \tCtrl-X"));
	editMenu->Append(Edit_Menu_Edit_Copy, _T("Copy \tCtrl-C"));
	editMenu->Append(Edit_Menu_Edit_Paste, _T("Paste \tCtrl-V"));
	editMenu->AppendSeparator();
	editMenu->Append(Edit_Menu_Edit_Find, _T("Find... \tCtrl-F"));
	editMenu->Append(Edit_Menu_Edit_Find_Next, _T("Find Next \tCtrl-G"));
	
	wxMenu *fontMenu = new wxMenu;
	fontMenu->Append(Menu_Font_Choose, _T("Select Font..."));
	fontMenu->Append(Menu_Font_Inc, _T("Increase Font Size \tCtrl-+"));
	fontMenu->Append(Menu_Font_Dec, _T("Decrease Font Size \tCtrl--"));
	menuBar->Append(fontMenu, _T("&Font"));
	
	
	logoFrame->SetMenuBar(menuBar);
}

     

// ----------------------------------------------------------------------------
// wxTerminal
// ----------------------------------------------------------------------------

BEGIN_DECLARE_EVENT_TYPES()
  DECLARE_EVENT_TYPE(wxEVT_MY_CUSTOM_COMMAND, 7777)
  END_DECLARE_EVENT_TYPES()
  DEFINE_EVENT_TYPE(wxEVT_MY_CUSTOM_COMMAND)

#define EVT_MY_CUSTOM_COMMAND(id, fn) \
    DECLARE_EVENT_TABLE_ENTRY( \
        wxEVT_MY_CUSTOM_COMMAND, id, -1, \
        (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)&fn, \
        (wxObject *) NULL \
    ),


BEGIN_DECLARE_EVENT_TYPES()
  DECLARE_EVENT_TYPE(wxEVT_TERM_CUSTOM_COMMAND, 7777)
  END_DECLARE_EVENT_TYPES()
  DEFINE_EVENT_TYPE(wxEVT_TERM_CUSTOM_COMMAND)

#define wxEVT_TERM_CUSTOM_COMMAND(id, fn) \
    DECLARE_EVENT_TABLE_ENTRY( \
        wxEVT_TERM_CUSTOM_COMMAND, id, -1, \
        (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)&fn, \
        (wxObject *) NULL \
    ),


BEGIN_EVENT_TABLE(wxTerminal, wxWindow)
EVT_ERASE_BACKGROUND(wxTerminal::OnEraseBackground)
EVT_PAINT(wxTerminal::OnPaint)
EVT_CHAR(wxTerminal::OnChar)
EVT_LEFT_DOWN(wxTerminal::OnLeftDown)
EVT_LEFT_UP(wxTerminal::OnLeftUp)
EVT_MOTION(wxTerminal::OnMouseMove)
//EVT_MY_CUSTOM_COMMAND(-1, wxTerminal::Flush)
EVT_SIZE(wxTerminal::OnSize)
EVT_KILL_FOCUS(wxTerminal::LoseFocus)
END_EVENT_TABLE()

wxCommandEvent * haveInputEvent = new wxCommandEvent(wxEVT_MY_CUSTOM_COMMAND);

extern "C" void color_init(void);

 wxTerminal::wxTerminal(wxWindow* parent, wxWindowID id,
               const wxPoint& pos,
               int width, int height,
               const wxString& name) :
  wxScrolledWindow(parent, id, pos, wxSize(-1, -1), wxWANTS_CHARS|wxVSCROLL, name)
//    wxScrolledWindow(parent, id, pos, wxSize(-1, -1), wxWANTS_CHARS, name)
{
  //allocating char structures.
  term_chars = (wxterm_char_buffer *) malloc(sizeof(wxterm_char_buffer));
  memset(term_chars, '\0', sizeof(wxterm_char_buffer));
  term_lines = (wxterm_line_buffer *) malloc(sizeof(wxterm_line_buffer));
  memset(term_lines, 0, sizeof(wxterm_line_buffer));
  term_chars->next = 0;
  term_lines->next = 0;

  //initializations
  curr_line_pos.buf = term_lines;
  curr_line_pos.offset = 0;
  line_of(curr_line_pos).buf = term_chars;
  line_of(curr_line_pos).offset = 0;

  curr_char_pos.buf = term_chars;
  curr_char_pos.offset = 0;
  //curr_char_pos line_length not used!

  //initializing history
  hist_inptr = hist_outptr = cmdHistory; 

  m_width = width;
  m_height = height;


  m_currMode = 0;
  y_max = 0;
  x_max = m_width - 1;


  // start us out not in char mode
  logo_char_mode = 0;
  // For printing the text
  htmlPrinter = 0;
  //  set_mode_flag(DESTRUCTBS);
  wxTerminal::terminal = this;
  int
    i;

  m_selecting = FALSE;
  m_selx1 = m_sely1 = m_selx2 = m_sely2 = 0;
  m_seloldx1 = m_seloldy1= m_seloldx2 = m_seloldy2 = 0;
  //m_marking = FALSE;
  m_curX = -1;
  m_curY = -1;

  //  m_boldStyle = FONT;

  GetColors(m_colors);

    color_init();
  SetBackgroundStyle(wxBG_STYLE_CUSTOM);
  SetBackgroundColour(TurtleCanvas::colors[m_curBG]);
  SetMinSize(wxSize(50, 50));

  for(i = 0; i < 16; i++)
    m_colorPens[i] = wxPen(m_colors[i], 1, wxSOLID);

  m_printerFN = 0;
  m_printerName = 0;

  wxClientDC
    dc(this);
  
  GetCharSize(&m_charWidth, &m_charHeight);
  //dc.GetTextExtent("M", &m_charWidth, &m_charHeight);
  //  m_charWidth--;

  m_inputReady = FALSE;
  m_inputLines = 0;
  
  //  int x, y;
  //GetSize(&x, &y);  
  
  //  parent->SetSize(-1,-1, m_charWidth * width, m_charHeight * height + 1);
  //  SetScrollbars(m_charWidth, m_charHeight, 0, 30);
  //SetScrollRate(0, m_charHeight);
  //SetVirtualSize(m_charWidth * width, 2 * m_charHeight);  //1 row (nothing displayed yet)


  //  ResizeTerminal(width, height);

}

wxTerminal::~wxTerminal()
{
  //clean up the buffers
  wxTerminal::terminal = 0;
}

void wxTerminal::deferUpdate(int flag) {
    if (flag)
	set_mode_flag(DEFERUPDATE);
    else
	clear_mode_flag(DEFERUPDATE);
}

void wxTerminal::set_mode_flag(int flag) {
  m_currMode |= flag;
}

void wxTerminal::clear_mode_flag(int flag) {
  m_currMode &= ~flag;
}


bool
wxTerminal::SetFont(const wxFont& font)
{
  wxWindow::SetFont(font);

  m_normalFont = font;
  m_underlinedFont = font;
  m_underlinedFont.SetUnderlined(TRUE);
  m_boldFont = font;
  m_boldFont.SetWeight(wxFONTWEIGHT_BOLD);
  m_boldUnderlinedFont = m_boldFont;
  m_boldUnderlinedFont.SetUnderlined(TRUE);
  GetCharSize(&m_charWidth, &m_charHeight);
  //  wxClientDC
  //	  dc(this);
  
  //  dc.GetTextExtent("M", &m_charWidth, &m_charHeight);
  //  m_charWidth--;
  ResizeTerminal(m_width, m_height);
  if(!(m_currMode & DEFERUPDATE)) {
    Refresh();
  } 
  return TRUE;
}

void 
wxTerminal::GetCharSize(int *cw, int *ch) {
  wxClientDC
    dc(this);
  
  //int dummy;
  //dc.GetTextExtent("M", cw, &dummy);
  //dc.GetTextExtent("(", &dummy, ch);

  int descent, extlead; 
  dc.GetTextExtent(wxString("M", wxConvUTF8, wxString::npos), cw, ch, &descent, &extlead);
  //for the tails of g's and y's, if needed.
#ifdef __WXMSW__
    *ch += descent + extlead + 1;
#endif
}

void
wxTerminal::GetColors(wxColour colors[16] /*, wxTerminal::BOLDSTYLE boldStyle*/)
{
    colors[0] = wxColour(0, 0, 0);                             // black
    colors[1] = wxColour(255, 0, 0);                           // red
    colors[2] = wxColour(0, 255, 0);                           // green
    colors[3] = wxColour(255, 0, 255);                         // yellow
    colors[4] = wxColour(0, 0, 255);                           // blue
    colors[5] = wxColour(255, 255, 0);                         // magenta
    colors[6] = wxColour(0, 255, 255);                         // cyan
    colors[7] = wxColour(255, 255, 255);                       // white
    colors[8] = wxColour(0, 0, 0);                             // black
    colors[9] = wxColour(255, 0, 0);                           // red
    colors[10] = wxColour(0, 255, 0);                          // green
    colors[11] = wxColour(255, 0, 255);                        // yellow
    colors[12] = wxColour(0, 0, 255);                          // blue
    colors[13] = wxColour(255, 255, 0);                        // magenta
    colors[14] = wxColour(0, 255, 255);                        // cyan
    colors[15] = wxColour(255, 255, 255);                      // white
}



/*
 * ProcessInput()
 *
 * passes input to logo, one line at a time
 * and prints to terminal as well
 *
 * assumes cursor is set at last logo position already 
 */
void wxTerminal::ProcessInput() {
  //pass input up to newline.
  int i;
  for(i = 0; i < input_index; i++) {
    if(input_buffer[i] == '\n') break;
  }
  PassInputToTerminal(i+1,input_buffer); //include '\n'
  last_logo_x = cursor_x;
  last_logo_y = cursor_y;
  
  PassInputToInterp();
  m_inputLines--;
  if(!m_inputLines) m_inputReady = FALSE;  
}


/*
 * Flush()
 * 
 * Handles output from logo
 */
void  wxTerminal::Flush (){
  set_mode_flag(BOLD);

  if(output_index == 0) {
    clear_mode_flag(BOLD);
    return;
  }


  bool cursor_moved = FALSE;

  if(input_index != 0){
    // set the cursor in the proper place 
    setCursor(last_logo_x, last_logo_y);
    //    scroll_region(last_logo_y, last_logo_y + 1, -1);
    cursor_moved = TRUE;
    
  }    //calculate new cursor location
  if (output_index != 0) {
    ClearSelection(); //eventually, only clear if overlap with updated region?  
    PassInputToTerminal(output_index, output_buffer);
    output_index = 0;
  }

  //save current cursor position to last_logo
  last_logo_x = cursor_x;
  last_logo_y = cursor_y;

  clear_mode_flag(BOLD);
  if(cursor_moved/* && readingInstruction*/){   
    cursor_moved = FALSE;

    if(m_inputReady && readingInstruction) {
      ProcessInput();
    }
    else {
      //pass the input up to the current input location to terminal
      //e.g. cpos is 6, then pass chars 0 to 5 to terminal (6 chars)
      PassInputToTerminal(input_current_pos, input_buffer);
      int new_cursor_x = cursor_x, new_cursor_y = cursor_y;
      //pass the rest of input to terminal
      //e.g. inputindex is 20, then pass chars 6 to 19 to terminal (14 chars)
      PassInputToTerminal(input_index-input_current_pos, input_buffer+input_current_pos);
      // set last_input coords
      last_input_x = cursor_x;
      last_input_y = cursor_y;
      // and set cursor back to proper location
      setCursor(new_cursor_x, new_cursor_y);
    }
  }

  if(!(m_currMode & DEFERUPDATE)) {
    Refresh();
  }

}


/* 
	PassInputToInterp() 
        takes all characters in the input buffer 
	up to the FIRST '\n' and hands
	them off to the logo interpreter
        if logo_char_mode, then just send the character
 ** does not edit cursor locations!
 */
void wxTerminal::PassInputToInterp() {
  int i;  
  if(logo_char_mode){
    //buff[buff_index++] = input_buffer[--input_index];
    buff_push(input_buffer[--input_index]);
    
    input_index = 0;
    input_current_pos = 0;
  }
  else {
    for (i = 0; i < input_index; i++) {
      buff_push(input_buffer[i]);	
      if(input_buffer[i] == '\n') {
	break;
      }
    }
    int saw_newline = i;

    //so create a string of size i+1 and copy the contents over
    char *histline = (char *)malloc(1+i);
    for(i = 0; i < saw_newline; i++) {
      histline[i] = input_buffer[i];
    }
    histline[saw_newline] = 0;
    //put it in the history
    *hist_inptr++ = histline;
    if (hist_inptr >= &cmdHistory[HIST_MAX]) {  //wraparound
      hist_inptr = cmdHistory;
    }
    if (*hist_inptr) { 
      free(*hist_inptr);
      *hist_inptr = 0;
    }
    hist_outptr = hist_inptr;

    for(i = saw_newline + 1; i < input_index; i++) {
      input_buffer[i - saw_newline - 1] = input_buffer[i];
    }
    // a to b, length is b - a + 1
    input_index = input_index - saw_newline - 1;
    input_current_pos = input_index;
  }
}


void wxTerminal::DoCopy(){
	
	if (wxTheClipboard->Open())
	{
		// This data objects are held by the clipboard, 
		// so do not delete them in the app.
		wxTheClipboard->SetData( new wxTextDataObject(GetSelection()) );
		wxTheClipboard->Close();
	}
	
}


void wxTerminal::DoPaste(){
	if (wxTheClipboard->Open())
	{
		if (wxTheClipboard->IsSupported( wxDF_TEXT ))
		{
		  wxClientDC dc(this);

		  wxTextDataObject data;
		  wxTheClipboard->GetData( data );
		  wxString s = data.GetText();
		  
		  int i; 
		  //char chars[2];
		  char c;
		  int num_newlines = 0;
		  int len;
		  char prev = ' ';
		  for (i = 0; i < s.Length() && input_index < MAXINBUFF; i++){
		    len = 1;
		    c = s.GetChar(i);
		    if (c == '\n') {
		      num_newlines++;
		    }
		    if (prev == ' ' && c == ' ') {
		      continue;
		    }
		    prev = c;
		    if(input_index < MAXINBUFF) {
		      input_buffer[input_index++] = c;
		    }
		    else {
		      break;
		    }
		    ClearSelection();
		    PassInputToTerminal(len, &c);
		  }
		  m_inputLines = num_newlines;
		  input_current_pos = input_index;
		}  
		wxTheClipboard->Close();
	}
	
}


void wxTerminal::LoseFocus (wxFocusEvent & event) {
}


extern "C" int keyact_set(void);
extern "C" void do_keyact(int);

/*
 OnChar
 is called each time the user types a character
 in the main terminal window
 */


void
wxTerminal::OnChar(wxKeyEvent& event)
{
  ClearSelection();
  int
      keyCode = 0,
      len;
  char buf[10];


  keyCode = (int)event.GetKeyCode();
  if (!readingInstruction && !reading_char_now && keyact_set()) {
    if (keyCode == WXK_RETURN) {
      keyCode = '\n';
    }
    else if (keyCode == WXK_BACK) {
      keyCode = 8;
    }
    else if (keyCode >= WXK_START) {
	/* ignore it */
      return;  //not sure about this (evan)
    } 
    else {
      
    }
    if (event.ControlDown()) keyCode &= 0237;
    if (event.AltDown()) keyCode += 0200;

    do_keyact(keyCode);
  }
  else if(logo_char_mode){
    if (keyCode == WXK_RETURN) {
      keyCode = '\n';
    }
    else if (keyCode == WXK_BACK) {
      keyCode = 8;
    }
    else if (keyCode >= WXK_START) {
	/* ignore it */
      return;  //not sure about this (evan)
    } 
    else {
      
    }
    if (event.ControlDown()) keyCode &= 0237;
    if (event.AltDown()) keyCode += 0200;
    if(input_index < MAXINBUFF) {
      input_buffer[input_index++] = keyCode;
      input_current_pos++;
      PassInputToInterp();
    }
  }
  else if (keyCode == WXK_RETURN) {
    //the following condition should never happen.
    //input_buffer is size MAXINBUFF+1, to leave room for \n char
    //this is the only code segment that's allowed to add a \n
    //in that last slot.
    if(input_index > MAXINBUFF) fprintf(stderr, "onChar: WXK_RETURN, moved past end of input buffer. Should never happen!\n");  

    
    if(input_current_pos < input_index) {
      setCursor(last_input_x, last_input_y);
    }

    //    buf[0] = 10;
    //buf[1] = 13;
    //len = 2;
    
    input_buffer[input_index++] = '\n';
    input_current_pos = input_index;

    char newline = '\n';
    PassInputToTerminal(1,&newline);

    m_inputReady = TRUE;
    m_inputLines++;

    if(readingInstruction) {
      setCursor(last_logo_x, last_logo_y);
      ProcessInput(); 
    }
    else {
      last_input_x = cursor_x;
      last_input_y = cursor_y;
    }
  }
  else if (keyCode == WXK_BACK) {
    handle_backspace();
  }
  else if (keyCode == WXK_UP) { // up
    handle_history_prev();
  }
  else if  (keyCode == WXK_DOWN) { // down
    handle_history_next();
  }
  else if  (keyCode == WXK_LEFT) { // left    
    handle_left();
  }
  else if  (keyCode == WXK_RIGHT) { // right
    handle_right();
  }
  else if (keyCode == WXK_TAB) { // tab
    //do nothing for now. could be tab completion later.
  }
  else if  (keyCode == WXK_DELETE) { // DEL key
    if(input_current_pos < input_index) {
      handle_right();
      handle_backspace();
    }
  }
  else if  (keyCode == WXK_HOME) {  //HOME key
    handle_home();
  }
  else if  (keyCode == WXK_END) {  //END key
    handle_end();
  }
  else if (keyCode >= WXK_START) {
    /* ignore it */
  } 
  else {
    if(input_index >= MAXINBUFF) return;	

    buf[0] = keyCode;
    len = 1;
    int doInsert = 0;
    if (input_current_pos < input_index ) { // we are in the middle of input
      doInsert = 1;
      int i;
      for (i = input_index; i >= input_current_pos + 1; i--) {
	input_buffer[i] = input_buffer[i - 1]; 
      }
      input_buffer[input_current_pos] = keyCode;
      input_index++;
      input_current_pos++;
    }
    else {
      input_buffer[input_index++] = keyCode;
      input_current_pos++;
    }

    if (doInsert) {
      cur_x = cursor_x; cur_y = cursor_y;


      //remember, input_current_pos - 1 has last character typed
      PassInputToTerminal(input_index - (input_current_pos - 1),
			  (input_buffer + (input_current_pos - 1)));
	
      //now the cursor is where the last input position is
      last_input_x = cursor_x;
      last_input_y = cursor_y;
	
      //set cursor back to cursorPos
      if (cur_x == x_max)
	setCursor(0, cur_y + 1);
      else
	setCursor(cur_x+1, cur_y);
    } 
    else {
      PassInputToTerminal(len, buf);
      //now the cursor is where the last input position is
      last_input_x = cursor_x;
      last_input_y = cursor_y;	
    }   
  }

  if(!(m_currMode & DEFERUPDATE)) {
    Refresh();
  }

}


void wxTerminal::handle_backspace() {
  if (input_index == 0)
    return;
    

  if (input_current_pos == 0)
    return;
    
  bool removing_newline = FALSE;
  if(input_buffer[input_current_pos-1] == '\n') {
    removing_newline = TRUE;
  }
    
  for (int i = input_current_pos; i < input_index; i++) {
    input_buffer[i-1] = input_buffer[i]; 
  }
  input_index--;
  input_current_pos--;

  cur_x = cursor_x - 1, cur_y = cursor_y;
  if(cur_x < 0) {
    wxterm_linepos cpos = GetLinePosition(cursor_y - 1);
    // x_max if wrapped line,  line_length otherwise.
    cur_x = min(x_max, line_of(cpos).line_length);
    cur_y = cursor_y - 1;
    setCursor(cur_x, cur_y);
  }
  else {
    setCursor(cur_x, cur_y);
  }
    
  PassInputToTerminal(input_index - input_current_pos,
		      input_buffer + input_current_pos);
    
  //cursor_x , cursor_y now at input's last location
  last_input_x = cursor_x;
  last_input_y = cursor_y;
    
    
  if(removing_newline) {
    //add a second newline, to erase contents of the last
    //input line.
    //this causes a very specific "feature"....
    //if last input line contains other noninput chars
    //then doing this will erase them too
    //this situation can happen when you use setcursor and hit Backspace...
    //it's a very specific situation that should not clash with 
    //intended behavior...
    char nl = '\n';
    PassInputToTerminal(1, &nl);
    PassInputToTerminal(1, &nl);  //pass two newlines

    m_inputLines--; //merged two lines
  }
  else {
    char spc = ' ';
    PassInputToTerminal(1, &spc);
  }
    
  //set cursor back to backspace'd location
  setCursor(cur_x,cur_y); 
}

void wxTerminal::handle_home() {
  setCursor(last_logo_x, last_logo_y);
  input_current_pos = 0;
}

void wxTerminal::handle_end() {
  setCursor(last_input_x, last_input_y);
  input_current_pos = input_index;
}


void wxTerminal::handle_clear_to_end() {
#if 0
  //old code that put spaces everyhwere...
  int xval;
  int yval;

  xval = cursor_x;
  yval = cursor_y;

  int i;

  for (i = input_current_pos; i < input_index; i++) {
      if(input_buffer[i] == '\n') {
	input_buffer[i] = '\n';
      }
      else {	    
	input_buffer[i] = ' ';
      }
  }
  PassInputToTerminal(input_index-input_current_pos, &input_buffer[i]);
  
  setCursor(xval, yval); 
#else
  //make the current position the end of the buffer 
  //update line structure accordingly

  char_of(curr_char_pos) = '\0';
  line_of(curr_line_pos).line_length = cursor_x;
  y_max = cursor_y;
#endif
}



// warning: the history buffer WRAPS around!
// so to detect for the beginning/end, check for NULL string pointer

void wxTerminal::handle_history_prev() {
  
  // Now get a history entry
  if (--hist_outptr < cmdHistory) {
    hist_outptr = &cmdHistory[HIST_MAX-1];
  }

  if (*hist_outptr == 0) {
    wxBell();
    hist_outptr++;  //put it back to where it was
    if (hist_outptr >= &cmdHistory[HIST_MAX]) {  //wraparound
      hist_outptr = cmdHistory;      
    }
    return;
  }

#if 0
  //if we're not currently storing anything 
  //in latest_history_buffer:
  //store current input buffer in it.
  //we are about to change the input
  if(!latest_history_stored) {
    strcpy(latest_history_buffer, input_buffer);
    latest_history_buffer[input_index] = 0;
    latest_history_stored++;
  }
#endif

  handle_home();  //go to the start of input

  int hist_len = strlen((const char *) *hist_outptr);
  strcpy(input_buffer, (char *)*hist_outptr);
  PassInputToTerminal(hist_len, input_buffer);

  m_inputLines = 0;

  input_current_pos = hist_len;

  handle_clear_to_end();  //clear to the old end of input_buffer

  input_index = hist_len;

  //cursor_x , cursor_y now at input's last location
  last_input_x = cursor_x;
  last_input_y = cursor_y;	
}

void wxTerminal::handle_history_next() {
  if (*hist_outptr != 0) { 
      hist_outptr++;
  }

  if (hist_outptr >= &cmdHistory[HIST_MAX]) {  //wraparound
    hist_outptr = cmdHistory;
  }


  if(*hist_outptr == 0) {
#if 0
    //if latest_history_buffer is not empty, put that here.
    if(latest_history_stored) {	
      handle_home();  //go to front
      int latest_len = strlen(latest_history_buffer);
      PassInputToTerminal(latest_len, latest_history_buffer);
      strcpy(input_buffer, latest_history_buffer);
      input_current_pos = latest_len;

      handle_clear_to_end();  //clear to old end of input

      input_index = latest_len;

      m_inputLines = 0;

      latest_history_stored--;
      
      //cursor_x , cursor_y now at input's last location
      last_input_x = cursor_x;
      last_input_y = cursor_y;	
    }
    else {
      wxBell();    
    }
#else
    wxBell();
    handle_home();
    handle_clear_to_end();
    input_current_pos = 0;
    input_index = 0;
    m_inputLines = 0;
      
    //cursor_x , cursor_y now at input's last location
    last_input_x = cursor_x;
    last_input_y = cursor_y;	

#endif
    return;
  }

    
  handle_home();  //jump to beginning

  int hist_len = strlen((const char *) *hist_outptr);
  strcpy(input_buffer, (char *)*hist_outptr);
  PassInputToTerminal(hist_len, input_buffer);

  m_inputLines = 0;

  input_current_pos = hist_len;

  handle_clear_to_end(); //clear to old end of input_buffer

  input_index = hist_len;
  
  //cursor_x , cursor_y now at input's last location
  last_input_x = cursor_x;
  last_input_y = cursor_y;	
}

void wxTerminal::handle_left() {
  if(input_current_pos > 0) {
    if (cursor_x - 1 < 0) {	  
      //if previous char is a newline, then cursor goes to line_length
      //otherwise, it's a wrapped line, and should go to the end
      // just use min...
      wxterm_linepos cpos = GetLinePosition(cursor_y - 1);
      setCursor(min(x_max, line_of(cpos).line_length), cursor_y - 1);   
    }   
    else {
      setCursor(cursor_x - 1, cursor_y);
    }
    input_current_pos--;
  }
}

void wxTerminal::handle_right() {
  if(input_current_pos < input_index) {
    if (input_buffer[input_current_pos] == '\n' ||
	cursor_x + 1 > x_max) {
      setCursor(0, cursor_y + 1);
    }
    else {
      setCursor(cursor_x + 1, cursor_y);	  
    }
    input_current_pos++;
  }
}


void wxTerminal::setCursor (int x, int y, bool fromLogo) {


  int vis_x,vis_y;
  GetViewStart(&vis_x,&vis_y);


  if(fromLogo) {
    //need to change to unscrolled coordinates

    if(x < 0 || x > m_width ||
       y < 0 || y > m_height) {
      return;
    }
    //GetViewStart(&cursor_x,&cursor_y);

    cursor_x = x;
    cursor_y = vis_y + y;

    
  }
  else {
    cursor_x = x;
    cursor_y = y;
  }


  int want_x, want_y;
  want_x = cursor_x;
  want_y = cursor_y;

  if(cursor_y < 0) {
    fprintf(stderr, "cursor_y < 0 in setcursor. BAD \n");
  }
  cursor_y = min(cursor_y,y_max);
  curr_line_pos = GetLinePosition(cursor_y);
  curr_char_pos = line_of(curr_line_pos);
  if(cursor_y < want_y ||  
     cursor_x > curr_char_pos.line_length) {
    cursor_x = curr_char_pos.line_length;
  }
  curr_char_pos.offset = curr_char_pos.offset + cursor_x;
  adjust_charpos(curr_char_pos);

  if(fromLogo && 
     (cursor_x != want_x ||
      cursor_y != want_y)) {
    //add spaces until we get to desired location

    if(cursor_x > x_max) {
      cursor_x = 0;
      cursor_y++;
      inc_linepos(curr_line_pos);
    }

    char space = ' ';  
    char newline = '\n';

    while(cursor_y != want_y) {
      PassInputToTerminal(1,&newline);
    }
    while(cursor_x != want_x) {
      PassInputToTerminal(1,&space);
    }
  }

  if(!(m_currMode & DEFERUPDATE)) {
    if(cursor_y >= vis_y &&
       cursor_y <= vis_y + m_height - 1) {
    }
    else {

      Scroll(-1, cursor_y);
      
      //      Refresh();
    }
  }
}


void wxTerminal::OnSize(wxSizeEvent& event) {      
	
  int x, y;
  GetSize(&x, &y);
  
  //leave one char on the right for scroll bar width
  if (m_width == (x / m_charWidth) - 1 && m_height == y / m_charHeight)
    return;
  x = (x / m_charWidth) - 1;
  y = y / m_charHeight;
  
  if (x < 1) 
    x = 1;
  if (y < 1) 
    y = 1;
  ResizeTerminal(x,y);
  Scroll(-1, cursor_y);
  Refresh();
}

wxMemoryDC * currentMemDC = NULL;
wxBitmap * currentBitmap = NULL;
int oldWidth = -1;
int oldHeight = -1;

void wxTerminal::OnEraseBackground(wxEraseEvent &WXUNUSED(event)) 
{
  //don't erase background.. for double buffering!
}

extern "C" void wxSetTextColor(int fg, int bg) {
    wxTerminal::terminal->m_curFG = fg;
    wxTerminal::terminal->m_curBG = bg;
    wxTerminal::terminal->SetBackgroundColour(
		TurtleCanvas::colors[wxTerminal::terminal->m_curBG]);
}

void wxTerminal::OnPaint(wxPaintEvent &WXUNUSED(event)) 
{
  wxBufferedPaintDC dc(this);

  DoPrepareDC(dc);
  dc.SetBackground(TurtleCanvas::colors[m_curBG]);
  dc.Clear();
  OnDraw(dc);
}

void wxTerminal::OnDraw(wxDC& dc)
{  
  //DebugOutputBuffer();
  
  wxRect rectUpdate = GetUpdateRegion().GetBox();
  CalcUnscrolledPosition(rectUpdate.x, rectUpdate.y,
			 &rectUpdate.x, &rectUpdate.y);
  int lineFrom = rectUpdate.y / m_charHeight;
  int lineTo = rectUpdate.GetBottom() / m_charHeight;

  if ( lineTo > y_max)
    lineTo = y_max;
  
  //find the position!
  wxterm_linepos tlpos;
  tlpos.buf = term_lines;
  wxterm_charpos tline;
  tlpos.offset = lineFrom;
  adjust_linepos(tlpos);

  for ( int line = lineFrom; line <= lineTo; line++ )
  {
    tline = line_of(tlpos);
    for ( int col = 0; col < tline.line_length; col++ ) {      
      DrawText(dc, m_curFG, m_curBG, mode_of(tline), col, line, 1, &char_of(tline));
      inc_charpos(tline);
    }

    inc_linepos(tlpos);
  }

  //draw text cursor as line if visible
  if(lineFrom <= cursor_y  && cursor_y <= lineTo &&
     !(m_currMode & CURSORINVISIBLE)) {
    int c_x = cursor_x;
    int c_y = cursor_y;
    int t_x = c_x*m_charWidth;
    int t_y = c_y*m_charHeight;
    dc.SetPen(wxPen(TurtleCanvas::colors[terminal->m_curFG],1));
    dc.DrawLine( t_x, t_y, t_x, t_y + m_charHeight);

  }

  MarkSelection(dc,FALSE);
  
}

// gets the click coordinate (unscrolled) in terms of characters
void wxTerminal::GetClickCoords(wxMouseEvent& event, int *click_x, int *click_y) {
  // pixel coordinates
  *click_x = event.GetX();
  *click_y = event.GetY();
  CalcUnscrolledPosition(*click_x, *click_y, click_x, click_y);

  // convert to character coordinates
  *click_x = *click_x / m_charWidth;
  *click_y = *click_y / m_charHeight;
  if(*click_x < 0) {
    *click_x = 0;
  }
  else if(*click_x > x_max) {
    *click_x = x_max;
  }

  if(*click_y < 0) { 
    *click_y = 0; 
  }
  else if(*click_y > y_max) {
    *click_y = y_max;
  }
}

void
wxTerminal::OnLeftDown(wxMouseEvent& event)
{
  m_selecting = TRUE;
  int click_x, click_y;
  GetClickCoords(event, &click_x, &click_y);

  m_selx1 = m_selx2 = click_x;
  m_sely1 = m_sely2 = click_y;
  //Refresh();

  event.Skip();  //let native handler reset focus
}

void
wxTerminal::OnLeftUp(wxMouseEvent& event)
{
  
  if ((m_sely2 != m_sely1 || m_selx2 != m_selx1))
    {
      if (wxTheClipboard->Open() ) {
	// This data objects are held by the clipboard, 
	// so do not delete them in the app.
	wxTheClipboard->SetData( new wxTextDataObject(GetSelection()) );
	wxTheClipboard->Close();
      }
    }
  m_selecting = FALSE;

  if (HasCapture()) {
    // uncapture mouse
    ReleaseMouse();
  }
}

void
wxTerminal::OnMouseMove(wxMouseEvent& event)
{
  if(m_selecting)
  {

    int click_x, click_y;
    GetClickCoords(event, &click_x, &click_y);
    m_selx2 = click_x;
    m_sely2 = click_y;
          
    if(!HasCapture()) {
      CaptureMouse();
    }      
  }

  if(!(m_currMode & DEFERUPDATE)) {
    Refresh();
  }

}

void
wxTerminal::ClearSelection()
{
  if (m_sely2 != m_sely1 || m_selx2 != m_selx1) {

    m_sely2 = m_sely1;
    m_selx2 = m_selx1;   

  }

  if(!(m_currMode & DEFERUPDATE)) {
    Refresh();
  }

}

void 
wxTerminal::InvertArea(wxDC &dc, int t_x, int t_y, int w, int h, bool scrolled_coord) {

  if(scrolled_coord) {
    CalcScrolledPosition(t_x,t_y,&t_x,&t_y);
    //calculate if out of bounds
    //    if(t_x < 0 || t_x > m_width * m_charWidth ||
    //   t_y < 0 || t_y > m_height * m_charHeight) {
    //  return;
    //}
  }
  if (w > 0 && h > 0) {
#ifndef __WXMAC__
    dc.Blit( t_x, t_y, w, h, &dc, t_x, t_y, wxINVERT);
#endif
  }
}


void
wxTerminal::MarkSelection(wxDC &dc, bool scrolled_coord) {

  int 
    pic_x1, pic_y1,
    pic_x2, pic_y2;

  if(m_sely1 > m_sely2 ||
     (m_sely1 == m_sely2 && m_selx1 > m_selx2)) {
    pic_x1 = m_selx2;
    pic_y1 = m_sely2;
    pic_x2 = m_selx1;
    pic_y2 = m_sely1;
  }
  else {
    pic_x1 = m_selx1;
    pic_y1 = m_sely1;
    pic_x2 = m_selx2;
    pic_y2 = m_sely2;
  }

  if(pic_y1 == pic_y2) {
    InvertArea(dc, 
	       pic_x1 * m_charWidth, pic_y1 * m_charHeight, 
	       (pic_x2 - pic_x1)*m_charWidth, m_charHeight,
	       scrolled_coord);
  }
  else if(pic_y1 < pic_y2) {
    InvertArea(dc, 
	       pic_x1 * m_charWidth, pic_y1 * m_charHeight, 
	       (x_max - pic_x1) * m_charWidth, m_charHeight,
	       scrolled_coord);
    InvertArea(dc, 
	       0, (pic_y1 + 1)*m_charHeight,
	       x_max * m_charWidth, (pic_y2 - pic_y1 - 1)*m_charHeight,
	       scrolled_coord);
    InvertArea(dc, 
	       0, pic_y2*m_charHeight, 
	       pic_x2*m_charWidth, m_charHeight,
	       scrolled_coord);
  }
}

bool
wxTerminal::HasSelection()
{
  return(m_selx1 != m_selx2 || m_sely1 != m_sely2);
}


/*
 * Gets characters from x1,y1 up to , but not including x2,y2
 */
wxString
wxTerminal::GetChars(int x1, int y1, int x2, int y2) 
{
  int tx,ty;
  if(y1 > y2 || 
     (y1 == y2 && x1 > x2)) {
    tx = x1;
    ty = y1;
    x1 = x2;
    y1 = y2;
    x2 = tx;
    y2 = ty;
  }

  //this case from dragging the mouse position off screen.
  if(x1 < 0) x1 = 0;
  if(x2 < 0) x2 = 0;
  if(y1 < 0) y1 = 0;
  if(y2 < 0) y2 = 0;

  wxString ret;

  if(0 < y1 && y1 > y_max) {
    return ret;
  }

  wxterm_charpos a = GetCharPosition(0,y1);

  a.offset = a.offset + min(x1, max(0,a.line_length - 1)); 
  adjust_charpos(a);

  wxterm_charpos b = GetCharPosition(0,min(y2, y_max));
  
  b.offset = b.offset + min(x2, b.line_length); 
  adjust_charpos(b);

  while(a.buf != b.buf) {
    //  size 10, offset 5,  copy 10-5=5 chars... yup
    ret.Append(wxString::FromAscii(a.buf->cbuf+a.offset, WXTERM_CB_SIZE-a.offset));
    if(a.buf->next) {
      a.offset = 0;
      a.buf = a.buf->next;
    }
    else {
      //bad
      fprintf(stderr, "BAD (getchars)\n");
    }
  }
  ret.Append(wxString::FromAscii(a.buf->cbuf+a.offset, b.offset - a.offset));
  return ret;
}

wxString
wxTerminal::GetSelection()
{
  return GetChars(m_selx1,m_sely1,m_selx2,m_sely2);
}

void
wxTerminal::SelectAll()
{
  m_selx1 = 0;
  m_sely1 = 0;
  m_selx2 = x_max;
  m_sely2 = y_max;

  //Refresh();
}

wxterm_linepos wxTerminal::GetLinePosition(int y) 
{
  wxterm_linepos lpos;
  lpos.buf = term_lines;
  lpos.offset = y;
  adjust_linepos(lpos);
  return lpos;
}

wxterm_charpos wxTerminal::GetCharPosition(int x, int y)
{ 
  wxterm_charpos ret = line_of(GetLinePosition(y));

  if(x > ret.line_length) {    
    fprintf(stderr, "invalid longer than linelength: %d\n", ret.line_length);
  }

  
  ret.offset = ret.offset + x;
  adjust_charpos(ret);
  return ret;  
}

void
wxTerminal::DrawText(wxDC& dc, int fg_color, int bg_color, int flags,
                 int x, int y, int len, char *string)
{
  wxString
    str((const char *)string, wxConvUTF8, len);

    if(flags & BOLD)
    {
      if(flags & UNDERLINE)
        dc.SetFont(m_boldUnderlinedFont);
      else
        dc.SetFont(m_boldFont);
    }
    else
    {
      if(flags & UNDERLINE)
        dc.SetFont(m_underlinedFont);
      else
        dc.SetFont(m_normalFont);
    }

  int coord_x, coord_y;
  dc.SetBackgroundMode(wxSOLID);
  dc.SetTextBackground(TurtleCanvas::colors[bg_color]);
  dc.SetTextForeground(TurtleCanvas::colors[fg_color]);
  coord_y = y * m_charHeight; 
  coord_x = x * (m_charWidth);	

  for(unsigned int i = 0; i < str.Length(); i++, coord_x+=m_charWidth){
    //clear the pixels first
    //dc.Blit(coord_x, coord_y, m_charWidth, m_charHeight, &dc, coord_x, coord_y, wxCLEAR);
    dc.DrawText(str.Mid(i, 1), coord_x, coord_y);
    //	  if(flags & BOLD && m_boldStyle == OVERSTRIKE)
    //	  dc.DrawText(str, x + 1, y);
    if(flags & INVERSE) {
      InvertArea(dc, coord_x, coord_y, m_charWidth, m_charHeight);
      //	    dc.Blit( coord_x, coord_y, m_charWidth, m_charHeight, &dc, coord_x, coord_y, wxINVERT);
    }
  }
}

void
wxTerminal::Bell()
{
  wxBell();
}

void 
wxTerminal::RenumberLines(int new_width) 
{
  //m_width is the OLD WIDTH at this point of the code.
  
  wxterm_linepos l_pos;
  l_pos.buf = term_lines;
  l_pos.offset = 0;

  wxterm_charpos c_pos;
  c_pos.buf = term_chars;
  c_pos.line_length = 0;
  c_pos.offset = 0; 
  wxterm_charpos last_logo_pos = GetCharPosition(last_logo_x,last_logo_y);

  //IMPORTANT: 
  //  * line_number stores the current line we're looking at,
  //  * c_pos.line_length is how far into the current line we are
  //  * c_pos.offset is the offset into the BUFFER

  int line_number = 0;
  
  //run until see '\0'
  int next_line = 0; // flag to say "mark next line".
  
  while(char_of(c_pos) != '\0') {
    if(c_pos.buf == curr_char_pos.buf && c_pos.offset == curr_char_pos.offset) {
      cursor_x = c_pos.line_length;
      cursor_y = line_number;
      curr_line_pos = l_pos;
    }
    if(c_pos.buf == last_logo_pos.buf && c_pos.offset == last_logo_pos.offset) {
      last_logo_x = c_pos.line_length;
      last_logo_y = line_number;      
    }
    if(char_of(c_pos) == '\n') {
      next_line = 1;
    }
    else {
      c_pos.line_length++;
      if(c_pos.line_length == new_width) {
	next_line = 1;
      }
    }

    inc_charpos(c_pos);

    if(next_line) {
      line_of(l_pos).line_length = c_pos.line_length;
      inc_linepos(l_pos);

      line_of(l_pos).buf = c_pos.buf;
      line_of(l_pos).offset = c_pos.offset;
      
      c_pos.line_length = 0;
      next_line = 0;
      line_number++;
    }



  }
  if(c_pos.buf == curr_char_pos.buf && c_pos.offset == curr_char_pos.offset) {
    cursor_x = c_pos.line_length;
    cursor_y = line_number;
    curr_line_pos = l_pos;
  }
  if(c_pos.buf == last_logo_pos.buf && c_pos.offset == last_logo_pos.offset) {
    last_logo_x = c_pos.line_length;
    last_logo_y = line_number;      
  }

  line_of(l_pos).line_length = c_pos.line_length;
  y_max = line_number;

  //sanity check on variables
  //fprintf(stderr, "cursor %d %d\n", cursor_x, cursor_y);
  //fprintf(stderr, "lastlogopos xy %d %d\n", last_logo_x, last_logo_y);
}

void
wxTerminal::ResizeTerminal(int width, int height)
{

  /*
  **  Set terminal size
  */
  if(width != m_width) {
    //need to renumber the lines
    RenumberLines(width);
    m_width = width;
    x_max = m_width - 1;
  }
  m_height = height;


  //reset virtual size
  SetScrollRate(0, m_charHeight);
  //number of lines is y_max + 1
  SetVirtualSize(m_width*m_charWidth,(y_max+1)*m_charHeight);
}


void wxTerminal::DebugOutputBuffer() {
  //debugging
  wxterm_linepos lpos;
  lpos.buf = term_lines;
  lpos.offset = 0;
  wxterm_charpos pos_1 = line_of(lpos);
  
  //    fprintf(stderr, "WXTERMINAL STATS: \n  width: %d, height: %d, \n cw: %d, ch: %d \n x_max: %d, y_max: %d \n cursor_x: %d, cursor_y: %d \n last_logo_x : %d, last_logo_y: %d \ncurr_charpos buf %ld offset %d  \ncurr_line buf %ld offset %d\n", m_width, m_height, m_charWidth, m_charHeight, x_max, y_max,cursor_x, cursor_y, last_logo_x, last_logo_y,(long)curr_char_pos.buf, curr_char_pos.offset, (long)curr_line_pos.buf, curr_line_pos.offset);
  //    fprintf(stderr, "WXTERMINAL CHARACTER BUFFER\n###############\n");
  while(char_of(pos_1) != '\0') {
    if(char_of(pos_1) == '\n') {
      fprintf(stderr, "\\n\n");
    }
    else {
      fprintf(stderr,"%c", char_of(pos_1));
      
    }
    inc_charpos(pos_1);
  }
  fprintf(stderr, "|");
    fprintf(stderr, "\n#############\n");
    fprintf(stderr, "WXTERMINAL LINE BUFFER\n##############\n");
  for(int i = 0; i <= y_max; i++) {
      //    fprintf(stderr, "LINE %d: buf: %ld, offset: %d, len: %d\n", i,(long)line_of(lpos).buf, line_of(lpos).offset, line_of(lpos).line_length);
    inc_linepos(lpos);
  }
    fprintf(stderr, "\n#############\n\n");
}

void wxTerminal::InsertChar(char c)
{
  
  //insert a character at current location

  //if there is a newline at the current location and we're not inserting one
  // scenario:
  // Buffer: abcde\nfgh
  //         *    X *
  // X = current position
  // * = line locations
  // 
  // After insert k:
  //         abcdek\nfgh
  //         *     X *

  if(char_of(curr_char_pos) == '\n' &&
     c != '\n') {
    // check case if we're about to insert the last character of the line
    if(line_of(curr_line_pos).line_length < m_width - 1) {       

      //have to add characters to current line, 

      //bump characters up.      
      wxterm_linepos lpos = curr_line_pos;
      wxterm_charpos pos_1 = curr_char_pos;
      wxterm_charpos pos_2 = pos_1;

      inc_charpos(pos_2);


      //  Method of relocating characters:
      //   need two variables, S = save, G = grab
      // 
      //   save 1, 
      //   S1  G      
      //  12345678
      //
      //   grab 2, place 1, save 2
      //  
      //  S2 G2
      //  _1345678
      //
      //  grab 3, place 2, save 3...
      //
      //  S3 G3
      //  _1245678
      // 
      //  etc...
      // ends when next position to grab is '\0'
      // (allocate buffer when necesary)
      // grab 8, place 7, save 8
      // place 8 in that last position

      char save_char, save_mode; 
      char grab_char, grab_mode;       
      save_char = char_of(pos_1);
      save_mode = mode_of(pos_1);

      while(char_of(pos_2) != '\0') {

	grab_char = char_of(pos_2);
	grab_mode = mode_of(pos_2);
	char_of(pos_2) = save_char;
	mode_of(pos_2) = save_mode;
	save_char = grab_char;
	save_mode = grab_mode;

	inc_charpos(pos_1);
	inc_charpos(pos_2);	
      }
      //insert "save" into pos2
      char_of(pos_2) = save_char;
      mode_of(pos_2) = save_mode;
      
      //now bump all the lines up.
      //look at the current line number (cursor_y)
      // go until  y_max, and adjust position of all lines +1
      inc_linepos(lpos);
      for(int lnum = cursor_y+1; lnum <= y_max; lnum++) {
	inc_charpos(line_of(lpos));
	inc_linepos(lpos);      
      }
    }
  }
  char_of(curr_char_pos) = c;
  mode_of(curr_char_pos) = m_currMode;
  inc_charpos(curr_char_pos);
}

void wxTerminal::NextLine() {
  //points next line position to current char position, and increments line offset.

  inc_linepos(curr_line_pos);

  line_of(curr_line_pos).buf = curr_char_pos.buf;
  line_of(curr_line_pos).offset = curr_char_pos.offset;
  //line_of(curr_line_pos).line_length = 0;


  cursor_y++;
  if(cursor_y > y_max) {
    y_max = cursor_y;
    int x,y;
    GetVirtualSize(&x,&y);

    //y_max + 1 = number of lines    
    SetVirtualSize(max(x,m_width*m_charWidth),max(y,(y_max+1)*m_charHeight)); 
  }
  cursor_x = 0;
}

void
wxTerminal::PassInputToTerminal(int len, char *data)
{
  int i;
  int numspaces, j;
  wxterm_linepos lpos;
  wxterm_charpos pos_1, pos_2;
  int new_line_length;

  int vis_x,vis_y;
  GetViewStart(&vis_x,&vis_y);
  static int old_vis_y = 0;

  char spc = ' ';


  for(i = 0; i < len; i++) {
    switch(data[i]) {
    case TOGGLE_STANDOUT:  // char 17
      //enter/exit standout mode , ignore character
      m_currMode ^= INVERSE;
      break;
    case '\t':
      // formula is: (8 - (cursorpos%8)) spaces
      numspaces = (8 - (cursor_x % 8));
      if(numspaces == 0) {
	numspaces = 8;
      }
      for(j = 0; j < numspaces; j++) {
	InsertChar(spc);


	cursor_x++;
	if(cursor_x > line_of(curr_line_pos).line_length) {
	  line_of(curr_line_pos).line_length = cursor_x;
	}
	if(cursor_x > x_max) {
	  //tab should stop inserting spaces.	   
	  NextLine();
	  break; //out of the for loop
	}
      }
      break;
    case '\r':
    case '\n':
      new_line_length = cursor_x;
      InsertChar('\n');

      
      if(i + 1 < len && 
	 ((data[i] == '\r' && data[i+1] == '\n') ||  //LF+CR
	  (data[i] == '\n' && data[i+1] == '\r')))  { //CR+LF
	i++;
      }

      // this case triggers when you do
      // ? setcursor [0 0]
      // and then press <ENTER>
      // if this is commented out, it will still work, but the characters
      // will remain in the buffer!

      if(new_line_length < line_of(curr_line_pos).line_length &&
	 cursor_y < y_max) {
	//shift all the characters down.
	//(remove characters between inserted newline and end of line)
	
	lpos = curr_line_pos;
	inc_linepos(lpos);
	pos_1 = curr_char_pos;
	pos_2 = line_of(lpos);
	while(char_of(pos_1) != '\0') {
	  if(char_of(pos_2) != '\0' &&
	     pos_2.buf == line_of(lpos).buf &&
	     pos_2.offset == line_of(lpos).offset) {
	    line_of(lpos).buf = pos_1.buf;
	    line_of(lpos).offset = pos_1.offset;
	    inc_linepos(lpos);
	  }
	  char_of(pos_1) = char_of(pos_2);
	  mode_of(pos_1) = mode_of(pos_2);
	  inc_charpos(pos_1);
	  inc_charpos(pos_2);
	}
      }

      line_of(curr_line_pos).line_length = new_line_length;
      
      NextLine();
      
      break;
    default:
      InsertChar(data[i]);


      cursor_x++;
      if(cursor_x > line_of(curr_line_pos).line_length) {
	line_of(curr_line_pos).line_length = cursor_x;
      }
      if(cursor_x > x_max) {
	NextLine();
      }      
      break;
    }   
  }


  if(!(m_currMode & DEFERUPDATE)) {
    //scroll if cursor current cursor not visible or 
    // if we're not reading an instruction (logo output)
    // old_vis_y keeps track of whether the screen has changed lately
    
    if((!readingInstruction &&
	1 ||                     //don't use old_vis_y??
	vis_y != old_vis_y) || 
       cursor_y < vis_y  ||
       cursor_y > vis_y + m_height - 1) {

      Scroll(-1, cursor_y);
      old_vis_y = vis_y;
      

      //Refresh();
    }  
    
  }
}

wxString * wxTerminal::get_text() 
{
  //  int i;
  wxString *outputString = new wxString();
  outputString->Clear();
  outputString->Append(_T("<HTML>\n"));
  outputString->Append(_T("<BODY>\n"));
  outputString->Append(_T("<FONT SIZE=2>\n"));
  wxString txt = GetChars(0,0,x_max,y_max);
  txt.Replace(_T("\n"),_T("<BR>\n"));
  outputString->Append(txt);
  /*
  wxterm_linepos tlpos = term_lines;
  for(i=0;i<ymax;i++){
    outputString->append(textString->Mid(linenumbers[i]*MAXWIDTH),MAXWIDTH);
    outputString->append(_T("<BR>"));		
    }*/
  outputString->Append(_T("<\\FONT>"));
  outputString->Append(_T("<\\BODY>"));
  outputString->Append(_T("<\\HTML>"));
  //  delete textString;
  return outputString;
}


void
wxTerminal::SelectPrinter(char *PrinterName)
{
  if(m_printerFN)
  {
    if(m_printerName[0] == '#')
      fclose(m_printerFN);
    else
#if defined(__WXMSW__)
      fclose(m_printerFN);
#else
      pclose(m_printerFN);
#endif

    m_printerFN = 0;
  }

  if(m_printerName)
  {
    free(m_printerName);
    m_printerName = 0;
  }

  if(strlen(PrinterName))
  {
    m_printerName = strdup(PrinterName);
  }
}

void
wxTerminal::PrintChars(int len, char *data)
{
  char
    pname[100];

  if(!m_printerFN)
  {
    if(!m_printerName)
      return;

    if(m_printerName[0] == '#')
    {
#if defined(__WXMSW__)
      sprintf(pname, "lpt%d", m_printerName[1] - '0' + 1);
#else
      sprintf(pname, "/dev/lp%d", m_printerName[1] - '0');
#endif
      m_printerFN = fopen(pname, "wb");
    }
    else
    {
#if defined(__WXMSW__)
      m_printerFN = fopen(m_printerName, "wb");
#else
      sprintf(pname, "lpr -P%s", m_printerName);
      m_printerFN = popen(pname, "w");
#endif
    }
  }
  
  if(m_printerFN)
  {
    fwrite(data, len, 1, m_printerFN);
  }
}



// ----------------------------------------------------------------------------
// Functions called from the interpreter thread
// ----------------------------------------------------------------------------

extern "C" void setCharMode(int mode){
	logo_char_mode = mode;
	
	//if turning charmode off, flush the
	//buffer (not the input buffer, logo's buffer)

	if(!logo_char_mode) {
          char tmp;
	  while(!buff_empty) {
	    buff_pop(tmp);
	  }
        }
}

extern "C" void wxClearText() {
  wxTerminal::terminal->ClearScreen();
  //  output_index = 0;
}

void wxTerminal::ClearScreen() {
  if(y_max > 0) {
    int x,y;
    GetVirtualSize(&x,&y);
    SetVirtualSize(max(x,m_width*m_charWidth),max(y,(y_max+1+m_height)*m_charHeight));
    Scroll(-1,y_max+1);
    int vx,vy;
    GetViewStart(&vx,&vy);
    //pretend setcursor from logo so that it can insert spaces if needed
    wxClientDC dc(this);
    setCursor(0,y_max + 1 - vy, TRUE); 
    if(!(m_currMode & DEFERUPDATE)) {
      Refresh();
    }
  }
}

//currently does nothing.
void wxTerminal::EnableScrolling(bool want_scrolling) {
  //wxScrolledWindow::EnableScrolling(FALSE,want_scrolling); //doesn't work
  return;
}

extern "C" void flushFile(FILE * stream);

extern "C" void wxSetCursor(int x, int y){
  //just call wxTerminal::setCursor with a special flag.
  flushFile(stdout);
  wxTerminal::terminal->EnableScrolling(FALSE);
  wxClientDC dc(wxTerminal::terminal);
  wxTerminal::terminal->setCursor(x,y,TRUE);
}

extern "C" void wxSetFont(char *fm, int sz) {

    int adjust_label = 0;
    if(fm != wx_font_face) {
        strcpy(wx_font_face, fm);
        adjust_label++;
    }

    wx_font_size = sz;

    wxFont f(FONT_CFG(wx_font_face, wx_font_size));

    wxTerminal::terminal->SetFont(f);
    editWindow->SetFont(f);

    //TurtleCanvas memDC, set size depending on scrunch!
    if(adjust_label) {
        turtleGraphics->SetFont(f);
    }

    logoFrame->AdjustSize();
}

extern "C" void wx_enable_scrolling() {
  wxTerminal::terminal->EnableScrolling(TRUE);
}

extern enum s_md {SCREEN_TEXT, SCREEN_SPLIT, SCREEN_FULL} screen_mode;


extern "C" int check_wx_stop(int force_yield, int pause_return_value) {
  logoEventManager->ProcessEvents(force_yield); 

  //give focus to terminal if text window shown
  //and Frame has focus
  wxWindow * focus_win = wxWindow::FindFocus();
  if(wxTerminal::terminal &&
     //screen_mode != SCREEN_FULL &&  // screen_text or screen_split mode
     !(focus_win == (wxWindow *)wxTerminal::terminal) &&
     (focus_win == (wxWindow *)logoFrame)) {
    wxTerminal::terminal->SetFocus();
  }

  if (logo_stop_flag) {
    logo_stop_flag = 0;
#ifdef SIG_TAKES_ARG
    logo_stop(0);
#else
    logo_stop();
#endif
    return 1;
  }
  if (logo_pause_flag) {
    logo_pause_flag = 0;
#ifdef SIG_TAKES_ARG
    logo_pause(0);
#else
    logo_pause();
#endif
    return pause_return_value;
  }
  return 0;
}

extern "C" int internal_check(){
 if (logo_stop_flag) {
    logo_stop_flag = 0;
#ifdef SIG_TAKES_ARG
    logo_stop(0);
#else
    logo_stop();
#endif
    return 1;
  }
  if (logo_pause_flag) {
    logo_pause_flag = 0;
#ifdef SIG_TAKES_ARG
    logo_pause(0);
#else
    logo_pause();
#endif
    return 1;
  }
  return 0;
}

extern "C" int getTermInfo(int type){
	switch (type){
	case X_COORD:
		return wxTerminal::terminal->cursor_x;
		break;
	case Y_COORD:
	  int vx,vy;
	  wxTerminal::terminal->GetViewStart(&vx,&vy);
		return wxTerminal::terminal->cursor_y - vy;
		break;
	case X_MAX:
	  //return wxTerminal::terminal->x_max;
	  return wxTerminal::terminal->m_width;
		break;
	case Y_MAX:
	  //return wxTerminal::terminal->y_max;
	  return wxTerminal::terminal->m_height;
		break;
	case EDIT_STATE:
		return editWindow->stateFlag;
		break;
	default:
		return -1;
	}
	
	return -1;
}

extern "C" void setTermInfo(int type, int val){
	switch (type){
		case X_COORD:
		  //wxTerminal::terminal->x_coord=val;
		  return;
			break;
		case Y_COORD:
		  //wxTerminal::terminal->y_coord=val;
		  return;
			break;
		case X_MAX:
		  return;
		  //wxTerminal::terminal->x_max=val;
			break;
		case Y_MAX:
		  return;
		  //wxTerminal::terminal->y_max=val;
			break;
		case EDIT_STATE:
			editWindow->stateFlag=val;
			break;
	}
}


extern "C" void doClose() {
  extern int wx_leave_mainloop;

  if(!wx_leave_mainloop) {
    logoFrame->Close(TRUE);
  }
}


extern "C" char * wx_get_original_dir_name(void) {
  return new_c_string_from_wx_string(originalWorkingDir);
}

extern "C" char * wx_get_current_dir_name(void) {
  return new_c_string_from_wx_string(wxGetCwd());
}

extern "C" void wx_chdir(char *file_path) {
  bool success = wxSetWorkingDirectory(wxString::FromAscii(file_path));
  assert(success);
}
The diff you're trying to view is too large. Only the first 1000 changed files have been loaded.
Showing with 0 additions and 0 deletions (0 / 0 diffs computed)
swh spinner

Computing file changes ...

back to top

Software Heritage — Copyright (C) 2015–2026, The Software Heritage developers. License: GNU AGPLv3+.
The source code of Software Heritage itself is available on our development forge.
The source code files archived by Software Heritage are available under their own copyright and licenses.
Terms of use: Archive access, API— Content policy— Contact— JavaScript license information— Web API