mirror of
https://github.com/fltk/fltk.git
synced 2026-05-20 04:31:25 +08:00
Reactivating Mergeback functionality. (#1226)
Reactivated code. Various fixes. New documentation.
This commit is contained in:
+3
-1
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "Fluid.h"
|
||||
|
||||
#include "proj/mergeback.h"
|
||||
#include "proj/undo.h"
|
||||
#include "app/templates.h"
|
||||
#include "nodes/Node.h"
|
||||
@@ -52,6 +53,7 @@ void help_cb(Fl_Widget *, void *) {
|
||||
Fluid.show_help("fluid.html");
|
||||
}
|
||||
static void save_template_cb(Fl_Widget *, void *) { fld::app::save_template(); }
|
||||
void mergeback_cb(Fl_Widget *, void *);
|
||||
|
||||
void manual_cb(Fl_Widget *, void *) {
|
||||
Fluid.show_help("index.html");
|
||||
@@ -99,7 +101,7 @@ Fl_Menu_Item Application::main_menu[] = {
|
||||
{"Save As &Template...", 0, save_template_cb, nullptr, FL_MENU_DIVIDER},
|
||||
{"&Print...", FL_COMMAND+'p', menu_file_print_cb},
|
||||
{"Write &Code", FL_COMMAND+FL_SHIFT+'c', write_cb, nullptr},
|
||||
// Matt: disabled {"MergeBack Code", FL_COMMAND+FL_SHIFT+'m', mergeback_cb, 0},
|
||||
{"MergeBack Code", FL_COMMAND+FL_SHIFT+'m', mergeback_cb, 0},
|
||||
{"&Write Strings", FL_COMMAND+FL_SHIFT+'w', write_strings_cb, nullptr, FL_MENU_DIVIDER},
|
||||
{Fluid.history.relpath[0], FL_COMMAND+'1', menu_file_open_history_cb, Fluid.history.abspath[0]},
|
||||
{Fluid.history.relpath[1], FL_COMMAND+'2', menu_file_open_history_cb, Fluid.history.abspath[1]},
|
||||
|
||||
@@ -792,6 +792,7 @@ INPUT = @CMAKE_CURRENT_SOURCE_DIR@/src/index.dox \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/src/page_widget_panel.dox \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/src/page_setting_dialog.dox \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/src/page_codeview_panel.dox \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/src/page_mergeback.dox \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/src/page_tutorial.dox \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/src/page_appendices.dox
|
||||
|
||||
|
||||
@@ -96,6 +96,8 @@
|
||||
- \ref setting_i18n
|
||||
- \ref setting_user
|
||||
|
||||
\subpage page_mergeback
|
||||
|
||||
\subpage page_tutorial
|
||||
- \ref fluid_hello_world_tutorial
|
||||
- \ref fluid_1of7guis_tutorial
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
|
||||
\page page_mergeback Fluid Mergeback
|
||||
|
||||
\tableofcontents
|
||||
|
||||
# Introduction to Mergeback #
|
||||
|
||||
Fluid has introduced an experimental feature called **MergeBack** in version 1.5.
|
||||
This feature allows developers to edit the C++ source files generated by Fluid and
|
||||
then merge those changes back into the corresponding Fluid project file (.fl). This
|
||||
can streamline the development process by reducing the need to switch between Fluid
|
||||
and your code editor for minor adjustments.
|
||||
|
||||
**Important Note:** MergeBack is currently experimental and may not handle all
|
||||
scenarios perfectly. It's advisable to back up your project files before using this
|
||||
feature to prevent potential data loss.
|
||||
|
||||
**Enabling MergeBack:**
|
||||
|
||||
1. **Open Your Project in Fluid:**
|
||||
- Launch Fluid and load your existing `.fl` project file.
|
||||
|
||||
2. **Enable MergeBack:**
|
||||
- Navigate to the **Settings Panel**.
|
||||
- In the **Project Settings**, locate and enable the **MergeBack** option.
|
||||
|
||||
Once enabled, Fluid assigns a unique ID to each node in your project.
|
||||
Additionally, user-editable code sections in the generated source files will
|
||||
be marked with special divider lines, indicating areas that can be edited
|
||||
and later merged back.
|
||||
|
||||
**Understanding the Code Markers:**
|
||||
|
||||
In the generated `.cxx` files, editable sections are demarcated as follows:
|
||||
|
||||
```cpp
|
||||
static void cb_script_panel(Fl_Double_Window*, void*) {
|
||||
//fl ▼ ---------------------- callback ~~----~~~~=-=~~~~=-~~~ ▼ fl//
|
||||
if (Fl::event() == FL_SHORTCUT && Fl::event_key() == FL_Escape) return;
|
||||
script_panel->hide();
|
||||
//fl ▲ ----------=~-~~=-=--=~-----------~-==--~=~-~~--~=-~=~- ▲ fl//
|
||||
}
|
||||
```
|
||||
|
||||
The lines beginning with `//fl ▼` and `//fl ▲` are markers that Fluid
|
||||
uses to identify editable sections. These markers contain encoded information
|
||||
about the code block, including a CRC32 checksum and a unique node ID. Fluid
|
||||
uses this information during the merge process to detect changes and associate
|
||||
them with the correct nodes in your project.
|
||||
|
||||
**Editing and Merging Back:**
|
||||
|
||||
1. **Edit the Source Code:**
|
||||
- Open the generated `.cxx` file in your preferred code editor.
|
||||
- Make your desired changes within the marked sections.
|
||||
|
||||
2. **Merge Changes Back into Fluid:**
|
||||
- After saving your edits, return to Fluid.
|
||||
- Select **File > MergeBack** from the main menu or press `Ctrl+Shift+M`.
|
||||
- Fluid will analyze the `.cxx` file, detect changes within the marked
|
||||
sections, and offer to merge them back into the `.fl` project file.
|
||||
|
||||
**Things to Keep in Mind:**
|
||||
|
||||
- **Scope of MergeBack:** Currently, MergeBack supports merging changes
|
||||
made to code blocks and widget callbacks. Other modifications might
|
||||
not be recognized or merged correctly.
|
||||
|
||||
- **Conflict Detection:** Fluid calculates checksums (CRC32) for the
|
||||
code blocks to detect changes. If discrepancies are found, Fluid
|
||||
will prompt you with options to merge or cancel the changes.
|
||||
|
||||
- **Undo Functionality:** In case of unintended merges, Fluid provides
|
||||
an undo feature to revert the project to its previous state.
|
||||
|
||||
**Caution:** Given the experimental nature of MergeBack, unexpected
|
||||
behaviors may occur. Always ensure you have backups of your project
|
||||
files before using this feature.
|
||||
|
||||
\note The MergeBack feature is still under development. It's recommended
|
||||
to use it cautiously and provide feedback to the FLTK development
|
||||
team to help improve its functionality and reliability.
|
||||
*/
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "Fluid.h"
|
||||
#include "Project.h"
|
||||
#include "proj/mergeback.h"
|
||||
#include "nodes/Window_Node.h"
|
||||
#include "nodes/Function_Node.h"
|
||||
|
||||
@@ -28,6 +29,7 @@
|
||||
|
||||
using namespace fld;
|
||||
using namespace fld::io;
|
||||
using namespace fld::proj;
|
||||
|
||||
/**
|
||||
Return true if c can be in a C identifier.
|
||||
@@ -103,11 +105,11 @@ const char* Code_Writer::unique_id(void* o, const char* type, const char* name,
|
||||
\return pointer to a static string
|
||||
*/
|
||||
const char *Code_Writer::indent(int set) {
|
||||
static const char* spaces = " ";
|
||||
static const char* spaces = " ";
|
||||
int i = set * 2;
|
||||
if (i>32) i = 32;
|
||||
if (i>64) i = 64;
|
||||
if (i<0) i = 0;
|
||||
return spaces+32-i;
|
||||
return spaces+64-i;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -774,9 +776,10 @@ Code_Writer::~Code_Writer()
|
||||
\param[in] type FD_TAG_GENERIC, FD_TAG_CODE, FD_TAG_MENU_CALLBACK, or FD_TAG_WIDGET_CALLBACK
|
||||
\param[in] uid the unique id of the current type
|
||||
*/
|
||||
void Code_Writer::tag(int type, unsigned short uid) {
|
||||
if (proj_.write_mergeback_data)
|
||||
fprintf(code_file, "//~fl~%d~%04x~%08x~~\n", type, (int)uid, (unsigned int)block_crc_);
|
||||
void Code_Writer::tag(proj::Mergeback::Tag prev_type, proj::Mergeback::Tag next_type, unsigned short uid) {
|
||||
if (proj_.write_mergeback_data) {
|
||||
Mergeback::print_tag(code_file, prev_type, next_type, uid, (uint32_t)block_crc_);
|
||||
}
|
||||
block_crc_ = crc32(0, nullptr, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#ifndef FLUID_IO_CODE_WRITER_H
|
||||
#define FLUID_IO_CODE_WRITER_H
|
||||
|
||||
#include "proj/mergeback.h"
|
||||
|
||||
#include <FL/fl_attr.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
@@ -114,7 +116,7 @@ public:
|
||||
int write_code(const char *cfile, const char *hfile, bool to_codeview=false);
|
||||
void write_public(int state); // writes pubic:/private: as needed
|
||||
|
||||
void tag(int type, unsigned short uid);
|
||||
void tag(proj::Mergeback::Tag prev_type, proj::Mergeback::Tag next_type, unsigned short uid);
|
||||
|
||||
static unsigned long block_crc(const void *data, int n=-1, unsigned long in_crc=0, bool *inout_line_start=nullptr);
|
||||
};
|
||||
|
||||
@@ -35,6 +35,9 @@
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
using namespace fld;
|
||||
using namespace fld::io;
|
||||
using namespace fld::proj;
|
||||
|
||||
/// Set a current class, so that the code of the children is generated correctly.
|
||||
Class_Node *current_class = nullptr;
|
||||
@@ -682,9 +685,9 @@ void Code_Node::write_code1(fld::io::Code_Writer& f) {
|
||||
if ( handle_editor_changes() == 1 ) {
|
||||
Fluid.main_window->redraw(); // tell fluid to redraw; edits may affect tree's contents
|
||||
}
|
||||
// Matt: disabled f.tag(FD_TAG_GENERIC, 0);
|
||||
f.tag(Mergeback::Tag::GENERIC, Mergeback::Tag::CODE, 0);
|
||||
f.write_c_indented(name(), 0, '\n');
|
||||
// Matt: disabled f.tag(FD_TAG_CODE, get_uid());
|
||||
f.tag(Mergeback::Tag::CODE, Mergeback::Tag::GENERIC, get_uid());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,6 +44,9 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
using namespace fld;
|
||||
using namespace fld::proj;
|
||||
|
||||
Fl_Menu_Item menu_item_type_menu[] = {
|
||||
{"Normal",0,nullptr,(void*)nullptr},
|
||||
{"Toggle",0,nullptr,(void*)FL_MENU_BOX},
|
||||
@@ -349,7 +352,7 @@ void Menu_Item_Node::write_static(fld::io::Code_Writer& f) {
|
||||
f.write_c(", %s", ut);
|
||||
if (use_v) f.write_c(" v");
|
||||
f.write_c(") {\n");
|
||||
// Matt: disabled f.tag(FD_TAG_GENERIC, 0);
|
||||
f.tag(Mergeback::Tag::GENERIC, Mergeback::Tag::MENU_CALLBACK, 0);
|
||||
f.write_c_indented(callback(), 1, 0);
|
||||
if (*(d-1) != ';' && *(d-1) != '}') {
|
||||
const char *p = strrchr(callback(), '\n');
|
||||
@@ -360,7 +363,7 @@ void Menu_Item_Node::write_static(fld::io::Code_Writer& f) {
|
||||
if (*p != '#' && *p) f.write_c(";");
|
||||
}
|
||||
f.write_c("\n");
|
||||
// Matt: disabled f.tag(FD_TAG_MENU_CALLBACK, get_uid());
|
||||
f.tag(Mergeback::Tag::MENU_CALLBACK, Mergeback::Tag::GENERIC, get_uid());
|
||||
f.write_c("}\n");
|
||||
|
||||
// If the menu item is part of a Class or Widget Class, FLUID generates
|
||||
|
||||
@@ -696,7 +696,6 @@ void Node::add(Node *anchor, Strategy strategy) {
|
||||
Fluid.proj.tree.first = this;
|
||||
}
|
||||
|
||||
#if 0
|
||||
{ // make sure that we have no duplicate uid's
|
||||
Node *tp = this;
|
||||
do {
|
||||
@@ -704,7 +703,6 @@ void Node::add(Node *anchor, Strategy strategy) {
|
||||
tp = tp->next;
|
||||
} while (tp!=end && tp!=nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Give the widgets in our tree a chance to update themselves
|
||||
for (Node *t = this; t && t!=end->next; t = t->next) {
|
||||
@@ -1274,11 +1272,14 @@ unsigned short Node::set_uid(unsigned short suggested_uid) {
|
||||
suggested_uid = (unsigned short)rand();
|
||||
for (;;) {
|
||||
Node *tp = Fluid.proj.tree.first;
|
||||
for ( ; tp; tp = tp->next)
|
||||
if (tp!=this && tp->uid_==suggested_uid)
|
||||
for ( ; tp; tp = tp->next) {
|
||||
if (tp!=this && tp->uid_==suggested_uid) {
|
||||
break;
|
||||
if (tp==nullptr)
|
||||
}
|
||||
}
|
||||
if (tp==nullptr) {
|
||||
break;
|
||||
}
|
||||
suggested_uid = (unsigned short)rand();
|
||||
}
|
||||
uid_ = suggested_uid;
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ class Project_Writer;
|
||||
Declare where a new type is placed and how to create it.
|
||||
|
||||
Placement can be as the first or last child of the anchor, or right after the
|
||||
anchor. In most cases, the anchor is the last selected type node.
|
||||
anchor. In most cases, the anchor is the last selected node.
|
||||
|
||||
If the source is FROM_USER, widgets may be created with default titles and
|
||||
labels. Type created FROM_FILE will start with no label, so the label is set
|
||||
|
||||
@@ -99,7 +99,7 @@ Node *Tree::find_by_uid(unsigned short uid) {
|
||||
}
|
||||
|
||||
|
||||
/** Find a type node by using the codeview text positions.
|
||||
/** Find a node by using the codeview text positions.
|
||||
|
||||
\param[in] text_type 0=source file, 1=header, 2=.fl project file
|
||||
\param[in] crsr cursor position in text
|
||||
|
||||
@@ -46,6 +46,9 @@
|
||||
#undef max
|
||||
#include <algorithm>
|
||||
|
||||
using namespace fld;
|
||||
using namespace fld::proj;
|
||||
|
||||
// Make an Widget_Node subclass instance.
|
||||
// It figures out the automatic size and parent of the new widget,
|
||||
// creates the Fl_Widget (by calling the virtual function _make),
|
||||
@@ -1468,7 +1471,7 @@ void Widget_Node::write_static(fld::io::Code_Writer& f) {
|
||||
f.write_c(", %s", ut);
|
||||
if (use_v) f.write_c(" v");
|
||||
f.write_c(") {\n");
|
||||
// Matt: disabled f.tag(FD_TAG_GENERIC, 0);
|
||||
f.tag(Mergeback::Tag::GENERIC, Mergeback::Tag::WIDGET_CALLBACK, 0);
|
||||
f.write_c_indented(callback(), 1, 0);
|
||||
if (*(d-1) != ';' && *(d-1) != '}') {
|
||||
const char *p = strrchr(callback(), '\n');
|
||||
@@ -1479,7 +1482,7 @@ void Widget_Node::write_static(fld::io::Code_Writer& f) {
|
||||
if (*p != '#' && *p) f.write_c(";");
|
||||
}
|
||||
f.write_c("\n");
|
||||
// Matt: disabled f.tag(FD_TAG_WIDGET_CALLBACK, get_uid());
|
||||
f.tag(Mergeback::Tag::WIDGET_CALLBACK, Mergeback::Tag::GENERIC, get_uid());
|
||||
f.write_c("}\n");
|
||||
if (k) {
|
||||
f.write_c("void %s::%s(%s* o, %s v) {\n", k, cn, t, ut);
|
||||
|
||||
@@ -1597,7 +1597,7 @@ Node *typename_to_prototype(const char *inName)
|
||||
}
|
||||
|
||||
/**
|
||||
Create and add a new type node to the widget tree.
|
||||
Create and add a new node to the widget tree.
|
||||
|
||||
This is used by the .fl file reader. New types are always created as
|
||||
the last child of the first compatible parent. New widgets have a default
|
||||
@@ -1605,7 +1605,7 @@ Node *typename_to_prototype(const char *inName)
|
||||
|
||||
\param[in] inName a C string that described the type we want
|
||||
\param[in] strategy add after current or as last child
|
||||
\return the type node that was created or nullptr
|
||||
\return the node that was created or nullptr
|
||||
\see add_new_widget_from_file(const char*, int)
|
||||
add_new_widget_from_user(Node*, int)
|
||||
add_new_widget_from_user(const char*, int)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// Setting and shell dialogs for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2023 by Bill Spitzak and others.
|
||||
// Copyright 1998-2025 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
@@ -2666,17 +2666,14 @@ Fl_Double_Window* make_settings_window() {
|
||||
o->labelfont(1);
|
||||
o->labelsize(11);
|
||||
o->align(Fl_Align(FL_ALIGN_LEFT));
|
||||
o->hide();
|
||||
} // Fl_Box* o
|
||||
{ // // Matt: disabled
|
||||
w_proj_mergeback = new Fl_Check_Button(100, 283, 220, 20, "generate MergeBack data");
|
||||
{ w_proj_mergeback = new Fl_Check_Button(100, 283, 220, 20, "generate MergeBack data");
|
||||
w_proj_mergeback->tooltip("MergeBack is a feature under construction that allows changes in code files t"
|
||||
"o be merged back into the project file. Checking this option will generate add"
|
||||
"itional data in code and project files.");
|
||||
w_proj_mergeback->down_box(FL_DOWN_BOX);
|
||||
w_proj_mergeback->labelsize(11);
|
||||
w_proj_mergeback->callback((Fl_Callback*)cb_w_proj_mergeback);
|
||||
w_proj_mergeback->hide();
|
||||
} // Fl_Check_Button* w_proj_mergeback
|
||||
{ Fl_Box* o = new Fl_Box(100, 530, 220, 10);
|
||||
o->hide();
|
||||
|
||||
@@ -34,7 +34,7 @@ snap {
|
||||
comment {//
|
||||
// Setting and shell dialogs for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2023 by Bill Spitzak and others.
|
||||
// Copyright 1998-2025 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
@@ -191,7 +191,7 @@ Function {make_settings_window()} {open
|
||||
} {
|
||||
Fl_Window settings_window {
|
||||
label {FLUID Settings} open
|
||||
xywh {392 362 340 580} type Double align 80 resizable size_range {340 580 0 0} visible
|
||||
xywh {504 366 340 580} type Double align 80 resizable size_range {340 580 0 0} visible
|
||||
} {
|
||||
Fl_Tabs w_settings_tabs {
|
||||
callback {propagate_load(o, v);} open
|
||||
@@ -428,7 +428,7 @@ or just ".ext" to set extension.}
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {Experimental: }
|
||||
xywh {100 283 0 20} labelfont 1 labelsize 11 align 4 hide
|
||||
xywh {100 283 0 20} labelfont 1 labelsize 11 align 4
|
||||
}
|
||||
Fl_Check_Button w_proj_mergeback {
|
||||
label {generate MergeBack data}
|
||||
@@ -440,8 +440,7 @@ or just ".ext" to set extension.}
|
||||
Fluid.proj.write_mergeback_data = o->value();
|
||||
}
|
||||
}}
|
||||
comment {// Matt: disabled}
|
||||
tooltip {MergeBack is a feature under construction that allows changes in code files to be merged back into the project file. Checking this option will generate additional data in code and project files.} xywh {100 283 220 20} down_box DOWN_BOX labelsize 11 hide
|
||||
tooltip {MergeBack is a feature under construction that allows changes in code files to be merged back into the project file. Checking this option will generate additional data in code and project files.} xywh {100 283 220 20} down_box DOWN_BOX labelsize 11
|
||||
}
|
||||
Fl_Box {} {
|
||||
xywh {100 530 220 10} hide resizable
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// Setting and shell dialogs for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2023 by Bill Spitzak and others.
|
||||
// Copyright 1998-2025 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
|
||||
+201
-70
@@ -14,9 +14,6 @@
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
#if 0
|
||||
// Matt: disabled
|
||||
|
||||
#include "proj/mergeback.h"
|
||||
|
||||
#include "Fluid.h"
|
||||
@@ -38,6 +35,9 @@ extern void propagate_load(Fl_Group*, void*);
|
||||
extern void load_panel();
|
||||
extern void redraw_browser();
|
||||
|
||||
using namespace fld;
|
||||
using namespace fld::proj;
|
||||
|
||||
// TODO: add application user setting to control mergeback
|
||||
// [] new projects default to mergeback
|
||||
// [] check mergeback when loading project
|
||||
@@ -76,8 +76,8 @@ extern void redraw_browser();
|
||||
Callers can set different task. FD_MERGEBACK_ANALYSE checks if there are any
|
||||
modifications in the code file and returns -1 if there was an error, or a
|
||||
bit field where bit 0 is set if internal structures were modified, bit 1 if
|
||||
code was changed, and bit 2 if modified blocks were found, but no Type node.
|
||||
Bit 3 is set, if code was changed in the code file *and* the project.
|
||||
code was changed, and bit 2 if modified blocks were found, but no node with the
|
||||
same UID. Bit 3 is set, if code was changed in the code file *and* the project.
|
||||
|
||||
FD_MERGEBACK_INTERACTIVE checks for changes and presents a status dialog box
|
||||
to the user if there were conflicting changes or if a mergeback is possible,
|
||||
@@ -101,9 +101,9 @@ extern void redraw_browser();
|
||||
\return -2 if no code file was found
|
||||
\return see above
|
||||
*/
|
||||
int merge_back(const std::string &s, const std::string &p, int task) {
|
||||
if (Fluid.proj.write_mergeback_data) {
|
||||
Fd_Mergeback mergeback;
|
||||
int merge_back(Project &proj, const std::string &s, const std::string &p, Mergeback::Task task) {
|
||||
if (proj.write_mergeback_data) {
|
||||
Mergeback mergeback(proj);
|
||||
return mergeback.merge_back(s, p, task);
|
||||
} else {
|
||||
// nothing to be done if the mergeback option is disabled in the project
|
||||
@@ -112,7 +112,8 @@ int merge_back(const std::string &s, const std::string &p, int task) {
|
||||
}
|
||||
|
||||
/** Allocate and initialize MergeBack class. */
|
||||
Fd_Mergeback::Fd_Mergeback() :
|
||||
Mergeback::Mergeback(Project &proj)
|
||||
: proj_(proj),
|
||||
code(nullptr),
|
||||
line_no(0),
|
||||
tag_error(0),
|
||||
@@ -124,7 +125,7 @@ Fd_Mergeback::Fd_Mergeback() :
|
||||
}
|
||||
|
||||
/** Release allocated resources. */
|
||||
Fd_Mergeback::~Fd_Mergeback()
|
||||
Mergeback::~Mergeback()
|
||||
{
|
||||
if (code) ::fclose(code);
|
||||
}
|
||||
@@ -132,7 +133,7 @@ Fd_Mergeback::~Fd_Mergeback()
|
||||
/** Remove the first two spaces at every line start.
|
||||
\param[inout] s block of C code
|
||||
*/
|
||||
void Fd_Mergeback::unindent(char *s) {
|
||||
void Mergeback::unindent(char *s) {
|
||||
char *d = s;
|
||||
bool line_start = true;
|
||||
while (*s) {
|
||||
@@ -154,7 +155,7 @@ void Fd_Mergeback::unindent(char *s) {
|
||||
\param[in] end end of text within the file
|
||||
\return a string holding the text that was found in the file
|
||||
*/
|
||||
std::string Fd_Mergeback::read_and_unindent_block(long start, long end) {
|
||||
std::string Mergeback::read_and_unindent_block(long start, long end) {
|
||||
long bsize = end-start;
|
||||
long here = ::ftell(code);
|
||||
::fseek(code, start, SEEK_SET);
|
||||
@@ -178,7 +179,7 @@ std::string Fd_Mergeback::read_and_unindent_block(long start, long end) {
|
||||
\return -1 if the user wants to cancel or an error occurred or an issue was presented
|
||||
(message or choice dialog was shown)
|
||||
*/
|
||||
int Fd_Mergeback::ask_user_to_merge(const std::string &code_filename, const std::string &proj_filename) {
|
||||
int Mergeback::ask_user_to_merge(const std::string &code_filename, const std::string &proj_filename) {
|
||||
if (tag_error) {
|
||||
fl_message("Comparing\n \"%s\"\nto\n \"%s\"\n\n"
|
||||
"MergeBack found an error in line %d while reading tags\n"
|
||||
@@ -192,7 +193,7 @@ int Fd_Mergeback::ask_user_to_merge(const std::string &code_filename, const std:
|
||||
if (num_changed_structure && !num_changed_code) {
|
||||
fl_message("Comparing\n \"%1$s\"\nto\n \"%2$s\"\n\n"
|
||||
"MergeBack found %3$d modifications in the project structure\n"
|
||||
"of the source code. These kind of changes can no be\n"
|
||||
"of the source code. These kind of changes can not be\n"
|
||||
"merged back and will be lost when the source code is\n"
|
||||
"generated again from the open project.",
|
||||
code_filename.c_str(), proj_filename.c_str(), num_changed_structure);
|
||||
@@ -205,14 +206,14 @@ int Fd_Mergeback::ask_user_to_merge(const std::string &code_filename, const std:
|
||||
"changed in the project. Merging will override changes in\n"
|
||||
"the project with changes from the source code file.";
|
||||
if (num_uid_not_found)
|
||||
msg += "\n\nWARNING: for %4$d of these modifications no Type node\n"
|
||||
"can be found and these modification can't be merged back.";
|
||||
msg += "\n\nWARNING: no Node can be found for %4$d of these\n"
|
||||
"modifications and they can not be merged back.";
|
||||
if (!num_possible_override && !num_uid_not_found)
|
||||
msg += "\nMerging these changes back appears to be safe.";
|
||||
|
||||
if (num_changed_structure)
|
||||
msg += "\n\nWARNING: %5$d modifications were found in the project\n"
|
||||
"structure. These kind of changes can no be merged back\n"
|
||||
"structure. These kind of changes can not be merged back\n"
|
||||
"and will be lost when the source code is generated again\n"
|
||||
"from the open project.";
|
||||
|
||||
@@ -238,8 +239,8 @@ int Fd_Mergeback::ask_user_to_merge(const std::string &code_filename, const std:
|
||||
/** Analyse the block and its corresponding widget callback.
|
||||
Return findings in num_changed_code, num_changed_code, and num_uid_not_found.
|
||||
*/
|
||||
void Fd_Mergeback::analyse_callback(unsigned long code_crc, unsigned long tag_crc, int uid) {
|
||||
Node *tp = Node::find_by_uid(uid);
|
||||
void Mergeback::analyse_callback(unsigned long code_crc, unsigned long tag_crc, int uid) {
|
||||
Node *tp = proj_.tree.find_by_uid(uid);
|
||||
if (tp && tp->is_true_widget()) {
|
||||
std::string cb = tp->callback(); cb += "\n";
|
||||
unsigned long project_crc = fld::io::Code_Writer::block_crc(cb.c_str());
|
||||
@@ -260,9 +261,9 @@ void Fd_Mergeback::analyse_callback(unsigned long code_crc, unsigned long tag_cr
|
||||
/** Analyse the block and its corresponding Code Type.
|
||||
Return findings in num_changed_code, num_changed_code, and num_uid_not_found.
|
||||
*/
|
||||
void Fd_Mergeback::analyse_code(unsigned long code_crc, unsigned long tag_crc, int uid) {
|
||||
Node *tp = Node::find_by_uid(uid);
|
||||
if (tp && tp->is_a(ID_Code)) {
|
||||
void Mergeback::analyse_code(unsigned long code_crc, unsigned long tag_crc, int uid) {
|
||||
Node *tp = proj_.tree.find_by_uid(uid);
|
||||
if (tp && tp->is_a(Type::Code)) {
|
||||
std::string code = tp->name(); code += "\n";
|
||||
unsigned long project_crc = fld::io::Code_Writer::block_crc(code.c_str());
|
||||
// check if the code and project crc are the same, so this modification was already applied
|
||||
@@ -279,8 +280,114 @@ void Fd_Mergeback::analyse_code(unsigned long code_crc, unsigned long tag_crc, i
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Decode a 22 bytes string of three distinct characters into a 32 bit integer.
|
||||
\param[in] text at least 22 characters '-', '~', and '='
|
||||
\return the decoded integer
|
||||
*/
|
||||
uint32_t Mergeback::decode_trichar32(const char *text) {
|
||||
uint32_t word = 0;
|
||||
for (int i=30; i>=0; i-=3) {
|
||||
char a = *text++;
|
||||
if (a==0) break;
|
||||
char b = *text++;
|
||||
if (b==0) break;
|
||||
// "--", "-~", "~-", "~~", "-=", "=-", "~=", "=~"
|
||||
uint32_t oct = 0;
|
||||
if (a=='-') {
|
||||
if (b=='~') oct = 1;
|
||||
else if (b=='-') oct = 0;
|
||||
else if (b=='=') oct = 4;
|
||||
} else if (a=='~') {
|
||||
if (b=='~') oct = 3;
|
||||
else if (b=='-') oct = 2;
|
||||
else if (b=='=') oct = 6;
|
||||
} else if (a=='=') {
|
||||
if (b=='~') oct = 7;
|
||||
else if (b=='-') oct = 5;
|
||||
}
|
||||
word |= (oct<<i);
|
||||
}
|
||||
return word;
|
||||
}
|
||||
|
||||
/** Analyse the code file and return findings in class member variables.
|
||||
/**
|
||||
Print a 32 value so it looks like a divider line.
|
||||
\param[in] out Write to this file.
|
||||
\param[in] value 32 bit integer value to encode.
|
||||
*/
|
||||
void Mergeback::print_trichar32(FILE *out, uint32_t value) {
|
||||
static const char *lut[] = { "--", "-~", "~-", "~~", "-=", "=-", "~=", "=~" };
|
||||
for (int i=30; i>=0; i-=3) fputs(lut[(value>>i)&7], out);
|
||||
}
|
||||
|
||||
/**
|
||||
Check if a line contains the special MergeBack tag
|
||||
\param[in] line A line of NUL terminated text.
|
||||
\return a pointer to the character after the tag, or nullptr if not found
|
||||
*/
|
||||
const char *Mergeback::find_mergeback_tag(const char *line) {
|
||||
const char *tag = strstr(line, "//fl ");
|
||||
if (tag) return tag + strlen("//fl ");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
Read all data from a MergeBack tag line.
|
||||
\param[in] tag start of tag string after "//fl " but before "▲" or "▼".
|
||||
\param[out] prev_type Return type information here, see FD_TAG_GENERIC etc.
|
||||
\param[out] uid Unique ID of the node that generated the tag
|
||||
\param[out] crc The CRC32 of the previous block.
|
||||
\return true if the tag could be read
|
||||
*/
|
||||
bool Mergeback::read_tag(const char *tag, Tag *prev_type, uint16_t *uid, uint32_t *crc) {
|
||||
// Tag starts with decoration:
|
||||
if (*tag==' ') tag += 1;
|
||||
if (strncmp(tag, "▲", 3)==0) tag += 3; // E2 96 B2
|
||||
if (*tag=='/') tag += 1;
|
||||
if (strncmp(tag, "▼", 3)==0) tag += 3; // E2 96 BC
|
||||
if (*tag==' ') tag += 1;
|
||||
uint32_t w1 = decode_trichar32(tag); // Read the first word
|
||||
for (int i=0; i<32; i++) if (*tag++ == 0) return false;
|
||||
uint32_t w2 = decode_trichar32(tag); // Read the second word
|
||||
// Return the decoded values
|
||||
*prev_type = static_cast<Tag>((w1>>16) & 0xff);
|
||||
*uid = (w1 & 0xffff);
|
||||
*crc = w2;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Mergeback::print_tag(FILE *out, Tag prev_type, Tag next_type, uint16_t uid, uint32_t crc) {
|
||||
static const char *tag_lut[] = { "----------", "-- code --", " callback ", " callback " };
|
||||
fputs("//fl ", out); // Distinct start of tag using utf8
|
||||
// Indicate that the text above can be edited
|
||||
if (prev_type != Tag::GENERIC) fputs("▲", out);
|
||||
if (prev_type != Tag::GENERIC && next_type != Tag::GENERIC) fputc('/', out);
|
||||
// Indicate that the text below can be edited
|
||||
if (next_type != Tag::GENERIC) fputs("▼", out);
|
||||
fputc(' ', out);
|
||||
// Write the first 32 bit word as an encoded divider line
|
||||
uint32_t pt = static_cast<uint32_t>(prev_type);
|
||||
uint32_t nt = static_cast<uint32_t>(next_type);
|
||||
uint32_t word = (0<<24) | (pt<<16) | (uid); // top 8 bit available for encoding type
|
||||
print_trichar32(out, word);
|
||||
// Write a string indicating the type of editable text
|
||||
if ( next_type != Tag::GENERIC) {
|
||||
fputs(tag_lut[nt], out);
|
||||
} else if (prev_type != Tag::GENERIC) {
|
||||
fputs(tag_lut[nt], out);
|
||||
}
|
||||
// Write the second 32 bit word as an encoded divider line
|
||||
print_trichar32(out, crc);
|
||||
// Repeat the intor pattern
|
||||
fputc(' ', out);
|
||||
if (prev_type != Tag::GENERIC) fputs("▲", out);
|
||||
if (prev_type != Tag::GENERIC && next_type != Tag::GENERIC) fputc('/', out);
|
||||
if (next_type != Tag::GENERIC) fputs("▼", out);
|
||||
fputs(" fl//\n", out);
|
||||
}
|
||||
|
||||
/** Analyze the code file and return findings in class member variables.
|
||||
|
||||
The code file must be open for reading already.
|
||||
|
||||
@@ -297,7 +404,7 @@ void Fd_Mergeback::analyse_code(unsigned long code_crc, unsigned long tag_crc, i
|
||||
|
||||
\return -1 if reading a tag failed, otherwise 0
|
||||
*/
|
||||
int Fd_Mergeback::analyse() {
|
||||
int Mergeback::analyse() {
|
||||
// initialize local variables
|
||||
unsigned long code_crc = 0;
|
||||
bool line_start = true;
|
||||
@@ -318,28 +425,33 @@ int Fd_Mergeback::analyse() {
|
||||
// get the next line until end of file
|
||||
if (fgets(line, 1023, code)==0) break;
|
||||
line_no++;
|
||||
const char *tag = strstr(line, "//~fl~");
|
||||
const char *tag = find_mergeback_tag(line);
|
||||
if (!tag) {
|
||||
// if this line has no tag, add the contents to the CRC and continue
|
||||
code_crc = fld::io::Code_Writer::block_crc(line, -1, code_crc, &line_start);
|
||||
} else {
|
||||
// if this line has a tag, read all tag data
|
||||
int tag_type = -1, uid = 0;
|
||||
unsigned long tag_crc = 0;
|
||||
int n = sscanf(tag, "//~fl~%d~%04x~%08lx~~", &tag_type, &uid, &tag_crc);
|
||||
if (n!=3 || tag_type<0 || tag_type>FD_TAG_LAST ) { tag_error = 1; return -1; }
|
||||
Tag tag_type = Tag::UNUSED_;
|
||||
uint16_t uid = 0;
|
||||
uint32_t tag_crc = 0;
|
||||
bool tag_ok = read_tag(tag, &tag_type, &uid, &tag_crc);
|
||||
if (!tag_ok || tag_type==Tag::UNUSED_ ) {
|
||||
tag_error = 1;
|
||||
return -1;
|
||||
}
|
||||
if (code_crc != tag_crc) {
|
||||
switch (tag_type) {
|
||||
case FD_TAG_GENERIC:
|
||||
case Tag::GENERIC:
|
||||
num_changed_structure++;
|
||||
break;
|
||||
case FD_TAG_MENU_CALLBACK:
|
||||
case FD_TAG_WIDGET_CALLBACK:
|
||||
case Tag::MENU_CALLBACK:
|
||||
case Tag::WIDGET_CALLBACK:
|
||||
analyse_callback(code_crc, tag_crc, uid);
|
||||
break;
|
||||
case FD_TAG_CODE:
|
||||
case Tag::CODE:
|
||||
analyse_code(code_crc, tag_crc, uid);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
// reset everything for the next block
|
||||
@@ -353,8 +465,8 @@ int Fd_Mergeback::analyse() {
|
||||
/** Apply callback mergebacks from the code file to the project.
|
||||
\return 1 if the project changed
|
||||
*/
|
||||
int Fd_Mergeback::apply_callback(long block_end, long block_start, unsigned long code_crc, int uid) {
|
||||
Node *tp = Node::find_by_uid(uid);
|
||||
int Mergeback::apply_callback(long block_end, long block_start, unsigned long code_crc, int uid) {
|
||||
Node *tp = proj_.tree.find_by_uid(uid);
|
||||
if (tp && tp->is_true_widget()) {
|
||||
std::string cb = tp->callback(); cb += "\n";
|
||||
unsigned long project_crc = fld::io::Code_Writer::block_crc(cb.c_str());
|
||||
@@ -369,9 +481,9 @@ int Fd_Mergeback::apply_callback(long block_end, long block_start, unsigned long
|
||||
/** Apply callback mergebacks from the code file to the project.
|
||||
\return 1 if the project changed
|
||||
*/
|
||||
int Fd_Mergeback::apply_code(long block_end, long block_start, unsigned long code_crc, int uid) {
|
||||
Node *tp = Node::find_by_uid(uid);
|
||||
if (tp && tp->is_a(ID_Code)) {
|
||||
int Mergeback::apply_code(long block_end, long block_start, unsigned long code_crc, int uid) {
|
||||
Node *tp = proj_.tree.find_by_uid(uid);
|
||||
if (tp && tp->is_a(Type::Code)) {
|
||||
std::string cb = tp->name(); cb += "\n";
|
||||
unsigned long project_crc = fld::io::Code_Writer::block_crc(cb.c_str());
|
||||
if (project_crc!=code_crc) {
|
||||
@@ -386,7 +498,7 @@ int Fd_Mergeback::apply_code(long block_end, long block_start, unsigned long cod
|
||||
The code file must be open for reading already.
|
||||
\return -1 if reading a tag failed, 0 if nothing changed, 1 if the project changed
|
||||
*/
|
||||
int Fd_Mergeback::apply() {
|
||||
int Mergeback::apply() {
|
||||
// initialize local variables
|
||||
unsigned long code_crc = 0;
|
||||
bool line_start = true;
|
||||
@@ -406,21 +518,25 @@ int Fd_Mergeback::apply() {
|
||||
// get the next line until end of file
|
||||
if (fgets(line, 1023, code)==0) break;
|
||||
line_no++;
|
||||
const char *tag = strstr(line, "//~fl~");
|
||||
const char *tag = find_mergeback_tag(line);
|
||||
if (!tag) {
|
||||
// if this line has no tag, add the contents to the CRC and continue
|
||||
code_crc = fld::io::Code_Writer::block_crc(line, -1, code_crc, &line_start);
|
||||
block_end = ::ftell(code);
|
||||
} else {
|
||||
// if this line has a tag, read all tag data
|
||||
int tag_type = -1, uid = 0;
|
||||
unsigned long tag_crc = 0;
|
||||
int n = sscanf(tag, "//~fl~%d~%04x~%08lx~~", &tag_type, &uid, &tag_crc);
|
||||
if (n!=3 || tag_type<0 || tag_type>FD_TAG_LAST ) { tag_error = 1; return -1; }
|
||||
Tag tag_type = Tag::UNUSED_;
|
||||
uint16_t uid = 0;
|
||||
uint32_t tag_crc = 0;
|
||||
bool tag_ok = read_tag(tag, &tag_type, &uid, &tag_crc);
|
||||
if (!tag_ok || tag_type==Tag::UNUSED_ ) {
|
||||
tag_error = 1;
|
||||
return -1;
|
||||
}
|
||||
if (code_crc != tag_crc) {
|
||||
if (tag_type==FD_TAG_MENU_CALLBACK || tag_type==FD_TAG_WIDGET_CALLBACK) {
|
||||
if (tag_type==Tag::MENU_CALLBACK || tag_type==Tag::WIDGET_CALLBACK) {
|
||||
changed |= apply_callback(block_end, block_start, code_crc, uid);
|
||||
} else if (tag_type==FD_TAG_CODE) {
|
||||
} else if (tag_type==Tag::CODE) {
|
||||
changed |= apply_code(block_end, block_start, code_crc, uid);
|
||||
}
|
||||
}
|
||||
@@ -441,12 +557,12 @@ int Fd_Mergeback::apply() {
|
||||
\return -2 if no code file was found
|
||||
\return See more at ::merge_back(const std::string &s, int task).
|
||||
*/
|
||||
int Fd_Mergeback::merge_back(const std::string &s, const std::string &p, int task) {
|
||||
int Mergeback::merge_back(const std::string &s, const std::string &p, Task task) {
|
||||
int ret = 0;
|
||||
code = fl_fopen(s.c_str(), "rb");
|
||||
if (!code) return -2;
|
||||
do { // no actual loop, just make sure we close the code file
|
||||
if (task == FD_MERGEBACK_ANALYSE) {
|
||||
if (task == Task::ANALYSE) {
|
||||
analyse();
|
||||
if (tag_error) {ret = -1; break; }
|
||||
if (num_changed_structure) ret |= 1;
|
||||
@@ -455,14 +571,14 @@ int Fd_Mergeback::merge_back(const std::string &s, const std::string &p, int tas
|
||||
if (num_possible_override) ret |= 8;
|
||||
break;
|
||||
}
|
||||
if (task == FD_MERGEBACK_INTERACTIVE) {
|
||||
if (task == Task::INTERACTIVE) {
|
||||
analyse();
|
||||
ret = ask_user_to_merge(s, p);
|
||||
if (ret != 1)
|
||||
return ret;
|
||||
task = FD_MERGEBACK_APPLY; // fall through
|
||||
task = Task::APPLY; // fall through
|
||||
}
|
||||
if (task == FD_MERGEBACK_APPLY_IF_SAFE) {
|
||||
if (task == Task::APPLY_IF_SAFE) {
|
||||
analyse();
|
||||
if (tag_error || num_changed_structure || num_possible_override) {
|
||||
ret = -1;
|
||||
@@ -472,12 +588,12 @@ int Fd_Mergeback::merge_back(const std::string &s, const std::string &p, int tas
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
task = FD_MERGEBACK_APPLY; // fall through
|
||||
task = Task::APPLY; // fall through
|
||||
}
|
||||
if (task == FD_MERGEBACK_APPLY) {
|
||||
if (task == Task::APPLY) {
|
||||
ret = apply();
|
||||
if (ret == 1) {
|
||||
Fluid.proj.set_modflag(1);
|
||||
proj_.set_modflag(1);
|
||||
redraw_browser();
|
||||
load_panel();
|
||||
}
|
||||
@@ -489,37 +605,55 @@ int Fd_Mergeback::merge_back(const std::string &s, const std::string &p, int tas
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Matt: disabled
|
||||
/**
|
||||
Merge the possibly modified content of code files back into the project.
|
||||
\brief Merges back code files with the project file.
|
||||
|
||||
This function flushes text widgets, checks if the project filename and
|
||||
mergeback data are available, and then attempts to merge back the code
|
||||
files with the project file. If MergeBack is not enabled, it displays
|
||||
a message to the user. It handles both batch and interactive modes.
|
||||
|
||||
\return int - Returns 1 if the project filename is not available,
|
||||
0 if MergeBack is not enabled,
|
||||
or the result of the merge_back function.
|
||||
*/
|
||||
int mergeback_code_files()
|
||||
int mergeback_code_files(Project &proj)
|
||||
{
|
||||
flush_text_widgets();
|
||||
if (!filename) return 1;
|
||||
if (!Fluid.proj.write_mergeback_data) {
|
||||
Fluid.flush_text_widgets();
|
||||
if (!proj.proj_filename) return 1;
|
||||
if (!proj.write_mergeback_data) {
|
||||
fl_message("MergeBack is not enabled for this project.\n"
|
||||
"Please enable MergeBack in the project settings\n"
|
||||
"dialog and re-save the project file and the code.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string proj_filename = Fluid.proj.projectfile_path() + Fluid.proj.projectfile_name();
|
||||
std::string proj_filename = proj.projectfile_path() + proj.projectfile_name();
|
||||
std::string code_filename;
|
||||
#if 1
|
||||
if (!Fluid.batch_mode) {
|
||||
// Depending on the workflow in interactive mode, an external copy of
|
||||
// Fluid may have written the source code elswhere (e.g. in a CMake setup).
|
||||
// Fluid tries to keep track of the last write location of a source file
|
||||
// matching a project, and uses that location instead.
|
||||
// TODO: this is not working as expected yet.
|
||||
Fl_Preferences build_records(Fl_Preferences::USER_L, "fltk.org", "fluid-build");
|
||||
Fl_Preferences path(build_records, proj_filename.c_str());
|
||||
int i, n = proj_filename.size();
|
||||
int i, n = (int)proj_filename.size();
|
||||
for (i=0; i<n; i++) if (proj_filename[i]=='\\') proj_filename[i] = '/';
|
||||
preferences_get(path, "code", code_filename, "");
|
||||
path.get("code", code_filename, "");
|
||||
}
|
||||
#endif
|
||||
if (code_filename.empty())
|
||||
code_filename = Fluid.proj.codefile_path() + Fluid.proj.codefile_name();
|
||||
code_filename = proj.codefile_path() + proj.codefile_name();
|
||||
if (!Fluid.batch_mode) proj.enter_project_dir();
|
||||
int c = merge_back(code_filename, proj_filename, FD_MERGEBACK_INTERACTIVE);
|
||||
int c = merge_back(proj, code_filename, proj_filename, Mergeback::Task::INTERACTIVE);
|
||||
if (c>0) {
|
||||
// update the project to reflect the changes
|
||||
proj.set_modflag(1);
|
||||
redraw_browser();
|
||||
load_panel();
|
||||
}
|
||||
if (!Fluid.batch_mode) proj.leave_project_dir();
|
||||
|
||||
if (c==0) fl_message("Comparing\n \"%s\"\nto\n \"%s\"\n\n"
|
||||
@@ -531,9 +665,6 @@ int mergeback_code_files()
|
||||
}
|
||||
|
||||
void mergeback_cb(Fl_Widget *, void *) {
|
||||
mergeback_code_files();
|
||||
mergeback_code_files(Fluid.proj);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+31
-20
@@ -14,34 +14,37 @@
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
// Matt: disabled
|
||||
#if 0
|
||||
|
||||
#ifndef _FLUID_MERGEBACK_H
|
||||
#define _FLUID_MERGEBACK_H
|
||||
#ifndef FLUID_PROJ_MERGEBACK_H
|
||||
#define FLUID_PROJ_MERGEBACK_H
|
||||
|
||||
#include <FL/fl_attr.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
const int FD_TAG_GENERIC = 0;
|
||||
const int FD_TAG_CODE = 1;
|
||||
const int FD_TAG_MENU_CALLBACK = 2;
|
||||
const int FD_TAG_WIDGET_CALLBACK = 3;
|
||||
const int FD_TAG_LAST = 3;
|
||||
namespace fld {
|
||||
|
||||
class Project;
|
||||
|
||||
namespace proj {
|
||||
|
||||
const int FD_MERGEBACK_ANALYSE = 0;
|
||||
const int FD_MERGEBACK_INTERACTIVE = 1;
|
||||
const int FD_MERGEBACK_APPLY = 2;
|
||||
const int FD_MERGEBACK_APPLY_IF_SAFE = 3;
|
||||
|
||||
/** Class that implements the MergeBack functionality.
|
||||
\see merge_back(const std::string &s, int task)
|
||||
*/
|
||||
class Fd_Mergeback
|
||||
class Mergeback
|
||||
{
|
||||
public:
|
||||
enum class Tag {
|
||||
GENERIC = 0, CODE, MENU_CALLBACK, WIDGET_CALLBACK, UNUSED_
|
||||
};
|
||||
enum class Task {
|
||||
ANALYSE = 0, INTERACTIVE, APPLY, APPLY_IF_SAFE = 3
|
||||
};
|
||||
protected:
|
||||
/// Apply mergeback for this project.
|
||||
Project &proj_;
|
||||
/// Pointer to the C++ code file.
|
||||
FILE *code;
|
||||
/// Current line number in the C++ code file.
|
||||
@@ -64,18 +67,26 @@ protected:
|
||||
int apply_callback(long block_end, long block_start, unsigned long code_crc, int uid);
|
||||
int apply_code(long block_end, long block_start, unsigned long code_crc, int uid);
|
||||
|
||||
static uint32_t decode_trichar32(const char *text);
|
||||
static void print_trichar32(FILE *out, uint32_t value);
|
||||
|
||||
static const char *find_mergeback_tag(const char *line);
|
||||
static bool read_tag(const char *tag, Tag *prev_type, uint16_t *uid, uint32_t *crc);
|
||||
|
||||
public:
|
||||
Fd_Mergeback();
|
||||
~Fd_Mergeback();
|
||||
int merge_back(const std::string &s, const std::string &p, int task);
|
||||
Mergeback(Project &proj);
|
||||
~Mergeback();
|
||||
int merge_back(const std::string &s, const std::string &p, Task task);
|
||||
int ask_user_to_merge(const std::string &s, const std::string &p);
|
||||
int analyse();
|
||||
int apply();
|
||||
static void print_tag(FILE *out, Tag prev_type, Tag next_type, uint16_t uid, uint32_t crc);
|
||||
};
|
||||
|
||||
extern int merge_back(const std::string &s, const std::string &p, int task);
|
||||
|
||||
} // namespace proj
|
||||
} // namespace fld
|
||||
|
||||
#endif // _FLUID_MERGEBACK_H
|
||||
#endif // FLUID_PROJ_MERGEBACK_H
|
||||
|
||||
#endif
|
||||
|
||||
+2
-2
@@ -187,7 +187,7 @@ Fl_Input::paste_menu_text = gettext("Paste");} {}
|
||||
xywh {0 0 100 20}
|
||||
}
|
||||
MenuItem {} {
|
||||
label {flip flops} selected
|
||||
label {flip flops}
|
||||
xywh {0 0 100 20}
|
||||
}
|
||||
MenuItem {} {
|
||||
@@ -203,7 +203,7 @@ Fl_Input::paste_menu_text = gettext("Paste");} {}
|
||||
xywh {35 112 100 24} type Radio down_box ROUND_DOWN_BOX
|
||||
}
|
||||
Fl_Round_Button wRight {
|
||||
label {right side}
|
||||
label {right side} selected
|
||||
xywh {35 136 100 24} type Radio down_box ROUND_DOWN_BOX
|
||||
}
|
||||
Fl_Box {} {
|
||||
|
||||
Reference in New Issue
Block a user