Word Unperfect
public
Read
Owner: themaster
Branch: main
Commits: 0
Git CLI clone URL
git clone https://www.xt-emporium.com/git/word-unperfect.git
Fullscreen desktop URL
Code
Commits
History
Branches
Bug Reports
Discussions
Compare
Settings
word-unperfect
/
rev
/
wp_layout_engine.c
File editor
#include "wp_layout_engine.h" #include "wp_record_parser.h" #include "wp_span_metrics.h" #include "wp_record_stream.h" #include <stddef.h> #include <stdlib.h> void wp_primary_buffer_bind_bytes_lifo(WpLayoutGlobals *wl, uint8_t *first, int count, uint buffer_space) { if (wl == NULL) { return; } if (first == NULL || count <= 0) { wl->primary_record.word = (intptr_t)first; wl->record_used_bytes = 0; } else { wl->primary_record.word = (intptr_t)(first + count); wl->record_used_bytes = count; } wl->record_buffer_space = buffer_space; } void wp_secondary_buffer_bind(WpLayoutGlobals *wl, uint8_t *buffer, int initial_count, int free_space) { if (wl == NULL) { return; } if (buffer == NULL) { wl->secondary_record.word = 0; wl->secondary_record_used_bytes = 0; } else { /* Cursor starts at the beginning of data; prepends move it down into free_space. */ wl->secondary_record.as_secondary_p = (undefined *)(buffer + free_space); wl->secondary_record_used_bytes = initial_count; } } static uint16_t wp_layout_active_unit_width(WpLayoutGlobals *wl) { uint32_t scaled; uint16_t scale_q8; uint16_t unit; unit = (uint16_t)layout_get_active_span_total_width(wl); if (unit == 0U) { unit = 1U; } scale_q8 = wl->span_scale_q8_5039; if (scale_q8 == 0U || scale_q8 == 0x0100U) { return unit; } scaled = ((uint32_t)unit * (uint32_t)scale_q8) >> 8; if (scaled == 0U) { scaled = 1U; } if (scaled > 0xffffU) { scaled = 0xffffU; } return (uint16_t)scaled; } static bool wp_layout_move_secondary_to_primary(WpLayoutGlobals *wl) { uint8_t *bytes; int count; int i; uint16_t value; if (wl->secondary_record_used_bytes <= 0) { return true; } count = wl->secondary_record_used_bytes; bytes = (uint8_t *)malloc((size_t)count); if (bytes == NULL) { return false; } for (i = 0; i < count; ++i) { value = parser_consume_next_input_byte(wl); if (value == 0xffffU) { free(bytes); return false; } bytes[i] = (uint8_t)value; } for (i = count; i > 0; --i) { append_byte_to_buffer(wl, bytes[i - 1]); } free(bytes); return true; } static uint16_t wp_layout_tab_width(uint16_t current_width, uint16_t unit_width) { uint16_t tab_width; uint16_t next_stop; tab_width = (uint16_t)(unit_width * 8U); if (tab_width == 0U) { tab_width = 8U; } next_stop = (uint16_t)(((uint32_t)current_width / tab_width + 1U) * tab_width); return (uint16_t)(next_stop - current_width); } static uint16_t wp_layout_record_width(const WpRecord *rec, uint16_t current_width, uint16_t unit_width) { if (rec->type == WP_CODE_CHAR) { return unit_width; } if (rec->type == WP_CODE_SINGLE_BYTE && rec->code == 0x84U) { return wp_layout_tab_width(current_width, unit_width); } if (rec->type == WP_CODE_VARIABLE_LENGTH && rec->code == 0xc0U && rec->is_complete) { return unit_width; } return 0U; } void wp_layout_break_line(WpLayoutGlobals *wl, WpLine *line) { uint16_t current_width; uint16_t target_width; uint16_t unit_width; if (wl == NULL || line == NULL) { return; } target_width = (uint16_t)wl->primary_limit; if (target_width == 0) { target_width = 80; } line->width = 0; line->space_count = 0; line->is_hard_return = 0; line->end_offset = line->start_offset; if (!wp_layout_move_secondary_to_primary(wl)) { return; } current_width = 0; unit_width = wp_layout_active_unit_width(wl); while (wl->record_used_bytes > 0) { WpLayoutGlobals before_loop = *wl; WpRecord rec; uint16_t delta; wp_parser_consume_record(wl, &rec); if (rec.length == 0U) { wp_record_free(&rec); break; } if (rec.type == WP_CODE_SINGLE_BYTE && rec.code == 0x80U) { line->is_hard_return = true; line->end_offset = (uint16_t)(line->end_offset + rec.length); wp_record_free(&rec); break; } delta = wp_layout_record_width(&rec, current_width, unit_width); if (delta != 0U && current_width > 0U && (uint32_t)current_width + (uint32_t)delta > (uint32_t)target_width) { *wl = before_loop; wp_record_free(&rec); break; } current_width = (uint16_t)(current_width + delta); line->end_offset = (uint16_t)(line->end_offset + rec.length); if (rec.type == WP_CODE_CHAR && rec.code == ' ') { line->space_count = (uint16_t)(line->space_count + 1U); } if (current_width >= target_width) { wp_record_free(&rec); break; } wp_record_free(&rec); } line->width = current_width; } void wp_layout_apply_justification(WpLine *line, uint16_t target_width) { if (line == NULL) { return; } if (line->justification == WP_JUSTIFY_FULL && !line->is_hard_return) { if (line->space_count > 0 && target_width > line->width) { uint16_t deficit = (uint16_t)(target_width - line->width); uint16_t extra_per_space = deficit / line->space_count; uint16_t remainder = deficit % line->space_count; (void)extra_per_space; (void)remainder; /* In WP 5.1, micro-spacing would distribute 'remainder' * across the first few spaces. */ } } } void wp_layout_paginate(WpLayoutGlobals *wl) { (void)wl; /* Background pagination: * 1. Start from the top of the document or last known good page break. * 2. Accumulate line heights until page height limit is reached. * 3. Account for Widows and Orphans (WP 5.1 feature). * 4. Insert/Update Soft Page breaks [SPg]. */ }
Commit message
This repository is read-only for this account.
Repository snapshot
Current branch
main
Visibility
public
Your access
Read
Remote
None
File activity
View file history