source: branches/stable/WINDOW/AW_select.cxx

Last change on this file was 16936, checked in by westram, 6 years ago
File size: 22.6 KB
Line 
1// ================================================================ //
2//                                                                  //
3//   File      : AW_select.cxx                                      //
4//   Purpose   :                                                    //
5//                                                                  //
6//   Coded by Ralf Westram (coder@reallysoft.de) in February 2010   //
7//   Institute of Microbiology (Technical University Munich)        //
8//   http://www.arb-home.de/                                        //
9//                                                                  //
10// ================================================================ //
11
12#include "aw_select.hxx"
13#include "aw_window_Xm.hxx"
14#include "aw_root.hxx"
15#include "aw_awar.hxx"
16
17#include <arb_strarray.h>
18#include <arb_strbuf.h>
19#include <arb_str.h>
20#include <arb_sort.h>
21#include <ad_cb.h>
22
23#include <Xm/List.h>
24
25// @@@ rename type_mismatch and other derivates (should make clear that program terminates!)
26__ATTR__NORETURN inline void TERMINATE_selection_type_mismatch(const char *triedType) { type_mismatch(triedType, "selection-list"); }
27
28// --------------------------
29//      AW_selection_list
30
31
32AW_selection_list::AW_selection_list(const char *variable_name_, int variable_type_, Widget select_list_widget_)
33    : variable_name(nulldup(variable_name_)),
34      variable_type(AW_VARIABLE_TYPE(variable_type_)),
35      update_cb(NULp),
36      cl_update(0),
37      select_list_widget(select_list_widget_),
38      list_table(NULp),
39      last_of_list_table(NULp),
40      default_select(NULp),
41      next(NULp)
42{}
43
44AW_selection_list::~AW_selection_list() {
45    clear();
46    free(variable_name);
47}
48
49inline XmString XmStringCreateSimple_wrapper(const char *text) {
50    return XmStringCreateSimple((char*)text);
51}
52
53void AW_selection_list::update() {
54    // Warning:
55    // update() will not set the connected awar to the default value
56    // if it contains a value which is not associated with a list entry!
57
58    size_t count = size();
59    if (default_select) count++;
60
61    XmString *strtab = new XmString[count];
62
63    count = 0;
64    for (AW_selection_list_entry *lt = list_table; lt; lt = lt->next) {
65        const char *s2 = lt->get_displayed();
66        if (!s2[0]) s2 = "  ";
67        strtab[count]  = XmStringCreateSimple_wrapper(s2);
68        count++;
69    }
70
71    if (default_select) {
72        const char *s2 = default_select->get_displayed();
73        if (!strlen(s2)) s2 = "  ";
74        strtab[count] = XmStringCreateSimple_wrapper(s2);
75        count++;
76    }
77    if (!count) {
78        strtab[count] = XmStringCreateSimple_wrapper("   ");
79        count ++;
80    }
81
82    XtVaSetValues(select_list_widget, XmNitemCount, count, XmNitems, strtab, NULp);
83
84    refresh();
85
86    for (size_t i=0; i<count; i++) XmStringFree(strtab[i]);
87    delete [] strtab;
88
89    if (update_cb) update_cb(this, cl_update);
90}
91
92void AW_selection_list::set_update_callback(sellist_update_cb ucb, AW_CL cl_user) {
93    aw_assert(!update_cb || !ucb); // overwrite allowed only with NULp!
94
95    update_cb = ucb;
96    cl_update = cl_user;
97}
98
99void AW_selection_list::refresh() {
100    if (!variable_name) return;     // not connected to awar
101
102    AW_root *root  = AW_root::SINGLETON;
103    bool     found = false;
104    int      pos   = 0;
105    AW_awar *awar  = root->awar(variable_name);
106
107    AW_selection_list_entry *lt;
108
109    switch (variable_type) {
110        case AW_STRING: {
111            char *var_value = awar->read_string();
112            for (lt = list_table; lt; lt = lt->next) {
113                if (strcmp(var_value, lt->get_value().get_string()) == 0) {
114                    found = true;
115                    break;
116                }
117                pos++;
118            }
119            free(var_value);
120            break;
121        }
122        case AW_INT: {
123            int var_value = awar->read_int();
124            for (lt = list_table; lt; lt = lt->next) {
125                if (var_value == lt->get_value().get_int()) {
126                    found = true;
127                    break;
128                }
129                pos++;
130            }
131            break;
132        }
133        case AW_FLOAT: {
134            float var_value = awar->read_float();
135            for (lt = list_table; lt; lt = lt->next) {
136                if (var_value == lt->get_value().get_float()) {
137                    found = true;
138                    break;
139                }
140                pos++;
141            }
142            break;
143        }
144        case AW_POINTER: {
145            GBDATA *var_value = awar->read_pointer();
146            for (lt = list_table; lt; lt = lt->next) {
147                if (var_value == lt->get_value().get_pointer()) {
148                    found = true;
149                    break;
150                }
151                pos++;
152            }
153            break;
154        }
155        default:
156            aw_assert(0);
157            GB_warning("Unknown AWAR type");
158            break;
159    }
160
161    if (found || default_select) {
162        pos++;
163        int top;
164        int vis;
165        XtVaGetValues(select_list_widget,
166                      XmNvisibleItemCount, &vis,
167                      XmNtopItemPosition, &top,
168                      NULp);
169        XmListSelectPos(select_list_widget, pos, False);
170
171        if (pos < top) {
172            if (pos > 1) pos --;
173            XmListSetPos(select_list_widget, pos);
174        }
175        if (pos >= top + vis) {
176            XmListSetBottomPos(select_list_widget, pos + 1);
177        }
178    }
179    else {
180        GBK_terminatef("Selection list '%s' has no default selection", variable_name);
181    }
182}
183
184void AW_selection::refresh() {
185    get_sellist()->clear();
186    fill();
187    get_sellist()->update();
188}
189
190void AW_selection_list::clear() {
191    /** Remove all items from the list. Default item is removed as well.*/
192    while (list_table) {
193        AW_selection_list_entry *nextEntry = list_table->next;
194        delete list_table;
195        list_table = nextEntry;
196    }
197    list_table         = NULp;
198    last_of_list_table = NULp;
199
200    delete_default();
201}
202
203bool AW_selection_list::default_is_selected() const {
204    const AW_scalar *sel = get_selected_value();
205    if (!sel) return true; // handle "nothing" like default
206    const AW_scalar *def = get_default_value();
207    return def && sel == def;
208}
209
210const AW_scalar *AW_selection_list::get_selected_value() const {
211    int                      i;
212    AW_selection_list_entry *lt;
213    AW_selection_list_entry *found = NULp;
214
215    aw_assert(select_list_widget);
216
217    // code below retrieves index of selected
218    // get_index_of_selected() does sth similar, but uses awar-value
219    // @@@ rethink
220
221    for (i=1, lt = list_table; lt; i++, lt = lt->next) {
222        bool is_selected = XmListPosSelected(select_list_widget, i);
223        if (is_selected && !found) found = lt;
224    }
225
226    if (default_select) {
227        bool is_selected = XmListPosSelected(select_list_widget, i);
228        if (is_selected && !found) found = default_select;
229    }
230    return found ? &found->get_value() : NULp;
231}
232
233
234AW_selection_list_entry *AW_selection_list::get_entry_at(int index) const {
235    AW_selection_list_entry *entry = list_table;
236    while (index && entry) {
237        entry = entry->next;
238        index--;
239    }
240    return entry;
241}
242
243
244void AW_selection_list::select_default() {
245    set_awar_value(*get_default_value());
246}
247
248void AW_selection_list::delete_element_at(const int index) {
249    if (index<0) return;
250
251    AW_selection_list_entry *prev = NULp;
252    if (index>0) {
253        prev = get_entry_at(index-1);
254        if (!prev) return; // invalid index
255    }
256
257    int selected_index = get_index_of_selected();
258    if (index == selected_index) select_default();
259
260    AW_selection_list_entry *toDel = prev ? prev->next : list_table;
261    aw_assert(toDel != default_select);
262
263    (prev ? prev->next : list_table) = toDel->next;
264    delete toDel;
265
266    if (last_of_list_table == toDel) last_of_list_table = prev;
267}
268
269void AW_selection_list::delete_value(const AW_scalar& value) {
270    int index = get_index_of(value);
271    delete_element_at(index);
272}
273
274AW_scalar AW_selection_list::get_awar_value() const {
275    AW_awar *awar = AW_root::SINGLETON->awar(variable_name);
276    return AW_scalar(awar);
277}
278
279
280char *AW_selection_list::get_content_as_string(long number_of_lines) {
281    // number_of_lines == 0 -> print all
282
283    AW_selection_list_entry *lt;
284    GBS_strstruct *fd = GBS_stropen(10000);
285
286    for (lt = list_table; lt; lt = lt->next) {
287        number_of_lines--;
288        GBS_strcat(fd, lt->get_displayed());
289        GBS_chrcat(fd, '\n');
290        if (!number_of_lines) break;
291    }
292    return GBS_strclose(fd);
293}
294
295const char *AW_selection_list::get_default_display() const {
296    return default_select ? default_select->get_displayed() : NULp;
297}
298const AW_scalar *AW_selection_list::get_default_value() const {
299    return default_select ? &default_select->get_value() : NULp;
300}
301
302
303int AW_selection_list::get_index_of(const AW_scalar& searched_value) {
304    /*! get index of an entry in the selection list
305     * @return 0..n-1 index of matching element (or -1)
306     */
307
308    int element_index = 0;
309    for (AW_selection_list_iterator entry(this); entry; ++entry) {
310        if (*entry.get_value() == searched_value) return element_index;
311        ++element_index;
312    }
313    return -1;
314}
315
316int AW_selection_list::get_index_of_selected() {
317    // returns index of element (or -1)
318    AW_scalar awar_value = get_awar_value();
319    return get_index_of(awar_value);
320}
321
322void AW_selection_list::init_from_array(const CharPtrArray& entries, const char *default_displayed, const char *default_value) {
323    // update selection list with contents of NULp-terminated array 'entries'
324    //
325    // 'default_displayed' and 'default_value' are used as default selection.
326    // To position the default selection, add 'default_value' to 'entries' as well.
327    //
328    // awar value will be changed to 'defaultEntry' if it does not match any other entry
329    //
330    // Note: This works only with selection lists bound to AW_STRING awars.
331
332    aw_assert(default_displayed);
333    aw_assert(default_value);
334
335    // use copies (just in case default_* points to a value free'd by clear())
336    char *defaultDispCopy  = strdup(default_displayed);
337    char *defaultValueCopy = strdup(default_value);
338
339    bool defInserted = false;
340
341    clear();
342    for (int i = 0; entries[i]; ++i) {
343        if (!defInserted && strcmp(entries[i], defaultValueCopy) == 0) {
344            insert_default(defaultDispCopy, defaultValueCopy);
345            defInserted = true;
346        }
347        else {
348            insert(entries[i], entries[i]);
349        }
350    }
351    if (!defInserted) insert_default(defaultDispCopy, defaultValueCopy);
352    update();
353
354    const AW_scalar *selected = get_selected_value();
355    if (selected) set_awar_value(*selected);
356
357    free(defaultValueCopy);
358    free(defaultDispCopy);
359}
360
361void AW_selection_list::append_entry(AW_selection_list_entry *new_entry) {
362    if (list_table) {
363        last_of_list_table->next = new_entry;
364        last_of_list_table = last_of_list_table->next;
365        last_of_list_table->next = NULp;
366    }
367    else {
368        last_of_list_table = list_table = new_entry;
369    }
370}
371
372void AW_selection_list::delete_default() {
373    /** Removes the default entry from the list*/
374    if (default_select) {
375        delete default_select;
376        default_select = NULp;
377    }
378}
379
380void AW_selection_list::insert(const char *displayed, const AW_scalar& value) {
381    if (!value.matches_variable_type(variable_type)) TERMINATE_selection_type_mismatch(value.get_type_name());
382    append_entry(new AW_selection_list_entry(displayed, value));
383}
384
385void AW_selection_list::insert_default(const char *displayed, const AW_scalar& value) {
386    if (!value.matches_variable_type(variable_type)) TERMINATE_selection_type_mismatch(value.get_type_name());
387    if (default_select) delete_default();
388    default_select = new AW_selection_list_entry(displayed, value);
389}
390
391void AW_selection_list::move_content_to(AW_selection_list *target_list) {
392    //! move all entries (despite default entry) to another AW_selection_list
393
394    if (default_select) {
395        char *defDisp = strdup(default_select->get_displayed());
396        char *defVal  = strdup(default_select->get_value().get_string());
397
398        delete_default();
399        move_content_to(target_list);
400        insert_default(defDisp, defVal);
401
402        free(defVal);
403        free(defDisp);
404    }
405    else {
406        AW_selection_list_entry *entry = list_table;
407        while (entry) {
408            target_list->append_entry(new AW_selection_list_entry(entry->get_displayed(), entry->get_value()));
409            entry = entry->next;
410        }
411        clear();
412    }
413}
414
415void AW_selection_list::move_selection(int offset) {
416    /*! move selection 'offset' position
417     *  offset == 1  -> select next element
418     *  offset == -1 -> select previous element
419     */
420
421    int index = get_index_of_selected();
422    select_element_at(index+offset);
423}
424
425const AW_scalar *AW_selection_list::get_value_at(int index) {
426    // get value of the entry at position 'index' [0..n-1] of the 'selection_list'
427    // returns NULp if index is out of bounds
428
429    AW_selection_list_entry *entry = get_entry_at(index);
430    return entry ? &entry->get_value() : NULp;
431}
432
433void AW_selection_list::select_element_at(int wanted_index) {
434    const AW_scalar *wanted_value = get_value_at(wanted_index);
435
436    if (!wanted_value) {
437        wanted_value = get_default_value();
438        aw_assert(wanted_value); // did set string-awar to "" in the past // @@@ what todo here? maybe just dont select?
439    }
440
441    if (wanted_value) set_awar_value(*wanted_value);
442}
443
444void AW_selection_list::set_awar_value(const AW_scalar& new_value) {
445    AW_awar *awar = AW_root::SINGLETON->awar(variable_name);
446    new_value.write_to(awar);
447}
448
449
450void AW_selection_list::set_file_suffix(const char *suffix) {
451    AW_root *aw_root = AW_root::SINGLETON;
452    char     filter[200];
453    sprintf(filter, "tmp/save_box_sel_%li/filter", (long)this);
454    aw_root->awar_string(filter, suffix);
455    sprintf(filter, "tmp/load_box_sel_%li/filter", (long)this);
456    aw_root->awar_string(filter, suffix);
457}
458
459size_t AW_selection_list::size() {
460    AW_selection_list_entry *lt    = list_table;
461    size_t                  count = 0;
462
463    while (lt) {
464        ++count;
465        lt = lt->next;
466    }
467    return count;
468}
469
470static int sel_sort_backward(const char *d1, const char *d2) { return strcmp(d2, d1); }
471static int sel_isort_backward(const char *d1, const char *d2) { return ARB_stricmp(d2, d1); }
472static int gb_compare_function__2__sellist_cmp_fun(const void *t1, const void *t2, void *v_selcmp) {
473    sellist_cmp_fun selcmp = (sellist_cmp_fun)v_selcmp;
474    return selcmp(static_cast<const AW_selection_list_entry*>(t1)->get_displayed(),
475                  static_cast<const AW_selection_list_entry*>(t2)->get_displayed());
476}
477
478void AW_selection_list::sortCustom(sellist_cmp_fun cmp) {
479    // (Note: motif always places default-element @ bottom)
480    size_t count = size();
481    if (count) {
482        AW_selection_list_entry **tables = new AW_selection_list_entry *[count];
483        count = 0;
484        for (AW_selection_list_entry *lt = list_table; lt; lt = lt->next) {
485            tables[count++] = lt;
486        }
487
488        GB_sort((void**)tables, 0, count, gb_compare_function__2__sellist_cmp_fun, (void*)cmp);
489
490        size_t i;
491        for (i=0; i<count-1; i++) {
492            tables[i]->next = tables[i+1];
493        }
494        tables[i]->next    = NULp;
495        list_table         = tables[0];
496        last_of_list_table = tables[i];
497
498        delete [] tables;
499    }
500}
501
502void AW_selection_list::sort(bool backward, bool case_sensitive) {
503    // (Note: motif always places default-element @ bottom)
504    sellist_cmp_fun cmp;
505    if (backward) {
506        if (case_sensitive) cmp = sel_sort_backward;
507        else cmp                = sel_isort_backward;
508    }
509    else {
510        if (case_sensitive) cmp = strcmp;
511        else cmp                = ARB_stricmp;
512    }
513    sortCustom(cmp);
514}
515
516void AW_selection_list::to_array(StrArray& array, bool values) {
517    /*! read contents of selection list into an array.
518     * @param values true->read values, false->read displayed strings
519     * Use GBT_free_names() to free the result.
520     *
521     * Note: if 'values' is true, this function only works for string selection lists!
522     */
523
524    array.reserve(size());
525
526    for (AW_selection_list_entry *lt = list_table; lt; lt = lt->next) {
527        array.put(strdup(values ? lt->get_value().get_string() : lt->get_displayed()));
528    }
529    aw_assert(array.size() == size());
530}
531
532GB_HASH *AW_selection_list::to_hash(bool case_sens) {
533    // creates a hash (key = value of selection list, value = display string from selection list)
534    // (Warning: changing the selection list will render the hash invalid!)
535
536    GB_HASH *hash = GBS_create_hash(size(), case_sens ? GB_MIND_CASE : GB_IGNORE_CASE);
537
538    for (AW_selection_list_entry *lt = list_table; lt; lt = lt->next) {
539        GBS_write_hash(hash, lt->get_value().get_string(), (long)lt->get_displayed());
540    }
541
542    return hash;
543}
544
545char *AW_selection_list_entry::copy_string_for_display(const char *str) {
546    size_t  len     = strlen(str);
547    bool    tooLong = len>MAX_DISPLAY_LENGTH;
548    char   *out;
549    if (tooLong) {
550        out = ARB_strndup(str, MAX_DISPLAY_LENGTH);
551        { // add message about truncation
552            char   *truncated = GBS_global_string_copy(" <truncated - original contains %zu byte>", len);
553            size_t  tlen      = strlen(truncated);
554            aw_assert(MAX_DISPLAY_LENGTH>tlen);
555            memcpy(out+MAX_DISPLAY_LENGTH-tlen, truncated, tlen);
556        }
557        len = MAX_DISPLAY_LENGTH;
558    }
559    else {
560        out = ARB_strduplen(str, len);
561    }
562
563    for (size_t i = 0; i<len; ++i) {
564        switch (out[i]) {
565            case ',':   out[i] = ';'; break;
566            case '\n':  out[i] = '#'; break;
567        }
568    }
569    return out;
570}
571
572// -------------------------
573//      AW_DB_selection
574
575static void AW_DB_selection_refresh_cb(GBDATA *, AW_DB_selection *selection) {
576    selection->refresh();
577}
578
579AW_DB_selection::AW_DB_selection(AW_selection_list *sellist_, GBDATA *gbd_) :
580    AW_selection(sellist_),
581    gbd(gbd_)
582{
583    GB_transaction ta(gbd);
584    GB_add_callback(gbd, GB_CB_CHANGED, makeDatabaseCallback(AW_DB_selection_refresh_cb, this));
585}
586
587AW_DB_selection::~AW_DB_selection() {
588    GB_transaction ta(gbd);
589    GB_remove_callback(gbd, GB_CB_CHANGED, makeDatabaseCallback(AW_DB_selection_refresh_cb, this));
590}
591
592GBDATA *AW_DB_selection::get_gb_main() {
593    return GB_get_root(gbd);
594}
595
596// --------------------------------------------------------------------------------
597
598#ifdef UNIT_TESTS
599#ifndef TEST_UNIT_H
600#include <test_unit.h>
601#endif
602
603#define TEST_LIST_CONTENT(list,values,expected) do {    \
604        StrArray a;                                     \
605        (list).to_array(a, values);                     \
606        char *str = GBT_join_strings(a, ';');           \
607        TEST_EXPECT_EQUAL(str, expected);               \
608        free(str);                                      \
609    } while(0)
610
611#define TEST_GET_LIST_CONTENT(list,expected) do {       \
612        char *str = (list).get_content_as_string(10);   \
613        TEST_EXPECT_EQUAL(str, expected);               \
614        free(str);                                      \
615    } while(0)
616
617void TEST_selection_list_access() {
618    AW_selection_list list0("bla", GB_STRING, NULp);
619    AW_selection_list list1("bla", GB_STRING, NULp);
620    AW_selection_list list2("alb", GB_STRING, NULp);
621
622    AW_scalar s1st("1st");
623    AW_scalar s2nd("2nd");
624    AW_scalar s3rd("3rd");
625    AW_scalar sempty("");
626
627    list0.insert_default("First",  s1st);
628    list0.insert        ("Second", s2nd);
629    list0.insert        ("Third",  s3rd);
630
631    list1.insert        ("First",  "1st");
632    list1.insert_default("Second", "2nd");
633    list1.insert        ("Third",  "3rd");
634
635    list2.insert        ("First",   s1st);
636    list2.insert        ("Second",  s2nd);
637    list2.insert        ("Third",   s3rd);
638    list2.insert_default("Default", sempty);
639
640    TEST_EXPECT_EQUAL(list0.size(), 2);
641    TEST_EXPECT_EQUAL(list1.size(), 2);
642    TEST_EXPECT_EQUAL(list2.size(), 3);
643
644    TEST_EXPECT_EQUAL(list1.get_default_value()->get_string(), "2nd");
645    TEST_EXPECT_EQUAL(list1.get_default_display(), "Second");
646
647    TEST_EXPECT_EQUAL(list0.get_index_of(s1st), -1); // default value is not indexed
648    TEST_EXPECT_EQUAL(list0.get_index_of(s2nd), 0);
649    TEST_EXPECT_EQUAL(list0.get_index_of(s3rd), 1);  // = second non-default entry
650
651    TEST_EXPECT_EQUAL(list1.get_index_of(s1st), 0);
652    TEST_EXPECT_EQUAL(list1.get_index_of(s2nd), -1); // default value is not indexed
653    TEST_EXPECT_EQUAL(list1.get_index_of(s3rd), 1);  // = second non-default entry
654
655    TEST_EXPECT_EQUAL(list2.get_index_of(s1st), 0);
656    TEST_EXPECT_EQUAL(list2.get_index_of(s2nd), 1);
657    TEST_EXPECT_EQUAL(list2.get_index_of(s3rd), 2);
658
659    TEST_EXPECT(*list0.get_value_at(0) == s2nd);
660    TEST_EXPECT(*list0.get_value_at(1) == s3rd);
661    TEST_EXPECT_NULL(list0.get_value_at(2));
662
663    TEST_EXPECT(*list1.get_value_at(0) == s1st);
664    TEST_EXPECT(*list1.get_value_at(1) == s3rd);
665    TEST_EXPECT_NULL(list1.get_value_at(2));
666
667    TEST_EXPECT(*list2.get_value_at(0) == s1st);
668    TEST_EXPECT(*list2.get_value_at(1) == s2nd);
669    TEST_EXPECT(*list2.get_value_at(2) == s3rd);
670    TEST_EXPECT_NULL(list2.get_value_at(3));
671
672    TEST_LIST_CONTENT(list1, true,  "1st;3rd");
673    TEST_LIST_CONTENT(list1, false, "First;Third");
674    TEST_GET_LIST_CONTENT(list1,    "First\nThird\n");
675
676    TEST_LIST_CONTENT(list2, true,  "1st;2nd;3rd");
677    TEST_LIST_CONTENT(list2, false, "First;Second;Third");
678    TEST_GET_LIST_CONTENT(list2,    "First\nSecond\nThird\n");
679
680    {
681        AW_selection_list_iterator iter1(&list1);
682        AW_selection_list_iterator iter2(&list2);
683
684        TEST_EXPECT(bool(iter1));
685        TEST_EXPECT(bool(iter2));
686
687        TEST_EXPECT_EQUAL(iter1.get_displayed(), "First");
688        TEST_EXPECT_EQUAL(iter2.get_displayed(), "First");
689
690        TEST_EXPECT(*iter1.get_value() == s1st);
691        TEST_EXPECT(*iter2.get_value() == s1st);
692
693        ++iter1;
694        ++iter2;
695
696        TEST_EXPECT(bool(iter1));
697        TEST_EXPECT(bool(iter2));
698
699        TEST_EXPECT_EQUAL(iter1.get_displayed(), "Third");
700        TEST_EXPECT_EQUAL(iter2.get_displayed(), "Second");
701
702        TEST_EXPECT(*iter1.get_value() == s3rd);
703        TEST_EXPECT(*iter2.get_value() == s2nd);
704
705        ++iter1;
706        ++iter2;
707
708        TEST_REJECT(bool(iter1));
709        TEST_EXPECT(bool(iter2));
710    }
711
712    {
713        AW_selection_list copy1("c1", GB_STRING, NULp);
714        AW_selection_list copy2("c2", GB_STRING, NULp);
715
716        list1.move_content_to(&copy1);
717        list2.move_content_to(&copy2);
718
719        TEST_EXPECT_EQUAL(list1.size(), 0);
720        TEST_EXPECT_EQUAL(list2.size(), 0);
721
722        TEST_LIST_CONTENT(copy1, true, "1st;3rd");
723        TEST_LIST_CONTENT(copy2, true, "1st;2nd;3rd");
724    }
725}
726TEST_PUBLISH(TEST_selection_list_access);
727
728#endif // UNIT_TESTS
729
730// --------------------------------------------------------------------------------
731
Note: See TracBrowser for help on using the repository browser.