/* Borland 32-bit shift and Turbo Pascal ShortString helpers from Code5. */ #include "tdkpin_shortstrings.h" uint32_t borland_shift_right_u32(uint32_t value, uint16_t count) { return value >> (count & 0x1f); } uint32_t borland_shift_left_u32(uint32_t value, uint16_t count) { return value << (count & 0x1f); } void borland_short_assign(Win16FarPtr destination, Win16FarPtr source) { uint8_t length = win16_read_u8(source); win16_write_u8(destination, length); for (uint16_t index = 1; index <= length; index++) { win16_write_u8( win16_far_add_offset(destination, index), win16_read_u8(win16_far_add_offset(source, index))); } } void borland_short_assign_truncated( Win16FarPtr destination, Win16FarPtr source, uint8_t maximum_length) { uint8_t length = win16_read_u8(source); if (length > maximum_length) { length = maximum_length; } win16_write_u8(destination, length); for (uint16_t index = 1; index <= length; index++) { win16_write_u8( win16_far_add_offset(destination, index), win16_read_u8(win16_far_add_offset(source, index))); } } void borland_short_substring( Win16FarPtr destination, Win16FarPtr source, int16_t index, int16_t count) { if (index < 1) { index = 1; } uint16_t source_length = win16_read_u8(source); uint16_t available = 0; if ((uint16_t)index <= source_length) { available = (uint16_t)(source_length - (uint16_t)index + 1); } uint16_t requested = count < 0 ? 0 : (uint16_t)count; uint8_t copied = (uint8_t)(available < requested ? available : requested); win16_write_u8(destination, copied); for (uint16_t offset = 0; offset < copied; offset++) { win16_write_u8( win16_far_add_offset(destination, (uint16_t)(offset + 1)), win16_read_u8(win16_far_add_offset( source, (uint16_t)((uint16_t)index + offset)))); } } void borland_short_concat(Win16FarPtr destination, Win16FarPtr source) { uint8_t destination_length = win16_read_u8(destination); uint8_t source_length = win16_read_u8(source); uint16_t sum = (uint16_t)destination_length + source_length; uint8_t copied = source_length; if (sum > 0xff) { copied = (uint8_t)~destination_length; win16_write_u8(destination, 0xff); } else { win16_write_u8(destination, (uint8_t)sum); } for (uint16_t index = 1; index <= copied; index++) { win16_write_u8( win16_far_add_offset( destination, (uint16_t)(destination_length + index)), win16_read_u8(win16_far_add_offset(source, index))); } } uint16_t borland_short_position(Win16FarPtr pattern, Win16FarPtr text) { uint8_t pattern_length = win16_read_u8(pattern); uint8_t text_length = win16_read_u8(text); if (pattern_length == 0 || pattern_length > text_length) { return 0; } uint16_t last = (uint16_t)(text_length - pattern_length + 1); for (uint16_t position = 1; position <= last; position++) { bool equal = true; for (uint16_t index = 1; index <= pattern_length; index++) { if (win16_read_u8(win16_far_add_offset(pattern, index)) != win16_read_u8(win16_far_add_offset( text, (uint16_t)(position + index - 1)))) { equal = false; break; } } if (equal) { return position; } } return 0; } /* Materialize the original FLAGS-only comparison as a signed C result. */ int16_t borland_short_compare(Win16FarPtr left, Win16FarPtr right) { uint8_t left_length = win16_read_u8(left); uint8_t right_length = win16_read_u8(right); uint8_t common = left_length < right_length ? left_length : right_length; for (uint16_t index = 1; index <= common; index++) { uint8_t left_byte = win16_read_u8(win16_far_add_offset(left, index)); uint8_t right_byte = win16_read_u8(win16_far_add_offset(right, index)); if (left_byte != right_byte) { return (int16_t)left_byte - right_byte; } } return (int16_t)left_length - right_length; } void borland_character_to_short(Win16FarPtr destination, uint8_t character) { win16_write_u8(destination, 1); win16_write_u8(win16_far_add_offset(destination, 1), character); } void borland_bytes_to_short( Win16FarPtr destination, Win16FarPtr source, uint16_t count) { win16_write_u8(destination, (uint8_t)count); for (uint16_t index = 0; index < count; index++) { win16_write_u8( win16_far_add_offset(destination, (uint16_t)(index + 1)), win16_read_u8(win16_far_add_offset(source, index))); } } static uint8_t copy_short_slice( uint8_t *output, uint8_t output_length, Win16FarPtr source, uint16_t first, uint16_t count, uint8_t maximum) { uint8_t source_length = win16_read_u8(source); if (first < 1) { first = 1; } uint16_t available = first <= source_length ? (uint16_t)(source_length - first + 1) : 0; uint16_t copied = available < count ? available : count; if (copied > (uint16_t)(maximum - output_length)) { copied = (uint16_t)(maximum - output_length); } for (uint16_t offset = 0; offset < copied; offset++) { output[output_length++] = win16_read_u8(win16_far_add_offset( source, (uint16_t)(first + offset))); } return output_length; } /* 1020:0b1b — Insert(insertion,destination,index) with destination max length. */ void borland_short_insert( Win16FarPtr destination, Win16FarPtr insertion, int16_t index, uint8_t maximum_length) { if (index < 1) { index = 1; } uint8_t result[255]; uint8_t length = 0; length = copy_short_slice( result, length, destination, 1, (uint16_t)(index - 1), maximum_length); length = copy_short_slice( result, length, insertion, 1, 255, maximum_length); length = copy_short_slice( result, length, destination, (uint16_t)index, 255, maximum_length); win16_write_u8(destination, length); for (uint16_t offset = 0; offset < length; offset++) { win16_write_u8( win16_far_add_offset(destination, (uint16_t)(offset + 1)), result[offset]); } } /* 1020:0b7a — Delete(string,index,count); invalid ranges leave it unchanged. */ void borland_short_delete(Win16FarPtr string, int16_t index, int16_t count) { if (index <= 0 || count <= 0 || count >= 256) { return; } if (index > 255) { index = 255; } uint8_t result[255]; uint8_t length = 0; length = copy_short_slice( result, length, string, 1, (uint16_t)(index - 1), 255); length = copy_short_slice( result, length, string, (uint16_t)(index + count), 255, 255); win16_write_u8(string, length); for (uint16_t offset = 0; offset < length; offset++) { win16_write_u8( win16_far_add_offset(string, (uint16_t)(offset + 1)), result[offset]); } }