/* * Adds a row to the list, keeping the null row and '...' row in the correct positions. * Must copy data to new array due to limitations in the forms library. */ void ListBox::addRow(const std::string& str) { FIELD **pNewFields = new FIELD*[m_numRows + (m_editable ? 2 : 1)]; //Copy existing fields, up to the second last ('...') row for (int i = 0; i < m_numRows - 1; i++) { pNewFields[i] = m_pFields[i]; } //Create '...' row if (m_editable) { //Create new field at third-to-last index (before '...' row) createField(&pNewFields[m_numRows - 1], m_numRows - 1, str); createField(&pNewFields[m_numRows], m_numRows, "..."); set_field_userptr(pNewFields[m_numRows], (void*)true); } else { createField(&pNewFields[m_numRows], m_numRows, str); } //Create null field pNewFields[m_editable ? m_numRows + 1 : m_numRows] = 0; for (int i = 0; i < m_numRows; i++) { if (m_pFields[i] != 0) { free_field(m_pFields[i]); } } m_numRows++; m_pFields = pNewFields; createForm(); }
/* * Recursive function responsible to create fields, position them and setting * the modifiable fields. All of this from a service dictionary. * To keep the cursor from moving on signal, a string is affected to mark each * field. This is used by repos_cursor(). * @param longest_key_len The longest length for a label * @param pos The index in main_fields[] * @param jobj The service dictionary * @param is_obj_modifiable Use to set the whole object as modifiable (usefull * for IPv4.Configuration for example) * @param obj_str The string representing the "hash" of a surrounding object */ static void render_fields_from_jobj(int longest_key_len, int *pos, struct json_object *jobj, bool is_obj_modifiable, const char *obj_str) { bool is_autoconnect = false, is_modifiable = false; struct userptr_data *data; json_object_object_foreach(jobj, key, val) { main_fields[*pos] = render_label(longest_key_len, key); assert(main_fields[*pos] != NULL); (*pos)++; is_modifiable = string_ends_with_configuration(key); is_modifiable |= is_obj_modifiable; if (json_object_get_type(val) == json_type_object) { move_field(main_fields[(*pos)-1], ++cur_y, cur_x); cur_y++; render_fields_from_jobj(longest_key_len, pos, val, is_modifiable, key); is_modifiable = false; } else { // insert the page delimiter if (cur_y >= win_body_lines-4) { cur_y = 1; set_new_page(main_fields[(*pos)-1], TRUE); move_field(main_fields[(*pos)-1], cur_y, cur_x); nb_pages++; } main_fields[*pos] = render_field(longest_key_len, val); assert(main_fields[*pos] != NULL); is_autoconnect = strcmp(key, key_serv_autoconnect) == 0; if (is_modifiable || is_autoconnect) { field_opts_on(main_fields[*pos], O_EDIT); field_opts_off(main_fields[*pos], O_BLANK); set_field_back(main_fields[*pos], A_UNDERLINE); } else field_opts_off(main_fields[*pos], O_EDIT); // Specific operations on fields config_fields_type(*pos, is_autoconnect, obj_str, key); field_opts_on(main_fields[*pos], O_NULLOK); data = malloc(sizeof(struct userptr_data)); data->dbus_name = strdup(get_str_key()); data->pretty_name = NULL; set_field_userptr(main_fields[*pos], data); (*pos)++; } cur_y++; }
/* * Define each field with an extra one, for reflecting "actual" text. */ static FIELD * make_field(int frow, int fcol, int rows, int cols) { FIELD *f = new_field(rows, cols, frow, fcol, o_value, 1); if (f) { FieldAttrs *ptr; set_field_back(f, A_UNDERLINE); /* * If -j and -d options are combined, -j loses. It is documented in * "Character User Interface Programming", page 12-15 that setting * O_STATIC off makes the form library ignore justification. */ set_field_just(f, j_value); if (d_option) { if (has_colors()) { set_field_fore(f, (chtype) COLOR_PAIR(2)); set_field_back(f, A_UNDERLINE | COLOR_PAIR(3)); } else { set_field_fore(f, A_BOLD); } /* * The field_opts_off() call dumps core with Solaris curses, * but that is a known bug in Solaris' form library -TD */ field_opts_off(f, O_STATIC); set_max_field(f, m_value); } /* * The userptr is used in edit_field.c's inactive_field(). */ ptr = (FieldAttrs *) field_userptr(f); if (ptr == 0) { ptr = typeCalloc(FieldAttrs, 1); ptr->background = field_back(f); } set_field_userptr(f, (void *) ptr); if (t_value) set_field_buffer(f, 0, t_value); } return (f); }
ListBox::ListBox(Panel *pPanel, int x, int y, int w, int h, bool editable) : Component(pPanel, x, y, w, h) { setSelectable(true); m_editable = true;//editable; TODO: revisit m_numRows = m_editable ? 1 : 0; m_pForm = 0; m_curRow = 0; //Create field array, init to null if (m_editable) { m_pFields = new FIELD*[2]; createField(&m_pFields[0], 0, "..."); set_field_userptr(m_pFields[0], (void*)true); m_pFields[1] = 0; } else { m_pFields = new FIELD*[1]; m_pFields[0] = 0; } createForm(); }
/* * Add a field to the form. * Automatically creates a label component. * Include | in your label to designate a field's initial content. */ void DialogForm::addField(const std::string &lbl, int rows, int cols, int x, int y, FieldType type, int *typeParams, int nParams, FIELD** pField) { //Split the label and field contents. int i; std::string contents, label; i = lbl.find_first_of('|'); if (i != std::string::npos) { //Put content after | in field contents = lbl.substr(i + 1); label = lbl.substr(0, i); } else { contents = ""; label = lbl; } //Create the field. if (rows == 1) { //Offset x by label strLen m_pFields[m_curField] = new_field(rows, cols, y + 1, label.size() + x, 0, 0); } else { //Position field under label m_pFields[m_curField] = new_field(rows, cols, y + 2, x, 0, 0); } set_field_buffer(m_pFields[m_curField], 0, contents.data()); //Set up field validation. if (type == FIELDTYPE_ALPHA) { if (typeParams == 0) { set_field_type(m_pFields[m_curField], TYPE_ALPHA, 1); } else if (nParams == 1) { set_field_type(m_pFields[m_curField], TYPE_ALPHA, typeParams[0]); } } else if (type == FIELDTYPE_INT) { if (typeParams == 0) { set_field_type(m_pFields[m_curField], TYPE_INTEGER, 0); } else if (nParams == 1) { set_field_type(m_pFields[m_curField], TYPE_INTEGER, typeParams[0]); } else if (nParams == 3) { set_field_type(m_pFields[m_curField], TYPE_INTEGER, typeParams[0], typeParams[1], typeParams[2]); } } else if (type == FIELDTYPE_FLOAT) { if (typeParams == 0) { set_field_type(m_pFields[m_curField], TYPE_NUMERIC, 0); } else if (nParams == 1) { set_field_type(m_pFields[m_curField], TYPE_NUMERIC, typeParams[0]); } else if (nParams == 3) { // set_field_type(m_pFields[m_curField], TYPE_NUMERIC, typeParams[0], typeParams[1], typeParams[2]); } } set_field_userptr(m_pFields[m_curField], (void*)new FieldType(type)); set_field_back(m_pFields[m_curField], A_UNDERLINE); if (rows == 1) { field_opts_off(m_pFields[m_curField], O_AUTOSKIP); } //Create the label Label* pLabel = new Label(this, label, x + 1, y + 3); add(pLabel); //Return pointer if (pField != 0) { *pField = m_pFields[m_curField]; } m_curField++; }