Thu, 28 Nov 2024 18:04:55 +0100
fix textarea crash when no value is specified (GTK)
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2014 Olaf Wintermann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <stdio.h> #include <stdlib.h> #include "container.h" #include "list.h" #include "../common/object.h" void* ui_strmodel_getvalue(void *elm, int column) { return column == 0 ? elm : NULL; } UIWIDGET ui_listview_str(UiObject *obj, UiList *list, ui_callback f, void *udata) { return ui_listview(obj, list, ui_strmodel_getvalue, f, udata); } UIWIDGET ui_listview_var(UiObject *obj, UiVar *var, ui_getvaluefunc getvalue, ui_callback f, void *udata) { int count; XmStringTable items = ui_create_stringlist(var->value, getvalue, &count); Arg args[8]; int n = 0; XtSetArg(args[n], XmNitemCount, count); n++; XtSetArg(args[n], XmNitems, count == 0 ? NULL : items); n++; UiContainer *ct = uic_get_current_container(obj); Widget parent = ct->prepare(ct, args, &n, TRUE); Widget widget = XmCreateScrolledList(parent, "listview", args, n); ct->add(ct, XtParent(widget)); XtManageChild(widget); UiListView *listview = cxMalloc(obj->ctx->allocator, sizeof(UiListView)); listview->widget = widget; listview->list = var; listview->getvalue = getvalue; for (int i=0;i<count;i++) { XmStringFree(items[i]); } XtFree((char *)items); if(f) { UiListViewEventData *event = cxMalloc( obj->ctx->allocator, sizeof(UiListViewEventData)); event->event.obj = obj; event->event.userdata = udata; event->event.callback = f; event->event.value = 0; event->var = var; XtAddCallback( widget, XmNdefaultActionCallback, (XtCallbackProc)ui_list_selection_callback, event); } return widget; } UIWIDGET ui_listview(UiObject *obj, UiList *list, ui_getvaluefunc getvalue, ui_callback f, void *udata) { UiVar *var = malloc(sizeof(UiVar)); var->value = list; var->type = UI_VAR_SPECIAL; return ui_listview_var(obj, var, getvalue, f, udata); } UIWIDGET ui_listview_nv(UiObject *obj, char *varname, ui_getvaluefunc getvalue, ui_callback f, void *udata) { UiVar *var = uic_create_var(obj->ctx, varname, UI_VAR_LIST); if(var) { UiListVar *value = var->value; return ui_listview_var(obj, var, getvalue, f, udata); } else { // TODO: error } return NULL; } XmStringTable ui_create_stringlist(UiList *list, ui_getvaluefunc getvalue, int *count) { int num = list->count(list); XmStringTable items = (XmStringTable)XtMalloc(num * sizeof(XmString)); void *data = list->first(list); for(int i=0;i<num;i++) { items[i] = XmStringCreateLocalized(getvalue(data, 0)); data = list->next(list); } *count = num; return items; } void ui_listview_update(UiEvent *event, UiListView *view) { int count; XmStringTable items = ui_create_stringlist( view->list->value, view->getvalue, &count); XtVaSetValues( view->widget, XmNitems, count == 0 ? NULL : items, XmNitemCount, count, NULL); for (int i=0;i<count;i++) { XmStringFree(items[i]); } XtFree((char *)items); } void ui_list_selection_callback (Widget widget, UiListViewEventData *event, XtPointer data) { XmListCallbackStruct *cbs = (XmListCallbackStruct *)data; UiEvent e; e.obj = event->event.obj; e.window = event->event.obj->window; e.document = event->event.obj->ctx->document; UiList *list = event->var->value; e.eventdata = list->get(list, cbs->item_position - 1); e.intval = cbs->item_position - 1; event->event.callback(&e, event->event.userdata); } /* --------------------------- ComboBox --------------------------- */ UIWIDGET ui_combobox_str(UiObject *obj, UiList *list, ui_callback f, void *udata) { return ui_combobox(obj, list, ui_strmodel_getvalue, f, udata); } UIWIDGET ui_combobox(UiObject *obj, UiList *list, ui_getvaluefunc getvalue, ui_callback f, void *udata) { UiVar *var = malloc(sizeof(UiVar)); var->value = list; var->type = UI_VAR_SPECIAL; return ui_combobox_var(obj, var, getvalue, f, udata); } UIWIDGET ui_combobox_nv(UiObject *obj, char *varname, ui_getvaluefunc getvalue, ui_callback f, void *udata) { UiVar *var = uic_create_var(obj->ctx, varname, UI_VAR_LIST); if(var) { UiListVar *value = var->value; return ui_combobox_var(obj, var, getvalue, f, udata); } else { // TODO: error } return NULL; } UIWIDGET ui_combobox_var(UiObject *obj, UiVar *var, ui_getvaluefunc getvalue, ui_callback f, void *udata) { UiListView *listview = cxMalloc( obj->ctx->allocator, sizeof(UiListView)); UiContainer *ct = uic_get_current_container(obj); Arg args[16]; int n = 0; XtSetArg(args[n], XmNindicatorOn, XmINDICATOR_NONE); n++; XtSetArg(args[n], XmNtraversalOn, FALSE); n++; XtSetArg(args[n], XmNwidth, 160); n++; Widget parent = ct->prepare(ct, args, &n, FALSE); Widget combobox = XmCreateDropDownList(parent, "combobox", args, n); XtManageChild(combobox); listview->widget = combobox; listview->list = var; listview->getvalue = getvalue; ui_listview_update(NULL, listview); return parent; }