I mean, I can debug somewhat better now, but I need to figure out why I can't read files very well. Maybe I should read smaller chunks of a file...

This commit is contained in:
Zaccari Silverman 2019-08-17 02:45:09 -04:00
parent 2f09dd8c91
commit f1ae7f9e31
14 changed files with 505 additions and 78 deletions

56
Autojerk.cpp Normal file
View File

@ -0,0 +1,56 @@
#include "Autojerk.h"
#include "Error.h"
Markov _markov;
void OpenAutojerkSourceFile(Point originPoint){
StandardFileReply reply; //A struct that will contain our result.
SFTypeList autojerkTypeList = {'TEXT',' ',' ',' '}; //The list of appropriate types we're okay with opening. These, I think, are the 4-letter creator codes?
short fileID;
StandardGetFile(NULL, 1, autojerkTypeList, &reply);
if (!reply.sfGood) {
//Str255 errorDescription =
PikaAlertWithText("\pThere was an error opening that file. Perhaps another application may have locked it?");
}
else {
//Read no more than 75% of the memory available to the application into memory.
//...though this won't take into account any changes made to the memory size made by the user.
OSErr err;
ControlRef control;
long count = 0.4 * programSize;
_markov.setRefNumber(reply.sfFile.vRefNum);
//Attempt to open the file's data fork.
err = FSpOpenDF(&reply.sfFile, fsRdPerm, &reply.sfFile.vRefNum);
if (err != noErr) PikaAlertWithText("\pFSpOpenDF failed in OpenAutojerkSourceFile, so nothing can be read.");
//Set our file position to the start of the file.
SetFPos(reply.sfFile.vRefNum, fsFromStart, 0);
char * readBuffer = (char *)calloc(count+1, sizeof(char));
if (readBuffer == NULL) PikaAlertWithText("\pThe read buffer could not be allocated. You or the application may be out of memory.");
err = FSRead(_markov.getRefNumber(), &count, readBuffer); //Read bytes into readBuffer EOF or count bytes have been read, whichever is less.
if (err != noErr && err != eofErr) PikaAlertWithText("\pAn error (other than reaching the end of the file) occurred while reading the file.");
_markov.create(readBuffer, 3, 100);
free(readBuffer);
}
}

18
Autojerk.h Normal file
View File

@ -0,0 +1,18 @@
#include <MacWindows.h>
#include <Quickdraw.h>
#include <Dialogs.h>
#include <Fonts.h>
#include <Events.h>
#include <Devices.h>
#include <Resources.h>
#include <Files.h>
#include <StandardFile.h>
#include <Types.h>
#include "constants.h"
#include "markov.h"
extern Markov _markov;
void OpenAutojerkSourceFile(Point originPoint);

30
Autojerk.r Normal file
View File

@ -0,0 +1,30 @@
#include "Dialogs.r"
#include "constants.h"
resource 'DLOG' (dlogAutojerkResult){ //Purgeable?
{0, 0, 280, 480},
dBoxProc,
visible,
goAway, //Revisit this
0,
ditlAutojerkResult,
"AutoJerk Result",
centerMainScreen
};
resource 'DITL' (ditlAutojerkResult, purgeable){
{
{ 240, 150, 260, 290},
Button {enabled, "Uh..."};
{ 240-5, 150-5, 260+5, 290+5 },
UserItem {enabled};
{12, 112, 220, 460},
StaticText { disabled, "^0^1^2^3"}; //use ^0 as the placeholder when ready to test it
{ 25, 10, 95, 105 },
Picture {enabled, pictPikawow};
}
};

View File

@ -8,11 +8,15 @@ cmake_minimum_required(VERSION 2.8)
add_application(MemeveyPro
constants.h
main.c
MainApp.c
main.cpp
MainApp.cpp
dialog.r
menus.r
pika.r
markov.h
Autojerk.r
Autojerk.cpp
Error.cpp
)
# Enable -ffunction-sections and -gc-sections to make the app as small as possible

54
Error.cpp Normal file
View File

@ -0,0 +1,54 @@
#include "Error.h"
pascal void ButtonFrameDraw(DialogRef dlg, DialogItemIndex itemNo){
DialogItemType type;
Handle itemH;
Rect box;
GetDialogItem(dlg, 1, &type, &itemH, &box);
InsetRect(&box, -4, -4);
PenSize(3,3);
FrameRoundRect(&box,16,16);
}
void NoteAlertWithText(ConstStr255Param inString){
ParamText(inString,"\p","\p","\p");
NoteAlert(alrtGenericTextless, NULL);
}
void CautionAlertWithText(ConstStr255Param inString){
ParamText(inString,"\p","\p","\p");
CautionAlert(alrtGenericTextless, NULL);
}
void StopAlertWithText(ConstStr255Param inString){
ParamText(inString,"\p","\p","\p");
StopAlert(alrtGenericTextless, NULL);
}
void PikaAlertWithText(ConstStr255Param inString){
DialogPtr pikaAlert = GetNewDialog(dlogPikaAlert, 0, (WindowPtr)-1);
DialogItemType type;
Handle itemH;
Rect box;
short item;
MacSetPort(pikaAlert);
UpdateDialog(pikaAlert, pikaAlert->visRgn);
GetDialogItem(pikaAlert, 2, &type, &itemH, &box);
SetDialogItem(pikaAlert, 2, type, (Handle) NewUserItemUPP(&ButtonFrameDraw), &box);
SelectWindow(pikaAlert);
ParamText(inString,"\p","\p","\p");
do {
ModalDialog(NULL, &item);
} while(item != 1);
FlushEvents(everyEvent, 0);
DisposeWindow(pikaAlert);
}

21
Error.h Normal file
View File

@ -0,0 +1,21 @@
#include <MacWindows.h>
#include <Quickdraw.h>
#include <Dialogs.h>
#include <Fonts.h>
#include <Events.h>
#include <Devices.h>
#include <Resources.h>
#include <Types.h>
#include "constants.h"
//Convenient ways to call errors with custom text, when combined with the appropriate ditl and alrt in dialog.r
void NoteAlertWithText(ConstStr255Param inString);
void CautionAlertWithText(ConstStr255Param inString);
void StopAlertWithText(ConstStr255Param inString);
void PikaAlertWithText(ConstStr255Param inString);

View File

@ -1,9 +1,8 @@
#include "MainApp.h"
DialogPtr _mainDialog;
char _run = 1; //Set this to 0 when it's time to quit.
int _activeDITL = ditlMain; //This keeps track of the current UI that _mainDialog displays.
pascal void ButtonFrameProc(DialogRef dlg, DialogItemIndex itemNo){
DialogItemType type;
Handle itemH;
@ -39,15 +38,55 @@ void PresentAboutBox(){
}
void PresentUnimplementedDlog(){
CautionAlert(alrtUnimplemented, NULL);
void PresentAutojerkResult(){
DialogPtr autojerkResultDialog = GetNewDialog(dlogAutojerkResult, 0, (WindowPtr)-1);
DialogItemType type;
Handle itemH;
Rect box;
short item;
GetDialogItem(autojerkResultDialog, 2, &type, &itemH, &box);
SetDialogItem(autojerkResultDialog, 2, type, (Handle) NewUserItemUPP(&ButtonFrameProc), &box);
MacSetPort(autojerkResultDialog);
UpdateDialog(autojerkResultDialog, autojerkResultDialog->visRgn);
SelectWindow(autojerkResultDialog);
/*The strings you pass in the parameters to ParamText cannot contain the special strings
^0 through ^3, or else the procedure will enter an endless loop of substitutions in
versions of system software earlier than 7.1.*/
if (!_markov.isInitialized()){
//Return an error eventually.
ParamText("\pThe Markov Object has not been initialized yet. Try opening a file.","\p","\p","\p");
do {
ModalDialog(NULL, &item);
} while(item != 1);
} else {
//ParamText(myString,myString,myString,myString);
ParamText("\pThe code to actually generate stuff hasn't been written yet...","\p","\p","\p");
do {
ModalDialog(NULL, &item);
} while(item != 1);
}
FlushEvents(everyEvent, 0);
DisposeWindow(autojerkResultDialog);
MacSetPort(_mainDialog);
}
void PresentUnimplementedDlog(){
//CautionAlert(alrtUnimplemented, NULL);
}
void PresentMainDlog(){
_mainDialog = GetNewWindow(windMain, 0, (WindowPtr)-1);
//_mainDialog = GetNewDialog(dlogMain, 0, (WindowPtr)-1);
//_mainDialog = GetNewWindow(windMain, 0, (WindowPtr)-1);
_mainDialog = GetNewDialog(dlogMain, 0, (WindowPtr)-1);
//SwitchDITL(ditlMain);
//Do anything else.
}
@ -55,6 +94,7 @@ void PresentMainDlog(){
//Changes the UI of the main dialog.
//This lets us keep one dialog box around and just change its guts.
//The only problem is that I have never gotten this to work, so...
/*
void SwitchDITL(short int toDitlID){
_activeDITL = toDitlID;
@ -67,9 +107,9 @@ void SwitchDITL(short int toDitlID){
AppendDITL(_mainDialog, newDitl, overlayDITL);
ReleaseResource(newDitl);
//UpdateDialog(_mainDialog, _mainDialog->visRgn);
UpdateDialog(_mainDialog, _mainDialog->visRgn);
}
*/
//
// Event Processing
@ -80,7 +120,7 @@ void EventLoop(){
//For now, present the main dialog here.
PresentMainDlog();
//Essentially, the app's main loop.
while (_run){
if (WaitNextEvent(everyEvent, &event, 0, NULL)){
@ -93,6 +133,7 @@ void EventLoop(){
}
}
//For the "Crash Computer" option: Just try opening a DITL/DLOG that doesn't exist, or something :thonk:
}
@ -152,7 +193,11 @@ void HandleMouseDown(EventRecord *eventPtr){
break;
case inGoAway: //with "goAway" being the close box
if (TrackGoAway(window, eventPtr->where)) QuitApp();
if (TrackGoAway(window, eventPtr->where)){
//We can do other things here, but for now...
QuitApp();
}
break;
}
@ -176,7 +221,7 @@ void HandleMenuChoice(long menuChoice){
}
else if (menuID == menuUser){
switch (menuItem){
case menuItemQuit:
case menuitemQuit:
QuitApp();
break;
default:
@ -184,6 +229,22 @@ void HandleMenuChoice(long menuChoice){
break;
}
}
else if (menuID == menuAutojerk){
switch (menuItem){
case menuitemAutojerkGenerate:
PresentAutojerkResult();
break;
case menuitemAutojerkOpenFile:
Point origin;
origin.h = 80;
origin.v = 80;
OpenAutojerkSourceFile(origin);
break;
default:
PresentUnimplementedDlog();
break;
}
}
else {
PresentUnimplementedDlog();
}
@ -206,25 +267,30 @@ void HandleUpdate(EventRecord *eventPtr){
void HandleInContent(EventRecord *eventPtr){
//Todo
WindowPtr window;
short int part;
DialogPtr dialog;
short part, item;
part = FindWindow(eventPtr->where, &window);
//SelectWindow(window); //Bring the clicked window to the front.
//Drag the window if CMD is held down.
if ((eventPtr->modifiers & cmdKey) != 0)
DragWindow(window, eventPtr->where, &qd.screenBits.bounds);
else //For now, drag the window anyway.
DragWindow(window, eventPtr->where, &qd.screenBits.bounds);
if ((eventPtr->modifiers & cmdKey) != 0) DragWindow(window, eventPtr->where, &qd.screenBits.bounds);
if (DialogSelect(eventPtr, &dialog, &item)){
if (dialog == _mainDialog) DragWindow(window, eventPtr->where, &qd.screenBits.bounds); //We'll do something more here later...
else {} //Do nothing for now
}
}
void QuitApp(){
_run = 0; //Now, the EventLoop will stop.
//Do any clean-up here.
CloseWindow(_mainDialog);
//CloseDialog(_mainDialog);
//CloseWindow(_mainDialog);
CloseDialog(_mainDialog);
//ExitToShell();
//For now, there isn't much else to do.

View File

@ -5,8 +5,12 @@
#include <Events.h>
#include <Devices.h>
#include <Resources.h>
#include <Types.h>
#include <string>
#include "constants.h"
#include "Autojerk.h"
extern DialogPtr _mainDialog;

View File

@ -6,10 +6,18 @@
</Plugin>
</Plugins>
<VirtualDirectory Name="MemeveyPro-m68k">
<File Name="Error.cpp"/>
<File Name="Error.h"/>
<File Name="Autojerk.cpp"/>
<File Name="Autojerk.h"/>
<File Name="main.cpp"/>
<File Name="MainApp.cpp"/>
<File Name="Autojerk.r"/>
<File Name="menus.r"/>
<File Name="dialog.r"/>
<File Name="markov.h"/>
<File Name="constants.h"/>
<File Name="main.c"/>
<File Name="MainApp.h"/>
<File Name="MainApp.c"/>
</VirtualDirectory>
<VirtualDirectory Name="build">
<VirtualDirectory Name="CMakeFiles">

View File

@ -1,6 +1,9 @@
// constants
//This is probably one of the dumber things I've ever done on a project like this.
//More importantly, this might be better-organized as a bunch of separate files.
/*Default Menu Bar*/
#define defaultMenubar 128
@ -10,44 +13,54 @@
#define menuitemAbout 1
/*Pets Menu*/
#define menuPets 129
//User Menu
#define menuUser 129
#define menuitemMyPets 1
#define menuitemNewPet 2
#define menuitemQuit 1 //Make sure this matches up with the position of the correct item in the menu
//AutoJerk Menu
#define menuAutojerk 130
#define menuitemAutojerkOpenFile 1
//Divider at 2
#define menuitemAutojerkGenerate 3
//
#define menuUser 131
#define menuitemLogin 1
#define menuItemLogout 2
#define menuItemQuit 4
//
#define menuRandom 132
#define menuAutoJerk 1
#define menuFuck 255
//
#define menuHelp 130
#define menuHelp 200
#define menuitemHelp 1
//
#define menuFuck 255
/*Dialogs, Alerts, and DITLs*/
#define dlogAbout 128
#define ditlAbout 128
#define alrtUnimplemented 129
#define ditlUnimplemented 129
#define alrtGenericTextless 129
#define ditlGenericTextless 129
#define windMain 130
#define dlogMain 130
#define ditlMain 130
#define dlogMainSmall 131
#define ditlMainSmall 131
#define dlogPikaAlert 131
#define ditlPikaAlert 131
//AutoJerk
#define ditlAutojerkOpenFile 200
#define dlogAutojerkOpenFile 200
#define ditlAutojerkResult 201
#define dlogAutojerkResult 201
//Picture Resources
#define pictPikawow 128
//Other Program Parameters
#define programSize 1000 * 1024 //1000 * 1 kB

View File

@ -26,14 +26,44 @@ resource 'DITL' (ditlAbout, purgeable) {
StaticText {enabled, "MemeveyPro-m68k 0.0.0\rBy Zac Silverman (macosten)"};
{ 25, 10, 95, 105 },
Picture {enabled, 128};
Picture {enabled, pictPikawow};
}
};
resource 'ALRT' (alrtUnimplemented, purgeable) {
resource 'DLOG' (dlogPikaAlert, purgeable) {
//Top Left Bottom Right
{ 0, 0, 145, 350 },
dBoxProc,
visible,
noGoAway, //No close box
0,
ditlPikaAlert,
"About MemeveyPro-m68k",
centerMainScreen
};
resource 'DITL' (ditlPikaAlert, purgeable) {
{
// Top Left Bottom Right
{ 110, 200, 130, 320 },
Button { enabled, "OK" };
{ 110-5, 200-5, 130+5, 320+5 },
UserItem {enabled};
{ 30, 110, 100, 350 },
StaticText {enabled, "^0"};
{ 25, 10, 95, 105 },
Picture {enabled, pictPikawow};
}
};
resource 'ALRT' (alrtGenericTextless, purgeable) {
{ 0, 0, 90, 400 },
ditlUnimplemented,
ditlGenericTextless,
{
OK, visible, sound1,
OK, visible, sound1,
@ -43,13 +73,13 @@ resource 'ALRT' (alrtUnimplemented, purgeable) {
alertPositionMainScreen
};
resource 'DITL' (ditlUnimplemented, purgeable){
resource 'DITL' (alrtGenericTextless, purgeable){
{
{56, 300, 56+20, 380},
Button {enabled, "OK"};
{8, 72, 38, 380},
StaticText { disabled, "This functionality has not yet been implemented."};
StaticText { disabled, "^0"}; //There was an error opening that file. Try a different file, or try again later/after a restart.
}
};
@ -77,7 +107,7 @@ resource 'DLOG' (dlogMain){ //Purgeable?
resource 'DITL' (ditlMain, purgeable){
{
{10, 10, 40, 300},
StaticText {disabled, "MemeveyPro Main Window."};
StaticText {disabled, "Memevey Pro Main Window."};
}
};
@ -100,11 +130,6 @@ resource 'SIZE' (-1) {
reserved,
reserved,
reserved,
#ifdef TARGET_API_MAC_CARBON
500 * 1024, // Carbon apparently needs additional memory.
500 * 1024
#else
200 * 1024,
200 * 1024
#endif
1000 * 1024,
1000 * 1024
};

View File

@ -1,6 +1,9 @@
#include "MainApp.h"
#include "constants.h"
#include <stdlib.h>
#include <time.h>
#ifndef TARGET_API_MAC_CARBON
/* NOTE: this is checking whether the Dialogs.h we use *knows* about Carbon,
not whether we are actually compiling for Cabon.
@ -39,7 +42,11 @@ void Initialize() {
//Draw the menu bar
DrawMenuBar();
//Seed the random number generator. There's a Macintosh Toolbox call for this, I think, but I forget what it was.
srand(time(0));
//Do anything else.
}

115
markov.h Normal file
View File

@ -0,0 +1,115 @@
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
#include <map>
typedef struct AutojerkStrings {
Str255 strings[4];
} AutojerkStrings;
class Markov {
public:
void create( char * readBuffer, unsigned int keyLen, unsigned int words ) {
fileBuffer = std::string(readBuffer);
if( fileBuffer.length() < 1 ) return;
createDictionary( keyLen );
initialized = true;
}
AutojerkStrings createText() {
std::string key, first, second, intermediateResult;
size_t next;
std::map<std::string, std::vector<std::string> >::iterator it = dictionary.begin();
std::advance( it, rand() % dictionary.size() );
key = ( *it ).first;
intermediateResult += key;
while( intermediateResult.length() < 1019 ) { //1019 being the capacity of 4 Str255s, minus one for the '!'.
std::vector<std::string> d = dictionary[key];
if( d.size() < 1 ) break;
second = d[rand() % d.size()];
if( second.length() < 1 ) break;
if (intermediateResult.size() + (" " + second).size() < 1019){
intermediateResult += (" " + second); //Keep going if the strings are small enough.
} else break;
next = key.find_first_of( 32, 0 );
first = key.substr( next + 1 );
key = first + " " + second;
}
intermediateResult += "!";
//Split these strings into 4 (safely).
std::vector<std::string> intermediateVector = split(intermediateResult, 4);
AutojerkStrings result;
//result.strings[0] = intermediateVector[0].c_str();
memcpy(result.strings[0], intermediateVector[0].c_str(), intermediateVector[0].length());
//result.strings[1] = intermediateVector[1].c_str();
memcpy(result.strings[1], intermediateVector[1].c_str(), intermediateVector[1].length());
//result.strings[2] = intermediateVector[2].c_str();
memcpy(result.strings[2], intermediateVector[2].c_str(), intermediateVector[2].length());
//result.strings[3] = intermediateVector[3].c_str();
memcpy(result.strings[3], intermediateVector[3].c_str(), intermediateVector[3].length());
return result;
}
bool isInitialized(){
return initialized;
}
//For file access purposes, we should keep track of the source file's referece number.
short getRefNumber(){
return fileRefNum;
}
void setRefNumber(short newRefNum){
fileRefNum = newRefNum;
}
private:
void createDictionary( unsigned int kl ) {
std::string w1, key;
size_t wc = 0, pos, next;
next = fileBuffer.find_first_not_of( 32, 0 );
if( next == std::string::npos ) return;
while( wc < kl ) {
pos = fileBuffer.find_first_of( ' ', next );
w1 = fileBuffer.substr( next, pos - next );
key += w1 + " ";
next = fileBuffer.find_first_not_of( 32, pos + 1 );
if( next == std::string::npos ) return;
wc++;
}
key = key.substr( 0, key.size() - 1 );
while( true ) {
next = fileBuffer.find_first_not_of( 32, pos + 1 );
if( next == std::string::npos ) return;
pos = fileBuffer.find_first_of( 32, next );
w1 = fileBuffer.substr( next, pos - next );
if( w1.size() < 1 ) break;
if( std::find( dictionary[key].begin(), dictionary[key].end(), w1 ) == dictionary[key].end() )
dictionary[key].push_back( w1 );
key = key.substr( key.find_first_of( 32 ) + 1 ) + " " + w1;
}
}
std::vector<std::string> split(std::string const & s, size_t count){
//Split s into count strings of size as close to equal as possible.
size_t minsize = s.size()/count;
int extra = s.size() - minsize * count;
std::vector<std::string> tokens;
for(size_t i = 0, offset=0 ; i < count; ++i, --extra){
size_t size = minsize + (extra>0?1:0);
if ( (offset + size) < s.size())
tokens.push_back(s.substr(offset,size));
else
tokens.push_back(s.substr(offset, s.size() - offset));
offset += size;
}
return tokens;
}
bool initialized;
std::string fileBuffer;
std::map<std::string, std::vector<std::string> > dictionary;
//Mac-specific info:
short fileRefNum;
};

38
menus.r
View File

@ -3,7 +3,7 @@
#include "constants.h"
resource 'MBAR' (defaultMenubar, preload) {
{menuApple, menuUser, menuPets, menuHelp};
{menuApple, menuUser, menuAutojerk, menuHelp, menuFuck};
};
/*See Inside Macintosh: Macintosh Toolbox / More Macintosh Toolbox*/
@ -19,7 +19,7 @@ resource 'MENU' (menuApple, preload) { /*resource ID, preload resource*/
apple, /*menu title*/
{
/*first menu item*/
"About PetProject...", /*text of menu item*/
"About Memevey Pro...", /*text of menu item*/
noicon, nokey, nomark, plain; /*item characteristics*/
/*second menu item*/
"-",
@ -28,8 +28,6 @@ resource 'MENU' (menuApple, preload) { /*resource ID, preload resource*/
};
resource 'MENU' (menuUser, preload) {
menuUser,
textMenuProc,
@ -37,27 +35,35 @@ resource 'MENU' (menuUser, preload) {
enabled,
"User",
{
"Login",
noicon, nokey, nomark, plain;
"Logout",
noicon, nokey, nomark, plain;
"-",
noicon, nokey, nomark, plain,
"Quit",
noicon, nokey, nomark, plain
}
};
resource 'MENU' (menuPets, preload) {
menuPets,
resource 'MENU' (menuAutojerk, preload) {
menuAutojerk,
textMenuProc,
0b1111111111111111111111111111111,
enabled,
"AutoJerk",
{
"Open Input File...",
noicon, nokey, nomark, plain,
"-",
noicon, nokey, nomark, plain,
"Generate",
noicon, nokey, nomark, plain
}
};
resource 'MENU' (menuFuck, preload) {
menuFuck,
textMenuProc,
0b1111111111111111111111111111111, /*I assume this enables all items, dunno though.*/
enabled,
"Pets",
"Fuck",
{
"View Pets",
noicon, nokey, nomark, plain;
"Create Pet",
"Attempt Overwrite of Low Memory...",
noicon, nokey, nomark, plain
}
};