Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - MrBcx

#1
Quote from: Quin on Today at 03:19:23 PMCool stuff, MrBcx! this is a super cool looking project.


Indeed -- Tony did a killer job on it.

I tinkered with it a few years ago.  It's a very impressive interpreter and, as I've briefly demonstrated,
really easy to embed into BCX.  I embedded my own basic interpreter into an engineering app that I wrote
35 years ago.  My interpreter was not as sophisticated as Tony Wang's but it still added a usefulness that
I would have dearly missed had I not built it into my app.

For some things, an easy to learn / easy to use scripting language is indispensable.
#2
Quote from: jos on Today at 01:52:22 PMHi,
Interesting! Would it be possible to do something similar with a Basic interpreter? (Written entirely in C. Very fast and competent.)

https://github.com/paladin-t/my_basic?tab=readme-ov-file

Yes. 

Download my_basic.h and my_basic.c

This BCX sample (below) builds using BED (all compilers except Lcc-Win32)

There will be compiler warnings.


#include "my_basic.c"

DIM bas AS struct mb_interpreter_t PTR
mb_init()
mb_open(&bas)
mb_load_string(bas, "print 22 / 7;", TRUE)
mb_run(bas, TRUE)
mb_close(&bas)
mb_dispose()

PAUSE

Here is a more elaborate BCX example derived from the my_basic wiki Lambda section:


#include "my_basic.c"

DIM script AS STRING

script  = " class my_list"                           + CRLF$
script += "    var l = list()"                       + CRLF$
script += "    var tail = " + WRAP$("__TAIL__")      + CRLF$
script += "    def push_back(i)"                     + CRLF$
script += "        push(l, i)"                       + CRLF$
script += "    enddef"                               + CRLF$
script += "    def pop_back()"                       + CRLF$
script += "        return pop(l)"                    + CRLF$
script += "    enddef"                               + CRLF$
script += "    def get_iterator()"                   + CRLF$
script += "        it = iterator(l)"                 + CRLF$
script += "        return lambda ()"                 + CRLF$
script += "        ("                                + CRLF$
script += "            if not move_next(it) then"    + CRLF$
script += "                return tail"              + CRLF$
script += "            endif"                        + CRLF$
script += "            return get(it)"               + CRLF$
script += "        )"                                + CRLF$
script += "    enddef"                               + CRLF$
script += "endclass"                              + CRLF$
script += "lst = new(my_list)"                    + CRLF$
script += "lst.push_back(1)"                      + CRLF$
script += "lst.push_back(2)"                      + CRLF$
script += "lst.push_back(3)"                      + CRLF$
script += "lst.push_back(4)"                      + CRLF$
script += "iter = lst.get_iterator()"             + CRLF$
script += "do"                                    + CRLF$
script += "    item = iter()"                        + CRLF$
script += "    if item <> lst.tail then"             + CRLF$
script += "        print item;"                      + CRLF$
script += "    endif"                                + CRLF$
script += "until item = lst.tail"                 + CRLF$


DIM bas AS struct mb_interpreter_t PTR
mb_init()
mb_open(&bas)
mb_load_string(bas, script, TRUE)
mb_run(bas, TRUE)
mb_close(&bas)
mb_dispose()

PAUSE


#3
Quote from: Quin on April 26, 2025, 01:05:09 PMKevin,
I got this to work by using #pragma warning(disable: 4244) like you suggested. However, using $Pragma instead of #pragma, even in a $Header block, doesn't work. Why is this?
Thanks!

Everything that you sandwich between $HEADER directives must be legal c/c++ or c/c++ pre-processors commands.  You cannot use BCX's BASIC directives, like $PRAGMA.
#4
This isn't my area of expertise but I thought someone might find this useful:
It compiles (console mode demo) and runs correctly using all the compilers:
Lcc-Win32, Pelles C, MSVC, Mingw, Clang


DIM r AS DOUBLE
DO
    r = RND_S()
    PRINT r
LOOP UNTIL INSTAT
PAUSE

FUNCTION RND_S AS DOUBLE
    '***************************************************************************
    ' Random values are uniformly distributed across the full [0.0, 1.0) range.
    ' No truncation, underflow, or casting issues.
    ' It's cryptographically secure thanks to CryptGenRandom.
    '***************************************************************************
    ' Can be considered FIPS-compliant when run on a properly configured system
    ' with a validated provider.  On Windows, enabled via Local Security Policy
    ' or: HKLM\System\CurrentControlSet\Control\Lsa\FIPSAlgorithmPolicy
    '***************************************************************************

    #include <wincrypt.h>

    STATIC hProv AS HCRYPTPROV
    STATIC isInit AS INT
    DIM n AS UINT
    DIM ok AS INT

    IF isInit = 0 THEN
        ok = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)
        IF ok = FALSE  THEN FUNCTION = -1
        isInit = 1
    END IF

    ' Cast &n to BYTE* so it works with CryptGenRandom
    ok = CryptGenRandom(hProv, SIZEOF(n), (BYTE*)&n)
    IF ok = FALSE THEN FUNCTION = -1

    FUNCTION = CAST(DOUBLE, n / 4294967296.0)
END FUNCTION

#5
User Contributions / Re: Versions of SLEEP
April 25, 2025, 11:57:55 AM
With the first version of BCX_SLEEP(), while playing Asteroids, my desktop clock widget flickers.

Not so with version two of BCX_SLEEP().
#6
User Contributions / Versions of SLEEP
April 25, 2025, 09:49:20 AM
On a good day, BCX's built in SLEEP() function is accurate to about 16 milliseconds.

Here is a version that I used in my Asteroids game that's accurate to about 1 millisecond:
It's good but it can sometimes affect other system timers resulting in stutters or flickers.


SUB BCX_SLEEP ( x AS INTEGER )
   '******************************************
   ' Gives precision to about 1 millisecond
   '******************************************
   DIM RAW tc AS TIMECAPS
   timeGetDevCaps(&tc, SIZEOF(TIMECAPS))
   timeBeginPeriod(tc.wPeriodMin)
   SLEEP(x)
   timeEndPeriod(tc.wPeriodMin)
END SUB


Here is my new favorite version that's good to about 100 nano-seconds
but I still have it setup to accept only milliseconds argument. It has lower
impacts on the system and could be extended to accept sub-millisecond
arguments but I will leave that to others, as I have no need for that.



SUB BCX_SLEEP (Milliseconds AS INTEGER)
    '***************************************************
    ' Intervals are precise to approx 100 nano-seconds
    ' BCX_SLEEP(0) resets this timer
    ' Only use this when you need short, high precision
    ' intervals (1 to  15 milliseconds) otherwise just
    ' use BCX's normal SLEEP() command
    '***************************************************
    STATIC hTimer AS HANDLE
    DIM liDueTime AS LARGE_INTEGER
    DIM success AS INT

    ' If called with 0, close and reset the timer handle
    IF Milliseconds = 0 THEN
        IF hTimer THEN
            CloseHandle(hTimer)
            hTimer = NULL
        END IF
        EXIT SUB
    END IF

    ' Initialize timer if not already created
    IF hTimer = NULL THEN
        hTimer = CreateWaitableTimer(NULL, TRUE, NULL)
        IF hTimer = NULL THEN EXIT SUB
    END IF

    ' Convert ms to 100ns intervals (negative = relative time)
    liDueTime.QuadPart = -1 * Milliseconds * 10000

    success = SetWaitableTimer(hTimer, &liDueTime, 0, NULL, NULL, FALSE)
    IF success THEN
        WaitForSingleObject(hTimer, INFINITE)
    END IF
END SUB


#7
You should only use $WARNINGS_ON or $WARNINGS_OFF one time (preferably near the top of your code)

It's an all or nothing directive.

That said, you can leave all the warnings enabled ($WARNINGS_ON) and still selectively disable warnings
by placing them in the header section, like so:

$WARNINGS_ON

$HEADER
#pragma warning(disable: 4244) // conversion from type1 to type2 warnings
$HEADER
#8
Quin,

Those warnings stem from the fact that Bcx_ScaleX and Bcx_ScaleY are single precision (floats)
being used in numerous BCX runtime functions. Correctly eliminating the warnings would have little
to no practical effect on the functioning of the code - maybe a pixel here or there.

One way to eliminate the warnings would involve wrapping an awful lot of runtime code inside
parenthesis and casting those parenthetical expressions to (int) or (long) which would result
in a lot of goofy looking code. 

IMO, warnings can be either useful or tediously annoying, or both.  Understanding the source
of a warning is the first step in determining whether code needs refinement.
#9
Bug Reports / Re: BCXBasicCoders file of zero bytes
April 24, 2025, 02:16:47 PM
I deleted the zero-byte files from the current (web) folders.

When browsing the current sub-folders here:

https://bcxbasiccoders.com/archives/YahooGroups/

we will not see the zero-byte files any more. 

I might edit the various _Description.png files in the future
but right now, I have more useful things to do with my time.

#10
Bug Reports / Re: BCXBasicCoders file of zero bytes
April 24, 2025, 09:03:38 AM
I confirm.

I spot checked several backups of that folder going back to 2019 and found several files
from your list are zero bytes inside the backup. Those should be removed from the folder
indexes but I don't know when (or if) I'll make time to do so.

This is the manually created list that I threw together showing the folders\files with zero bytes:

\archives\YahooGroups\Com
06/30/2024  09:37 PM                 0 Csv Sql Query.Zip


\archives\YahooGroups\Games
06/30/2024  09:34 PM                 0 D&D.Zip


\archives\YahooGroups\Mru_Stuff
06/30/2024  09:36 PM                 0 Bcxcalling(Msvb)Isnumeric 18Oct11.Zip
06/30/2024  09:36 PM                 0 Bcxcheckboxdemo.Zip
06/30/2024  09:36 PM                 0 Bcxglossybuttondemo 10Nov11.Zip
06/30/2024  09:36 PM                 0 Bcxlistviewdemo Wsort.Zip
06/30/2024  09:36 PM                 0 Bcxstringtestingdemo 20Sept11.Zip
06/30/2024  09:36 PM                 0 Bcxuid&Pwd Miniapp 11Oct11.Zip


\archives\YahooGroups\Neptune_Century
06/30/2024  09:42 PM                 0 Download.Zip
06/30/2024  09:42 PM                 0 Libdemo.Zip
06/30/2024  09:42 PM                 0 Ncs Lib V0 07B.Zip
06/30/2024  09:42 PM                 0 Plugins.Zip
06/30/2024  09:42 PM                 0 Png.Zip


\archives\YahooGroups\Source_Code
06/30/2024  09:36 PM                 0 Crc32.Zip
06/30/2024  09:36 PM                 0 Dc2Bcx.Bas
06/30/2024  09:36 PM                 0 Dc301.Zip
06/30/2024  09:36 PM                 0 Dll Progressbar.Zip
06/30/2024  09:36 PM                 0 Keyparser.Zip
06/30/2024  09:36 PM                 0 Legend Builder.Zip

 
\archives\YahooGroups\Wip_Works_ In_ Progress
06/30/2024  09:36 PM                 0 AboutDialogTest.bas
06/30/2024  09:36 PM                 0 Doyle.Zip
06/30/2024  09:36 PM                 0 Regression.m
 
 
#11
Quote from: Quin on April 23, 2025, 03:52:17 PMHi Kevin,
Using the generated C code as a base as well as the subclassing windows controls section of the BCX help, I tried subclassing the edit control myself, like so. However, I still am unable to insert tabs. Am I missing something?
 
Thanks!

Quin,

Yes, you're code was missing a few very important things that I've inserted for you.


Gui "Test", Pixels

Dim As Control MainForm, Edit

Sub Formload
    MainForm = Bcx_Form("Test")
    Edit = Bcx_Richedit("", MainForm, 101, 5, 5, 600, 400)
    Global EditBeforeSubclass As WNDPROC                   ' Edited by MrBcx
    EditBeforeSubclass = SubclassWindow(Edit, EditFieldProc)
    Center(MainForm)
    Show(MainForm)
    SetFocus(Edit)
End Sub

Begin Events
    Select Case Cbmsg
        Case WM_CLOSE, WM_DESTROY, WM_QUIT
        DestroyWindow(MainForm)
    End Select
End Events

Callback Function EditFieldProc
    If Cbmsg = WM_KEYDOWN And Cbwparam = VK_TAB Then
        $Iprint_Off                             ' Added by MrBcx
        SendMessage(hWnd, EM_REPLACESEL, True, (LPARAM)"\t")
        $Iprint_On                             ' Added by MrBcx 
        Function = 0
    End If
    Function = CallWindowProc(EditBeforeSubclass, Cbhwnd, Cbmsg, Cbwparam, Cblparam)  ' Added by MrBcx 
End Function

Here is a slimmer version of the subclass procedure:

Callback Function EditFieldProc
    If Cbmsg = WM_KEYDOWN And Cbwparam = VK_TAB Then
        SendMessage(hWnd, EM_REPLACESEL, True, Tab$)   ' Edited by MrBcx - use the BCX builtin TAB$ constant
        Function = 0
    End If
    Function = CallWindowProc(EditBeforeSubclass, Cbhwnd, Cbmsg, Cbwparam, Cblparam);
End Function


#12
I shared the relevant runtime codes with ChatGpt along with your question and was given this reply:

To allow tab characters in a RichEdit, you must intercept WM_KEYDOWN and insert the \t manually, as shown in the subclassing approach below.

You could wrap this in a reusable BCX-style function or optionally subclass the RichEdit only if the user wants tab input. For instance:
🧪 Sample BCX-enhanced version:

Here's a BCX-style enhancement you could add to the BCX_RichEdit function:

WNDPROC OldRichProc;

LRESULT CALLBACK RichSubclass(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
  if (Msg == WM_KEYDOWN && wParam == VK_TAB)
  {
    SendMessage(hWnd, EM_REPLACESEL, TRUE, (LPARAM)"\t");
    RETURN 0;
  }
  RETURN CallWindowProc(OldRichProc, hWnd, Msg, wParam, lParam);
}

And in BCX_RichEdit, if you want to make this optional:

if (enableTabs) // a parameter you define for optional tab input
{
  OldRichProc = (WNDPROC)SetWindowLongPtr(A, GWLP_WNDPROC, (LONG_PTR)RichSubclass);
}

🛠� So to recap:

    ✅ ModStyle is great — just not applicable here.

    🔑 You need subclassing to change key behavior like handling the TAB key.
#13
Due to the underwhelming response, I've decided to not build any of this into BCX
and to instead share what I have in the form of an $INCLUDE file along with two demos.

Not extensively tested but the demos suggest they are working predictably. 

#14
Before I paint myself into a corner, here are my thoughts on the new CHRW() function and a few others
that I haven't mentioned yet.  It seems certain that BCX will continue its long history of generating
code that targets the WINAPI  (A) ANSI functions and not the (W) Unicode functions. 

That said, I feel certain there are times when just a little bit of built-in UNICODE enabling functions
would be a welcome improvement.  Identifying just what those enabling functions might include is what
I've been giving some recent thought, research, and experimentation to.

I am attaching two screenshots -- one is of my test code that shows the functions that I have working while
the other screenshot shows the output from that code.  You've already seen the GUI app that shows the hieroglyphs.

In a nutshell, these new functions are helpers for easily storing, copying, and printing strings, which should be
generally useful in console, GUI, and DLL projects. 

Two existing builtin BCX functions, AnsiToWide() and WideToAnsi() easily lend themselves to my new functions,
meaning it should not be necessary to reinvent a lot of wheels just to put a bit more UNICODE goodness into
our apps.

There are certainly other new BCX functions that I haven't considered yet that might make good additions as
builtin BCX functions but before I devote anymore time on this subject, I need to read your opinions on whether
this makes sense, and whether this stuff will actually be used by someone.
#15
CHRW() ... Sneak peek ... coming to BCX 8.2.7

See attached screen shot.