Commit cf1c7da3 authored by Morten Welinder's avatar Morten Welinder

Large leak hunt.

parent f874ead9
1999-06-15 Morten Welinder <terra@diku.dk>
* src/style.c (style_font_new_simple): Plug leak.
* src/cell.c (cell_set_formula_tree_simple): Ref before unref,
just in case.
* src/fn-math.c (callback_function_criteria): Just collect the
values, not (incorrectly) allocated pointers to them.
(gnumeric_countif): Release the values. (Leak fix.)
(gnumeric_sumif): Ditto.
(gnumeric_countif): Plug leak.
(gnumeric_sumif): Ditto.
(gnumeric_seriessum): Plug three leaks.
(gnumeric_subtotal): Plug leaks and fix error handling.
* src/style.c (style_font_new_simple): Fix memory access problem.
* src/style.c (font_init): Rework. (Work in progress. Things
......
1999-06-15 Morten Welinder <terra@diku.dk>
* src/style.c (style_font_new_simple): Plug leak.
* src/cell.c (cell_set_formula_tree_simple): Ref before unref,
just in case.
* src/fn-math.c (callback_function_criteria): Just collect the
values, not (incorrectly) allocated pointers to them.
(gnumeric_countif): Release the values. (Leak fix.)
(gnumeric_sumif): Ditto.
(gnumeric_countif): Plug leak.
(gnumeric_sumif): Ditto.
(gnumeric_seriessum): Plug three leaks.
(gnumeric_subtotal): Plug leaks and fix error handling.
* src/style.c (style_font_new_simple): Fix memory access problem.
* src/style.c (font_init): Rework. (Work in progress. Things
......
1999-06-15 Morten Welinder <terra@diku.dk>
* src/style.c (style_font_new_simple): Plug leak.
* src/cell.c (cell_set_formula_tree_simple): Ref before unref,
just in case.
* src/fn-math.c (callback_function_criteria): Just collect the
values, not (incorrectly) allocated pointers to them.
(gnumeric_countif): Release the values. (Leak fix.)
(gnumeric_sumif): Ditto.
(gnumeric_countif): Plug leak.
(gnumeric_sumif): Ditto.
(gnumeric_seriessum): Plug three leaks.
(gnumeric_subtotal): Plug leaks and fix error handling.
* src/style.c (style_font_new_simple): Fix memory access problem.
* src/style.c (font_init): Rework. (Work in progress. Things
......
1999-06-15 Morten Welinder <terra@diku.dk>
* src/style.c (style_font_new_simple): Plug leak.
* src/cell.c (cell_set_formula_tree_simple): Ref before unref,
just in case.
* src/fn-math.c (callback_function_criteria): Just collect the
values, not (incorrectly) allocated pointers to them.
(gnumeric_countif): Release the values. (Leak fix.)
(gnumeric_sumif): Ditto.
(gnumeric_countif): Plug leak.
(gnumeric_sumif): Ditto.
(gnumeric_seriessum): Plug three leaks.
(gnumeric_subtotal): Plug leaks and fix error handling.
* src/style.c (style_font_new_simple): Fix memory access problem.
* src/style.c (font_init): Rework. (Work in progress. Things
......
1999-06-15 Morten Welinder <terra@diku.dk>
* ms-formula-read.c (ms_excel_parse_formula): Handle bools. Plug
leak.
(make_function): Plug leak.
* ms-excel-read.c (biff_font_data_get_style_font): Supply correct
size when initialising.
(biff_nasty_font_check_function): Revert last change. Extra
......
1999-06-15 Morten Welinder <terra@diku.dk>
* ms-ole.c (ms_ole_destroy): Plug leak.
1999-06-15 Michael Meeks <michael@edenproject.org>
* ms-ole.c: Large updates to helper macros, to allow
......
......@@ -1288,6 +1288,23 @@ ms_ole_create (const char *name)
return f;
}
static void
destroy_pps (GList *l)
{
GList *tmp;
for (tmp = l; tmp; tmp = g_list_next (tmp)) {
PPS *pps = tmp->data;
if (pps->name)
g_free (pps->name);
destroy_pps (pps->children);
g_free (pps);
}
g_list_free (l);
}
/**
* This closes the file and truncates any free blocks
**/
......@@ -1319,6 +1336,8 @@ ms_ole_destroy (MS_OLE *f)
g_free (f->mem);
f->mem = 0;
#endif
destroy_pps (f->pps);
close (f->file_des);
g_free (f);
......
......@@ -1413,7 +1413,6 @@ ms_excel_sheet_insert_form (MS_EXCEL_SHEET * sheet, int xfidx,
int col, int row, ExprTree *tr)
{
Cell *cell = sheet_cell_fetch (sheet->gnum_sheet, col, row);
/* NB. cell_set_text _certainly_ strdups *text */
if (tr)
{
sheet->blank = 0 ;
......
......@@ -671,8 +671,12 @@ make_function (PARSE_LIST **stack, int fn_idx, int numargs)
tmp = parse_list_pop (stack) ;
if (!tmp || tmp->oper != OPER_CONSTANT ||
tmp->u.constant->type != VALUE_STRING) {
parse_list_free (&fn->u.function.arg_list);
fn->u.function.symbol =
symbol_lookup (global_symbol_table, "ERROR");
symbol_ref (fn->u.function.symbol);
expr_tree_unref (fn);
parse_list_push (stack, expr_tree_string (_("Broken function")));
printf ("Killroy was here. Did not know what he was doing.\n");
return 0;
}
else {
......@@ -710,10 +714,17 @@ make_function (PARSE_LIST **stack, int fn_idx, int numargs)
if (fd->prefix)
name = symbol_lookup (global_symbol_table, fd->prefix);
if (!name) {
printf ("Unknown fn '%s'\n", fd->prefix);
parse_list_free (&fn->u.function.arg_list);
parse_list_push (stack, expr_tree_string (g_strdup_printf ("Duff fn '%s'",
fd->prefix?fd->prefix:"Umm...")));
char *txt;
txt = g_strdup_printf ("[Function '%s']",
fd->prefix?fd->prefix:"?");
printf ("Unknown %s\n", txt);
parse_list_push (stack, expr_tree_string (txt));
g_free (txt);
fn->u.function.symbol =
symbol_lookup (global_symbol_table, "ERROR");
symbol_ref (fn->u.function.symbol);
expr_tree_unref (fn);
return 0;
}
symbol_ref (name);
......@@ -1095,9 +1106,9 @@ ms_excel_parse_formula (MS_EXCEL_SHEET *sheet, guint8 *mem,
ptg_length = 2 ;
break;
}
case FORMULA_PTG_BOOL: /* FIXME: True / False */
case FORMULA_PTG_BOOL:
{
parse_list_push_raw (&stack, value_new_int (BIFF_GETBYTE(cur)));
parse_list_push_raw (&stack, value_new_bool (BIFF_GETBYTE(cur)));
ptg_length = 1 ;
break ;
}
......@@ -1168,9 +1179,10 @@ ms_excel_parse_formula (MS_EXCEL_SHEET *sheet, guint8 *mem,
if (!stack)
return expr_tree_string ("Stack too short - unusual");
if (g_list_length(stack) > 1)
if (g_list_length(stack) > 1) {
parse_list_free (&stack);
return expr_tree_string ("Too much data on stack - probable cause: "
"fixed args function is var-arg, put '-1' in the table above");
}
return parse_list_pop (&stack);
}
......@@ -122,7 +122,6 @@ callback_function_criteria (Sheet *sheet, int col, int row,
{
math_criteria_t *mm = user_data;
Value *v;
gpointer p;
if (cell == NULL || cell->value == NULL)
return TRUE;
......@@ -142,9 +141,7 @@ callback_function_criteria (Sheet *sheet, int col, int row,
}
if (mm->fun(v, mm->test_value)) {
p = g_new(Value, 1);
*((Value **) p) = v;
mm->list = g_slist_append(mm->list, p);
mm->list = g_slist_append (mm->list, v);
mm->num++;
} else
value_release(v);
......@@ -487,6 +484,7 @@ gnumeric_countif (struct FunctionDefinition *i,
Value *argv [], char **error_string)
{
Value *range = argv[0];
Value *tmpvalue = NULL;
math_criteria_t items;
int ret;
GSList *list;
......@@ -503,9 +501,11 @@ gnumeric_countif (struct FunctionDefinition *i,
if (VALUE_IS_NUMBER(argv[1])) {
items.fun = (criteria_test_fun_t) criteria_test_equal;
items.test_value = argv[1];
} else
} else {
parse_criteria(argv[1]->v.str->str,
&items.fun, &items.test_value);
tmpvalue = items.test_value;
}
ret = sheet_cell_foreach_range (
range->v.cell_range.cell_a.sheet, TRUE,
......@@ -515,6 +515,10 @@ gnumeric_countif (struct FunctionDefinition *i,
range->v.cell_range.cell_b.row,
callback_function_criteria,
&items);
if (tmpvalue)
value_release (tmpvalue);
if (ret == FALSE) {
*error_string = gnumeric_err_VALUE;
return NULL;
......@@ -523,7 +527,7 @@ gnumeric_countif (struct FunctionDefinition *i,
list = items.list;
while (list != NULL) {
g_free(list->data);
value_release (list->data);
list = list->next;
}
g_slist_free(items.list);
......@@ -549,6 +553,7 @@ gnumeric_sumif (struct FunctionDefinition *i,
Value *argv [], char **error_string)
{
Value *range = argv[0];
Value *tmpvalue = NULL;
math_criteria_t items;
int ret;
float_t sum;
......@@ -566,9 +571,11 @@ gnumeric_sumif (struct FunctionDefinition *i,
if (VALUE_IS_NUMBER(argv[1])) {
items.fun = (criteria_test_fun_t) criteria_test_equal;
items.test_value = argv[1];
} else
} else {
parse_criteria(argv[1]->v.str->str,
&items.fun, &items.test_value);
tmpvalue = items.test_value;
}
ret = sheet_cell_foreach_range (
range->v.cell_range.cell_a.sheet, TRUE,
......@@ -578,6 +585,10 @@ gnumeric_sumif (struct FunctionDefinition *i,
range->v.cell_range.cell_b.row,
callback_function_criteria,
&items);
if (tmpvalue)
value_release (tmpvalue);
if (ret == FALSE) {
*error_string = gnumeric_err_VALUE;
return NULL;
......@@ -587,11 +598,11 @@ gnumeric_sumif (struct FunctionDefinition *i,
sum = 0;
while (list != NULL) {
Value *v = *((Value **) list->data);
Value *v = list->data;
if (v != NULL)
sum += value_get_as_float (v);
g_free(list->data);
value_release (v);
list = list->next;
}
g_slist_free(items.list);
......@@ -2336,12 +2347,15 @@ gnumeric_subtotal (Sheet *tsheet, GList *expr_node_list,
}
val = eval_expr (tsheet, tree, eval_col, eval_row, error_string);
if (! VALUE_IS_NUMBER(val)) {
if (!val) return NULL;
if (!VALUE_IS_NUMBER (val)) {
value_release (val);
*error_string = gnumeric_err_VALUE;
return NULL;
}
fun_nbr = value_get_as_int(val);
value_release (val);
if (fun_nbr < 1 || fun_nbr > 11) {
*error_string = gnumeric_err_NUM;
return NULL;
......@@ -2449,10 +2463,12 @@ gnumeric_seriessum (Sheet *sheet, GList *expr_node_list,
val = eval_expr (sheet, tree, eval_col, eval_row, error_string);
if (!val) return NULL;
if (!VALUE_IS_NUMBER (val)) {
value_release (val);
*error_string = gnumeric_err_VALUE;
return NULL;
}
x = value_get_as_float (val);
value_release (val);
expr_node_list = expr_node_list->next;
/* Get n */
......@@ -2464,10 +2480,12 @@ gnumeric_seriessum (Sheet *sheet, GList *expr_node_list,
val = eval_expr (sheet, tree, eval_col, eval_row, error_string);
if (!val) return NULL;
if (!VALUE_IS_NUMBER (val)) {
value_release (val);
*error_string = gnumeric_err_VALUE;
return NULL;
}
n = value_get_as_float (val);
value_release (val);
expr_node_list = expr_node_list->next;
/* Get m */
......@@ -2479,10 +2497,12 @@ gnumeric_seriessum (Sheet *sheet, GList *expr_node_list,
val = eval_expr (sheet, tree, eval_col, eval_row, error_string);
if (!val) return NULL;
if (!VALUE_IS_NUMBER (val)) {
value_release (val);
*error_string = gnumeric_err_VALUE;
return NULL;
}
m = value_get_as_float (val);
value_release (val);
expr_node_list = expr_node_list->next;
p.n = n;
......
......@@ -724,13 +724,14 @@ cell_set_formula_tree_simple (Cell *cell, ExprTree *formula)
cell_modified (cell);
expr_tree_ref (formula);
if (cell->parsed_node){
sheet_cell_formula_unlink (cell);
expr_tree_unref (cell->parsed_node);
}
cell->parsed_node = formula;
expr_tree_ref (formula);
cell_formula_changed (cell);
}
......
......@@ -122,7 +122,6 @@ callback_function_criteria (Sheet *sheet, int col, int row,
{
math_criteria_t *mm = user_data;
Value *v;
gpointer p;
if (cell == NULL || cell->value == NULL)
return TRUE;
......@@ -142,9 +141,7 @@ callback_function_criteria (Sheet *sheet, int col, int row,
}
if (mm->fun(v, mm->test_value)) {
p = g_new(Value, 1);
*((Value **) p) = v;
mm->list = g_slist_append(mm->list, p);
mm->list = g_slist_append (mm->list, v);
mm->num++;
} else
value_release(v);
......@@ -487,6 +484,7 @@ gnumeric_countif (struct FunctionDefinition *i,
Value *argv [], char **error_string)
{
Value *range = argv[0];
Value *tmpvalue = NULL;
math_criteria_t items;
int ret;
GSList *list;
......@@ -503,9 +501,11 @@ gnumeric_countif (struct FunctionDefinition *i,
if (VALUE_IS_NUMBER(argv[1])) {
items.fun = (criteria_test_fun_t) criteria_test_equal;
items.test_value = argv[1];
} else
} else {
parse_criteria(argv[1]->v.str->str,
&items.fun, &items.test_value);
tmpvalue = items.test_value;
}
ret = sheet_cell_foreach_range (
range->v.cell_range.cell_a.sheet, TRUE,
......@@ -515,6 +515,10 @@ gnumeric_countif (struct FunctionDefinition *i,
range->v.cell_range.cell_b.row,
callback_function_criteria,
&items);
if (tmpvalue)
value_release (tmpvalue);
if (ret == FALSE) {
*error_string = gnumeric_err_VALUE;
return NULL;
......@@ -523,7 +527,7 @@ gnumeric_countif (struct FunctionDefinition *i,
list = items.list;
while (list != NULL) {
g_free(list->data);
value_release (list->data);
list = list->next;
}
g_slist_free(items.list);
......@@ -549,6 +553,7 @@ gnumeric_sumif (struct FunctionDefinition *i,
Value *argv [], char **error_string)
{
Value *range = argv[0];
Value *tmpvalue = NULL;
math_criteria_t items;
int ret;
float_t sum;
......@@ -566,9 +571,11 @@ gnumeric_sumif (struct FunctionDefinition *i,
if (VALUE_IS_NUMBER(argv[1])) {
items.fun = (criteria_test_fun_t) criteria_test_equal;
items.test_value = argv[1];
} else
} else {
parse_criteria(argv[1]->v.str->str,
&items.fun, &items.test_value);
tmpvalue = items.test_value;
}
ret = sheet_cell_foreach_range (
range->v.cell_range.cell_a.sheet, TRUE,
......@@ -578,6 +585,10 @@ gnumeric_sumif (struct FunctionDefinition *i,
range->v.cell_range.cell_b.row,
callback_function_criteria,
&items);
if (tmpvalue)
value_release (tmpvalue);
if (ret == FALSE) {
*error_string = gnumeric_err_VALUE;
return NULL;
......@@ -587,11 +598,11 @@ gnumeric_sumif (struct FunctionDefinition *i,
sum = 0;
while (list != NULL) {
Value *v = *((Value **) list->data);
Value *v = list->data;
if (v != NULL)
sum += value_get_as_float (v);
g_free(list->data);
value_release (v);
list = list->next;
}
g_slist_free(items.list);
......@@ -2336,12 +2347,15 @@ gnumeric_subtotal (Sheet *tsheet, GList *expr_node_list,
}
val = eval_expr (tsheet, tree, eval_col, eval_row, error_string);
if (! VALUE_IS_NUMBER(val)) {
if (!val) return NULL;
if (!VALUE_IS_NUMBER (val)) {
value_release (val);
*error_string = gnumeric_err_VALUE;
return NULL;
}
fun_nbr = value_get_as_int(val);
value_release (val);
if (fun_nbr < 1 || fun_nbr > 11) {
*error_string = gnumeric_err_NUM;
return NULL;
......@@ -2449,10 +2463,12 @@ gnumeric_seriessum (Sheet *sheet, GList *expr_node_list,
val = eval_expr (sheet, tree, eval_col, eval_row, error_string);
if (!val) return NULL;
if (!VALUE_IS_NUMBER (val)) {
value_release (val);
*error_string = gnumeric_err_VALUE;
return NULL;
}
x = value_get_as_float (val);
value_release (val);
expr_node_list = expr_node_list->next;
/* Get n */
......@@ -2464,10 +2480,12 @@ gnumeric_seriessum (Sheet *sheet, GList *expr_node_list,
val = eval_expr (sheet, tree, eval_col, eval_row, error_string);
if (!val) return NULL;
if (!VALUE_IS_NUMBER (val)) {
value_release (val);
*error_string = gnumeric_err_VALUE;
return NULL;
}
n = value_get_as_float (val);
value_release (val);
expr_node_list = expr_node_list->next;
/* Get m */
......@@ -2479,10 +2497,12 @@ gnumeric_seriessum (Sheet *sheet, GList *expr_node_list,
val = eval_expr (sheet, tree, eval_col, eval_row, error_string);
if (!val) return NULL;
if (!VALUE_IS_NUMBER (val)) {
value_release (val);
*error_string = gnumeric_err_VALUE;
return NULL;
}
m = value_get_as_float (val);
value_release (val);
expr_node_list = expr_node_list->next;
p.n = n;
......
......@@ -122,7 +122,6 @@ callback_function_criteria (Sheet *sheet, int col, int row,
{
math_criteria_t *mm = user_data;
Value *v;
gpointer p;
if (cell == NULL || cell->value == NULL)
return TRUE;
......@@ -142,9 +141,7 @@ callback_function_criteria (Sheet *sheet, int col, int row,
}
if (mm->fun(v, mm->test_value)) {
p = g_new(Value, 1);
*((Value **) p) = v;
mm->list = g_slist_append(mm->list, p);
mm->list = g_slist_append (mm->list, v);
mm->num++;
} else
value_release(v);
......@@ -487,6 +484,7 @@ gnumeric_countif (struct FunctionDefinition *i,
Value *argv [], char **error_string)
{
Value *range = argv[0];
Value *tmpvalue = NULL;
math_criteria_t items;
int ret;
GSList *list;
......@@ -503,9 +501,11 @@ gnumeric_countif (struct FunctionDefinition *i,
if (VALUE_IS_NUMBER(argv[1])) {
items.fun = (criteria_test_fun_t) criteria_test_equal;
items.test_value = argv[1];
} else
} else {
parse_criteria(argv[1]->v.str->str,
&items.fun, &items.test_value);
tmpvalue = items.test_value;
}
ret = sheet_cell_foreach_range (
range->v.cell_range.cell_a.sheet, TRUE,
......@@ -515,6 +515,10 @@ gnumeric_countif (struct FunctionDefinition *i,
range->v.cell_range.cell_b.row,
callback_function_criteria,
&items);
if (tmpvalue)
value_release (tmpvalue);
if (ret == FALSE) {
*error_string = gnumeric_err_VALUE;
return NULL;
......@@ -523,7 +527,7 @@ gnumeric_countif (struct FunctionDefinition *i,
list = items.list;
while (list != NULL) {
g_free(list->data);
value_release (list->data);
list = list->next;
}
g_slist_free(items.list);
......@@ -549,6 +553,7 @@ gnumeric_sumif (struct FunctionDefinition *i,
Value *argv [], char **error_string)
{
Value *range = argv[0];
Value *tmpvalue = NULL;
math_criteria_t items;
int ret;
float_t sum;
......@@ -566,9 +571,11 @@ gnumeric_sumif (struct FunctionDefinition *i,
if (VALUE_IS_NUMBER(argv[1])) {
items.fun = (criteria_test_fun_t) criteria_test_equal;
items.test_value = argv[1];
} else
} else {
parse_criteria(argv[1]->v.str->str,
&items.fun, &items.test_value);
tmpvalue = items.test_value;
}
ret = sheet_cell_foreach_range (
range->v.cell_range.cell_a.sheet, TRUE,
......@@ -578,6 +585,10 @@ gnumeric_sumif (struct FunctionDefinition *i,
range->v.cell_range.cell_b.row,
callback_function_criteria,
&items);
if (tmpvalue)
value_release (tmpvalue);
if (ret == FALSE) {
*error_string = gnumeric_err_VALUE;
return NULL;
......@@ -587,11 +598,11 @@ gnumeric_sumif (struct FunctionDefinition *i,
sum = 0;
while (list != NULL) {
Value *v = *((Value **) list->data);
Value *v = list->data;
if (v != NULL)
sum += value_get_as_float (v);
g_free(list->data);
value_release (v);
list = list->next;
}
g_slist_free(items.list);
......@@ -2336,12 +2347,15 @@ gnumeric_subtotal (Sheet *tsheet, GList *expr_node_list,
}
val = eval_expr (tsheet, tree, eval_col, eval_row, error_string);
if (! VALUE_IS_NUMBER(val)) {
if (!val) return NULL;
if (!VALUE_IS_NUMBER (val)) {
value_release (val);
*error_string = gnumeric_err_VALUE;
return NULL;
}
fun_nbr = value_get_as_int(val);
value_release (val);
if (fun_nbr < 1 || fun_nbr > 11) {
*error_string = gnumeric_err_NUM;
return NULL;
......@@ -2449,10 +2463,12 @@ gnumeric_seriessum (Sheet *sheet, GList *expr_node_list,
val = eval_expr (sheet, tree, eval_col, eval_row, error_string);
if (!val) return NULL;
if (!VALUE_IS_NUMBER (val)) {
value_release (val);
*error_string = gnumeric_err_VALUE;
return NULL;
}
x = value_get_as_float (val);
value_release (val);
expr_node_list = expr_node_list->next;
/* Get n */
......@@ -2464,10 +2480,12 @@ gnumeric_seriessum (Sheet *sheet, GList *expr_node_list,
val = eval_expr (sheet, tree, eval_col, eval_row, error_string);
if (!val) return NULL;
if (!VALUE_IS_NUMBER (val)) {
value_release (val);
*error_string = gnumeric_err_VALUE;
return NULL;
}
n = value_get_as_float (val);
value_release (val);
expr_node_list = expr_node_list->next;
/* Get m */
......@@ -2479,10 +2497,12 @@ gnumeric_seriessum (Sheet *sheet, GList *expr_node_list,
val = eval_expr (sheet, tree, eval_col, eval_row, error_string);
if (!val) return NULL;
if (!VALUE_IS_NUMBER (val)) {
value_release (val);
*error_string = gnumeric_err_VALUE;
return NULL;
}
m = value_get_as_float (val);
value_release (val);
expr_node_list = expr_node_list->next;
p.n = n;
......
......@@ -106,7 +106,7 @@ font_compute_hints (StyleFont *font)
#include <X11/Xlib.h>
#include "gdk/gdkprivate.h" /* Sorry */
static const char *
static char *
my_gdk_actual_font_name (GdkFont *font)
{
GdkFontPrivate *private;
......@@ -115,8 +115,13 @@ my_gdk_actual_font_name (GdkFont *font)
private = (GdkFontPrivate *)font;
font_atom = XInternAtom (private->xdisplay, "FONT", True);
if (font_atom != None) {
if (XGetFontProperty (private->xfont, font_atom, &atom) == True)
return XGetAtomName (private->xdisplay, atom);
if (XGetFontProperty (private->xfont, font_atom, &atom) == True) {
char *xname, *gname;
xname = XGetAtomName (private->xdisplay, atom);
gname = g_strdup (xname);
XFree (xname);
return gname;
}
}
return NULL;
}
......@@ -169,8 +174,11 @@ style_font_new_simple (const char *font_name, int units)
}
#ifdef DEBUG_FONTS
printf ("was resolved as \"%s\".\n\n",
my_gdk_actual_font_name (gdk_font));
{
char *fname = my_gdk_actual_font_name (gdk_font);
printf ("was resolved as \"%s\".\n\n", fname);
g_free (fname);
}
#endif
font_compute_hints (font);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment