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
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 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 ## How to use Messages for Macintosh
There are two setup guides for 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: 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 - [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 - [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 - [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 outgoingSerialPortReference;
IOParam incomingSerialPortReference; IOParam incomingSerialPortReference;
// #define PRINT_ERRORS 1 // #define PRINT_ERRORS 1
// #define DEBUGGING 1 #define DEBUGGING 1
#define MAX_ATTEMPTS 10 #define MAX_ATTEMPTS 10
#define RECEIVE_WINDOW_SIZE 32767 // receive in up to 32kb chunks #define RECEIVE_WINDOW_SIZE 32767 // receive in up to 32kb chunks
#define MAX_RECEIVE_SIZE 32767 // matching RECEIVE_WINDOW_SIZE for now #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 // make sure output variable is clear
memset(output, '\0', MAX_RECEIVE_SIZE); memset(output, '\0', MAX_RECEIVE_SIZE);
memset(tempOutput, '\0', MAX_RECEIVE_SIZE);
bool done = false; bool done = false;
long int totalByteCount = 0; long int totalByteCount = 0;
@ -326,7 +327,7 @@ void readSerialPort(char* output) {
#ifdef DEBUGGING #ifdef DEBUGGING
writeSerialPortDebug(boutRefNum, "done building temp output\n"); writeSerialPortDebug(boutRefNum, "done building temp output");
writeSerialPortDebug(boutRefNum, tempOutput); writeSerialPortDebug(boutRefNum, tempOutput);
// char debugOutput[255]; // char debugOutput[255];
@ -343,7 +344,7 @@ void readSerialPort(char* output) {
} }
// attach the gathered up output from the buffer to the output variable // attach the gathered up output from the buffer to the output variable
strncat(output, tempOutput, totalByteCount); memcpy(output, tempOutput, totalByteCount);
#ifdef DEBUGGING #ifdef DEBUGGING
writeSerialPortDebug(boutRefNum, "coprocessor.readSerialPort complete, output:"); 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 MAC_APP_DEBUGGING
// #define PROFILING 1 // #define PROFILING 1
// #define DEBUG_FUNCTION_CALLS #define DEBUG_FUNCTION_CALLS
#ifdef PROFILING #ifdef PROFILING
OSErr writeSerialPortProfile(const char* str) OSErr writeSerialPortProfile(const char* str)

View File

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

View File

@ -28,7 +28,7 @@
#define ENABLED_DOUBLE_BUFFERING #define ENABLED_DOUBLE_BUFFERING
#define COMMAND_CACHING #define COMMAND_CACHING
#include "nuklear.h" #include "nuklear.h"
// #define NK_QUICKDRAW_GRAPHICS_DEBUGGING #define NK_QUICKDRAW_GRAPHICS_DEBUGGING
// #define DRAW_BLIT_LOCATION // #define DRAW_BLIT_LOCATION
Boolean lastInputWasBackspace; 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-102.html#MARKER-9-372
// http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/QuickDraw/QuickDraw-103.html#HEADING103-0 // 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; const struct nk_command_rect *r = (const struct nk_command_rect *)cmd;
writeSerialPortDebug(boutRefNum, "NK_COMMAND_RECT2");
#ifdef COMMAND_CACHING #ifdef COMMAND_CACHING
@ -567,21 +568,26 @@ void updateBounds(int top, int bottom, int left, int right) {
break; break;
} }
#endif #endif
writeSerialPortDebug(boutRefNum, "NK_COMMAND_RECT3");
ForeColor(r->color); ForeColor(r->color);
PenSize(r->line_thickness, r->line_thickness); PenSize(r->line_thickness, r->line_thickness);
writeSerialPortDebug(boutRefNum, "NK_COMMAND_RECT4");
Rect quickDrawRectangle; Rect quickDrawRectangle;
quickDrawRectangle.top = r->y; quickDrawRectangle.top = r->y;
quickDrawRectangle.left = r->x; quickDrawRectangle.left = r->x;
quickDrawRectangle.bottom = r->y + r->h; quickDrawRectangle.bottom = r->y + r->h;
quickDrawRectangle.right = r->x + r->w; quickDrawRectangle.right = r->x + r->w;
writeSerialPortDebug(boutRefNum, "NK_COMMAND_RECT5");
#ifdef ENABLED_DOUBLE_BUFFERING #ifdef ENABLED_DOUBLE_BUFFERING
updateBounds(quickDrawRectangle.top, quickDrawRectangle.bottom, quickDrawRectangle.left, quickDrawRectangle.right); updateBounds(quickDrawRectangle.top, quickDrawRectangle.bottom, quickDrawRectangle.left, quickDrawRectangle.right);
#endif #endif
writeSerialPortDebug(boutRefNum, "NK_COMMAND_RECT6");
FrameRoundRect(&quickDrawRectangle, r->rounding, r->rounding); FrameRoundRect(&quickDrawRectangle, r->rounding, r->rounding);
writeSerialPortDebug(boutRefNum, "NK_COMMAND_RECT7 (done)");
} }
break; break;
@ -1080,6 +1086,7 @@ void updateBounds(int top, int bottom, int left, int right) {
#ifdef COMMAND_CACHING #ifdef COMMAND_CACHING
int lastCalls = 0; int lastCalls = 0;
int currentCalls; int currentCalls;
const struct nk_command *lastCmd;
#endif #endif
NK_API void nk_quickdraw_render(WindowPtr window, struct nk_context *ctx) { 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 #endif
#ifdef COMMAND_CACHING #ifdef COMMAND_CACHING
const struct nk_command *lastCmd;
lastCmd = nk_ptr_add_const(struct nk_command, last, 0); lastCmd = nk_ptr_add_const(struct nk_command, last, 0);
#endif #endif
@ -1143,14 +1149,25 @@ NK_API void nk_quickdraw_render(WindowPtr window, struct nk_context *ctx) {
#endif #endif
#ifdef COMMAND_CACHING #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 // 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. // 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. // 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); 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++; currentCalls++;
#endif #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(); NkQuickDrawFont *quickdrawfont = nk_quickdraw_font_create_from_file();
struct nk_user_font *font = &quickdrawfont->nk; 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); last = calloc(1, MAX_MEMORY_IN_KB * 1024);
buf = 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); nk_init_fixed(&quickdraw.nuklear_context, buf, MAX_MEMORY_IN_KB * 1024, font);