* recursively note_insert the children of an inserted element.
* recursively note_delete
* make mergers clone contexts before modifying them.
* make mergers indicate strategy in merge context.
*/
#include <stdlib.h>
+#include <string.h>
#include "debug.h"
#include "config.h"
#include "gl_list.h"
#include <stdbool.h>
#include "minmax.h"
+#include "print.h"
#include "doc_elt.h"
#include "doc_ref.h"
void
doc_reflist_print (gl_list_t reflist, void *context, doc_stream *out)
{
- /**
- * @todo make the print ctxt pass around correctly
+ /*
+ * copy the mave context to allow nested movement conflicts
*/
+ print_ctxt * print_ctxt = context;
+
+ conflict_state parent_move_state = print_ctxt_get_movement_state (print_ctxt);
+ print_ctxt_set_movement_state (print_ctxt, no_conflict);
+
+ size_t parent_level = print_ctxt->current_level;
+
debug_msg (DOC, 5, "Printing element list\n");
gl_list_iterator_t i;
i = gl_list_iterator (reflist);
{
debug_msg (DOC, 4, "Printing element\n");
elt = doc_ref_get_elt (ref);
+ print_ctxt->current_level = parent_level;
doc_elt_print (ref, context, out);
+ enter_movement_conflict (print_ctxt, no_conflict, "Moved\n", out);
}
+
+ print_ctxt_set_movement_state (print_ctxt, parent_move_state);
+
debug_msg (DOC, 5, "Finished printing element\n");
gl_list_iterator_free (&i);
return;
}
+void
+doc_reflist_note_insert (gl_list_t reflist, merge_ctxt *ctxt)
+{
+ debug_msg (DOC, 5, "Inserting element list\n");
+ gl_list_iterator_t i;
+ i = gl_list_iterator (reflist);
+ doc_ref *ref;
+ doc_elt *elt;
+
+ while (gl_list_iterator_next (&i, (const void **) &ref, NULL))
+ {
+ elt = doc_ref_get_elt (ref);
+ doc_elt_note_insert (ref, ctxt);
+ }
+ gl_list_iterator_free (&i);
+ return;
+}
+
+void
+doc_reflist_note_delete(gl_list_t reflist, merge_ctxt *ctxt)
+{
+ debug_msg (DOC, 5, "Deleting element list\n");
+ gl_list_iterator_t i;
+ i = gl_list_iterator (reflist);
+ doc_ref *ref;
+ doc_elt *elt;
+
+ while (gl_list_iterator_next (&i, (const void **) &ref, NULL))
+ {
+ elt = doc_ref_get_elt (ref);
+ doc_elt_note_delete (ref, ctxt);
+ }
+ gl_list_iterator_free (&i);
+ return;
+}
+
struct context;
typedef enum mapped_state
}
void
-doc_reflist_merge (doc_ref *parent, gl_list_t ancestor, gl_list_t descendant, merge_ctxt *merge_ctxt)
+doc_reflist_merge (doc_ref *parent, gl_list_t ancestor, gl_list_t descendant, merge_ctxt *m_ctxt)
{
+
+ /* Clone the merge context */
+ merge_ctxt new_m_ctxt = *m_ctxt;
+ // memcpy (&new_m_ctxt, m_ctxt, sizeof (merge_ctxt));
+ new_m_ctxt.strategy = LOCAL_LIST_MERGE;
+
/* First, create a mapped_state for every element that will be mapped.
* Compare the two strigs marking mapped and unmapped nodes. Then,
* merge the two lists, combining mapped elements ino a sigle element.
ctxt.a_state = a_state;
ctxt.ancestor = ancestor;
ctxt.descendant = descendant;
- ctxt.merge_ctxt = merge_ctxt;
+ ctxt.merge_ctxt = &new_m_ctxt;
/* Allocate data for the algorithm to use*/
size_t diags = a_size + d_size + 3;
//doc_ref_check_for_circular_conflict (d_ref);
//mark_insert_children ();
- doc_elt_note_insert (d_ref, merge_ctxt);
+ doc_elt_note_insert (d_ref, &new_m_ctxt);
a_index++;
a_size++;
doc_ref * a_ref = (doc_ref *) gl_list_get_at (ancestor, a_index);
// mark_remove_children (m_child, src);
- doc_elt_note_delete (a_ref, merge_ctxt);
+ doc_elt_note_delete (a_ref, &new_m_ctxt);
a_index++;
}
else if ((a_index != a_size) && (d_index != d_size))
doc_ref_add_src (a_ref, doc_ref_get_src (d_ref));
/* get the element to merge the content and children */
- doc_elt_merge (a_ref, d_ref, merge_ctxt);
+ doc_elt_merge (a_ref, d_ref, &new_m_ctxt);
/* make the doc_refs point to the same element */
- //doc_ref_set_elt (d_ref, doc_ref_get_elt (a_ref) );
+ doc_ref_set_elt (d_ref, doc_ref_get_elt (a_ref) );
//doc_ref_set_parent (d_ref, doc_ref_get_parent (a_ref));
- //printf ("merging docrefs, par=%d, ref=%d\n", doc_ref_get_elt (a_ref), doc_ref_get_elt (d_ref));
+
a_index++;
d_index++;
}
#include <stdlib.h>
#include "gl_list.h"
#include "doc_stream.h"
-//#include "doc_elt.h"
-/* #include "doc_elt.h" */
struct doc_elt;
typedef struct doc_elt doc_elt;
typedef struct merge_ctxt merge_ctxt;
static inline bool doc_ref_isexactly (doc_ref *ref, doc_src src);
static inline bool doc_ref_contains (doc_ref *ref, doc_src src);
static inline doc_ref *doc_ref_get_parent (doc_ref *ref);
-static inline void doc_ref_set_paraent (doc_ref *ref, doc_ref* parent);
+static inline void doc_ref_set_parent (doc_ref *ref, doc_ref* parent);
+
+void doc_reflist_note_insert (gl_list_t reflist, merge_ctxt *ctxt);
+void doc_reflist_note_delete (gl_list_t reflist, merge_ctxt *ctxt);
/* circular conflict */
static inline bool doc_ref_is_circular_conflict (doc_ref *ref);
void
merge_ctxt_init (merge_ctxt *ctxt)
{
+ ctxt->strategy = NO_STRATEGY;
ctxt->global_smerger = NULL;
ctxt->priorities = NULL;
return;
#ifndef MERGE_CTXT_H
#define MERGE_CTXT_H
+typedef enum merge_strategy {
+ NO_STRATEGY,
+ GLOBAL_SEARCH_MERGE,
+ LOCAL_LIST_MERGE,
+ LOCAL_SEARCH_MERGE
+} merge_strategy;
+
struct gl_list_impl;
typedef struct gl_list_impl * gl_list_t;
{
smerger *global_smerger;
gl_list_t priorities;
+ merge_strategy strategy;
} merge_ctxt;
/**
static const char *middle_mark = "======= ";
static const char *end_mark = "<<<<<<< ";
+/*
+ * Print the conflict markers
+ */
+static void
+print_conflict_markers (conflict_state *current_state, conflict_state state,
+ char* msg, doc_stream *out);
+
+
void
enter_structural_conflict (print_ctxt *ctxt, conflict_state state,
char* msg, doc_stream *out)
if ( ctxt->structure_conflict != state )
{
- enter_content_conflict (ctxt, no_conflict, NULL, out);
+ enter_movement_conflict (ctxt, no_conflict, NULL, out);
}
else
return;
if (state != no_conflict)
ctxt->conflict_occurred = true;
- while (ctxt->structure_conflict != state )
- {
- /*conflict wrap up */
- switch (ctxt->structure_conflict)
- {
- case no_conflict:
- doc_stream_puts (start_mark, out);
- break;
- case local_side:
- doc_stream_puts (middle_mark, out);
- break;
- case remote_side:
- doc_stream_puts (end_mark, out);
- break;
- }
- ctxt->structure_conflict ++;
-
- if (ctxt->structure_conflict == 3)
- ctxt->structure_conflict = 0;
+ print_conflict_markers (&ctxt->structure_conflict, state, msg, out);
- if (ctxt->structure_conflict != state)
- doc_stream_putc ('\n', out);
- }
+ return;
+}
- if (msg != NULL)
+void
+enter_movement_conflict (print_ctxt *ctxt, conflict_state state,
+ char* msg, doc_stream *out)
+{
+ /* wrap up the conflicts, print a message on the last conflict
+ * marker, if there is one */
+ if ( ctxt->movement_conflict != state )
{
- doc_stream_puts (msg, out);
+ enter_content_conflict (ctxt, no_conflict, NULL, out);
}
else
- {
- doc_stream_putc ('\n', out);
- }
+ return;
+
+ if (state != no_conflict)
+ ctxt->conflict_occurred = true;
+
+ print_conflict_markers (&ctxt->movement_conflict, state, msg, out);
return;
}
if (state != no_conflict)
ctxt->conflict_occurred = true;
- while ( ctxt->content_conflict != state )
+ print_conflict_markers (&ctxt->content_conflict, state, msg, out);
+
+ return;
+}
+
+static void
+print_conflict_markers (conflict_state *current_state, conflict_state state,
+ char* msg, doc_stream *out)
+{
+
+ while (*current_state != state )
{
/*conflict wrap up */
- switch (ctxt->content_conflict)
+ switch (*current_state)
{
case no_conflict:
doc_stream_puts (start_mark, out);
doc_stream_puts (end_mark, out);
break;
}
- ctxt->content_conflict ++;
+ (*current_state) ++;
- if (ctxt->content_conflict == 3)
- ctxt->content_conflict = 0;
+ if (*current_state == 3)
+ *current_state = 0;
- if (ctxt->content_conflict != state)
+ if (*current_state != state)
doc_stream_putc ('\n', out);
-
}
if (msg != NULL)
{
doc_stream_putc ('\n', out);
}
-
return;
}
-
#define PRINT_H
#include "doc_stream.h"
-struct print_ctxt;
-typedef struct print_ctxt print_ctxt;
+#include "print_ctxt.h"
/**
* @todo Find a way to deal with advancing the print mode with the
*/
/**
- * @brief A context for the current printing mode.
- *
- * It acts as a request to print only certain information. It does
- * not imply what side of a conflict we are printing.
- */
-typedef enum print_state
- {
- print_merged,
- print_remote,
- print_local,
- print_ancestor
- } print_state;
-
-/**
- * @brief The current state of conflict markers.
- */
-typedef enum conflict_state
- {
- no_conflict = 0,
- local_side = 1,
- remote_side = 2
- } conflict_state;
-
-/**
* @brief enter a certain part of a structural conflict.
*
* This function enters a structural conflict. If it is already in
- * the correct state, it will do nothing. It will wrap up any content
+ * the correct state, it will do nothing. It will wrap up any movement
* conflicts before switching
*/
void enter_structural_conflict (print_ctxt *ctxt, conflict_state state,
char* msg, doc_stream *out);
/**
+ * @brief enter a certain part of a movement conflict.
+ *
+ * This function enters a structural conflict. If it is already in the
+ * correct state, it will do nothing. It will wrap up any content
+ * conflicts before switching. Movement Conflicts are assumed to be
+ * nestable between parents and children. It is up to the parent to
+ * ensure that the print ctxt is set up for this.
+ */
+void enter_movement_conflict (print_ctxt *ctxt, conflict_state state,
+ char* msg, doc_stream *out);
+
+/**
* @brief enter a certain part of a content conflict.
*
* This function enters a content conflict. If it is already in the
void enter_content_conflict (print_ctxt *ctxt, conflict_state state,
char* msg, doc_stream *out);
+static inline conflict_state print_ctxt_get_content_state (print_ctxt *ctxt);
+
+static inline conflict_state print_ctxt_get_structure_state (print_ctxt *ctxt);
+
+static inline conflict_state print_ctxt_get_movement_state (print_ctxt *ctxt);
+static inline void print_ctxt_set_movement_state (print_ctxt *ctxt, conflict_state state);
+
+/*
+ * Implementation
+ */
+
+static inline conflict_state
+print_ctxt_get_content_state (print_ctxt *ctxt)
+{
+ return ctxt->structure_conflict;
+}
+
+static inline conflict_state
+print_ctxt_get_structure_state (print_ctxt *ctxt)
+{
+ return ctxt->content_conflict;
+}
+
+static inline conflict_state
+print_ctxt_get_movement_state (print_ctxt *ctxt)
+{
+ return ctxt->movement_conflict;
+}
+
+static inline void
+print_ctxt_set_movement_state (print_ctxt *ctxt, conflict_state state)
+{
+ ctxt->movement_conflict = state;
+}
+
#endif /* PRINT_H */
print_ctxt_init (print_ctxt *ctxt)
{
ctxt->depth = 0;
+ ctxt->current_level = 0;
ctxt->rmargin = 0;
ctxt->tab_width = 0;
ctxt->use_tabs = 0;
ctxt->nested_conflicts = no_conflict;
ctxt->structure_conflict = no_conflict;
ctxt->content_conflict = no_conflict;
+ ctxt->movement_conflict = no_conflict;
ctxt->conflict_occurred = false;
return;
}
#ifndef PRINT_CTXT_H
#define PRINT_CTXT_H
-#include "print.h"
+//#include "print.h"
#include "stdbool.h"
/**
+ * @brief A context for the current printing mode.
+ *
+ * It acts as a request to print only certain information. It does
+ * not imply what side of a conflict we are printing.
+ */
+typedef enum print_state
+ {
+ print_merged,
+ print_remote,
+ print_local,
+ print_ancestor
+ } print_state;
+
+/**
+ * @brief The current state of conflict markers.
+ */
+typedef enum conflict_state
+ {
+ no_conflict = 0,
+ local_side = 1,
+ remote_side = 2
+ } conflict_state;
+
+/**
* @brief A context for printing doc_elt's in a tree.
*/
typedef struct print_ctxt
{
int depth; /*< The current depth in a document tree */
+ size_t current_level; /*< the current level of a document */
size_t rmargin; /*< The column of the doc's right margin */
size_t tab_width; /*< The column width of a tab character */
bool use_tabs; /*< Should generated output use tabs? */
bool nested_conflicts; /*< if there are nested conflicts */
conflict_state structure_conflict; /*< the current state of conflicts */
conflict_state content_conflict; /*< the current state of conflicts */
- bool conflict_occurred; /* IF a conflict occured */
+ conflict_state movement_conflict; /*< the current state of conflict */
+ bool conflict_occurred; /*< IF a conflict occured */
} print_ctxt;
/**
+#include <string.h>
+
#include "config.h"
#include "gl_rbtree_list.h"
#include "gl_list.h"
smerger_match_remove (gl_list_t list, doc_ref *ref, merge_ctxt *ctxt)
{
debug_msg (SMERGER, 5, "Begin\n");
- /*
- if (SMERGER_PRINTLEVEL > 3)
- {
- debug_msg (SMERGER, 3, "Matching heading ='");
- doc_elt_print (ref, NULL, stdout);
- debug_msg (SMERGER, 3, "'\n");
- }
- */
+
doc_ref *match = NULL;
gl_list_node_t listnode = NULL;
int last_pos = 0;
* element.
*/
static inline int
-smerger_merge (doc_ref *ancestor, doc_ref *descendant, merge_ctxt *ctxt)
+smerger_merge (doc_ref *ancestor, doc_ref *descendant, merge_ctxt *old_ctxt)
{
debug_msg (SMERGER, 5, "Begin\n");
int status = 0;
doc_elt *anc_elt = doc_ref_get_elt (ancestor);
- /* check for a circular conflict */
- //doc_ref_set_elt (descendant, anc_elt);
- //doc_ref_set_parent (descendant, ancestor->parent);
- //doc_ref_check_for_circular_conflict (descendant);
- // doc_ref_set_parent (ancestor,descendant->parent);
+ /* Clone the context */
+ merge_ctxt new_ctxt = *old_ctxt;
+ //memcpy (&new_ctxt, ctxt, sizeof (merge_ctxt));
- doc_elt_merge (ancestor, descendant, ctxt);
+ /* Modify the strategy to indicate */
+ new_ctxt.strategy = GLOBAL_SEARCH_MERGE;
- //if (doc_elt_get_type (anc_elt) == ORG_HEADING)
- //if (doc_ref_contains (descendant, LOC_SRC))
- //{
- //org_heading_set_doc_ref ((org_heading *)anc_elt, descendant);
- //}
+ doc_elt_merge (ancestor, descendant, &new_ctxt);
+ doc_ref_set_elt (descendant, anc_elt);
debug_msg (SMERGER, 5, "Return =%d\n", status);
return status;