Compare commits

...

10 Commits

7 changed files with 74 additions and 72 deletions

View File

@ -1,7 +1,7 @@
# Messages For Macintosh
Messages for Macintosh is a software suite for classic Macintosh (System 2.0 through MacOS 9.2.2) systems to interoperate with Apple iMessages via a familiar interface, with [supporting software](https://github.com/CamHenlin/imessagegraphqlserver) running on a newer Mac computer.
![messages for macintosh](/images/messagesformacintosh.png)
![messages for macintosh](https://henlin.net/images/messagesformacintosh.png)
## How to use Messages for Macintosh
There are two setup guides for Messages for Macintosh:
@ -13,7 +13,7 @@ There are two setup guides for Messages for Macintosh:
Messages for Macintosh is built on a lot of technologies. The READMEs of each of these is each worth familiarizing yourself with if you would like to contribute to Messages for Macintosh:
- [Retro68](https://github.com/autc04/Retro68) - a GCC-based cross compilation env for classic Macintosh systems
- [Nuklear Quickdraw](https://github.com/CamHenlin/nuklear-quickdraw) - a heavily modified, Macintosh-specific version of [Nuklear](https://github.com/Immediate-Mode-UI/Nuklear) allowing a simple way to provide GUI services
- [Nuklear Quickdraw](https://github.com/CamHenlin/nuklear-quickdraw) - a heavily modified, classic Macintosh-specific version of [Nuklear](https://github.com/Immediate-Mode-UI/Nuklear) allowing a simple way to provide GUI services
- [CoprocessorJS](https://github.com/CamHenlin/coprocessor.js) - a library that allows us to handle nodejs workloads sent over a serial port
- [serialperformanceanalyzer](https://github.com/CamHenlin/serialperformanceanalyzer) - used to analyze the performance of many different parts of the application

View File

@ -12,7 +12,7 @@
IOParam outgoingSerialPortReference;
IOParam incomingSerialPortReference;
// #define PRINT_ERRORS 1
// #define DEBUGGING 1
#define DEBUGGING 1
#define MAX_ATTEMPTS 10
#define RECEIVE_WINDOW_SIZE 32767 // receive in up to 32kb chunks
#define MAX_RECEIVE_SIZE 32767 // matching RECEIVE_WINDOW_SIZE for now
@ -225,6 +225,7 @@ void readSerialPort(char* output) {
// make sure output variable is clear
memset(output, '\0', MAX_RECEIVE_SIZE);
memset(tempOutput, '\0', MAX_RECEIVE_SIZE);
bool done = false;
long int totalByteCount = 0;
@ -326,7 +327,7 @@ void readSerialPort(char* output) {
#ifdef DEBUGGING
writeSerialPortDebug(boutRefNum, "done building temp output\n");
writeSerialPortDebug(boutRefNum, "done building temp output");
writeSerialPortDebug(boutRefNum, tempOutput);
// char debugOutput[255];
@ -343,7 +344,7 @@ void readSerialPort(char* output) {
}
// attach the gathered up output from the buffer to the output variable
strncat(output, tempOutput, totalByteCount);
memcpy(output, tempOutput, totalByteCount);
#ifdef DEBUGGING
writeSerialPortDebug(boutRefNum, "coprocessor.readSerialPort complete, output:");

Binary file not shown.

Binary file not shown.

View File

@ -25,7 +25,7 @@
// #define MAC_APP_DEBUGGING
// #define PROFILING 1
// #define DEBUG_FUNCTION_CALLS
#define DEBUG_FUNCTION_CALLS
#ifdef PROFILING
OSErr writeSerialPortProfile(const char* str)

View File

@ -15,69 +15,52 @@
// #define MESSAGES_FOR_MACINTOSH_DEBUGGING
// based on https://github.com/jwerle/strsplit.c -- cleaned up and modified to use strtokm rather than strtok
int strsplit (const char *str, char *parts[], const char *delimiter) {
// based on https://github.com/mr21/strsplit.c/blob/master/strsplit.c
static char** _strsplit( const char* s, const char* delim, int* nb ) {
#ifdef DEBUG_FUNCTION_CALLS
writeSerialPortDebug(boutRefNum, "DEBUG_FUNCTION_CALLS: strsplit");
writeSerialPortDebug(boutRefNum, "DEBUG_FUNCTION_CALLS: _strsplit");
#endif
void* data;
char* _s = ( char* )s;
const char** ptrs;
int
ptrsSize,
nbWords = 1,
sLen = strlen( s ),
delimLen = strlen( delim );
char *pch;
int i = 0;
char *copy = NULL;
char *tmp = NULL;
copy = strdup(str);
if (! copy) {
goto bad;
}
pch = strtokm(copy, delimiter);
tmp = strdup(pch);
if (!tmp) {
goto bad;
}
parts[i++] = tmp;
while (pch) {
pch = strtokm(NULL, delimiter);
if (NULL == pch) {
break;
while ( ( _s = strstr( _s, delim ) ) ) {
_s += delimLen;
++nbWords;
}
tmp = strdup(pch);
if (! tmp) {
goto bad;
ptrsSize = ( nbWords + 1 ) * sizeof( char* );
ptrs =
data = malloc( ptrsSize + sLen + 1 );
if ( data ) {
*ptrs =
_s = strcpy( ( ( char* )data ) + ptrsSize, s );
if ( nbWords > 1 ) {
while ( ( _s = strstr( _s, delim ) ) ) {
*_s = '\0';
_s += delimLen;
*++ptrs = _s;
}
}
*++ptrs = NULL;
}
if ( nb ) {
*nb = data ? nbWords : 0;
}
return data;
}
parts[i++] = tmp;
}
char** strsplit( const char* s, const char* delim ) {
return _strsplit( s, delim, NULL );
}
free(copy);
return i;
bad:
free(copy);
for (int j = 0; j < i; j++) {
free(parts[j]);
}
return -1;
char** strsplit_count( const char* s, const char* delim, int* nb ) {
return _strsplit( s, delim, nb );
}
void aFailed(char *file, int line) {
@ -232,8 +215,8 @@ void sendIPAddressToCoprocessor() {
}
// set up function to get messages in current chat
// limit to recent messages
// figure out pagination?? button on the top that says "get previous chats"?, TODO
// limit to recent messages
// figure out pagination?? button on the top that says "get previous chats"?, TODO
void getMessages(char *thread, int page) {
#ifdef DEBUG_FUNCTION_CALLS
@ -296,9 +279,8 @@ void getChatCounts() {
strcpy(tempChatCountFunctionResponse, chatCountFunctionResponse);
int chatCount = 0;
char *(*chats[16])[64];
chatCount = strsplit(tempChatCountFunctionResponse, (char **)chats, ",");
char **chats = strsplit_count(tempChatCountFunctionResponse, ",", &chatCount);
for (int chatLoopCounter = 0; chatLoopCounter < chatCount; chatLoopCounter++) {
@ -320,9 +302,8 @@ void getChatCounts() {
strcpy(tempChatCountFunctionResponse, chatCountFunctionResponse);
int results = 0;
char *(*chatUpdate[2])[64];
results = strsplit((char *)chats[chatLoopCounter], (char **)chatUpdate, ":::");
char **chatUpdate = strsplit_count((char *)chats[chatLoopCounter], ":::", &results);
if (results != 2) {
@ -360,9 +341,8 @@ void getChatCounts() {
sprintf(chatName, "%.63s", &chatFriendlyNames[i * MAX_FRIENDLY_NAME_LENGTH]);
int updateResults = 0;
char *(*updatePieces[2])[64];
updateResults = strsplit(chatName, (char **)updatePieces, " new) ");
char **updatePieces = strsplit_count(chatName, " new) ", &updateResults);
if (updateResults != 2) {

View File

@ -28,7 +28,7 @@
#define ENABLED_DOUBLE_BUFFERING
#define COMMAND_CACHING
#include "nuklear.h"
// #define NK_QUICKDRAW_GRAPHICS_DEBUGGING
#define NK_QUICKDRAW_GRAPHICS_DEBUGGING
// #define DRAW_BLIT_LOCATION
Boolean lastInputWasBackspace;
@ -555,6 +555,7 @@ void updateBounds(int top, int bottom, int left, int right) {
// http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/QuickDraw/QuickDraw-102.html#MARKER-9-372
// http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/QuickDraw/QuickDraw-103.html#HEADING103-0
const struct nk_command_rect *r = (const struct nk_command_rect *)cmd;
writeSerialPortDebug(boutRefNum, "NK_COMMAND_RECT2");
#ifdef COMMAND_CACHING
@ -567,21 +568,26 @@ void updateBounds(int top, int bottom, int left, int right) {
break;
}
#endif
writeSerialPortDebug(boutRefNum, "NK_COMMAND_RECT3");
ForeColor(r->color);
PenSize(r->line_thickness, r->line_thickness);
writeSerialPortDebug(boutRefNum, "NK_COMMAND_RECT4");
Rect quickDrawRectangle;
quickDrawRectangle.top = r->y;
quickDrawRectangle.left = r->x;
quickDrawRectangle.bottom = r->y + r->h;
quickDrawRectangle.right = r->x + r->w;
writeSerialPortDebug(boutRefNum, "NK_COMMAND_RECT5");
#ifdef ENABLED_DOUBLE_BUFFERING
updateBounds(quickDrawRectangle.top, quickDrawRectangle.bottom, quickDrawRectangle.left, quickDrawRectangle.right);
#endif
writeSerialPortDebug(boutRefNum, "NK_COMMAND_RECT6");
FrameRoundRect(&quickDrawRectangle, r->rounding, r->rounding);
writeSerialPortDebug(boutRefNum, "NK_COMMAND_RECT7 (done)");
}
break;
@ -1080,6 +1086,7 @@ void updateBounds(int top, int bottom, int left, int right) {
#ifdef COMMAND_CACHING
int lastCalls = 0;
int currentCalls;
const struct nk_command *lastCmd;
#endif
NK_API void nk_quickdraw_render(WindowPtr window, struct nk_context *ctx) {
@ -1130,7 +1137,6 @@ NK_API void nk_quickdraw_render(WindowPtr window, struct nk_context *ctx) {
#endif
#ifdef COMMAND_CACHING
const struct nk_command *lastCmd;
lastCmd = nk_ptr_add_const(struct nk_command, last, 0);
#endif
@ -1143,14 +1149,25 @@ NK_API void nk_quickdraw_render(WindowPtr window, struct nk_context *ctx) {
#endif
#ifdef COMMAND_CACHING
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
writeSerialPortDebug(boutRefNum, "COMMAND_CACHING: get next cached command");
#endif
// TODO: if this becomes worth pursuing later, it causes address errors. I suspect that the memcpy
// command that builds up the last variable is not properly allocating memory.
// the address error pops up on the line of the conditional itself and can sometimes take hours to trigger.
if (currentCalls < lastCalls && lastCmd && lastCmd->next) {
if (currentCalls < lastCalls - 1 && lastCmd && lastCmd->next) {
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
writeSerialPortDebug(boutRefNum, "COMMAND_CACHING: inside conditional");
#endif
lastCmd = nk_ptr_add_const(struct nk_command, last, lastCmd->next);
}
#ifdef NK_QUICKDRAW_GRAPHICS_DEBUGGING
writeSerialPortDebug(boutRefNum, "COMMAND_CACHING: done getting lastCmd");
#endif
currentCalls++;
#endif
}
@ -1482,6 +1499,10 @@ NK_API struct nk_context* nk_quickdraw_init(unsigned int width, unsigned int hei
NkQuickDrawFont *quickdrawfont = nk_quickdraw_font_create_from_file();
struct nk_user_font *font = &quickdrawfont->nk;
#ifdef COMMAND_CACHING
lastCmd = malloc(sizeof(struct nk_command));
#endif
last = calloc(1, MAX_MEMORY_IN_KB * 1024);
buf = calloc(1, MAX_MEMORY_IN_KB * 1024);
nk_init_fixed(&quickdraw.nuklear_context, buf, MAX_MEMORY_IN_KB * 1024, font);