'******************************************************************
' BCX Basic Demo: Send and Receive from a Free AI Server
'
' NOTE: You must replace "YOUR_API_KEY_HERE" and the URL with a
' valid, key-free, or free-tier AI API. This structure is
' common for services like Gemini, OpenAI, or other LLMs.
'******************************************************************
DIM AS OBJECT http ' The WinHttp request object
DIM AS STRING URL$, API_KEY$ ' API URL and Key
DIM AS STRING json_request$ ' The JSON payload to send (request)
DIM response_text$ * 10000 ' The JSON payload received (response)
DIM AS LONG statusCode ' HTTP Status Code
' 1. Set your API credentials and URL
API_KEY$ = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ' <<< REPLACE THIS WITH YOUR Gemini free-tier KEY >>>
URL$ = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=" + API_KEY$
' NOTE: This specific URL is for the Gemini API, requiring an API key.
' For a truly free, key-less API, you would need to find a suitable
' alternative and update the URL and JSON request structure.
' 2. Build the JSON POST Request Body
' The structure sends a list of "contents" with a single "part" that contains "text".
json_request$ = "{" + CRLF$
json_request$ += " " + ENC$("contents") + ": [" + CRLF$
json_request$ += " {" + CRLF$
json_request$ += " " + ENC$("parts") + ": [{" + CRLF$
json_request$ += " " + ENC$("text") + ": " + ENC$("Write a BCX Basic temperature converter.") + CRLF$
json_request$ += " }]" + CRLF$
json_request$ += " }" + CRLF$
json_request$ += " ]" + CRLF$
json_request$ += "}"
' 3. Create the HTTP request object
http = COM("WinHttp.WinHttpRequest.5.1")
' 4. Open the connection with POST method
' Syntax: Open(Method, URL, Async)
http.OPEN("POST", URL$, FALSE) ' FALSE = synchronous
' 5. Set necessary headers
http.SetRequestHeader("Content-Type", "application/json")
http.SetRequestHeader("Accept", "application/json") ' Optional, but good practice
' 6. Send the JSON data
PRINT "Sending request to AI server..."
http.Send(json_request$)
' 7. Get the response
statusCode = http.Status
response_text$ = http.ResponseText
REPLACE "\n" WITH CRLF$ IN response_text$
' 8. Display results
PRINT ""
PRINT "=================================================="
PRINT "HTTP Status Code: " + STR$(statusCode)
PRINT "=================================================="
IF statusCode = 200 THEN
PRINT "AI Response (JSON):"
' The response is a large JSON string. We print it fully.
PRINT response_text$
ELSE
PRINT "Error: Request failed."
PRINT "Response Text: " + response_text$
END IF
' Release the COM object
UNCOM(http)
PAUSE
END
' Here's a BCX Basic program that converts temperatures between Fahrenheit and Celsius.
'**Features:**
'**Menu-driven:** Allows the user to choose the conversion type.
'**Two-way conversion:** Fahrenheit to Celsius, and Celsius to Fahrenheit.
'**Looping:** Continues until the user chooses to exit.
'**Input validation:** Basic check for menu choices.
'**Formatted output:** Displays results with two decimal places.
' BCX Temperature Converter
' Converts between Fahrenheit and Celsius
' --- Variable Declarations ---
DIM choice AS INTEGER ' Stores the user's menu choice
DIM fahrenheitValue AS DOUBLE ' Stores temperature in Fahrenheit
DIM celsiusValue AS DOUBLE ' Stores temperature in Celsius
CLS ' Clear the console screen
PRINT "----------------------------------"
PRINT " BCX Temperature Converter "
PRINT "----------------------------------"
PRINT "This program converts temperatures"
PRINT "between Fahrenheit and Celsius."
PRINT
DO
' Display menu options
PRINT "Choose a conversion type:"
PRINT " 1. Fahrenheit to Celsius"
PRINT " 2. Celsius to Fahrenheit"
PRINT " 3. Exit"
PRINT
' Get user's choice
INPUT "Enter your choice (1-3): ", choice
PRINT
SELECT CASE choice
CASE 1 ' Fahrenheit to Celsius
INPUT "Enter temperature in Fahrenheit : ", fahrenheitValue
' Formula: C = (F - 32) * 5/9
celsiusValue = (fahrenheitValue - 32) * (5.0 / 9.0) ' Use 5.0/9.0 for double precision division
PRINT USING$( "##.##", fahrenheitValue), " degrees F is ", USING$("##.##", celsiusValue), " degrees C"
PRINT
CASE 2 ' Celsius to Fahrenheit
INPUT "Enter temperature in Celsius : ", celsiusValue
' Formula: F = (C * 9/5) + 32
fahrenheitValue = (celsiusValue * (9.0 / 5.0)) + 32 ' Use 9.0/5.0 for double precision division
PRINT USING$ ("##.##", celsiusValue), " degrees C is ", USING$ ("##.##", fahrenheitValue), " degrees F"
PRINT
CASE 3 ' Exit
PRINT "Exiting temperature converter. Goodbye!"
EXIT DO ' Exit the DO...LOOP
CASE ELSE ' Invalid input
PRINT "Invalid choice. Please enter 1, 2, or 3."
PRINT
END SELECT
' Optional: Add a short pause for better readability between iterations
' SLEEP 1 ' Pause for 1 second (uncomment if needed)
LOOP ' Continue looping until EXIT DO is executed
END ' Terminate the program
'******************************************************************
' WinHttp PUT example - Send_JSON data to a REST API
' MrBcx -- December 05, 2025 MIT License
'******************************************************************
DIM AS OBJECT http
DIM url$
DIM json$
DIM response$
DIM statusCode AS LONG
' The URL endpoint where you want to PUT the data
url$ = "https://jsonplaceholder.typicode.com/posts/1" ' <--- CHANGE THIS to your API endpoint
' Build your JSON data
json$ = "{"
json$ += " " + ENC$("title") + ": " + ENC$("Updated Title") + ","
json$ += " " + ENC$("body") + ": " + ENC$("This is updated content") + ","
json$ += " " + ENC$("userId") + ": 1"
json$ += "}"
' Create the HTTP request object
http = COM("WinHttp.WinHttpRequest.5.1")
' Open the connection with PUT method
' Syntax: Open(Method, URL, Async)
http.OPEN("PUT", url$, FALSE) ' FALSE = synchronous (wait for response)
' Set the content type header for JSON
http.SetRequestHeader("Content-Type", "application/json")
' Optional: Add authentication header if needed
' http.SetRequestHeader("Authorization", "Bearer YOUR_TOKEN_HERE")
' Optional: Add other headers
' http.SetRequestHeader("Accept", "application/json")
' Send the JSON data
http.Send(json$)
' Get the response
statusCode = http.Status
response$ = http.ResponseText
' Display results
PRINT "Status Code: " + STR$(statusCode) + CRLF$ + CRLF$ + "Response:" + CRLF$ + response$
' Clean up
UNCOM(http)
PAUSE
END
Status Code: 200
Response:
{
"title": "Updated Title",
"body": "This is updated content",
"userId": 1,
"id": 1
}
Press any key to continue . . .
'******************************************************************
' ServerXMLHTTP GET - Alternative COM object
'******************************************************************
DIM AS OBJECT http
DIM url$
DIM json$ * 8192 ' Change as needed
DIM statusCode AS LONG
url$ = "https://jsonplaceholder.typicode.com/users"
http = COM("Msxml2.ServerXMLHTTP.6.0")
IF NOT ISOBJECT(http) THEN
MSGBOX "Failed to create ServerXMLHTTP object!"
END
END IF
http.OPEN("GET", url$, FALSE)
http.setRequestHeader("Accept", "application/json")
http.Send
statusCode = http.Status
IF statusCode = 200 THEN
json$ = http.ResponseText
PRINT json$
PAUSE
ELSE
PRINT "Status code: " + STR$(statusCode)
PAUSE
END IF
UNCOM(http)
END
[
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere@april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
},
{
"id": 2,
"name": "Ervin Howell",
"username": "Antonette",
"email": "Shanna@melissa.tv",
"address": {
"street": "Victor Plains",
"suite": "Suite 879",
"city": "Wisokyburgh",
"zipcode": "90566-7771",
"geo": {
"lat": "-43.9509",
"lng": "-34.4618"
}
},
"phone": "010-692-6593 x09125",
"website": "anastasia.net",
"company": {
"name": "Deckow-Crist",
"catchPhrase": "Proactive didactic contingency",
"bs": "synergize scalable supply-chains"
}
},
{
"id": 3,
"name": "Clementine Bauch",
"username": "Samantha",
"email": "Nathan@yesenia.net",
"address": {
"street": "Douglas Extension",
"suite": "Suite 847",
"city": "McKenziehaven",
"zipcode": "59590-4157",
"geo": {
"lat": "-68.6102",
"lng": "-47.0653"
}
},
"phone": "1-463-123-4447",
"website": "ramiro.info",
"company": {
"name": "Romaguera-Jacobson",
"catchPhrase": "Face to face bifurcated interface",
"bs": "e-enable strategic applications"
}
},
{
"id": 4,
"name": "Patricia Lebsack",
"username": "Karianne",
"email": "Julianne.OConner@kory.org",
"address": {
"street": "Hoeger Mall",
"suite": "Apt. 692",
"city": "South Elvis",
"zipcode": "53919-4257",
"geo": {
"lat": "29.4572",
"lng": "-164.2990"
}
},
"phone": "493-170-9623 x156",
"website": "kale.biz",
"company": {
"name": "Robel-Corkery",
"catchPhrase": "Multi-tiered zero tolerance productivity",
"bs": "transition cutting-edge web services"
}
},
{
"id": 5,
"name": "Chelsey Dietrich",
"username": "Kamren",
"email": "Lucio_Hettinger@annie.ca",
"address": {
"street": "Skiles Walks",
"suite": "Suite 351",
"city": "Roscoeview",
"zipcode": "33263",
"geo": {
"lat": "-31.8129",
"lng": "62.5342"
}
},
"phone": "(254)954-1289",
"website": "demarco.info",
"company": {
"name": "Keebler LLC",
"catchPhrase": "User-centric fault-tolerant solution",
"bs": "revolutionize end-to-end systems"
}
},
{
"id": 6,
"name": "Mrs. Dennis Schulist",
"username": "Leopoldo_Corkery",
"email": "Karley_Dach@jasper.info",
"address": {
"street": "Norberto Crossing",
"suite": "Apt. 950",
"city": "South Christy",
"zipcode": "23505-1337",
"geo": {
"lat": "-71.4197",
"lng": "71.7478"
}
},
"phone": "1-477-935-8478 x6430",
"website": "ola.org",
"company": {
"name": "Considine-Lockman",
"catchPhrase": "Synchronised bottom-line interface",
"bs": "e-enable innovative applications"
}
},
{
"id": 7,
"name": "Kurtis Weissnat",
"username": "Elwyn.Skiles",
"email": "Telly.Hoeger@billy.biz",
"address": {
"street": "Rex Trail",
"suite": "Suite 280",
"city": "Howemouth",
"zipcode": "58804-1099",
"geo": {
"lat": "24.8918",
"lng": "21.8984"
}
},
"phone": "210.067.6132",
"website": "elvis.io",
"company": {
"name": "Johns Group",
"catchPhrase": "Configurable multimedia task-force",
"bs": "generate enterprise e-tailers"
}
},
{
"id": 8,
"name": "Nicholas Runolfsdottir V",
"username": "Maxime_Nienow",
"email": "Sherwood@rosamond.me",
"address": {
"street": "Ellsworth Summit",
"suite": "Suite 729",
"city": "Aliyaview",
"zipcode": "45169",
"geo": {
"lat": "-14.3990",
"lng": "-120.7677"
}
},
"phone": "586.493.6943 x140",
"website": "jacynthe.com",
"company": {
"name": "Abernathy Group",
"catchPhrase": "Implemented secondary concept",
"bs": "e-enable extensible e-tailers"
}
},
{
"id": 9,
"name": "Glenna Reichert",
"username": "Delphine",
"email": "Chaim_McDermott@dana.io",
"address": {
"street": "Dayna Park",
"suite": "Suite 449",
"city": "Bartholomebury",
"zipcode": "76495-3109",
"geo": {
"lat": "24.6463",
"lng": "-168.8889"
}
},
"phone": "(775)976-6794 x41206",
"website": "conrad.com",
"company": {
"name": "Yost and Sons",
"catchPhrase": "Switchable contextually-based project",
"bs": "aggregate real-time technologies"
}
},
{
"id": 10,
"name": "Clementina DuBuque",
"username": "Moriah.Stanton",
"email": "Rey.Padberg@karina.biz",
"address": {
"street": "Kattie Turnpike",
"suite": "Suite 198",
"city": "Lebsackbury",
"zipcode": "31428-2261",
"geo": {
"lat": "-38.2386",
"lng": "57.2232"
}
},
"phone": "024-648-3804",
"website": "ambrose.net",
"company": {
"name": "Hoeger LLC",
"catchPhrase": "Centralized empowering task-force",
"bs": "target end-to-end models"
}
}
]
Press any key to continue . . .
'******************************************************************
' Demos All WinHttp COM object HTTP Methods. This Demo Uses
' https://jsonplaceholder.typicode.com (this is a real test API)
'******************************************************************
' Here's what each status code means:
'******************************************************************
' GET: Status 200 - Successfully retrieved data
' POST: Status 201 - Successfully created (201 = "Created")
' PUT: Status 200 - Successfully updated entire record
' PATCH: Status 200 - Successfully updated partial record
' DELETE: Status 200 - Successfully deleted - {} confirms deletion
'******************************************************************
' You now have a complete REST API toolkit in BCX!
'******************************************************************
DIM AS OBJECT http
DIM json$
DIM statusCode AS LONG
http = COM("WinHttp.WinHttpRequest.5.1")
'******************************************************************
' GET: Fetch data
'******************************************************************
PRINT "===== GET: Fetch data ====="
http.OPEN("GET", "https://jsonplaceholder.typicode.com/posts/1", FALSE)
http.SetRequestHeader("Accept", "application/json")
http.Send
statusCode = http.Status
json$ = http.ResponseText
PRINT "Status: " + STR$(statusCode)
PRINT "Response: " + LEFT$(json$, 200)
PRINT ""
'******************************************************************
' POST: Create new record
'******************************************************************
PRINT "===== POST: Create new record ====="
json$ = "{"
json$ += ENC$("title") + ": " + ENC$("New Post") + ","
json$ += ENC$("body") + ": " + ENC$("This is a new post") + ","
json$ += ENC$("userId") + ": 1"
json$ += "}"
http.OPEN("POST", "https://jsonplaceholder.typicode.com/posts", FALSE)
http.SetRequestHeader("Content-Type", "application/json")
http.Send(json$)
statusCode = http.Status
json$ = http.ResponseText
PRINT "Status: " + STR$(statusCode)
PRINT "Response: " + json$
PRINT ""
'******************************************************************
' PUT: Update entire record
'******************************************************************
PRINT "===== PUT: Update entire record ====="
json$ = "{"
json$ += ENC$("id") + ": 1,"
json$ += ENC$("title") + ": " + ENC$("Updated Post") + ","
json$ += ENC$("body") + ": " + ENC$("This post was updated") + ","
json$ += ENC$("userId") + ": 1"
json$ += "}"
http.OPEN("PUT", "https://jsonplaceholder.typicode.com/posts/1", FALSE)
http.SetRequestHeader("Content-Type", "application/json")
http.Send(json$)
statusCode = http.Status
json$ = http.ResponseText
PRINT "Status: " + STR$(statusCode)
PRINT "Response: " + json$
PRINT ""
'******************************************************************
' PATCH: Partial update
'******************************************************************
PRINT "===== PATCH: Partial update ====="
json$ = "{"
json$ += ENC$("title") + ": " + ENC$("Patched Title Only")
json$ += "}"
http.OPEN("PATCH", "https://jsonplaceholder.typicode.com/posts/1", FALSE)
http.SetRequestHeader("Content-Type", "application/json")
http.Send(json$)
statusCode = http.Status
json$ = http.ResponseText
PRINT "Status: " + STR$(statusCode)
PRINT "Response: " + json$
PRINT ""
'******************************************************************
' DELETE: Remove record
'******************************************************************
PRINT "===== DELETE: Remove record ====="
http.OPEN("DELETE", "https://jsonplaceholder.typicode.com/posts/1", FALSE)
http.Send
statusCode = http.Status
json$ = http.ResponseText
PRINT "Status: " + STR$(statusCode)
PRINT "Response: " + json$
PRINT ""
UNCOM(http)
PRINT "All HTTP methods tested!"
PAUSE
===== GET: Fetch data =====
Status: 200
Response: {
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nrepr
===== POST: Create new record =====
Status: 201
Response: {
"title": "New Post",
"body": "This is a new post",
"userId": 1,
"id": 101
}
===== PUT: Update entire record =====
Status: 200
Response: {
"id": 1,
"title": "Updated Post",
"body": "This post was updated",
"userId": 1
}
===== PATCH: Partial update =====
Status: 200
Response: {
"userId": 1,
"id": 1,
"title": "Patched Title Only",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}
===== DELETE: Remove record =====
Status: 200
Response: {}
All HTTP methods tested!
Press any key to continue . . .
Robert Wishlaw
... changed the Return Value: Data Type: of the ANSITOWIDE$ function from LPOLESTR to PWSTR. Added NULLTerm [OPTIONAL] parameter description.
... changed the UnicodeStr parameter Data Type: of the WIDETOANSI$ function from LPOLESTR to LPWSTR.
... replaced the WIDETOANSI$ function example.
... added ANSITOWIDE$ function example.
... corrected several errors in the descriptions in the GETSAVEASFILENAME$ function section.
... replaced, where appropriate, the acronym "ASCII" with "Windows Code Page code point".
The replacement usually was made where a reference existed that included the numeric 128 to 255
code point values used in Windows code pages. "ASCII" was retained in cases where the reference
was made to ASCII code points (0 - 127), common to all Windows Code Pages.
"ANSI", the acronym for the American National Standards Institute, was considered as a replacement
for the inappropriate "ASCII" usage, but was rejected as a misnomer.
In a Glossary of terms published by Microsoft, it is stated,
"The term "ANSI" as used to signify Windows code pages is a historical reference,
but is nowadays a misnomer that continues to persist in the Windows community.
The source of this comes from the fact that the Windows code page 1252 was originally based on an ANSI draft,
which became International Organization for Standardization (ISO) Standard 8859-1."
... repaired hundreds of broken hyperlinks to their primary reference document.
1738CC30076017A3AA1278B271C2B004395151251A5E412E0552FB563A391DF1
6903c03e395776b5c50266330d760d10bff5f52359854cfed7324060194d728a
*********************************************************************************************
2025/11/26 Changes in 8.3.1 from 8.3.0
*********************************************************************************************
Robert Wishlaw : MrBcx discovered AnsiToWide() has had a bug in it since 2003.
Robert Wishlaw corrected and enhanced AnsiToWide(), adding an optional argument
that directs the function to null-terminate its result. This new optional
argument defaults to TRUE - the result will be null-terminated. This is
the desired behavior when using AnsiToWide() with relevant WinApi functions.
Robert Wishlaw : Modified the console-mode SCREEN function to support foreign codepages.
James Fuller : BUG FIX: += operator misconverted in XFOR statements. Fixed by MrBcx
Kevin Diggins : BUG FIX: An edge case involving user-defined string functions containing
optional arguments was not emitting "char *BCX_RetStr={0};"
DIM AS INTEGER RetVal
DIM AS STRING Aphorism
DIM AS STRING Caption
Caption = " ἹΠΠΟΚΡΑΤΟΥΣ "
' Aphorism is UTF-8
$FILL Aphorism
" Ὁ βίος βραχύς," & CRLF$
" ἡ δὲ τέχνη μακρή," & CRLF$
" ὁ δὲ καιρὸς ὀξύς," & CRLF$
" ἡ δὲ πεῖρα σφαλερή," & CRLF$
" ἡ δὲ κρίσις χαλεπή." & CRLF$
$FILL
DIM AS PWSTR Caption_UTF16
Caption_UTF16 = A2W$(Caption, 65001)
DIM AS PWSTR Aphorism_UTF16
Aphorism_UTF16 = A2W$(Aphorism, 65001)
RetVal = MessageBoxW(GetActiveWindow(), Aphorism_UTF16, Caption_UTF16, MB_SYSTEMMODAL)
Quote" This reflects the idea that while life is fleeting,
the practice of medicine requires a long-term commitment to learning and skill development."