Merge branch 'QB64-Phoenix-Edition:main' into midi-update
|
@ -11413,7 +11413,7 @@ int32_t chrwidth(uint32_t character) {
|
||||||
// Custom font
|
// Custom font
|
||||||
// a740g: No need to render just to find the pixel length
|
// a740g: No need to render just to find the pixel length
|
||||||
if ((fontflags[f] & FONT_LOAD_UNICODE)) { // UNICODE character
|
if ((fontflags[f] & FONT_LOAD_UNICODE)) { // UNICODE character
|
||||||
w = FontPrintWidthUTF32(font[f], (uint32_t *)&character, 1);
|
w = FontPrintWidthUTF32(font[f], (char32_t *)&character, 1);
|
||||||
} else { // ASCII character
|
} else { // ASCII character
|
||||||
character &= 255;
|
character &= 255;
|
||||||
w = FontPrintWidthASCII(font[f], (uint8_t *)&character, 1);
|
w = FontPrintWidthASCII(font[f], (uint8_t *)&character, 1);
|
||||||
|
@ -30354,7 +30354,7 @@ void display() {
|
||||||
render_option = 1;
|
render_option = 1;
|
||||||
if (rt_data_last)
|
if (rt_data_last)
|
||||||
free(rt_data_last);
|
free(rt_data_last);
|
||||||
ok = FontRenderTextUTF32(font[f], &chr_utf32, 1, render_option, &rt_data, &rt_w, &rt_h);
|
ok = FontRenderTextUTF32(font[f], (char32_t *)&chr_utf32, 1, render_option, &rt_data, &rt_w, &rt_h);
|
||||||
rt_data_last = rt_data;
|
rt_data_last = rt_data;
|
||||||
cp2 = rt_data;
|
cp2 = rt_data;
|
||||||
f_pitch = 0;
|
f_pitch = 0;
|
||||||
|
@ -31964,11 +31964,11 @@ extern "C" void qb64_os_event_linux(XEvent *event, Display *display, int *qb64_o
|
||||||
|
|
||||||
if (*qb64_os_event_info == OS_EVENT_POST_PROCESSING) {
|
if (*qb64_os_event_info == OS_EVENT_POST_PROCESSING) {
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
case EnterNotify:
|
case FocusIn:
|
||||||
window_focused = -1;
|
window_focused = -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LeaveNotify:
|
case FocusOut:
|
||||||
window_focused = 0;
|
window_focused = 0;
|
||||||
// Iterate over all modifiers
|
// Iterate over all modifiers
|
||||||
for (uint32 key = VK + QBVK_RSHIFT; key <= VK + QBVK_MODE; key++) {
|
for (uint32 key = VK + QBVK_RSHIFT; key <= VK + QBVK_MODE; key++) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
// QB64-PE Font Library
|
// QB64-PE Font Library
|
||||||
// Powered by FreeType 2.4.12 (https://github.com/vinniefalco/FreeTypeAmalgam)
|
// Powered by FreeType (https://freetype.org/)
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
@ -45,14 +45,15 @@ uint8_t *FontLoadFileToMemory(const char *file_path_name, int32_t *out_bytes);
|
||||||
int32_t FontLoad(const uint8_t *content_original, int32_t content_bytes, int32_t default_pixel_height, int32_t which_font, int32_t &options);
|
int32_t FontLoad(const uint8_t *content_original, int32_t content_bytes, int32_t default_pixel_height, int32_t which_font, int32_t &options);
|
||||||
void FontFree(int32_t fh);
|
void FontFree(int32_t fh);
|
||||||
int32_t FontWidth(int32_t fh);
|
int32_t FontWidth(int32_t fh);
|
||||||
bool FontRenderTextUTF32(int32_t fh, const uint32_t *codepoint, int32_t codepoints, int32_t options, uint8_t **out_data, int32_t *out_x, int32_t *out_y);
|
bool FontRenderTextUTF32(int32_t fh, const char32_t *codepoint, int32_t codepoints, int32_t options, uint8_t **out_data, int32_t *out_x, int32_t *out_y);
|
||||||
bool FontRenderTextASCII(int32_t fh, const uint8_t *codepoint, int32_t codepoints, int32_t options, uint8_t **out_data, int32_t *out_x, int32_t *out_y);
|
bool FontRenderTextASCII(int32_t fh, const uint8_t *codepoint, int32_t codepoints, int32_t options, uint8_t **out_data, int32_t *out_x, int32_t *out_y);
|
||||||
int32_t FontPrintWidthUTF32(int32_t fh, const uint32_t *codepoint, int32_t codepoints);
|
int32_t FontPrintWidthUTF32(int32_t fh, const char32_t *codepoint, int32_t codepoints);
|
||||||
int32_t FontPrintWidthASCII(int32_t fh, const uint8_t *codepoint, int32_t codepoints);
|
int32_t FontPrintWidthASCII(int32_t fh, const uint8_t *codepoint, int32_t codepoints);
|
||||||
|
|
||||||
qbs *func__md5(qbs *text);
|
qbs *func__md5(qbs *text);
|
||||||
int32_t func__UFontHeight(int32_t qb64_fh, int32_t passed);
|
int32_t func__UFontHeight(int32_t qb64_fh, int32_t passed);
|
||||||
int32_t func__UPrintWidth(const qbs *text, int32_t utf_encoding, int32_t qb64_fh, int32_t passed);
|
int32_t func__UPrintWidth(const qbs *text, int32_t utf_encoding, int32_t qb64_fh, int32_t passed);
|
||||||
int32_t func__ULineSpacing(int32_t qb64_fh, int32_t passed);
|
int32_t func__ULineSpacing(int32_t qb64_fh, int32_t passed);
|
||||||
void sub__UPrintString(int32_t start_x, int32_t start_y, const qbs *text, int32_t max_width, int32_t utf_encoding, int32_t qb64_fh, int32_t passed);
|
void sub__UPrintString(int32_t start_x, int32_t start_y, const qbs *text, int32_t max_width, int32_t utf_encoding, int32_t qb64_fh, int32_t dst_img,
|
||||||
|
int32_t passed);
|
||||||
int32_t func__UCharPos(const qbs *text, void *arr, int32_t utf_encoding, int32_t qb64_fh, int32_t passed);
|
int32_t func__UCharPos(const qbs *text, void *arr, int32_t utf_encoding, int32_t qb64_fh, int32_t passed);
|
||||||
|
|
|
@ -70,13 +70,11 @@ void sub_environ(qbs *str) {
|
||||||
buf = (char *)malloc(str->len + 1);
|
buf = (char *)malloc(str->len + 1);
|
||||||
buf[str->len] = '\0';
|
buf[str->len] = '\0';
|
||||||
memcpy(buf, str->chr, str->len);
|
memcpy(buf, str->chr, str->len);
|
||||||
// Name and value may be separated by = or space
|
// Name and value may be separated by = or space, whichever appears first.
|
||||||
separator = strchr(buf, ' ');
|
separator = buf + strcspn(buf, " =");
|
||||||
if (!separator) {
|
if (*separator == '\0') {
|
||||||
separator = strchr(buf, '=');
|
|
||||||
}
|
|
||||||
if (!separator) {
|
|
||||||
// It is an error is there is no separator
|
// It is an error is there is no separator
|
||||||
|
free(buf);
|
||||||
error(5);
|
error(5);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -635,7 +635,7 @@ qbs *func__files(qbs *qbsFileSpec, int32_t passed) {
|
||||||
std::string fileSpec(reinterpret_cast<char *>(qbsFileSpec->chr), qbsFileSpec->len);
|
std::string fileSpec(reinterpret_cast<char *>(qbsFileSpec->chr), qbsFileSpec->len);
|
||||||
|
|
||||||
if (fileSpec.empty())
|
if (fileSpec.empty())
|
||||||
fileSpec = "*.*";
|
fileSpec = "*";
|
||||||
|
|
||||||
if (FS_DirectoryExists(filepath_fix_directory(fileSpec))) {
|
if (FS_DirectoryExists(filepath_fix_directory(fileSpec))) {
|
||||||
directory = fileSpec;
|
directory = fileSpec;
|
||||||
|
|
|
@ -1155,7 +1155,10 @@ void fgOpenWindow( SFG_Window* window, const char* title,
|
||||||
StructureNotifyMask | SubstructureNotifyMask | ExposureMask |
|
StructureNotifyMask | SubstructureNotifyMask | ExposureMask |
|
||||||
ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
|
ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
|
||||||
VisibilityChangeMask | EnterWindowMask | LeaveWindowMask |
|
VisibilityChangeMask | EnterWindowMask | LeaveWindowMask |
|
||||||
PointerMotionMask | ButtonMotionMask;
|
PointerMotionMask | ButtonMotionMask |
|
||||||
|
// QB64-PE: custom code begin
|
||||||
|
FocusChangeMask;
|
||||||
|
// QB64-PE: custom code end
|
||||||
winAttr.background_pixmap = None;
|
winAttr.background_pixmap = None;
|
||||||
winAttr.background_pixel = 0;
|
winAttr.background_pixel = 0;
|
||||||
winAttr.border_pixel = 0;
|
winAttr.border_pixel = 0;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
// QB64-PE Font Library
|
// QB64-PE Font Library
|
||||||
// Powered by FreeType 2.4.12 (https://github.com/vinniefalco/FreeTypeAmalgam)
|
// Powered by FreeType (https://freetype.org/)
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
#define FONT_DEBUG 0
|
#define FONT_DEBUG 0
|
||||||
|
@ -12,12 +12,15 @@
|
||||||
#include "libqb-common.h"
|
#include "libqb-common.h"
|
||||||
#include "mutex.h"
|
#include "mutex.h"
|
||||||
#include "rounding.h"
|
#include "rounding.h"
|
||||||
|
#include <codecvt>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "freetype/md5.h"
|
#include "freetype/md5.h"
|
||||||
}
|
}
|
||||||
|
#include <locale>
|
||||||
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -40,146 +43,82 @@ void pset_and_clip(int32_t x, int32_t y, uint32_t col);
|
||||||
|
|
||||||
/// @brief A simple class that manages conversions from various encodings to UTF32
|
/// @brief A simple class that manages conversions from various encodings to UTF32
|
||||||
class UTF32 {
|
class UTF32 {
|
||||||
private:
|
static const uint32_t MAX_UNICODE_CODEPOINT = 0x10FFFFu;
|
||||||
// See DecodeUTF8() below for more details
|
|
||||||
enum UTF8DecoderState { ACCEPT = 0, REJECT = 1 };
|
|
||||||
|
|
||||||
/// @brief See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
|
|
||||||
/// Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
|
|
||||||
/// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
|
||||||
/// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
|
||||||
/// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
|
||||||
/// is furnished to do so, subject to the following conditions:
|
|
||||||
/// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
||||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||||
/// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
/// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
|
||||||
/// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
/// @param state The current state of the decoder
|
|
||||||
/// @param codep The decoded codepoint after state changes to UTF8DecodeState::ACCEPT
|
|
||||||
/// @param byte The next UTF-8 byte in the input stream
|
|
||||||
/// @return UTF8DecodeState::ACCEPT if enough bytes have been read for a character,
|
|
||||||
/// UTF8DecodeState::REJECT if the byte is not allowed to occur at its position,
|
|
||||||
/// and some other positive value if more bytes have to be read
|
|
||||||
uint32_t DecodeUTF8(uint32_t *state, uint32_t *codep, uint8_t byte) {
|
|
||||||
// clang-format off
|
|
||||||
static const uint8_t utf8d[] = {
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f
|
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f
|
|
||||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f
|
|
||||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf
|
|
||||||
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df
|
|
||||||
0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef
|
|
||||||
0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff
|
|
||||||
0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0
|
|
||||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2
|
|
||||||
1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4
|
|
||||||
1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6
|
|
||||||
1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8
|
|
||||||
};
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
uint32_t type = utf8d[byte];
|
|
||||||
*codep = (*state != UTF8DecoderState::ACCEPT) ? (byte & 0x3fu) | (*codep << 6) : (0xff >> type) & (byte);
|
|
||||||
*state = utf8d[256 + *state * 16 + type];
|
|
||||||
|
|
||||||
return *state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
std::u32string string; // UTF32 string
|
||||||
|
|
||||||
UTF32 &operator=(const UTF32 &) = delete;
|
UTF32 &operator=(const UTF32 &) = delete;
|
||||||
UTF32 &operator=(UTF32 &&) = delete;
|
UTF32 &operator=(UTF32 &&) = delete;
|
||||||
|
|
||||||
std::vector<uint32_t> codepoints; // UTF32 codepoint dynamic array
|
/// @brief Converts an ASCII string to UTF-32
|
||||||
|
/// @param str The ASCII string
|
||||||
/// @brief Converts an ASCII array to UTF-32
|
/// @param len The size of the string in bytes
|
||||||
/// @param str The ASCII array
|
|
||||||
/// @param byte_len The size of the array in bytes
|
|
||||||
/// @return The number of codepoints that were converted
|
/// @return The number of codepoints that were converted
|
||||||
size_t ConvertASCII(const uint8_t *str, size_t byte_len) {
|
size_t ConvertASCII(const uint8_t *str, size_t len) {
|
||||||
// Clear the codepoint vector
|
string.resize(len);
|
||||||
codepoints.clear();
|
|
||||||
|
|
||||||
// Convert the ASCII string
|
for (size_t i = 0; i < len; i++)
|
||||||
for (size_t i = 0; i < byte_len; i++)
|
string[i] = codepage437_to_unicode16[str[i]];
|
||||||
codepoints.push_back(codepage437_to_unicode16[str[i]]);
|
|
||||||
|
|
||||||
return codepoints.size();
|
return string.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Converts an UTF-8 array to UTF-32. This does not check for BOM
|
/// @brief Converts an UTF-8 string to UTF-32
|
||||||
/// @param str The UTF-8 array
|
/// @param str The UTF-8 string
|
||||||
/// @param byte_len The size of the array in bytes
|
/// @param len The size of the string in bytes
|
||||||
/// @return The number of codepoints that were converted
|
/// @return The number of codepoints that were converted
|
||||||
size_t ConvertUTF8(const uint8_t *str, size_t byte_len) {
|
size_t ConvertUTF8(const uint8_t *str, size_t len) {
|
||||||
// Clear the codepoint vector
|
try {
|
||||||
codepoints.clear();
|
string = std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t>().from_bytes((const char *)str, (const char *)str + len);
|
||||||
|
} catch (...) {
|
||||||
uint32_t prevState = UTF8DecoderState::ACCEPT, currentState = UTF8DecoderState::ACCEPT;
|
string.clear();
|
||||||
uint32_t cp;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < byte_len; i++, prevState = currentState) {
|
|
||||||
switch (DecodeUTF8(¤tState, &cp, str[i])) {
|
|
||||||
case UTF8DecoderState::ACCEPT:
|
|
||||||
// Good codepoint
|
|
||||||
codepoints.push_back(cp);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case UTF8DecoderState::REJECT:
|
|
||||||
// Codepoint would be U+FFFD (replacement character)
|
|
||||||
cp = 0xFFFD;
|
|
||||||
currentState = UTF8DecoderState::ACCEPT;
|
|
||||||
if (prevState != UTF8DecoderState::ACCEPT)
|
|
||||||
--i;
|
|
||||||
codepoints.push_back(cp);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// Need to read continuation bytes
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return codepoints.size();
|
return string.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Converts an UTF-16LE array to UTF-32. This does not check for BOM
|
/// @brief Converts an UTF-16 LE/BE string (with BOM or naked) to UTF-32
|
||||||
/// @param str The UTF-16LE array
|
/// @param str The UTF-16 string. If no BOM is present, little-endian is assumed
|
||||||
/// @param byte_len The size of the array in bytes
|
/// @param len The size of the string in bytes
|
||||||
/// @return The number of codepoints that were converted
|
/// @return The number of codepoints that were converted
|
||||||
size_t ConvertUTF16(const uint8_t *str, size_t byte_len) {
|
size_t ConvertUTF16(const uint8_t *str, size_t len) {
|
||||||
// Clear the codepoint vector
|
try {
|
||||||
codepoints.clear();
|
if (len > 2) {
|
||||||
|
// Detect BOM
|
||||||
// We'll assume the worst case scenario and allocate a buffer that is byte_len / 2 codepoints long
|
if (str[0] == 0xFF && str[1] == 0xFE) {
|
||||||
auto len16 = byte_len / sizeof(uint16_t);
|
// Little-endian
|
||||||
auto str16 = (const uint16_t *)str;
|
string = std::wstring_convert<
|
||||||
uint32_t cp;
|
std::codecvt_utf16<char32_t, MAX_UNICODE_CODEPOINT,
|
||||||
|
static_cast<std::codecvt_mode>(std::codecvt_mode::consume_header | std::codecvt_mode::little_endian)>,
|
||||||
for (size_t i = 0; i < len16; i++) {
|
char32_t>()
|
||||||
auto ch = str16[i];
|
.from_bytes((const char *)str, (const char *)str + len);
|
||||||
|
} else if (str[0] == 0xFE && str[1] == 0xFF) {
|
||||||
// If the character is a surrogate, we need to combine it with the next character to get the actual codepoint
|
// Big-endian (C++ default)
|
||||||
if (ch >= 0xD800 && ch <= 0xDBFF && i + 1 < len16) {
|
string =
|
||||||
auto ch2 = str16[i + 1];
|
std::wstring_convert<std::codecvt_utf16<char32_t, MAX_UNICODE_CODEPOINT, std::codecvt_mode::consume_header>, char32_t>().from_bytes(
|
||||||
if (ch2 >= 0xDC00 && ch2 <= 0xDFFF) {
|
(const char *)str, (const char *)str + len);
|
||||||
cp = ((ch - 0xD800) << 10) + (ch2 - 0xDC00) + 0x10000;
|
|
||||||
++i; // skip the second surrogate
|
|
||||||
} else {
|
} else {
|
||||||
cp = 0xFFFD; // invalid surrogate pair
|
// No BOM, assuming little-endian by default
|
||||||
|
string = std::wstring_convert<
|
||||||
|
std::codecvt_utf16<char32_t, MAX_UNICODE_CODEPOINT,
|
||||||
|
static_cast<std::codecvt_mode>(std::codecvt_mode::consume_header | std::codecvt_mode::little_endian)>,
|
||||||
|
char32_t>()
|
||||||
|
.from_bytes((const char *)str, (const char *)str + len);
|
||||||
}
|
}
|
||||||
} else if (ch >= 0xDC00 && ch <= 0xDFFF) {
|
|
||||||
cp = 0xFFFD; // invalid surrogate pair
|
|
||||||
} else {
|
} else {
|
||||||
cp = ch;
|
// Short string, assuming little-endian by default
|
||||||
|
string = std::wstring_convert<
|
||||||
|
std::codecvt_utf16<char32_t, MAX_UNICODE_CODEPOINT,
|
||||||
|
static_cast<std::codecvt_mode>(std::codecvt_mode::consume_header | std::codecvt_mode::little_endian)>,
|
||||||
|
char32_t>()
|
||||||
|
.from_bytes((const char *)str, (const char *)str + len);
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
string.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
codepoints.push_back(cp);
|
return string.size();
|
||||||
}
|
|
||||||
|
|
||||||
return codepoints.size();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -317,7 +256,7 @@ struct FontManager {
|
||||||
/// @param codepoint A valid UTF-32 codepoint
|
/// @param codepoint A valid UTF-32 codepoint
|
||||||
/// @param parentFont The parent font object
|
/// @param parentFont The parent font object
|
||||||
/// @return True if successful or if bitmap is already cached
|
/// @return True if successful or if bitmap is already cached
|
||||||
bool CacheBitmap(uint32_t codepoint, Font *parentFont) {
|
bool CacheBitmap(char32_t codepoint, Font *parentFont) {
|
||||||
if (!bitmap) {
|
if (!bitmap) {
|
||||||
// Get the glyph index first and store it
|
// Get the glyph index first and store it
|
||||||
// Note that this can return a valid glyph index but the index need not have any glyph bitmap
|
// Note that this can return a valid glyph index but the index need not have any glyph bitmap
|
||||||
|
@ -396,7 +335,7 @@ struct FontManager {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unordered_map<uint32_t, Glyph *> glyphs; // holds pointers to cached glyph data for codepoints
|
std::unordered_map<char32_t, Glyph *> glyphs; // holds pointers to cached glyph data for codepoints
|
||||||
|
|
||||||
// Delete copy and move constructors and assignments
|
// Delete copy and move constructors and assignments
|
||||||
Font(const Font &) = delete;
|
Font(const Font &) = delete;
|
||||||
|
@ -436,7 +375,7 @@ struct FontManager {
|
||||||
/// @param codepoint A valid UTF-32 codepoint
|
/// @param codepoint A valid UTF-32 codepoint
|
||||||
/// @param isMono True for mono bitmap and false for gray
|
/// @param isMono True for mono bitmap and false for gray
|
||||||
/// @return The glyph pointer if successful or if the glyph is already in the map, nullptr otherwise
|
/// @return The glyph pointer if successful or if the glyph is already in the map, nullptr otherwise
|
||||||
Glyph *GetGlyph(uint32_t codepoint, bool isMono) {
|
Glyph *GetGlyph(char32_t codepoint, bool isMono) {
|
||||||
if (glyphs.count(codepoint) == 0) {
|
if (glyphs.count(codepoint) == 0) {
|
||||||
// The glyph is not cached yet
|
// The glyph is not cached yet
|
||||||
auto newGlyph = new Glyph;
|
auto newGlyph = new Glyph;
|
||||||
|
@ -471,7 +410,7 @@ struct FontManager {
|
||||||
/// @param codepoint The codepoint array (string)
|
/// @param codepoint The codepoint array (string)
|
||||||
/// @param codepoints The number of codepoints in the array
|
/// @param codepoints The number of codepoints in the array
|
||||||
/// @return The length of the string in pixels
|
/// @return The length of the string in pixels
|
||||||
FT_Pos GetStringPixelWidth(const uint32_t *codepoint, size_t codepoints) {
|
FT_Pos GetStringPixelWidth(const char32_t *codepoint, size_t codepoints) {
|
||||||
if (monospaceWidth) // return monospace width simply by multiplying the fixed width by the codepoints
|
if (monospaceWidth) // return monospace width simply by multiplying the fixed width by the codepoints
|
||||||
return monospaceWidth * codepoints;
|
return monospaceWidth * codepoints;
|
||||||
|
|
||||||
|
@ -896,7 +835,7 @@ int32_t FontWidth(int32_t fh) {
|
||||||
/// @param codepoint The UTF32 codepoint array
|
/// @param codepoint The UTF32 codepoint array
|
||||||
/// @param codepoints The number of codepoints
|
/// @param codepoints The number of codepoints
|
||||||
/// @return Length in pixels
|
/// @return Length in pixels
|
||||||
int32_t FontPrintWidthUTF32(int32_t fh, const uint32_t *codepoint, int32_t codepoints) {
|
int32_t FontPrintWidthUTF32(int32_t fh, const char32_t *codepoint, int32_t codepoints) {
|
||||||
libqb_mutex_guard lock(fontManager.m);
|
libqb_mutex_guard lock(fontManager.m);
|
||||||
|
|
||||||
if (codepoints > 0) {
|
if (codepoints > 0) {
|
||||||
|
@ -922,7 +861,7 @@ int32_t FontPrintWidthASCII(int32_t fh, const uint8_t *codepoint, int32_t codepo
|
||||||
|
|
||||||
// Attempt to convert the string to UTF32 and get the actual width in pixels
|
// Attempt to convert the string to UTF32 and get the actual width in pixels
|
||||||
auto count = utf32.ConvertASCII(codepoint, codepoints);
|
auto count = utf32.ConvertASCII(codepoint, codepoints);
|
||||||
return FontPrintWidthUTF32(fh, utf32.codepoints.data(), count);
|
return FontPrintWidthUTF32(fh, utf32.string.data(), count);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -937,7 +876,7 @@ int32_t FontPrintWidthASCII(int32_t fh, const uint8_t *codepoint, int32_t codepo
|
||||||
/// @param out_x A pointer to the output width of the rendered text in pixels
|
/// @param out_x A pointer to the output width of the rendered text in pixels
|
||||||
/// @param out_y A pointer to the output height of the rendered text in pixels
|
/// @param out_y A pointer to the output height of the rendered text in pixels
|
||||||
/// @return success = 1, failure = 0
|
/// @return success = 1, failure = 0
|
||||||
bool FontRenderTextUTF32(int32_t fh, const uint32_t *codepoint, int32_t codepoints, int32_t options, uint8_t **out_data, int32_t *out_x, int32_t *out_y) {
|
bool FontRenderTextUTF32(int32_t fh, const char32_t *codepoint, int32_t codepoints, int32_t options, uint8_t **out_data, int32_t *out_x, int32_t *out_y) {
|
||||||
libqb_mutex_guard lock(fontManager.m);
|
libqb_mutex_guard lock(fontManager.m);
|
||||||
|
|
||||||
FONT_DEBUG_CHECK(IS_VALID_FONT_HANDLE(fh));
|
FONT_DEBUG_CHECK(IS_VALID_FONT_HANDLE(fh));
|
||||||
|
@ -972,7 +911,7 @@ bool FontRenderTextUTF32(int32_t fh, const uint32_t *codepoint, int32_t codepoin
|
||||||
auto glyph = fnt->GetGlyph(cp, isMonochrome);
|
auto glyph = fnt->GetGlyph(cp, isMonochrome);
|
||||||
if (glyph) {
|
if (glyph) {
|
||||||
glyph->RenderBitmap(outBuf, strPixSize.x, strPixSize.y,
|
glyph->RenderBitmap(outBuf, strPixSize.x, strPixSize.y,
|
||||||
penX + glyph->bitmap->bearing.x + fnt->monospaceWidth / 2 - glyph->bitmap->advanceWidth / 2,
|
penX + glyph->bitmap->bearing.x + (fnt->monospaceWidth >> 1) - (glyph->bitmap->advanceWidth >> 1),
|
||||||
fnt->baseline - glyph->bitmap->bearing.y);
|
fnt->baseline - glyph->bitmap->bearing.y);
|
||||||
penX += fnt->monospaceWidth;
|
penX += fnt->monospaceWidth;
|
||||||
}
|
}
|
||||||
|
@ -1025,7 +964,7 @@ bool FontRenderTextASCII(int32_t fh, const uint8_t *codepoint, int32_t codepoint
|
||||||
|
|
||||||
// Attempt to convert the string to UTF32 and forward to FontRenderTextUTF32()
|
// Attempt to convert the string to UTF32 and forward to FontRenderTextUTF32()
|
||||||
auto count = utf32.ConvertASCII(codepoint, codepoints);
|
auto count = utf32.ConvertASCII(codepoint, codepoints);
|
||||||
return FontRenderTextUTF32(fh, utf32.codepoints.data(), count, options, out_data, out_x, out_y);
|
return FontRenderTextUTF32(fh, utf32.string.data(), count, options, out_data, out_x, out_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -1082,7 +1021,7 @@ int32_t func__UFontHeight(int32_t qb64_fh, int32_t passed) {
|
||||||
auto face = fnt->face;
|
auto face = fnt->face;
|
||||||
|
|
||||||
if (FT_IS_SCALABLE(face))
|
if (FT_IS_SCALABLE(face))
|
||||||
return (((FT_Pos)face->ascender - (FT_Pos)face->descender) * fnt->defaultHeight) / (FT_Pos)face->units_per_EM;
|
return FT_MulDiv(((FT_Long)face->ascender - (FT_Long)face->descender), (FT_Long)fnt->defaultHeight, (FT_Long)face->units_per_EM);
|
||||||
|
|
||||||
return fnt->defaultHeight;
|
return fnt->defaultHeight;
|
||||||
}
|
}
|
||||||
|
@ -1120,31 +1059,31 @@ int32_t func__UPrintWidth(const qbs *text, int32_t utf_encoding, int32_t qb64_fh
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the string to UTF-32 if needed
|
// Convert the string to UTF-32 if needed
|
||||||
uint32_t const *str32 = nullptr;
|
char32_t const *str32 = nullptr;
|
||||||
size_t codepoints = 0;
|
size_t codepoints = 0;
|
||||||
|
|
||||||
switch (utf_encoding) {
|
switch (utf_encoding) {
|
||||||
case 32: // UTF-32: no conversion needed
|
case 32: // UTF-32: no conversion needed
|
||||||
str32 = (uint32_t *)text->chr;
|
str32 = (char32_t *)text->chr;
|
||||||
codepoints = text->len / sizeof(uint32_t);
|
codepoints = text->len / sizeof(char32_t);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 16: // UTF-16: conversion required
|
case 16: // UTF-16: conversion required
|
||||||
codepoints = utf32.ConvertUTF16(text->chr, text->len);
|
codepoints = utf32.ConvertUTF16(text->chr, text->len);
|
||||||
if (codepoints)
|
if (codepoints)
|
||||||
str32 = utf32.codepoints.data();
|
str32 = utf32.string.data();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 8: // UTF-8: conversion required
|
case 8: // UTF-8: conversion required
|
||||||
codepoints = utf32.ConvertUTF8(text->chr, text->len);
|
codepoints = utf32.ConvertUTF8(text->chr, text->len);
|
||||||
if (codepoints)
|
if (codepoints)
|
||||||
str32 = utf32.codepoints.data();
|
str32 = utf32.string.data();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: // ASCII: conversion required
|
default: // ASCII: conversion required
|
||||||
codepoints = utf32.ConvertASCII(text->chr, text->len);
|
codepoints = utf32.ConvertASCII(text->chr, text->len);
|
||||||
if (codepoints)
|
if (codepoints)
|
||||||
str32 = utf32.codepoints.data();
|
str32 = utf32.string.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qb64_fh < 32)
|
if (qb64_fh < 32)
|
||||||
|
@ -1184,7 +1123,7 @@ int32_t func__ULineSpacing(int32_t qb64_fh, int32_t passed) {
|
||||||
auto face = fnt->face;
|
auto face = fnt->face;
|
||||||
|
|
||||||
if (FT_IS_SCALABLE(face))
|
if (FT_IS_SCALABLE(face))
|
||||||
return ((FT_Pos)face->height * fnt->defaultHeight) / (FT_Pos)face->units_per_EM;
|
return FT_MulDiv((FT_Long)face->height, (FT_Long)fnt->defaultHeight, (FT_Long)face->units_per_EM);
|
||||||
|
|
||||||
return fnt->defaultHeight;
|
return fnt->defaultHeight;
|
||||||
}
|
}
|
||||||
|
@ -1193,28 +1132,23 @@ int32_t func__ULineSpacing(int32_t qb64_fh, int32_t passed) {
|
||||||
/// @param start_x The starting x position
|
/// @param start_x The starting x position
|
||||||
/// @param start_y The starting y position
|
/// @param start_y The starting y position
|
||||||
/// @param text The text that needs to be rendered
|
/// @param text The text that needs to be rendered
|
||||||
/// @param max_width The maximum width of the text (rendering will be clipped beyond width)
|
/// @param max_width [optional] The maximum width of the text (rendering will be clipped beyond width)
|
||||||
/// @param utf_encoding The UTF encoding of the text (0 = ASCII, 8 = UTF-8, 16 - UTF-16, 32 = UTF-32)
|
/// @param utf_encoding [optional] The UTF encoding of the text (0 = ASCII, 8 = UTF-8, 16 - UTF-16, 32 = UTF-32)
|
||||||
/// @param qb64_fh A QB64 font handle (this can be a builtin font as well)
|
/// @param qb64_fh [optional] A QB64 font handle (this can be a builtin font as well)
|
||||||
|
/// @param dst_img [optional] A QB64 image handle (zero designates current SCREEN page)
|
||||||
/// @param passed Optional arguments flag
|
/// @param passed Optional arguments flag
|
||||||
void sub__UPrintString(int32_t start_x, int32_t start_y, const qbs *text, int32_t max_width, int32_t utf_encoding, int32_t qb64_fh, int32_t passed) {
|
void sub__UPrintString(int32_t start_x, int32_t start_y, const qbs *text, int32_t max_width, int32_t utf_encoding, int32_t qb64_fh, int32_t dst_img,
|
||||||
|
int32_t passed) {
|
||||||
libqb_mutex_guard lock(fontManager.m);
|
libqb_mutex_guard lock(fontManager.m);
|
||||||
|
|
||||||
if (is_error_pending() || !text->len)
|
if (is_error_pending() || !text->len)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Check if we are in text mode and generate an error if we are
|
|
||||||
if (write_page->text) {
|
|
||||||
error(QB_ERROR_ILLEGAL_FUNCTION_CALL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FONT_DEBUG_PRINT("Graphics mode set. Proceeding...");
|
|
||||||
|
|
||||||
// Check max width
|
// Check max width
|
||||||
if (passed & 1) {
|
if (passed & 1) {
|
||||||
if (max_width < 1)
|
if (max_width < 1) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
max_width = 0;
|
max_width = 0;
|
||||||
}
|
}
|
||||||
|
@ -1229,10 +1163,29 @@ void sub__UPrintString(int32_t start_x, int32_t start_y, const qbs *text, int32_
|
||||||
utf_encoding = 0;
|
utf_encoding = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t old_dst_img;
|
||||||
|
|
||||||
|
if (passed & 8) {
|
||||||
|
old_dst_img = func__dest();
|
||||||
|
sub__dest(dst_img);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we are in text mode and generate an error if we are
|
||||||
|
if (write_page->text) {
|
||||||
|
error(QB_ERROR_ILLEGAL_FUNCTION_CALL);
|
||||||
|
if (passed & 8)
|
||||||
|
sub__dest(old_dst_img);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FONT_DEBUG_PRINT("Graphics mode set. Proceeding...");
|
||||||
|
|
||||||
// Check if a valid font handle was passed
|
// Check if a valid font handle was passed
|
||||||
if (passed & 4) {
|
if (passed & 4) {
|
||||||
if (!IS_VALID_QB64_FONT_HANDLE(qb64_fh)) {
|
if (!IS_VALID_QB64_FONT_HANDLE(qb64_fh)) {
|
||||||
error(QB_ERROR_INVALID_HANDLE);
|
error(QB_ERROR_INVALID_HANDLE);
|
||||||
|
if (passed & 8)
|
||||||
|
sub__dest(old_dst_img);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1240,39 +1193,42 @@ void sub__UPrintString(int32_t start_x, int32_t start_y, const qbs *text, int32_
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the string to UTF-32 if needed
|
// Convert the string to UTF-32 if needed
|
||||||
uint32_t const *str32 = nullptr;
|
char32_t const *str32 = nullptr;
|
||||||
size_t codepoints = 0;
|
size_t codepoints = 0;
|
||||||
|
|
||||||
switch (utf_encoding) {
|
switch (utf_encoding) {
|
||||||
case 32: // UTF-32: no conversion needed
|
case 32: // UTF-32: no conversion needed
|
||||||
FONT_DEBUG_PRINT("UTF-32 string. Skipping conversion");
|
FONT_DEBUG_PRINT("UTF-32 string. Skipping conversion");
|
||||||
str32 = (uint32_t *)text->chr;
|
str32 = (char32_t *)text->chr;
|
||||||
codepoints = text->len / sizeof(uint32_t);
|
codepoints = text->len / sizeof(char32_t);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 16: // UTF-16: conversion required
|
case 16: // UTF-16: conversion required
|
||||||
FONT_DEBUG_PRINT("UTF-16 string. Converting to UTF32");
|
FONT_DEBUG_PRINT("UTF-16 string. Converting to UTF32");
|
||||||
codepoints = utf32.ConvertUTF16(text->chr, text->len);
|
codepoints = utf32.ConvertUTF16(text->chr, text->len);
|
||||||
if (codepoints)
|
if (codepoints)
|
||||||
str32 = utf32.codepoints.data();
|
str32 = utf32.string.data();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 8: // UTF-8: conversion required
|
case 8: // UTF-8: conversion required
|
||||||
FONT_DEBUG_PRINT("UTF-8 string. Converting to UTF32");
|
FONT_DEBUG_PRINT("UTF-8 string. Converting to UTF32");
|
||||||
codepoints = utf32.ConvertUTF8(text->chr, text->len);
|
codepoints = utf32.ConvertUTF8(text->chr, text->len);
|
||||||
if (codepoints)
|
if (codepoints)
|
||||||
str32 = utf32.codepoints.data();
|
str32 = utf32.string.data();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: // ASCII: conversion required
|
default: // ASCII: conversion required
|
||||||
FONT_DEBUG_PRINT("ASCII string. Converting to UTF32");
|
FONT_DEBUG_PRINT("ASCII string. Converting to UTF32");
|
||||||
codepoints = utf32.ConvertASCII(text->chr, text->len);
|
codepoints = utf32.ConvertASCII(text->chr, text->len);
|
||||||
if (codepoints)
|
if (codepoints)
|
||||||
str32 = utf32.codepoints.data();
|
str32 = utf32.string.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!codepoints)
|
if (!codepoints) {
|
||||||
|
if (passed & 8)
|
||||||
|
sub__dest(old_dst_img);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
FontManager::Font *fnt = nullptr;
|
FontManager::Font *fnt = nullptr;
|
||||||
FT_Face face = nullptr;
|
FT_Face face = nullptr;
|
||||||
|
@ -1290,7 +1246,7 @@ void sub__UPrintString(int32_t start_x, int32_t start_y, const qbs *text, int32_
|
||||||
strPixSize.x = fnt->GetStringPixelWidth(str32, codepoints);
|
strPixSize.x = fnt->GetStringPixelWidth(str32, codepoints);
|
||||||
pen.x = 0;
|
pen.x = 0;
|
||||||
if (FT_IS_SCALABLE(face)) {
|
if (FT_IS_SCALABLE(face)) {
|
||||||
strPixSize.y = (((FT_Pos)face->ascender - (FT_Pos)face->descender) * fnt->defaultHeight) / (FT_Pos)face->units_per_EM;
|
strPixSize.y = FT_MulDiv(((FT_Long)face->ascender - (FT_Long)face->descender), (FT_Long)fnt->defaultHeight, (FT_Long)face->units_per_EM);
|
||||||
pen.y = ((FT_Pos)face->ascender * fnt->defaultHeight) / (FT_Pos)face->units_per_EM;
|
pen.y = ((FT_Pos)face->ascender * fnt->defaultHeight) / (FT_Pos)face->units_per_EM;
|
||||||
} else {
|
} else {
|
||||||
strPixSize.y = fnt->defaultHeight;
|
strPixSize.y = fnt->defaultHeight;
|
||||||
|
@ -1305,8 +1261,11 @@ void sub__UPrintString(int32_t start_x, int32_t start_y, const qbs *text, int32_
|
||||||
strPixSize.x = max_width;
|
strPixSize.x = max_width;
|
||||||
|
|
||||||
auto drawBuf = (uint8_t *)calloc(strPixSize.x, strPixSize.y);
|
auto drawBuf = (uint8_t *)calloc(strPixSize.x, strPixSize.y);
|
||||||
if (!drawBuf)
|
if (!drawBuf) {
|
||||||
|
if (passed & 8)
|
||||||
|
sub__dest(old_dst_img);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
FONT_DEBUG_PRINT("Allocated (%lu x %lu) buffer", strPixSize.x, strPixSize.y);
|
FONT_DEBUG_PRINT("Allocated (%lu x %lu) buffer", strPixSize.x, strPixSize.y);
|
||||||
|
|
||||||
|
@ -1364,7 +1323,7 @@ void sub__UPrintString(int32_t start_x, int32_t start_y, const qbs *text, int32_
|
||||||
break;
|
break;
|
||||||
|
|
||||||
glyph->RenderBitmap(drawBuf, strPixSize.x, strPixSize.y,
|
glyph->RenderBitmap(drawBuf, strPixSize.x, strPixSize.y,
|
||||||
pen.x + glyph->bitmap->bearing.x + fnt->monospaceWidth / 2 - glyph->bitmap->advanceWidth / 2,
|
pen.x + glyph->bitmap->bearing.x + (fnt->monospaceWidth >> 1) - (glyph->bitmap->advanceWidth >> 1),
|
||||||
pen.y - glyph->bitmap->bearing.y);
|
pen.y - glyph->bitmap->bearing.y);
|
||||||
pen.x += fnt->monospaceWidth;
|
pen.x += fnt->monospaceWidth;
|
||||||
}
|
}
|
||||||
|
@ -1506,6 +1465,9 @@ void sub__UPrintString(int32_t start_x, int32_t start_y, const qbs *text, int32_
|
||||||
}
|
}
|
||||||
|
|
||||||
free(drawBuf);
|
free(drawBuf);
|
||||||
|
|
||||||
|
if (passed & 8)
|
||||||
|
sub__dest(old_dst_img);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Calculate the starting pixel positions of each codepoint to an array. First one being zero.
|
/// @brief Calculate the starting pixel positions of each codepoint to an array. First one being zero.
|
||||||
|
@ -1550,31 +1512,31 @@ int32_t func__UCharPos(const qbs *text, void *arr, int32_t utf_encoding, int32_t
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the string to UTF-32 if needed
|
// Convert the string to UTF-32 if needed
|
||||||
uint32_t const *str32 = nullptr;
|
char32_t const *str32 = nullptr;
|
||||||
size_t codepoints = 0;
|
size_t codepoints = 0;
|
||||||
|
|
||||||
switch (utf_encoding) {
|
switch (utf_encoding) {
|
||||||
case 32: // UTF-32: no conversion needed
|
case 32: // UTF-32: no conversion needed
|
||||||
str32 = (uint32_t *)text->chr;
|
str32 = (char32_t *)text->chr;
|
||||||
codepoints = text->len / sizeof(uint32_t);
|
codepoints = text->len / sizeof(char32_t);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 16: // UTF-16: conversion required
|
case 16: // UTF-16: conversion required
|
||||||
codepoints = utf32.ConvertUTF16(text->chr, text->len);
|
codepoints = utf32.ConvertUTF16(text->chr, text->len);
|
||||||
if (codepoints)
|
if (codepoints)
|
||||||
str32 = utf32.codepoints.data();
|
str32 = utf32.string.data();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 8: // UTF-8: conversion required
|
case 8: // UTF-8: conversion required
|
||||||
codepoints = utf32.ConvertUTF8(text->chr, text->len);
|
codepoints = utf32.ConvertUTF8(text->chr, text->len);
|
||||||
if (codepoints)
|
if (codepoints)
|
||||||
str32 = utf32.codepoints.data();
|
str32 = utf32.string.data();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: // ASCII: conversion required
|
default: // ASCII: conversion required
|
||||||
codepoints = utf32.ConvertASCII(text->chr, text->len);
|
codepoints = utf32.ConvertASCII(text->chr, text->len);
|
||||||
if (codepoints)
|
if (codepoints)
|
||||||
str32 = utf32.codepoints.data();
|
str32 = utf32.string.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simply return the codepoint count if we do not have any array
|
// Simply return the codepoint count if we do not have any array
|
||||||
|
|
|
@ -24,7 +24,7 @@ int32_t FontWidth(int32_t fh) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FontRenderTextUTF32(int32_t fh, const uint32_t *codepoint, int32_t codepoints, int32_t options, uint8_t **out_data, int32_t *out_x, int32_t *out_y) {
|
bool FontRenderTextUTF32(int32_t fh, const char32_t *codepoint, int32_t codepoints, int32_t options, uint8_t **out_data, int32_t *out_x, int32_t *out_y) {
|
||||||
(void)fh;
|
(void)fh;
|
||||||
(void)codepoint;
|
(void)codepoint;
|
||||||
(void)codepoints;
|
(void)codepoints;
|
||||||
|
@ -46,7 +46,7 @@ bool FontRenderTextASCII(int32_t fh, const uint8_t *codepoint, int32_t codepoint
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t FontPrintWidthUTF32(int32_t fh, const uint32_t *codepoint, int32_t codepoints) {
|
int32_t FontPrintWidthUTF32(int32_t fh, const char32_t *codepoint, int32_t codepoints) {
|
||||||
(void)fh;
|
(void)fh;
|
||||||
(void)codepoint;
|
(void)codepoint;
|
||||||
(void)codepoints;
|
(void)codepoints;
|
||||||
|
|
|
@ -7,7 +7,7 @@ if (_FUNC_EVALUATEFUNCTION_ARRAY_UDT_ARGS[2]&1){
|
||||||
tmp_long=_FUNC_EVALUATEFUNCTION_ARRAY_UDT_ARGS[5];
|
tmp_long=_FUNC_EVALUATEFUNCTION_ARRAY_UDT_ARGS[5];
|
||||||
while(tmp_long--) {
|
while(tmp_long--) {
|
||||||
|
|
||||||
qbs_free(*(qbs**)(_FUNC_EVALUATEFUNCTION_ARRAY_UDT_ARGS[0]+(480/8+1-1)*tmp_long+ 48));}
|
qbs_free(*(qbs**)(_FUNC_EVALUATEFUNCTION_ARRAY_UDT_ARGS[0]+60*tmp_long+ 48));}
|
||||||
free((void*)(_FUNC_EVALUATEFUNCTION_ARRAY_UDT_ARGS[0]));
|
free((void*)(_FUNC_EVALUATEFUNCTION_ARRAY_UDT_ARGS[0]));
|
||||||
}
|
}
|
||||||
free_mem_lock( (mem_lock*)((ptrszint*)_FUNC_EVALUATEFUNCTION_ARRAY_UDT_ARGS)[8] );
|
free_mem_lock( (mem_lock*)((ptrszint*)_FUNC_EVALUATEFUNCTION_ARRAY_UDT_ARGS)[8] );
|
||||||
|
|
|
@ -3,7 +3,7 @@ if (_SUB_DEBUGMODE_ARRAY_UDT_BUTTON[2]&1){
|
||||||
tmp_long=_SUB_DEBUGMODE_ARRAY_UDT_BUTTON[5];
|
tmp_long=_SUB_DEBUGMODE_ARRAY_UDT_BUTTON[5];
|
||||||
while(tmp_long--) {
|
while(tmp_long--) {
|
||||||
|
|
||||||
qbs_free(*(qbs**)(_SUB_DEBUGMODE_ARRAY_UDT_BUTTON[0]+(128/8+1-1)*tmp_long+ 8));}
|
qbs_free(*(qbs**)(_SUB_DEBUGMODE_ARRAY_UDT_BUTTON[0]+16*tmp_long+ 8));}
|
||||||
free((void*)(_SUB_DEBUGMODE_ARRAY_UDT_BUTTON[0]));
|
free((void*)(_SUB_DEBUGMODE_ARRAY_UDT_BUTTON[0]));
|
||||||
}
|
}
|
||||||
free_mem_lock( (mem_lock*)((ptrszint*)_SUB_DEBUGMODE_ARRAY_UDT_BUTTON)[8] );
|
free_mem_lock( (mem_lock*)((ptrszint*)_SUB_DEBUGMODE_ARRAY_UDT_BUTTON)[8] );
|
||||||
|
|
|
@ -20,7 +20,7 @@ if (_FUNC_IDEVARIABLEWATCHBOX_ARRAY_UDT_VARDLGLIST[2]&1){
|
||||||
tmp_long=_FUNC_IDEVARIABLEWATCHBOX_ARRAY_UDT_VARDLGLIST[5];
|
tmp_long=_FUNC_IDEVARIABLEWATCHBOX_ARRAY_UDT_VARDLGLIST[5];
|
||||||
while(tmp_long--) {
|
while(tmp_long--) {
|
||||||
|
|
||||||
qbs_free(*(qbs**)(_FUNC_IDEVARIABLEWATCHBOX_ARRAY_UDT_VARDLGLIST[0]+(264/8+1-1)*tmp_long+ 25));}
|
qbs_free(*(qbs**)(_FUNC_IDEVARIABLEWATCHBOX_ARRAY_UDT_VARDLGLIST[0]+33*tmp_long+ 25));}
|
||||||
free((void*)(_FUNC_IDEVARIABLEWATCHBOX_ARRAY_UDT_VARDLGLIST[0]));
|
free((void*)(_FUNC_IDEVARIABLEWATCHBOX_ARRAY_UDT_VARDLGLIST[0]));
|
||||||
}
|
}
|
||||||
free_mem_lock( (mem_lock*)((ptrszint*)_FUNC_IDEVARIABLEWATCHBOX_ARRAY_UDT_VARDLGLIST)[8] );
|
free_mem_lock( (mem_lock*)((ptrszint*)_FUNC_IDEVARIABLEWATCHBOX_ARRAY_UDT_VARDLGLIST)[8] );
|
||||||
|
|
|
@ -19,7 +19,7 @@ if (_FUNC_IDEELEMENTWATCHBOX_ARRAY_UDT_VARDLGLIST[2]&1){
|
||||||
tmp_long=_FUNC_IDEELEMENTWATCHBOX_ARRAY_UDT_VARDLGLIST[5];
|
tmp_long=_FUNC_IDEELEMENTWATCHBOX_ARRAY_UDT_VARDLGLIST[5];
|
||||||
while(tmp_long--) {
|
while(tmp_long--) {
|
||||||
|
|
||||||
qbs_free(*(qbs**)(_FUNC_IDEELEMENTWATCHBOX_ARRAY_UDT_VARDLGLIST[0]+(264/8+1-1)*tmp_long+ 25));}
|
qbs_free(*(qbs**)(_FUNC_IDEELEMENTWATCHBOX_ARRAY_UDT_VARDLGLIST[0]+33*tmp_long+ 25));}
|
||||||
free((void*)(_FUNC_IDEELEMENTWATCHBOX_ARRAY_UDT_VARDLGLIST[0]));
|
free((void*)(_FUNC_IDEELEMENTWATCHBOX_ARRAY_UDT_VARDLGLIST[0]));
|
||||||
}
|
}
|
||||||
free_mem_lock( (mem_lock*)((ptrszint*)_FUNC_IDEELEMENTWATCHBOX_ARRAY_UDT_VARDLGLIST)[8] );
|
free_mem_lock( (mem_lock*)((ptrszint*)_FUNC_IDEELEMENTWATCHBOX_ARRAY_UDT_VARDLGLIST)[8] );
|
||||||
|
|
|
@ -11,7 +11,7 @@ if (_FUNC_IDEASCIIBOX_ARRAY_UDT_ASCIITABLE[2]&1){
|
||||||
tmp_long=_FUNC_IDEASCIIBOX_ARRAY_UDT_ASCIITABLE[5];
|
tmp_long=_FUNC_IDEASCIIBOX_ARRAY_UDT_ASCIITABLE[5];
|
||||||
while(tmp_long--) {
|
while(tmp_long--) {
|
||||||
|
|
||||||
qbs_free(*(qbs**)(_FUNC_IDEASCIIBOX_ARRAY_UDT_ASCIITABLE[0]+(96/8+1-1)*tmp_long+ 4));}
|
qbs_free(*(qbs**)(_FUNC_IDEASCIIBOX_ARRAY_UDT_ASCIITABLE[0]+12*tmp_long+ 4));}
|
||||||
free((void*)(_FUNC_IDEASCIIBOX_ARRAY_UDT_ASCIITABLE[0]));
|
free((void*)(_FUNC_IDEASCIIBOX_ARRAY_UDT_ASCIITABLE[0]));
|
||||||
}
|
}
|
||||||
free_mem_lock( (mem_lock*)((ptrszint*)_FUNC_IDEASCIIBOX_ARRAY_UDT_ASCIITABLE)[8] );
|
free_mem_lock( (mem_lock*)((ptrszint*)_FUNC_IDEASCIIBOX_ARRAY_UDT_ASCIITABLE)[8] );
|
||||||
|
|
47122
internal/source/main.txt
|
@ -52,7 +52,7 @@ if (__ARRAY_UDT_CONSTFUNCS[2]&1){
|
||||||
tmp_long=__ARRAY_UDT_CONSTFUNCS[5];
|
tmp_long=__ARRAY_UDT_CONSTFUNCS[5];
|
||||||
while(tmp_long--) {
|
while(tmp_long--) {
|
||||||
|
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_CONSTFUNCS[0]+(80/8+1-1)*tmp_long+ 0));}
|
qbs_free(*(qbs**)(__ARRAY_UDT_CONSTFUNCS[0]+10*tmp_long+ 0));}
|
||||||
free((void*)(__ARRAY_UDT_CONSTFUNCS[0]));
|
free((void*)(__ARRAY_UDT_CONSTFUNCS[0]));
|
||||||
}
|
}
|
||||||
free_mem_lock( (mem_lock*)((ptrszint*)__ARRAY_UDT_CONSTFUNCS)[8] );
|
free_mem_lock( (mem_lock*)((ptrszint*)__ARRAY_UDT_CONSTFUNCS)[8] );
|
||||||
|
@ -401,17 +401,17 @@ if (__ARRAY_UDT_BACKUPUSEDVARIABLELIST[2]&1){
|
||||||
tmp_long=__ARRAY_UDT_BACKUPUSEDVARIABLELIST[5];
|
tmp_long=__ARRAY_UDT_BACKUPUSEDVARIABLELIST[5];
|
||||||
while(tmp_long--) {
|
while(tmp_long--) {
|
||||||
|
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]+(960/8+1-1)*tmp_long+ 32));
|
qbs_free(*(qbs**)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]+120*tmp_long+ 32));
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]+(960/8+1-1)*tmp_long+ 40));
|
qbs_free(*(qbs**)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]+120*tmp_long+ 40));
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]+(960/8+1-1)*tmp_long+ 48));
|
qbs_free(*(qbs**)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]+120*tmp_long+ 48));
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]+(960/8+1-1)*tmp_long+ 56));
|
qbs_free(*(qbs**)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]+120*tmp_long+ 56));
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]+(960/8+1-1)*tmp_long+ 64));
|
qbs_free(*(qbs**)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]+120*tmp_long+ 64));
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]+(960/8+1-1)*tmp_long+ 72));
|
qbs_free(*(qbs**)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]+120*tmp_long+ 72));
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]+(960/8+1-1)*tmp_long+ 80));
|
qbs_free(*(qbs**)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]+120*tmp_long+ 80));
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]+(960/8+1-1)*tmp_long+ 88));
|
qbs_free(*(qbs**)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]+120*tmp_long+ 88));
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]+(960/8+1-1)*tmp_long+ 96));
|
qbs_free(*(qbs**)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]+120*tmp_long+ 96));
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]+(960/8+1-1)*tmp_long+ 104));
|
qbs_free(*(qbs**)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]+120*tmp_long+ 104));
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]+(960/8+1-1)*tmp_long+ 112));}
|
qbs_free(*(qbs**)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]+120*tmp_long+ 112));}
|
||||||
free((void*)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]));
|
free((void*)(__ARRAY_UDT_BACKUPUSEDVARIABLELIST[0]));
|
||||||
}
|
}
|
||||||
free_mem_lock( (mem_lock*)((ptrszint*)__ARRAY_UDT_BACKUPUSEDVARIABLELIST)[8] );
|
free_mem_lock( (mem_lock*)((ptrszint*)__ARRAY_UDT_BACKUPUSEDVARIABLELIST)[8] );
|
||||||
|
@ -802,7 +802,7 @@ if (__ARRAY_UDT_IDS[2]&1){
|
||||||
tmp_long=__ARRAY_UDT_IDS[5];
|
tmp_long=__ARRAY_UDT_IDS[5];
|
||||||
while(tmp_long--) {
|
while(tmp_long--) {
|
||||||
|
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_IDS[0]+(22952/8+1-1)*tmp_long+ 2861));}
|
qbs_free(*(qbs**)(__ARRAY_UDT_IDS[0]+2869*tmp_long+ 2861));}
|
||||||
free((void*)(__ARRAY_UDT_IDS[0]));
|
free((void*)(__ARRAY_UDT_IDS[0]));
|
||||||
}
|
}
|
||||||
free_mem_lock( (mem_lock*)((ptrszint*)__ARRAY_UDT_IDS)[8] );
|
free_mem_lock( (mem_lock*)((ptrszint*)__ARRAY_UDT_IDS)[8] );
|
||||||
|
@ -955,17 +955,17 @@ if (__ARRAY_UDT_USEDVARIABLELIST[2]&1){
|
||||||
tmp_long=__ARRAY_UDT_USEDVARIABLELIST[5];
|
tmp_long=__ARRAY_UDT_USEDVARIABLELIST[5];
|
||||||
while(tmp_long--) {
|
while(tmp_long--) {
|
||||||
|
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_USEDVARIABLELIST[0]+(960/8+1-1)*tmp_long+ 32));
|
qbs_free(*(qbs**)(__ARRAY_UDT_USEDVARIABLELIST[0]+120*tmp_long+ 32));
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_USEDVARIABLELIST[0]+(960/8+1-1)*tmp_long+ 40));
|
qbs_free(*(qbs**)(__ARRAY_UDT_USEDVARIABLELIST[0]+120*tmp_long+ 40));
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_USEDVARIABLELIST[0]+(960/8+1-1)*tmp_long+ 48));
|
qbs_free(*(qbs**)(__ARRAY_UDT_USEDVARIABLELIST[0]+120*tmp_long+ 48));
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_USEDVARIABLELIST[0]+(960/8+1-1)*tmp_long+ 56));
|
qbs_free(*(qbs**)(__ARRAY_UDT_USEDVARIABLELIST[0]+120*tmp_long+ 56));
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_USEDVARIABLELIST[0]+(960/8+1-1)*tmp_long+ 64));
|
qbs_free(*(qbs**)(__ARRAY_UDT_USEDVARIABLELIST[0]+120*tmp_long+ 64));
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_USEDVARIABLELIST[0]+(960/8+1-1)*tmp_long+ 72));
|
qbs_free(*(qbs**)(__ARRAY_UDT_USEDVARIABLELIST[0]+120*tmp_long+ 72));
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_USEDVARIABLELIST[0]+(960/8+1-1)*tmp_long+ 80));
|
qbs_free(*(qbs**)(__ARRAY_UDT_USEDVARIABLELIST[0]+120*tmp_long+ 80));
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_USEDVARIABLELIST[0]+(960/8+1-1)*tmp_long+ 88));
|
qbs_free(*(qbs**)(__ARRAY_UDT_USEDVARIABLELIST[0]+120*tmp_long+ 88));
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_USEDVARIABLELIST[0]+(960/8+1-1)*tmp_long+ 96));
|
qbs_free(*(qbs**)(__ARRAY_UDT_USEDVARIABLELIST[0]+120*tmp_long+ 96));
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_USEDVARIABLELIST[0]+(960/8+1-1)*tmp_long+ 104));
|
qbs_free(*(qbs**)(__ARRAY_UDT_USEDVARIABLELIST[0]+120*tmp_long+ 104));
|
||||||
qbs_free(*(qbs**)(__ARRAY_UDT_USEDVARIABLELIST[0]+(960/8+1-1)*tmp_long+ 112));}
|
qbs_free(*(qbs**)(__ARRAY_UDT_USEDVARIABLELIST[0]+120*tmp_long+ 112));}
|
||||||
free((void*)(__ARRAY_UDT_USEDVARIABLELIST[0]));
|
free((void*)(__ARRAY_UDT_USEDVARIABLELIST[0]));
|
||||||
}
|
}
|
||||||
free_mem_lock( (mem_lock*)((ptrszint*)__ARRAY_UDT_USEDVARIABLELIST)[8] );
|
free_mem_lock( (mem_lock*)((ptrszint*)__ARRAY_UDT_USEDVARIABLELIST)[8] );
|
||||||
|
|
|
@ -1536,7 +1536,6 @@ FUNCTION ide2 (ignore)
|
||||||
END IF
|
END IF
|
||||||
END IF
|
END IF
|
||||||
|
|
||||||
IF os$ = "WIN" OR MacOSX = 1 THEN
|
|
||||||
IF _WINDOWHASFOCUS THEN
|
IF _WINDOWHASFOCUS THEN
|
||||||
LOCATE , , 1
|
LOCATE , , 1
|
||||||
_PALETTECOLOR 5, IDEBracketHighlightColor, 0
|
_PALETTECOLOR 5, IDEBracketHighlightColor, 0
|
||||||
|
@ -1546,7 +1545,6 @@ FUNCTION ide2 (ignore)
|
||||||
_PALETTECOLOR 5, IDEBackgroundColor, 0
|
_PALETTECOLOR 5, IDEBackgroundColor, 0
|
||||||
_PALETTECOLOR 6, IDEBackgroundColor, 0
|
_PALETTECOLOR 6, IDEBackgroundColor, 0
|
||||||
END IF
|
END IF
|
||||||
END IF
|
|
||||||
|
|
||||||
IF KALT THEN 'alt held
|
IF KALT THEN 'alt held
|
||||||
|
|
||||||
|
@ -1570,7 +1568,7 @@ FUNCTION ide2 (ignore)
|
||||||
idealthighlight = 0
|
idealthighlight = 0
|
||||||
LOCATE , , 0: COLOR 0, 7: _PRINTSTRING (1, 1), menubar$
|
LOCATE , , 0: COLOR 0, 7: _PRINTSTRING (1, 1), menubar$
|
||||||
IF ideentermenu = 1 AND KCONTROL = 0 THEN 'alt was pressed then released
|
IF ideentermenu = 1 AND KCONTROL = 0 THEN 'alt was pressed then released
|
||||||
IF _WINDOWHASFOCUS OR os$ = "LNX" THEN
|
IF _WINDOWHASFOCUS THEN
|
||||||
LOCATE , , , IDENormalCursorStart, IDENormalCursorEnd
|
LOCATE , , , IDENormalCursorStart, IDENormalCursorEnd
|
||||||
skipdisplay = 0
|
skipdisplay = 0
|
||||||
ideentermenu = 0
|
ideentermenu = 0
|
||||||
|
@ -4421,7 +4419,7 @@ FUNCTION ide2 (ignore)
|
||||||
DO
|
DO
|
||||||
_LIMIT 100
|
_LIMIT 100
|
||||||
GetInput
|
GetInput
|
||||||
IF _WINDOWHASFOCUS = 0 AND (os$ = "WIN" OR MacOSX = 1) THEN
|
IF _WINDOWHASFOCUS = 0 THEN
|
||||||
COLOR 0, 7: _PRINTSTRING (1, 1), menubar$
|
COLOR 0, 7: _PRINTSTRING (1, 1), menubar$
|
||||||
SCREEN , , 3, 0: PCOPY 3, 0
|
SCREEN , , 3, 0: PCOPY 3, 0
|
||||||
GOTO ideloop
|
GOTO ideloop
|
||||||
|
@ -4434,7 +4432,7 @@ FUNCTION ide2 (ignore)
|
||||||
KB = KEY_ESC
|
KB = KEY_ESC
|
||||||
END IF
|
END IF
|
||||||
|
|
||||||
IF _WINDOWHASFOCUS = 0 AND (os$ = "WIN" OR MacOSX = 1) THEN
|
IF _WINDOWHASFOCUS = 0 THEN
|
||||||
COLOR 0, 7: _PRINTSTRING (1, 1), menubar$
|
COLOR 0, 7: _PRINTSTRING (1, 1), menubar$
|
||||||
SCREEN , , 3, 0: PCOPY 3, 0
|
SCREEN , , 3, 0: PCOPY 3, 0
|
||||||
GOTO ideloop
|
GOTO ideloop
|
||||||
|
@ -4657,7 +4655,7 @@ FUNCTION ide2 (ignore)
|
||||||
DO
|
DO
|
||||||
_LIMIT 100
|
_LIMIT 100
|
||||||
GetInput
|
GetInput
|
||||||
IF _WINDOWHASFOCUS = 0 AND (os$ = "WIN" OR MacOSX = 1) THEN
|
IF _WINDOWHASFOCUS = 0 THEN
|
||||||
COLOR 0, 7: _PRINTSTRING (1, 1), menubar$
|
COLOR 0, 7: _PRINTSTRING (1, 1), menubar$
|
||||||
PCOPY 3, 0: SCREEN , , 3, 0
|
PCOPY 3, 0: SCREEN , , 3, 0
|
||||||
GOTO ideloop
|
GOTO ideloop
|
||||||
|
@ -4677,7 +4675,7 @@ FUNCTION ide2 (ignore)
|
||||||
ideexit = 1: GOTO ideloop
|
ideexit = 1: GOTO ideloop
|
||||||
END IF
|
END IF
|
||||||
END IF
|
END IF
|
||||||
IF _WINDOWHASFOCUS = 0 AND (os$ = "WIN" OR MacOSX = 1) THEN
|
IF _WINDOWHASFOCUS = 0 THEN
|
||||||
COLOR 0, 7: _PRINTSTRING (1, 1), menubar$
|
COLOR 0, 7: _PRINTSTRING (1, 1), menubar$
|
||||||
PCOPY 3, 0: SCREEN , , 3, 0
|
PCOPY 3, 0: SCREEN , , 3, 0
|
||||||
IF IdeDebugMode = 2 THEN GOTO EnterDebugMode
|
IF IdeDebugMode = 2 THEN GOTO EnterDebugMode
|
||||||
|
@ -11856,7 +11854,7 @@ SUB ideinsline (i, text$)
|
||||||
idegotoline i
|
idegotoline i
|
||||||
'insert line
|
'insert line
|
||||||
textlen = LEN(text$)
|
textlen = LEN(text$)
|
||||||
idet$ = LEFT$(idet$, ideli - 1) + MKL$(textlen) + text$ + MKL$(textlen) + RIGHT$(idet$, LEN(idet$) - ideli + 1)
|
idet$ = LEFT$(idet$, ideli - 1) + (MKL$(textlen) + text$ + MKL$(textlen)) + RIGHT$(idet$, LEN(idet$) - ideli + 1)
|
||||||
iden = iden + 1
|
iden = iden + 1
|
||||||
END SUB
|
END SUB
|
||||||
|
|
||||||
|
@ -12536,7 +12534,7 @@ SUB idesetline (i, text$)
|
||||||
|
|
||||||
IF i <> -1 THEN idegotoline i
|
IF i <> -1 THEN idegotoline i
|
||||||
textlen = LEN(text$)
|
textlen = LEN(text$)
|
||||||
idet$ = LEFT$(idet$, ideli - 1) + MKL$(textlen) + text$ + MKL$(textlen) + RIGHT$(idet$, LEN(idet$) - ideli + 1 - CVL(MID$(idet$, ideli, 4)) - 8)
|
idet$ = LEFT$(idet$, ideli - 1) + (MKL$(textlen) + text$ + MKL$(textlen)) + RIGHT$(idet$, LEN(idet$) - ideli + 1 - CVL(MID$(idet$, ideli, 4)) - 8)
|
||||||
|
|
||||||
END SUB
|
END SUB
|
||||||
|
|
||||||
|
|
|
@ -1537,10 +1537,10 @@ id.n = qb64prefix$ + "UPrintString"
|
||||||
id.Dependency = DEPENDENCY_LOADFONT
|
id.Dependency = DEPENDENCY_LOADFONT
|
||||||
id.subfunc = 2
|
id.subfunc = 2
|
||||||
id.callname = "sub__UPrintString"
|
id.callname = "sub__UPrintString"
|
||||||
id.args = 6
|
id.args = 7
|
||||||
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(STRINGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
|
id.arg = MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(STRINGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER) + MKL$(LONGTYPE - ISPOINTER)
|
||||||
id.specialformat = "(?,?),?[,[?][,[?][,?]]]"
|
id.specialformat = "(?,?),?[,[?][,[?][,[?][,?]]]]"
|
||||||
id.hr_syntax = "_UPRINTSTRING (x&, y&), text$[, maxWidth&][, utfEncoding&][, fontHandle&]"
|
id.hr_syntax = "_UPRINTSTRING (x&, y&), text$[, maxWidth&][, utfEncoding&][, fontHandle&][, imageHandle&]"
|
||||||
regid
|
regid
|
||||||
|
|
||||||
clearid
|
clearid
|
||||||
|
|
48
tests/compile_tests/environ/set_environ.bas
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
$CONSOLE:ONLY
|
||||||
|
ON ERROR GOTO ehandler
|
||||||
|
|
||||||
|
'Test setting with =
|
||||||
|
ENVIRON "FOO=BAR"
|
||||||
|
PRINT ENVIRON$("FOO")
|
||||||
|
|
||||||
|
|
||||||
|
'Test settings with space
|
||||||
|
ENVIRON "VAR VAL"
|
||||||
|
PRINT ENVIRON$("VAR")
|
||||||
|
|
||||||
|
|
||||||
|
'Test setting value with spaces with = separator
|
||||||
|
ENVIRON "ABC=DEF GHI"
|
||||||
|
PRINT ENVIRON$("ABC")
|
||||||
|
|
||||||
|
|
||||||
|
'Test setting value with spaces with space separator
|
||||||
|
ENVIRON "JKL MNO PQR"
|
||||||
|
PRINT ENVIRON$("JKL")
|
||||||
|
|
||||||
|
|
||||||
|
'Test overwriting existing
|
||||||
|
ENVIRON "X=XY"
|
||||||
|
ENVIRON "X=ZZZ"
|
||||||
|
PRINT ENVIRON$("X")
|
||||||
|
|
||||||
|
|
||||||
|
'Test unset variable with = separator
|
||||||
|
ENVIRON "NAME=LUKE"
|
||||||
|
ENVIRON "NAME="
|
||||||
|
PRINT "["; ENVIRON$("NAME"); "]"
|
||||||
|
|
||||||
|
|
||||||
|
'Test unset variable with space separator
|
||||||
|
ENVIRON "TEXT BOO"
|
||||||
|
ENVIRON "TEXT "
|
||||||
|
PRINT "["; ENVIRON$("TEXT"); "]"
|
||||||
|
|
||||||
|
'Test no separator
|
||||||
|
ENVIRON "NOSEP"
|
||||||
|
|
||||||
|
SYSTEM
|
||||||
|
|
||||||
|
ehandler:
|
||||||
|
print "Error"; ERR; "line"; _ERRORLINE
|
||||||
|
RESUME NEXT
|
8
tests/compile_tests/environ/set_environ.output
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
BAR
|
||||||
|
VAL
|
||||||
|
DEF GHI
|
||||||
|
MNO PQR
|
||||||
|
ZZZ
|
||||||
|
[]
|
||||||
|
[]
|
||||||
|
Error 5 line 42
|
|
@ -20,7 +20,7 @@ NAME "temp_dir" AS "dummy_dir"
|
||||||
PRINT "_DIREXISTS(dummy_dir):"; _DIREXISTS("./dummy_dir")
|
PRINT "_DIREXISTS(dummy_dir):"; _DIREXISTS("./dummy_dir")
|
||||||
|
|
||||||
PRINT "Creating a temporary file inside dummy_dir"
|
PRINT "Creating a temporary file inside dummy_dir"
|
||||||
DIM fileName AS STRING: fileName = CreateDummyFile$("./dummy_dir/")
|
DIM fileName AS STRING: fileName = CreateDummyFile("./dummy_dir/", ".tmp")
|
||||||
|
|
||||||
PRINT "_FILEEXISTS(fileName):"; _FILEEXISTS(fileName)
|
PRINT "_FILEEXISTS(fileName):"; _FILEEXISTS(fileName)
|
||||||
|
|
||||||
|
@ -29,9 +29,41 @@ KILL fileName
|
||||||
|
|
||||||
PRINT "Creating 10 dummy files inside dummy_dir"
|
PRINT "Creating 10 dummy files inside dummy_dir"
|
||||||
DIM i AS LONG: FOR i = 0 TO 9
|
DIM i AS LONG: FOR i = 0 TO 9
|
||||||
fileName = CreateDummyFile$("./dummy_dir/")
|
fileName = CreateDummyFile("./dummy_dir/", ".tmp")
|
||||||
NEXT i
|
NEXT i
|
||||||
|
|
||||||
|
' Start _FILES$ test
|
||||||
|
CHDIR "dummy_dir"
|
||||||
|
|
||||||
|
fileName = CreateDummyFile("./", "")
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
DIM dirEntry AS STRING: dirEntry = _FILES$("") ' should count 13 entries
|
||||||
|
|
||||||
|
DO WHILE LEN(dirEntry) > 0
|
||||||
|
i = i + 1
|
||||||
|
|
||||||
|
dirEntry = _FILES$
|
||||||
|
LOOP
|
||||||
|
|
||||||
|
PRINT "Counted"; i; "entries."
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
dirEntry = _FILES$("*.*") ' should count 12 entries
|
||||||
|
|
||||||
|
DO WHILE LEN(dirEntry) > 0
|
||||||
|
i = i + 1
|
||||||
|
|
||||||
|
dirEntry = _FILES$
|
||||||
|
LOOP
|
||||||
|
|
||||||
|
PRINT "Counted"; i; "entries."
|
||||||
|
|
||||||
|
KILL fileName
|
||||||
|
|
||||||
|
CHDIR ".."
|
||||||
|
' End _FILES$ test
|
||||||
|
|
||||||
PRINT "Deleting all 10 dummy files"
|
PRINT "Deleting all 10 dummy files"
|
||||||
KILL "./dummy_dir/*.tmp"
|
KILL "./dummy_dir/*.tmp"
|
||||||
|
|
||||||
|
@ -44,9 +76,10 @@ test_failed:
|
||||||
PRINT "Test failed!"
|
PRINT "Test failed!"
|
||||||
SYSTEM 1
|
SYSTEM 1
|
||||||
|
|
||||||
FUNCTION CreateDummyFile$ (directory AS STRING)
|
|
||||||
|
FUNCTION CreateDummyFile$ (directory AS STRING, extension AS STRING)
|
||||||
DO
|
DO
|
||||||
DIM fileName AS STRING: fileName = directory + LTRIM$(STR$(100! * (TIMER + RND))) + ".tmp"
|
DIM fileName AS STRING: fileName = directory + LTRIM$(STR$(INT(100! * (TIMER + RND)))) + extension
|
||||||
LOOP WHILE _FILEEXISTS(fileName)
|
LOOP WHILE _FILEEXISTS(fileName)
|
||||||
|
|
||||||
DIM h AS LONG: h = FREEFILE
|
DIM h AS LONG: h = FREEFILE
|
||||||
|
|
|
@ -7,5 +7,7 @@ Creating a temporary file inside dummy_dir
|
||||||
_FILEEXISTS(fileName):-1
|
_FILEEXISTS(fileName):-1
|
||||||
Deleting fileName
|
Deleting fileName
|
||||||
Creating 10 dummy files inside dummy_dir
|
Creating 10 dummy files inside dummy_dir
|
||||||
|
Counted 13 entries.
|
||||||
|
Counted 12 entries.
|
||||||
Deleting all 10 dummy files
|
Deleting all 10 dummy files
|
||||||
Deleting dummy_dir
|
Deleting dummy_dir
|
||||||
|
|
|
@ -97,8 +97,8 @@ SUB PrintFontDetails (handle AS LONG, testFileName AS STRING)
|
||||||
_DEST image
|
_DEST image
|
||||||
_FONT handle
|
_FONT handle
|
||||||
COLOR _RGB32(255)
|
COLOR _RGB32(255)
|
||||||
_UPRINTSTRING (0, 0), SAMPLE_TEXT_1
|
_UPRINTSTRING (0, 0), SAMPLE_TEXT_1, , , handle
|
||||||
_UPRINTSTRING (0, uLineSpacing), SAMPLE_TEXT_2
|
_UPRINTSTRING (0, uLineSpacing), SAMPLE_TEXT_2, , , , image
|
||||||
'_SAVEIMAGE testFileName + "u", image, TEST_IMAGE_FORMAT
|
'_SAVEIMAGE testFileName + "u", image, TEST_IMAGE_FORMAT
|
||||||
|
|
||||||
_FONT 16
|
_FONT 16
|
||||||
|
|
|
@ -65,8 +65,8 @@ Success, images are identical!
|
||||||
Loading font from memory (automono) ... done.
|
Loading font from memory (automono) ... done.
|
||||||
_FONTWIDTH = 0
|
_FONTWIDTH = 0
|
||||||
_FONTHEIGHT = 22
|
_FONTHEIGHT = 22
|
||||||
_UFONTHEIGHT = 27
|
_UFONTHEIGHT = 28
|
||||||
_ULINESPACING = 27
|
_ULINESPACING = 28
|
||||||
_PRINTWIDTH = 1088
|
_PRINTWIDTH = 1088
|
||||||
_UPRINTWIDTH = 1088
|
_UPRINTWIDTH = 1088
|
||||||
_UCHARPOS = 95
|
_UCHARPOS = 95
|
||||||
|
@ -78,7 +78,7 @@ Loading font LiberationSans-Regular.ttf () ... done.
|
||||||
_FONTWIDTH = 0
|
_FONTWIDTH = 0
|
||||||
_FONTHEIGHT = 12
|
_FONTHEIGHT = 12
|
||||||
_UFONTHEIGHT = 13
|
_UFONTHEIGHT = 13
|
||||||
_ULINESPACING = 13
|
_ULINESPACING = 14
|
||||||
_PRINTWIDTH = 606
|
_PRINTWIDTH = 606
|
||||||
_UPRINTWIDTH = 606
|
_UPRINTWIDTH = 606
|
||||||
_UCHARPOS = 95
|
_UCHARPOS = 95
|
||||||
|
@ -89,7 +89,7 @@ Success, images are identical!
|
||||||
Loading font LiberationSans-Regular.ttf (monospace) ... done.
|
Loading font LiberationSans-Regular.ttf (monospace) ... done.
|
||||||
_FONTWIDTH = 15
|
_FONTWIDTH = 15
|
||||||
_FONTHEIGHT = 16
|
_FONTHEIGHT = 16
|
||||||
_UFONTHEIGHT = 17
|
_UFONTHEIGHT = 18
|
||||||
_ULINESPACING = 18
|
_ULINESPACING = 18
|
||||||
_PRINTWIDTH = 1425
|
_PRINTWIDTH = 1425
|
||||||
_UPRINTWIDTH = 1425
|
_UPRINTWIDTH = 1425
|
||||||
|
@ -101,7 +101,7 @@ Success, images are identical!
|
||||||
Loading font LiberationSans-Regular.ttf (automono) ... done.
|
Loading font LiberationSans-Regular.ttf (automono) ... done.
|
||||||
_FONTWIDTH = 0
|
_FONTWIDTH = 0
|
||||||
_FONTHEIGHT = 22
|
_FONTHEIGHT = 22
|
||||||
_UFONTHEIGHT = 24
|
_UFONTHEIGHT = 25
|
||||||
_ULINESPACING = 25
|
_ULINESPACING = 25
|
||||||
_PRINTWIDTH = 1094
|
_PRINTWIDTH = 1094
|
||||||
_UPRINTWIDTH = 1094
|
_UPRINTWIDTH = 1094
|
||||||
|
@ -114,7 +114,7 @@ Loading font LiberationSerif-Regular.ttf () ... done.
|
||||||
_FONTWIDTH = 0
|
_FONTWIDTH = 0
|
||||||
_FONTHEIGHT = 12
|
_FONTHEIGHT = 12
|
||||||
_UFONTHEIGHT = 13
|
_UFONTHEIGHT = 13
|
||||||
_ULINESPACING = 13
|
_ULINESPACING = 14
|
||||||
_PRINTWIDTH = 583
|
_PRINTWIDTH = 583
|
||||||
_UPRINTWIDTH = 583
|
_UPRINTWIDTH = 583
|
||||||
_UCHARPOS = 95
|
_UCHARPOS = 95
|
||||||
|
@ -125,7 +125,7 @@ Success, images are identical!
|
||||||
Loading font LiberationSerif-Regular.ttf (monospace) ... done.
|
Loading font LiberationSerif-Regular.ttf (monospace) ... done.
|
||||||
_FONTWIDTH = 15
|
_FONTWIDTH = 15
|
||||||
_FONTHEIGHT = 16
|
_FONTHEIGHT = 16
|
||||||
_UFONTHEIGHT = 17
|
_UFONTHEIGHT = 18
|
||||||
_ULINESPACING = 18
|
_ULINESPACING = 18
|
||||||
_PRINTWIDTH = 1425
|
_PRINTWIDTH = 1425
|
||||||
_UPRINTWIDTH = 1425
|
_UPRINTWIDTH = 1425
|
||||||
|
@ -149,8 +149,8 @@ Success, images are identical!
|
||||||
Loading font LiberationMono-Regular.ttf () ... done.
|
Loading font LiberationMono-Regular.ttf () ... done.
|
||||||
_FONTWIDTH = 0
|
_FONTWIDTH = 0
|
||||||
_FONTHEIGHT = 12
|
_FONTHEIGHT = 12
|
||||||
_UFONTHEIGHT = 13
|
_UFONTHEIGHT = 14
|
||||||
_ULINESPACING = 13
|
_ULINESPACING = 14
|
||||||
_PRINTWIDTH = 665
|
_PRINTWIDTH = 665
|
||||||
_UPRINTWIDTH = 665
|
_UPRINTWIDTH = 665
|
||||||
_UCHARPOS = 95
|
_UCHARPOS = 95
|
||||||
|
@ -173,8 +173,8 @@ Success, images are identical!
|
||||||
Loading font LiberationMono-Regular.ttf (automono) ... done.
|
Loading font LiberationMono-Regular.ttf (automono) ... done.
|
||||||
_FONTWIDTH = 13
|
_FONTWIDTH = 13
|
||||||
_FONTHEIGHT = 22
|
_FONTHEIGHT = 22
|
||||||
_UFONTHEIGHT = 24
|
_UFONTHEIGHT = 25
|
||||||
_ULINESPACING = 24
|
_ULINESPACING = 25
|
||||||
_PRINTWIDTH = 1235
|
_PRINTWIDTH = 1235
|
||||||
_UPRINTWIDTH = 1235
|
_UPRINTWIDTH = 1235
|
||||||
_UCHARPOS = 95
|
_UCHARPOS = 95
|
||||||
|
|
Before Width: | Height: | Size: 230 KiB After Width: | Height: | Size: 238 KiB |
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 200 KiB After Width: | Height: | Size: 200 KiB |
Before Width: | Height: | Size: 214 KiB After Width: | Height: | Size: 214 KiB |
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 200 KiB After Width: | Height: | Size: 200 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 73 KiB |
Before Width: | Height: | Size: 232 KiB After Width: | Height: | Size: 241 KiB |
|
@ -148,6 +148,9 @@ SUB AssertImage2 (originalActualImage AS LONG, expectedFileName AS STRING)
|
||||||
|
|
||||||
DIM actual AS _MEM, expected AS _MEM
|
DIM actual AS _MEM, expected AS _MEM
|
||||||
|
|
||||||
|
actual = _MEMIMAGE(actualImage)
|
||||||
|
expected = _MEMIMAGE(expectedImage)
|
||||||
|
|
||||||
IF _WIDTH(actualImage) <> _WIDTH(expectedImage) THEN
|
IF _WIDTH(actualImage) <> _WIDTH(expectedImage) THEN
|
||||||
PRINT "Failure! Image width differs, actual:"; _WIDTH(actualImage); ", Expected:"; _WIDTH(expectedImage)
|
PRINT "Failure! Image width differs, actual:"; _WIDTH(actualImage); ", Expected:"; _WIDTH(expectedImage)
|
||||||
GOTO freeImages
|
GOTO freeImages
|
||||||
|
@ -158,9 +161,6 @@ SUB AssertImage2 (originalActualImage AS LONG, expectedFileName AS STRING)
|
||||||
GOTO freeImages
|
GOTO freeImages
|
||||||
END IF
|
END IF
|
||||||
|
|
||||||
actual = _MEMIMAGE(actualImage)
|
|
||||||
expected = _MEMIMAGE(expectedImage)
|
|
||||||
|
|
||||||
IF actual.SIZE <> expected.SIZE THEN
|
IF actual.SIZE <> expected.SIZE THEN
|
||||||
PRINT "Failure! Image sizes differ, Actual:"; actual.SIZE; ", Expected:"; expected.SIZE
|
PRINT "Failure! Image sizes differ, Actual:"; actual.SIZE; ", Expected:"; expected.SIZE
|
||||||
GOTO freeImages
|
GOTO freeImages
|
||||||
|
|