LOL
This commit is contained in:
parent
cf3d4046a3
commit
6b4aabb6e3
|
@ -0,0 +1,3 @@
|
||||||
|
node_modules/
|
||||||
|
dialog.r
|
||||||
|
build/
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Linux",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**",
|
||||||
|
"../R68/toolchain/m68k-apple-macos/include"
|
||||||
|
],
|
||||||
|
"defines": [],
|
||||||
|
"compilerPath": "/usr/bin/clang",
|
||||||
|
"cStandard": "c11",
|
||||||
|
"cppStandard": "c++17",
|
||||||
|
"intelliSenseMode": "clang-x64"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"quickdraw.h": "c",
|
||||||
|
"cstring": "cpp",
|
||||||
|
"cstdio": "c"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
|
||||||
|
add_application(Dialog
|
||||||
|
main.c
|
||||||
|
dialog.c
|
||||||
|
dialog.r
|
||||||
|
dukbridge.c
|
||||||
|
duktape.c
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(Dialog -lm)
|
||||||
|
|
||||||
|
# Enable -ffunction-sections and -gc-sections to make the app as small as possible
|
||||||
|
# On 68K, also enable --mac-single to build it as a single-segment app (so that this code path doesn't rot)
|
||||||
|
set_target_properties(Dialog PROPERTIES COMPILE_OPTIONS -ffunction-sections)
|
||||||
|
if(CMAKE_SYSTEM_NAME MATCHES Retro68)
|
||||||
|
set_target_properties(Dialog PROPERTIES LINK_FLAGS "-Wl,-gc-sections -Wl,--mac-single")
|
||||||
|
|
||||||
|
else()
|
||||||
|
set_target_properties(Dialog PROPERTIES LINK_FLAGS "-Wl,-gc-sections")
|
||||||
|
endif()
|
|
@ -0,0 +1,8 @@
|
||||||
|
all:
|
||||||
|
node makeResource.js > dialog.r
|
||||||
|
rm -Rf build
|
||||||
|
mkdir build
|
||||||
|
cd build && cmake .. -DCMAKE_TOOLCHAIN_FILE=~/github/R68/toolchain/m68k-apple-macos/cmake/retro68.toolchain.cmake
|
||||||
|
cd build && make
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
Macintosh fake-react native
|
||||||
|
===
|
||||||
|
|
||||||
|
This is a porting of my afternoon experiment to the Macintosh platform
|
||||||
|
|
||||||
|
It's based on the work I've done for Windows 3.11 for [this twitter thread](twitter.com/kentaromiura/status/1216742960408055809)
|
||||||
|
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
===
|
||||||
|
You need a build of https://github.com/autc04/Retro68, that includes the Apple Universal Interfaces,
|
||||||
|
to get those download the image from one of the links, open it in Basilisk and then copy those file back to windows: I used HVFExplorer and I copied them w/out the resource partition, seems to work.
|
||||||
|
About basilisk, I'm using the windows build, in order to enable the sharing between windows and basilisk I had to add `ignoresegv true` to the preference file as it keeps crashing otherwise in Windows 10.
|
||||||
|
|
||||||
|
To simplify this step you can find a pce/macplus image [linked in this article](http://www.toughdev.com/content/2018/12/developing-68k-mac-apps-with-codelite-ide-retro68-and-pce-macplus-emulator/)
|
||||||
|
I personally did not try it but should work fine, but probably you'll need to pull the latest changes from git (recursively).
|
||||||
|
|
||||||
|
I used WSL2, you can get this to work fine with WSL1 probably as long as you use a windows shared folder mounted on your linux for using the `launchAPPL` utility, otherwise you'll have to use HVFExplorer to copy the executable to the mac image.
|
||||||
|
If you use the launchAPPL I suggest to make an alias like
|
||||||
|
```
|
||||||
|
alias launchAPPL='/path/to/Retro68/build/build-host/LaunchAPPL/Client/LaunchAPPL -e shared --shared-directory /mnt/c/share'
|
||||||
|
```
|
||||||
|
If you use other emulators such as minivmac2 you can probably use the network share, it doesn't work on Basilisk though.
|
||||||
|
|
||||||
|
Ensure the node dependencies are installed by running yarn.
|
||||||
|
I wrote a script to create and embed the sources as mac resources inside the executable resource partition,
|
||||||
|
node wasn't strictly necessary for this, but I still needed babel to convert the JSX to ES3 that can be run in duktape, so that's why it's a nodejs file.
|
||||||
|
|
||||||
|
In the Makefile you'll need to edit the path to your Retro68 build, just change the value of `CMAKE_TOOLCHAIN_FILE` to the appropriate path.
|
||||||
|
|
||||||
|
How does this work?
|
||||||
|
===
|
||||||
|
|
||||||
|
The `main.c` is just a simple barebone program that initialize everything needed by the mac to start up an application, then it loads [duktape](https://duktape.org/) a real stack based JS engine that can run the code that babel outputs; the dukbridge file creates 2 duktape native functions that will we use to bridge the JS world to the native world.
|
||||||
|
|
||||||
|
First though we load the _app/fakeReact.js_ that creates some globals that we need, `React` with its 2 functions `createElement` and `mount`, plus a `MessageBox` and a `Dialog` _native_ components (you might notice that will call some weird `React.duktape.` methods, explained later), and two implementation specific things, an empty object property named `duktape`, under the `React` global to avoid too much pollution, and a `native` property that simply maps all the native components, this is used by `React.mount` to know if it needs to call the _native_ function or continue rendering; a little note here is that I didn't implement a fully descendant reconciler, it only supports 2 levels, the one needed for the demo, sorry!
|
||||||
|
|
||||||
|
Anyway, at this point the `populateCtx` in _dukbridge.c_ runs and connects the JS world to the native world by adding the `showDialog` and `showMessageBox` native functions to `React.duktape`.
|
||||||
|
|
||||||
|
At this point the main setup is done, so the _app/index.js_ is loaded first and the `main` function is mounted.
|
|
@ -0,0 +1,48 @@
|
||||||
|
(function(global){
|
||||||
|
global.Dialog = function(descriptor){
|
||||||
|
var message = descriptor.children;
|
||||||
|
var title = descriptor.properties.title;
|
||||||
|
var onYes = descriptor.properties.onYes;
|
||||||
|
var onNo = descriptor.properties.onNo;
|
||||||
|
global.React.duktape.showDialog(title, message, onYes, onNo);
|
||||||
|
};
|
||||||
|
global.MessageBox = function(descriptor) {
|
||||||
|
var message = descriptor.children;
|
||||||
|
global.React.duktape.showMessageBox(message);
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
global.React = {
|
||||||
|
native: {
|
||||||
|
'Dialog': Dialog,
|
||||||
|
'MessageBox': MessageBox
|
||||||
|
},
|
||||||
|
duktape: {},
|
||||||
|
createElement: function (component, properties, children) {
|
||||||
|
return {
|
||||||
|
component: component,
|
||||||
|
properties: properties,
|
||||||
|
children: children
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mount: function(root) {
|
||||||
|
var handled;
|
||||||
|
Object.keys(global.React.native).forEach(function (component) {
|
||||||
|
if(global.React.native[component] == root.component) {
|
||||||
|
handled = function workaroundForBug() {root.component(root)};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (handled) handled();
|
||||||
|
if (!handled) {
|
||||||
|
var newRoot = root.component(
|
||||||
|
Object.assign(
|
||||||
|
{
|
||||||
|
children: root.children
|
||||||
|
},
|
||||||
|
root.properties
|
||||||
|
)
|
||||||
|
);
|
||||||
|
newRoot.component(newRoot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})(new Function('return this')());
|
|
@ -0,0 +1,29 @@
|
||||||
|
let showMessageBox = message => {
|
||||||
|
React.mount(<MessageBox>{message}</MessageBox>);
|
||||||
|
}
|
||||||
|
|
||||||
|
let nop = () => {};
|
||||||
|
|
||||||
|
let YesNoDialog = ({
|
||||||
|
onYes = nop,
|
||||||
|
onNo = nop,
|
||||||
|
message = '',
|
||||||
|
title = ''
|
||||||
|
}) => (
|
||||||
|
<Dialog
|
||||||
|
title={title}
|
||||||
|
onYes={onYes}
|
||||||
|
onNo={onNo}
|
||||||
|
>
|
||||||
|
{message}
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
|
||||||
|
let main = () => (
|
||||||
|
<YesNoDialog
|
||||||
|
title={'Attention!'}
|
||||||
|
onYes={() => showMessageBox('Ok, bye then!')}
|
||||||
|
onNo={() => showMessageBox('Alas there is not much more to do here!')}
|
||||||
|
message={'Are you sure you want to quit?'}
|
||||||
|
/>
|
||||||
|
);
|
|
@ -0,0 +1,83 @@
|
||||||
|
#include <Quickdraw.h>
|
||||||
|
#include <Dialogs.h>
|
||||||
|
#include <Fonts.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "types.h"
|
||||||
|
#include "utils.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.
|
||||||
|
If Dialogs.h is older, we add a define to be able to use the new name
|
||||||
|
for NewUserItemUPP, which used to be NewUserItemProc. */
|
||||||
|
|
||||||
|
#define NewUserItemUPP NewUserItemProc
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// define position in resource dialog.r (128)
|
||||||
|
#define MessageBoxOK 1
|
||||||
|
#define MessageBoxMessage 2
|
||||||
|
#define MessageBoxCancel 3
|
||||||
|
#define MessageBoxTitle 4
|
||||||
|
|
||||||
|
#define AlertOK 1
|
||||||
|
#define AlertMessage 2
|
||||||
|
|
||||||
|
bool ShowAlert(char *message) {
|
||||||
|
DialogItemType type;
|
||||||
|
Handle controlHandle;
|
||||||
|
Rect box;
|
||||||
|
|
||||||
|
DialogPtr adlg = GetNewDialog(129,0,(WindowPtr)-1);
|
||||||
|
InitCursor();
|
||||||
|
{
|
||||||
|
GetDialogItem(adlg, AlertMessage, &type, &controlHandle, &box);
|
||||||
|
PString _message = toPascal(message);
|
||||||
|
SetDialogItemText(controlHandle, toConstStr255Param(_message));
|
||||||
|
}
|
||||||
|
ShowWindow(adlg);
|
||||||
|
|
||||||
|
short itemHit = NULL;
|
||||||
|
|
||||||
|
while (itemHit != AlertOK) {
|
||||||
|
ModalDialog(NULL, &itemHit);
|
||||||
|
}
|
||||||
|
DisposeDialog(adlg);
|
||||||
|
FreeDialog(129);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShowDialog(char *message, char *title, char *ok, char *cancel) {
|
||||||
|
DialogItemType type;
|
||||||
|
Handle controlHandle;
|
||||||
|
Rect box;
|
||||||
|
|
||||||
|
DialogPtr dlg = GetNewDialog(128,0,(WindowPtr)-1);
|
||||||
|
InitCursor();
|
||||||
|
|
||||||
|
{
|
||||||
|
GetDialogItem(dlg, MessageBoxMessage, &type, &controlHandle, &box);
|
||||||
|
PString _message = toPascal(message);
|
||||||
|
SetDialogItemText(controlHandle, toConstStr255Param(_message));
|
||||||
|
|
||||||
|
GetDialogItem(dlg, MessageBoxTitle, &type, &controlHandle, &box);
|
||||||
|
PString _title = toPascal(title);
|
||||||
|
SetDialogItemText(controlHandle, toConstStr255Param(_title));
|
||||||
|
|
||||||
|
GetDialogItem(dlg, MessageBoxOK, &type, &controlHandle, &box);
|
||||||
|
PString _ok = toPascal(ok);
|
||||||
|
SetControlTitle(controlHandle, toConstStr255Param(_ok));
|
||||||
|
|
||||||
|
GetDialogItem(dlg, MessageBoxCancel, &type, &controlHandle, &box);
|
||||||
|
PString _cancel = toPascal(cancel);
|
||||||
|
SetControlTitle(controlHandle, toConstStr255Param(_cancel));
|
||||||
|
}
|
||||||
|
ShowWindow(dlg);
|
||||||
|
short itemHit = NULL;
|
||||||
|
|
||||||
|
while (itemHit != MessageBoxOK && itemHit != MessageBoxCancel) {
|
||||||
|
ModalDialog(NULL, &itemHit);
|
||||||
|
}
|
||||||
|
DisposeDialog(dlg);
|
||||||
|
return itemHit == MessageBoxOK;
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef DIALOG_H
|
||||||
|
#define DIALOG_H
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
bool ShowAlert(char *message);
|
||||||
|
bool ShowDialog(char *message, char *title, char *ok, char *cancel);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,31 @@
|
||||||
|
data 'DLOG' (128) {
|
||||||
|
$"0064 0051 012A 01B3 0003 0100 0100 0000" /*
|
||||||
|
.d.Q.*.>........ */
|
||||||
|
$"0000 0080 0000 280A" /* ...<2E>..(. */
|
||||||
|
};
|
||||||
|
|
||||||
|
data 'DLOG' (129) {
|
||||||
|
$"0028 0028 00F0 0118 0001 0100 0100 0000" /* .(.(. ..........
|
||||||
|
*/
|
||||||
|
$"0000 0081 0000 280A" /* ...<2E>..(. */
|
||||||
|
};
|
||||||
|
|
||||||
|
data 'DITL' (128) {
|
||||||
|
$"0003 0000 0000 00AA 0122 00BE 015C 0402" /* ....... .".<2E>.\..
|
||||||
|
*/
|
||||||
|
$"5E31 0000 0000 0028 000A 00A5 0159 8802" /*
|
||||||
|
^1.....(...<2E>.Y<>. */
|
||||||
|
$"5E30 0000 0000 00AA 000A 00BE 0044 0402" /* ^0.....
|
||||||
|
...<2E>.D.. */
|
||||||
|
$"5E32 0000 0000 000A 0073 001A 00EF 8805" /*
|
||||||
|
^2.......s...O<>. */
|
||||||
|
$"5469 746C 6500" /* Title. */
|
||||||
|
};
|
||||||
|
|
||||||
|
data 'DITL' (129) {
|
||||||
|
$"0001 0000 0000 00A0 005B 00B4 0095 0402" /* .......+.[.<2E>.<2E>..
|
||||||
|
*/
|
||||||
|
$"4F4B 0000 0000 001E 0014 008F 00DD 8807" /*
|
||||||
|
OK.........<2E>.><3E>. */
|
||||||
|
$"4D65 7373 6167 6500" /* Message. */
|
||||||
|
};
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,45 @@
|
||||||
|
// This file is almost the same used for windows 3.1 (save for LPCStrings and minor things)
|
||||||
|
#include "dukbridge.h"
|
||||||
|
#include "dialog.h"
|
||||||
|
|
||||||
|
void populateCtx(duk_context *ctx) {
|
||||||
|
duk_get_global_string(ctx, "React"); //0
|
||||||
|
duk_get_prop_string(ctx, -1, "duktape"); //1
|
||||||
|
duk_push_c_lightfunc(ctx, DUK_DIALOG, 4,4,0); //2
|
||||||
|
duk_put_prop_string(ctx, -2, "showDialog");
|
||||||
|
|
||||||
|
duk_push_c_lightfunc(ctx, DUK_MessageBox, 1,1,0);
|
||||||
|
duk_put_prop_string(ctx, -2, "showMessageBox");
|
||||||
|
}
|
||||||
|
|
||||||
|
void emptyStack(duk_context *ctx) {
|
||||||
|
duk_idx_t idx_top;
|
||||||
|
do {
|
||||||
|
idx_top = duk_get_top_index(ctx);
|
||||||
|
if (idx_top != DUK_INVALID_INDEX) duk_pop(ctx);
|
||||||
|
} while(idx_top != DUK_INVALID_INDEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
duk_ret_t DUK_DIALOG(duk_context *ctx) {
|
||||||
|
|
||||||
|
duk_idx_t top = duk_get_top(ctx);
|
||||||
|
char* title = duk_safe_to_string(ctx, 0);
|
||||||
|
char* message = duk_safe_to_string(ctx, 1);
|
||||||
|
|
||||||
|
int ok = ShowDialog(message, title, "Yes", "No");
|
||||||
|
if (ok) {
|
||||||
|
duk_dup(ctx, 2);
|
||||||
|
} else {
|
||||||
|
duk_dup(ctx, 3);
|
||||||
|
}
|
||||||
|
duk_call(ctx, 0);
|
||||||
|
duk_pop_n(ctx, 5);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
duk_ret_t DUK_MessageBox(duk_context *ctx) {
|
||||||
|
const char* message = duk_safe_to_string(ctx, 0);
|
||||||
|
ShowAlert(message);
|
||||||
|
duk_pop(ctx);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef DUKBRIDGE_H
|
||||||
|
#define DUKBRIDGE_H
|
||||||
|
#include "duktape.h"
|
||||||
|
duk_ret_t DUK_DIALOG(duk_context *ctx);
|
||||||
|
duk_ret_t DUK_MessageBox(duk_context *ctx);
|
||||||
|
|
||||||
|
void emptyStack(duk_context *ctx);
|
||||||
|
void populateCtx(duk_context *ctx);
|
||||||
|
#endif
|
|
@ -0,0 +1,72 @@
|
||||||
|
#include <Quickdraw.h>
|
||||||
|
#include <Dialogs.h>
|
||||||
|
#include <Fonts.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <Resources.h>
|
||||||
|
|
||||||
|
// This is probably not needed to save space,
|
||||||
|
// in case you encounter any issues aliasing builtins remove this.
|
||||||
|
#define DUK_USE_LIGHTFUNC_BUILTINS
|
||||||
|
|
||||||
|
#include "duktape.h"
|
||||||
|
#include "dukbridge.h"
|
||||||
|
#include "dialog.h"
|
||||||
|
|
||||||
|
void Initialize();
|
||||||
|
void MainLoop();
|
||||||
|
void Terminate();
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Initialize();
|
||||||
|
MainLoop();
|
||||||
|
Terminate();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Initialize()
|
||||||
|
{
|
||||||
|
#if !TARGET_API_MAC_CARBON
|
||||||
|
InitGraf(&qd.thePort);
|
||||||
|
InitFonts();
|
||||||
|
InitWindows();
|
||||||
|
InitMenus();
|
||||||
|
TEInit();
|
||||||
|
InitDialogs(NULL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
char * readFromResource(int resourceId) {
|
||||||
|
Handle hnd = GetResource('TEXT', resourceId);
|
||||||
|
long size = GetResourceSizeOnDisk(hnd);
|
||||||
|
char * out = malloc(size + 1);
|
||||||
|
ReadPartialResource(hnd, 0, out, size);
|
||||||
|
out[size] = '\0';
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainLoop()
|
||||||
|
{
|
||||||
|
char * fakeReact = readFromResource(129); // app/fakeReact.js
|
||||||
|
|
||||||
|
duk_context *ctx = duk_create_heap_default();
|
||||||
|
duk_eval_string(ctx, fakeReact);
|
||||||
|
free(fakeReact);
|
||||||
|
emptyStack(ctx);
|
||||||
|
|
||||||
|
populateCtx(ctx);
|
||||||
|
emptyStack(ctx);
|
||||||
|
|
||||||
|
char * source = readFromResource(128); // app/index.js
|
||||||
|
duk_eval_string(ctx, source);
|
||||||
|
free(source);
|
||||||
|
emptyStack(ctx);
|
||||||
|
|
||||||
|
duk_eval_string(ctx, "React.mount(main())");
|
||||||
|
emptyStack(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Terminate()
|
||||||
|
{
|
||||||
|
ExitToShell();
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
const babel = require('@babel/core'),
|
||||||
|
presetEnv = require('@babel/preset-env'),
|
||||||
|
presetReact = require('@babel/preset-react'),
|
||||||
|
transformClasses = require('@babel/plugin-transform-classes');
|
||||||
|
|
||||||
|
const input = fs.readFileSync('./app/index.js', 'utf8');
|
||||||
|
const fakeReact = fs.readFileSync('./app/fakeReact.js', 'utf8');
|
||||||
|
|
||||||
|
const asResource = (input, id = 128) => {
|
||||||
|
const toHex = input => {
|
||||||
|
const result = [];
|
||||||
|
let next = input;
|
||||||
|
while(next.length) {
|
||||||
|
const next16 = next
|
||||||
|
.slice(0,16)
|
||||||
|
.padEnd(16, '\0')
|
||||||
|
.split('')
|
||||||
|
.map(x => x.charCodeAt(0).toString(16).padStart(2, '0'));
|
||||||
|
result.push(` $"${next16[0]}${next16[1]} ${next16[2]}${next16[3]} ${next16[4]}${next16[5]} ${next16[6]}${next16[7]} ${next16[8]}${next16[9]} ${next16[10]}${next16[11]} ${next16[12]}${next16[13]} ${next16[14]}${next16[15]}"`)
|
||||||
|
next = next.slice(16);
|
||||||
|
}
|
||||||
|
return result.join('\n');
|
||||||
|
}
|
||||||
|
return `data 'TEXT' (${id}) {
|
||||||
|
${toHex(input)}
|
||||||
|
};`
|
||||||
|
}
|
||||||
|
|
||||||
|
const main = asResource(babel.transform(input, {
|
||||||
|
filename: 'index.js',
|
||||||
|
presets: [[presetEnv, {
|
||||||
|
"targets": {
|
||||||
|
"browsers": ["ie < 8"]
|
||||||
|
}
|
||||||
|
}],presetReact],
|
||||||
|
plugins: [transformClasses],
|
||||||
|
retainLines: true
|
||||||
|
}).code.replace('"use strict";', ''));
|
||||||
|
|
||||||
|
const react = asResource(babel.transform(fakeReact, {
|
||||||
|
filename: 'react.js',
|
||||||
|
presets: [[presetEnv, {
|
||||||
|
"targets": {
|
||||||
|
"browsers": ["ie < 8"]
|
||||||
|
}
|
||||||
|
}],presetReact],
|
||||||
|
plugins: [transformClasses],
|
||||||
|
retainLines: true
|
||||||
|
}).code.replace('"use strict";', ''), 129);
|
||||||
|
|
||||||
|
const template = fs.readFileSync('./dialog.tpl');
|
||||||
|
|
||||||
|
console.log(`${template}
|
||||||
|
|
||||||
|
${main}
|
||||||
|
|
||||||
|
${react}`);
|
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"name": "NativeReactLikeMacintosh",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"author": "Cristian Carlesso <@kentaromiura>",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/core": "^7.9.6",
|
||||||
|
"@babel/plugin-transform-classes": "^7.9.5",
|
||||||
|
"@babel/preset-env": "^7.9.6",
|
||||||
|
"@babel/preset-react": "^7.9.4"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef __TYPES_H
|
||||||
|
#define __TYPES_H
|
||||||
|
typedef struct PascalString {
|
||||||
|
unsigned char len;
|
||||||
|
char content[255];
|
||||||
|
} PString;
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
#include "types.h"
|
||||||
|
#include <Dialogs.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef UTILS_H
|
||||||
|
#define UTILS_H
|
||||||
|
|
||||||
|
#define toConstStr255Param(var) (ConstStr255Param) &(var)
|
||||||
|
|
||||||
|
// Probably better to return a malloc'd struct for performance,
|
||||||
|
// for now this is fine.
|
||||||
|
PString toPascal(char * str) {
|
||||||
|
PString pStr;
|
||||||
|
unsigned char len = strlen(str);
|
||||||
|
if (len > 255) len = 255;
|
||||||
|
strncpy(pStr.content, str, len);
|
||||||
|
pStr.len = len;
|
||||||
|
return pStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue