Merge branch 'widget-rewrite-1' into master

* widget-rewrite-1:
  Now it's done.
  Partially done.
  Local RAII
  Requested anchor RAIIed.
  Image owns its alt text.
  Some const correctness in the Java pseudo core.
  Local ownership for font name.
  Fix building with no libjpeg.
This commit is contained in:
2025-08-21 23:38:12 -04:00
21 changed files with 92 additions and 96 deletions

View File

@ -146,19 +146,19 @@ void FltkFont::initSystemFonts ()
int k = Fl::set_fonts ("-*-iso10646-1");
for (int i = 0; i < k; i++) {
int t;
char *name = dStrdup (Fl::get_font_name ((Fl_Font) i, &t));
std::string name = Fl::get_font_name ((Fl_Font) i, &t);
// normalize font family names (strip off "bold", "italic")
if (t & FL_ITALIC)
strstrip(name, " italic");
strstrip(name.data(), " italic");
if (t & FL_BOLD)
strstrip(name, " bold");
strstrip(name.data(), " bold");
_MSG("Found font: %s%s%s\n", name, t & FL_BOLD ? " bold" : "",
t & FL_ITALIC ? " italic" : "");
auto &family = (*systemFonts)[ name ];
auto &family = (*systemFonts)[ name.c_str() ];
if( family ) {
family->set ((Fl_Font) i, t);
} else {
@ -167,8 +167,6 @@ void FltkFont::initSystemFonts ()
family = std::make_unique< FontFamily >( (Fl_Font) i, -1, -1, -1 );
family->set( (Fl_Font) i, t );
}
free (name);
}
}

View File

@ -131,11 +131,11 @@ int ImageMapsList::link (object::Object *key, int x, int y)
// ----------------------------------------------------------------------
Image::Image(const char *altText)
Image::Image(const std::optional< std::string_view > altText)
{
DBG_OBJ_CREATE ("dw::Image");
registerName ("dw::Image", typeid(*this));
this->altText = altText ? dStrdup (altText) : NULL;
this->altText = altText;
altTextWidth = -1; // not yet calculated
buffer = NULL;
bufWidth = bufHeight = -1;
@ -151,8 +151,6 @@ Image::Image(const char *altText)
Image::~Image()
{
if (altText)
free(altText);
if (buffer)
buffer->unref ();
if (mapKey)
@ -177,10 +175,10 @@ void Image::sizeRequestSimpl (core::Requisition *requisition)
requisition->ascent = buffer->getRootHeight ();
requisition->descent = 0;
} else {
if (altText && altText[0]) {
if (altText && altText.value()[0]) {
if (altTextWidth == -1)
altTextWidth =
layout->textWidth (getStyle()->font, altText, strlen (altText));
layout->textWidth (getStyle()->font, altText.value().c_str(), altText.value().size());
requisition->width = altTextWidth;
requisition->ascent = getStyle()->font->ascent;
@ -220,10 +218,10 @@ void Image::getExtremesSimpl (core::Extremes *extremes)
if (buffer)
contentWidth = buffer->getRootWidth ();
else {
if (altText && altText[0]) {
if (altText && altText.value()[0]) {
if (altTextWidth == -1)
altTextWidth =
layout->textWidth (getStyle()->font, altText, strlen (altText));
layout->textWidth (getStyle()->font, altText.value().c_str(), altText.value().size());
contentWidth = altTextWidth;
} else
contentWidth = 0;
@ -422,14 +420,14 @@ void Image::draw (core::View *view, core::Rectangle *area,
} else {
core::View *clippingView;
if (altText && altText[0]) {
if (altText && altText.value()[0]) {
core::View *usedView = view;
clippingView = NULL;
if (altTextWidth == -1)
altTextWidth =
layout->textWidth (getStyle()->font, altText, strlen (altText));
layout->textWidth (getStyle()->font, altText.value().c_str(), altText.value().size());
if ((getContentWidth() < altTextWidth) ||
(getContentHeight() <
@ -445,7 +443,7 @@ void Image::draw (core::View *view, core::Rectangle *area,
core::style::Color::SHADING_NORMAL,
allocation.x + boxOffsetX (),
allocation.y + boxOffsetY (),
getContentWidth(), getContentHeight(), altText);
getContentWidth(), getContentHeight(), altText.value().c_str());
if (clippingView)
view->mergeClippingView (clippingView);

View File

@ -3,6 +3,9 @@
#include "core.hh"
#include <optional>
#include <string>
namespace dw {
/**
@ -115,7 +118,7 @@ public:
class Image: public core::Widget, public core::ImgRenderer
{
private:
char *altText;
std::optional< std::string > altText;
core::Imgbuf *buffer;
int bufWidth, bufHeight;
int altTextWidth;
@ -145,7 +148,7 @@ protected:
//core::Iterator *iterator (Content::Type mask, bool atEnd);
public:
Image(const char *altText);
Image(std::optional< std::string_view > altText);
~Image();
// For images, the minimal width is not well defined, and

View File

@ -248,13 +248,6 @@ bool Layout::LinkEmitter::emitClick (Widget *widget, int link, int img,
// ---------------------------------------------------------------------
Layout::Anchor::~Anchor ()
{
free(name);
}
// ---------------------------------------------------------------------
Layout::Layout (std::unique_ptr< Platform > platform, bool limit)
{
this->platform = std::move( platform );
@ -281,7 +274,6 @@ Layout::Layout (std::unique_ptr< Platform > platform, bool limit)
DBG_OBJ_SET_NUM ("hScrollbarThickness", hScrollbarThickness);
DBG_OBJ_SET_NUM ("vScrollbarThickness", vScrollbarThickness);
requestedAnchor = NULL;
scrollIdleId = -1;
scrollIdleNotInterrupted = false;
@ -332,9 +324,6 @@ Layout::~Layout ()
delete view;
delete textZone;
if (requestedAnchor)
free (requestedAnchor);
DBG_OBJ_DELETE ();
}
@ -410,7 +399,7 @@ void Layout::removeWidget ()
view->setViewportSize (viewportWidth, viewportHeight, 0, 0);
view->queueDrawTotal ();
setAnchor (NULL);
setAnchor (std::nullopt);
updateAnchor ();
emitter.emitCanvasSizeChanged (canvasWidth, canvasAscent, canvasDescent);
@ -724,31 +713,31 @@ int Layout::currVScrollbarThickness()
/**
* Sets the anchor to scroll to.
*/
void Layout::setAnchor (const char *anchor)
void Layout::setAnchor (const std::optional< std::string_view > anchor)
{
_MSG("setAnchor (%s)\n", anchor);
_MSG("setAnchor (%s)\n", anchor.value_or("").string().c_str());
if (requestedAnchor)
free (requestedAnchor);
requestedAnchor = anchor ? dStrdup (anchor) : NULL;
requestedAnchor = anchor;
updateAnchor ();
}
/**
* Used, when the widget is not allocated yet.
*/
char *Layout::addAnchor (Widget *widget, const char* name)
std::optional< std::string >
Layout::addAnchor (Widget *widget, const std::string &name)
{
return addAnchor (widget, name, -1);
}
char *Layout::addAnchor (Widget *widget, const char* name, int y)
std::optional< std::string >
Layout::addAnchor (Widget *widget, const std::string &name, int y)
{
if (anchorsTable.contains (name))
return NULL;
return std::nullopt;
else {
auto anchor = std::make_unique< Anchor >();
char *const rv= anchor->name = dStrdup (name);
std::string rv= anchor->name= name;
anchor->widget = widget;
anchor->y = y;
@ -759,7 +748,7 @@ char *Layout::addAnchor (Widget *widget, const char* name, int y)
}
}
void Layout::changeAnchor (Widget *widget, char* name, int y)
void Layout::changeAnchor (Widget *widget, const std::string &name, int y)
{
Anchor *const anchor = anchorsTable.at( name ).get();
assert (anchor);
@ -768,7 +757,7 @@ void Layout::changeAnchor (Widget *widget, char* name, int y)
updateAnchor ();
}
void Layout::removeAnchor (Widget *widget, char* name)
void Layout::removeAnchor (Widget *widget, const std::string &name)
{
anchorsTable.erase( name );
}
@ -776,9 +765,9 @@ void Layout::removeAnchor (Widget *widget, char* name)
void Layout::updateAnchor ()
{
Anchor *anchor= nullptr;
if (requestedAnchor and anchorsTable.contains( requestedAnchor ) )
if (requestedAnchor and anchorsTable.contains( requestedAnchor.value() ) )
{
anchor= anchorsTable[ requestedAnchor ].get();
anchor= anchorsTable[ requestedAnchor.value() ].get();
}
if (anchor == NULL) {
@ -1292,7 +1281,7 @@ void Layout::scrollPosChanged (View *view, int x, int y)
scrollX = x;
scrollY = y;
setAnchor (NULL);
setAnchor( std::nullopt );
updateAnchor ();
}
}

View File

@ -150,11 +150,9 @@ private:
class Anchor: public lout::object::Object
{
public:
char *name;
std::string name;
Widget *widget;
int y;
~Anchor ();
};
std::unique_ptr< Platform > platform;
@ -182,7 +180,7 @@ private:
VPosition scrollTargetVpos;
int scrollTargetX, scrollTargetY, scrollTargetWidth, scrollTargetHeight;
char *requestedAnchor;
std::optional< std::string > requestedAnchor;
int scrollIdleId, resizeIdleId;
bool scrollIdleNotInterrupted;
@ -236,10 +234,10 @@ private:
/* Widget */
char *addAnchor (Widget *widget, const char* name);
char *addAnchor (Widget *widget, const char* name, int y);
void changeAnchor (Widget *widget, char* name, int y);
void removeAnchor (Widget *widget, char* name);
std::optional< std::string > addAnchor (Widget *widget, const std::string &name);
std::optional< std::string > addAnchor (Widget *widget, const std::string &name, int y);
void changeAnchor (Widget *widget, const std::string &name, int y);
void removeAnchor (Widget *widget, const std::string &name);
void setCursor (style::Cursor cursor);
void updateCursor ();
void queueDraw (int x, int y, int width, int height);
@ -300,7 +298,7 @@ public:
void scrollTo (HPosition hpos, VPosition vpos,
int x, int y, int width, int height);
void scroll (ScrollCommand);
void setAnchor (const char *anchor);
void setAnchor (std::optional< std::string_view > anchor);
/* View */

View File

@ -67,7 +67,8 @@ OOFFloatsMgr::Float::Float (OOFFloatsMgr *oofm, Widget *widget,
}
}
void OOFFloatsMgr::Float::intoStringBuffer(StringBuffer *sb)
void
OOFFloatsMgr::Float::intoStringBuffer(StringBuffer *sb) const
{
sb->append ("{ widget = ");
sb->appendPointer (getWidget ());
@ -1380,6 +1381,15 @@ Widget *OOFFloatsMgr::getWidget (int i)
return rightFloats->get(i - leftFloats->size())->getWidget ();
}
const Widget *
OOFFloatsMgr::getWidget (int i) const
{
if (i < leftFloats->size())
return leftFloats->get(i)->getWidget ();
else
return rightFloats->get(i - leftFloats->size())->getWidget ();
}
} // namespace oof
} // namespace dw

View File

@ -39,6 +39,7 @@ private:
WidgetInfo (OOFFloatsMgr *oofm, core::Widget *widget);
inline core::Widget *getWidget () { return widget; }
inline const core::Widget *getWidget () const { return widget; }
};
class Float: public WidgetInfo
@ -78,7 +79,7 @@ private:
Float (OOFFloatsMgr *oofm, core::Widget *widget,
OOFAwareWidget *generatingBlock, int externalIndex);
void intoStringBuffer(lout::misc::StringBuffer *sb);
void intoStringBuffer(lout::misc::StringBuffer *sb) const override;
bool covers (int y, int h);
};
@ -281,6 +282,7 @@ public:
int getNumWidgets ();
core::Widget *getWidget (int i);
const core::Widget *getWidget (int i) const;
};
} // namespace oof

View File

@ -282,7 +282,7 @@ Textblock::~Textblock ()
for( const Anchor &anchor: anchors )
{
/* This also frees the names (see removeAnchor() and related). */
removeAnchor(anchor.name);
removeAnchor(std::string{ anchor.name });
}
delete paragraphs;
@ -721,7 +721,7 @@ void Textblock::sizeAllocateImpl (core::Allocation *allocation)
Line *line = lines->getRef(findLineOfWord (anchor->wordIndex));
y = lineYOffsetCanvas (line, allocation);
}
changeAnchor (anchor->name, y);
changeAnchor (std::string{ anchor->name }, y);
}
DBG_OBJ_LEAVE ();
@ -2555,11 +2555,11 @@ void Textblock::addWidget (core::Widget *widget, core::style::Style *style)
* Return true on success, and false, when this anchor had already been
* added to the widget tree.
*/
bool Textblock::addAnchor (const char *name, core::style::Style *style)
bool Textblock::addAnchor (const std::string &name, core::style::Style *style)
{
DBG_OBJ_ENTER ("construct.word", 0, "addAnchor", "\"%s\", %p", name, style);
DBG_OBJ_ENTER ("construct.word", 0, "addAnchor", "\"%s\", %p", name.c_str(), style);
char *copy;
std::optional< std::string > copy;
int y;
bool result;
@ -2574,7 +2574,7 @@ bool Textblock::addAnchor (const char *name, core::style::Style *style)
} else
copy = Widget::addAnchor (name);
if (copy == NULL)
if (not copy.has_value())
/**
* \todo It may be necessary for future uses to save the anchor in
* some way, e.g. when parts of the widget tree change.
@ -2584,7 +2584,7 @@ bool Textblock::addAnchor (const char *name, core::style::Style *style)
anchors.emplace_back();
Anchor &anchor= anchors.back();
anchor.name = copy;
anchor.name = copy.value();
anchor.wordIndex = words->size();
result = true;
}

View File

@ -505,7 +505,7 @@ protected:
struct Anchor
{
char *name;
std::string_view name;
int wordIndex;
};
@ -890,7 +890,7 @@ public:
inline void addText (const char *text, core::style::Style *style)
{ addText (text, strlen(text), style); }
void addWidget (core::Widget *widget, core::style::Style *style);
bool addAnchor (const char *name, core::style::Style *style);
bool addAnchor (const std::string &name, core::style::Style *style);
void addSpace (core::style::Style *style);
void addBreakOption (core::style::Style *style, bool forceBreak);
void addParbreak (int space, core::style::Style *style);

View File

@ -394,16 +394,16 @@ protected:
virtual void enterNotifyImpl (EventCrossing *event);
virtual void leaveNotifyImpl (EventCrossing *event);
inline char *addAnchor (const char* name)
inline std::optional< std::string > addAnchor (const std::string &name)
{ return layout->addAnchor (this, name); }
inline char *addAnchor (const char* name, int y)
inline std::optional< std::string > addAnchor (const std::string &name, int y)
{ return layout->addAnchor (this, name, y); }
inline void changeAnchor (char* name, int y)
inline void changeAnchor (const std::string &name, int y)
{ layout->changeAnchor (this, name, y); }
inline void removeAnchor (char* name)
inline void removeAnchor (const std::string &name)
{ if (layout) layout->removeAnchor (this, name); }
//inline void updateBgColor () { layout->updateBgColor (); }

View File

@ -85,11 +85,12 @@ Iterator::~Iterator()
// Collection
// ----------------
void Collection::intoStringBuffer(misc::StringBuffer *sb)
void
Collection::intoStringBuffer( misc::StringBuffer *sb ) const
{
sb->append("{ ");
bool first = true;
for (Iterator it = iterator(); it.hasNext(); ) {
for (Iterator it = const_cast< Collection * >( this )->iterator(); it.hasNext(); ) {
if (!first)
sb->append(", ");
it.getNext()->intoStringBuffer(sb);

View File

@ -135,7 +135,7 @@ public:
class Collection: public Collection0
{
public:
void intoStringBuffer(misc::StringBuffer *sb);
void intoStringBuffer(misc::StringBuffer *sb) const override;
inline Iterator iterator() { Iterator it(createIterator()); return it; }
virtual int size() = 0;
};

View File

@ -26,7 +26,8 @@ namespace identity {
std::map< std::type_index, std::string > IdentifiableObject::classNames;
void IdentifiableObject::intoStringBuffer(misc::StringBuffer *sb)
void
IdentifiableObject::intoStringBuffer(misc::StringBuffer *sb) const
{
sb->append("<instance ");
sb->appendPointer(this);

View File

@ -37,13 +37,13 @@ protected:
void registerName (const char *className, std::type_index index);
public:
void intoStringBuffer(misc::StringBuffer *sb) override;
void intoStringBuffer(misc::StringBuffer *sb) const override;
/**
* \brief Return the name, under which the class of this object was
* registered.
*/
const char *getClassName() { return classNames.at( typeid( *this ) ).c_str(); }
const char *getClassName() const { return classNames.at( typeid( *this ) ).c_str(); }
};
} // namespace identity

View File

@ -581,7 +581,7 @@ public:
inline void append(const char *str) { appendNoCopy(dStrdup(str)); }
inline void appendInt(int n)
{ char buf[32]; sprintf (buf, "%d", n); append (buf); }
inline void appendPointer(void *p)
inline void appendPointer(const void *p)
{ char buf[32]; sprintf (buf, "%p", p); append (buf); }
inline void appendBool(bool b) { append (b ? "true" : "false"); }
void appendNoCopy(char *str);

View File

@ -75,17 +75,13 @@ Object *Object::clone()
/**
* \brief Use object::Object::intoStringBuffer to return a textual
* representation of the object.
*
* The caller does not have to free the memory, object::Object is responsible
* for this.
*/
const char *Object::toString()
std::string
Object::toString() const
{
/** \todo garbage! */
misc::StringBuffer sb;
intoStringBuffer(&sb);
char *s = dStrdup(sb.getChars());
return s;
return sb.getChars();
}
/**
@ -93,7 +89,8 @@ const char *Object::toString()
*
* This is used by object::Object::toString.
*/
void Object::intoStringBuffer(misc::StringBuffer *sb)
void
Object::intoStringBuffer(misc::StringBuffer *sb) const
{
sb->append("<not further specified object ");
sb->appendPointer(this);

View File

@ -28,8 +28,8 @@ public:
virtual bool equals(Object *other);
virtual int hashValue();
virtual Object *clone();
virtual void intoStringBuffer(misc::StringBuffer *sb);
const char *toString();
virtual void intoStringBuffer(misc::StringBuffer *sb) const;
std::string toString() const;
virtual size_t sizeOf();
};

View File

@ -41,7 +41,8 @@ Emitter::~Emitter ()
}
}
void Emitter::intoStringBuffer(misc::StringBuffer *sb)
void
Emitter::intoStringBuffer(misc::StringBuffer *sb) const
{
sb->append ("<emitter: ");
container::intoStringBuffer( receivers, sb );
@ -117,7 +118,7 @@ Receiver::~Receiver()
}
}
void Receiver::intoStringBuffer(misc::StringBuffer *sb)
void Receiver::intoStringBuffer(misc::StringBuffer *sb) const
{
// emitters are not listed, to prevent recursion
sb->append ("<receiver>");

View File

@ -241,7 +241,7 @@ public:
Emitter();
~Emitter();
void intoStringBuffer(misc::StringBuffer *sb);
void intoStringBuffer(misc::StringBuffer *sb) const override;
};
/**
@ -266,7 +266,7 @@ public:
Receiver();
~Receiver();
void intoStringBuffer(misc::StringBuffer *sb);
void intoStringBuffer(misc::StringBuffer *sb) const override;
};
/**

View File

@ -422,8 +422,8 @@ static void Jpeg_write(DilloJpeg *jpeg, void *Buf, uint_t BufSize)
#else /* ENABLE_JPEG */
void *a_Jpeg_new() { return 0; }
void a_Jpeg_callback() { return; }
void *a_Jpeg_new(DilloImage *, DilloUrl *, int) { return 0; }
void a_Jpeg_callback(int, void *) { return; }
const char *a_Jpeg_version(void) { return 0; }
#endif /* ENABLE_JPEG */

View File

@ -984,7 +984,7 @@ void UI::customize()
*/
void UI::change_panel(int new_size, int small_icons)
{
char *loc_text = dStrdup(Location->value());
std::string loc_text = Location->value();
// Remove current panel's bars
init_sizes();
@ -1004,10 +1004,8 @@ void UI::change_panel(int new_size, int small_icons)
a_UIcmd_set_buttons_sens(a_UIcmd_get_bw_by_widget(this));
TopGroup->rearrange();
Location->value(loc_text);
Location->value(loc_text.c_str());
Location->take_focus();
dFree(loc_text);
}
/**