void dropdown_widget::set_value(const std::string& key, const variant& v) { if(key == "on_change") { on_change_ = boost::bind(&dropdown_widget::change_delegate, this, _1); change_handler_ = get_environment()->create_formula(v); } else if(key == "on_select") { on_select_ = boost::bind(&dropdown_widget::select_delegate, this, _1, _2); select_handler_ = get_environment()->create_formula(v); } else if(key == "item_list") { list_ = v.as_list_string(); current_selection_ = 0; } else if(key == "selection") { current_selection_ = v.as_int(); } else if(key == "type") { std::string s = v.as_string(); if(s == "combo" || s == "combobox") { type_ = DROPDOWN_COMBOBOX; } else if(s == "list" || s == "listbox") { type_ = DROPDOWN_LIST; } else { ASSERT_LOG(false, "Unreognised type: " << s); } } widget::set_value(key, v); }
void widget::process_delegate() { if(get_environment()) { variant value = ffl_on_process_->execute(*get_environment()); get_environment()->execute_command(value); } else { std::cerr << "widget::process_delegate() called without environment!" << std::endl; } }
void button::click() { if(get_environment()) { variant value = click_handler_->execute(*get_environment()); get_environment()->execute_command(value); } else { std::cerr << "button::click() called without environment!" << std::endl; } }
String OS_Haiku::get_config_path() const { if (has_environment("XDG_CONFIG_HOME")) { return get_environment("XDG_CONFIG_HOME"); } else if (has_environment("HOME")) { return get_environment("HOME").plus_file("config/settings"); } else { return "."; } }
String OS_Haiku::get_data_path() const { if (has_environment("XDG_DATA_HOME")) { return get_environment("XDG_DATA_HOME"); } else if (has_environment("HOME")) { return get_environment("HOME").plus_file("config/data"); } else { return get_config_path(); } }
String OS_Haiku::get_cache_path() const { if (has_environment("XDG_CACHE_HOME")) { return get_environment("XDG_CACHE_HOME"); } else if (has_environment("HOME")) { return get_environment("HOME").plus_file("config/cache"); } else { return get_config_path(); } }
void dropdown_widget::change_delegate(const std::string& s) { if(get_environment()) { game_logic::map_formula_callable* callable = new game_logic::map_formula_callable(get_environment()); callable->add("selection", variant(s)); variant v(callable); variant value = change_handler_->execute(*callable); get_environment()->execute_command(value); } else { std::cerr << "dropdown_widget::change_delegate() called without environment!" << std::endl; } }
grid::grid(const variant& v, game_logic::formula_callable* e) : widget(v, e), scrollable_widget(v, e), row_height_(0), selected_row_(-1), allow_selection_(false), must_select_(false), swallow_clicks_(false), hpad_(0), show_background_(false), max_height_(-1), allow_highlight_(true), set_h_(0), set_w_(0) { ASSERT_LOG(get_environment() != 0, "You must specify a callable environment"); if(v.has_key("on_select")) { ffl_on_select_ = get_environment()->create_formula(v["on_select"]); on_select_ = boost::bind(&grid::select_delegate, this, _1); } if(v.has_key("on_mouseover")) { ffl_on_mouseover_ = get_environment()->create_formula(v["on_mouseover"]); on_select_ = boost::bind(&grid::mouseover_delegate, this, _1); } ncols_ = v["columns"].as_int(1); if(v.has_key("column_widths")) { if(v["column_widths"].is_list()) { std::vector<int> li = v["column_widths"].as_list_int(); col_widths_.assign(li.begin(), li.end()); } else if(v["column_widths"].is_int()) { col_widths_.assign(ncols_, v["column_widths"].as_int()); } else { ASSERT_LOG(false, "grid: column_widths must be an int or list of ints"); } } else { col_widths_.assign(ncols_, 0); } if(v.has_key("column_alignments")) { if(v["column_alignments"].is_list()) { // XXX this could be a list of strings as well. int col = 0; foreach(const variant& c, v["column_alignments"].as_list()) { if(c.is_int()) { set_align(col, static_cast<COLUMN_ALIGN>(c.as_int())); } else if(c.is_string()) { const std::string& s = c.as_string(); if(s == "center" || s == "centre") { set_align(col, ALIGN_CENTER); } else if(s == "right") { set_align(col, ALIGN_RIGHT); } else if(s == "left") { set_align(col, ALIGN_LEFT); } else { ASSERT_LOG(false, "grid: column_alignments must be \"left\", \"right\" or \"center\""); } } else { ASSERT_LOG(false, "grid: column alignment members must be an integer or a string."); } col++; } } else if(v["column_alignments"].is_int()) {
selector_widget::selector_widget(const variant& v, game_logic::formula_callable* e) : widget(v, e), current_selection_(v["selection"].as_int(0)) { if(v.has_key("list") || v.has_key("children")) { const variant& l = v.has_key("list") ? v["list"] : v["children"]; ASSERT_LOG(l.is_list(), "'list'/'children' attribute must be a list"); foreach(const variant& child, l.as_list()) { if(child.is_list()) { ASSERT_LOG(child.num_elements() == 2, "items in the sub-list must have two elements."); widget_ptr w; if(child[1].is_map()) { w = widget_factory::create(child[1], e); } else { w = child[1].try_convert<widget>(); ASSERT_LOG(w != NULL, "Couldn't convert second element to widget."); } list_.push_back(selector_pair(child[0].as_string(), w)); } else if(child.is_string()) { const std::string& s = child.as_string(); list_.push_back(selector_pair(s, widget_ptr(new label(s)))); } else { widget_ptr w; std::string s; if(child.is_map()) { w = widget_factory::create(child, e); ASSERT_LOG(child.has_key("id") || child.has_key("select_string"), "list items must supply 'id' or 'select_string' attribute."); s = child.has_key("id") ? child["id"].as_string() : child["select_string"].as_string(); } else { w = child.try_convert<widget>(); ASSERT_LOG(w != NULL, "Couldn't convert item to widget."); ASSERT_LOG(!w->id().empty(), "list items must have 'id' attribute"); s = w->id(); } list_.push_back(selector_pair(s, w)); } } } if(v.has_key("on_change")) { change_handler_ = get_environment()->create_formula(v["on_change"]); on_change_ = boost::bind(&selector_widget::change_delegate, this, _1); } if(v.has_key("on_select")) { select_handler_ = get_environment()->create_formula(v["on_select"]); on_select_ = boost::bind(&selector_widget::select_delegate, this, _1); } init(); }
bool Camera::_get(const StringName& p_name,Variant &r_ret) const { if (p_name=="projection") { r_ret= mode; } else if (p_name=="fov" || p_name=="fovy" || p_name=="fovx") r_ret= fov; else if (p_name=="size" || p_name=="sizex" || p_name=="sizey") r_ret= size; else if (p_name=="near") r_ret= near; else if (p_name=="far") r_ret= far; else if (p_name=="keep_aspect") r_ret= int(keep_aspect); else if (p_name=="current") { if (is_inside_tree() && get_tree()->is_node_being_edited(this)) { r_ret=current; } else { r_ret=is_current(); } } else if (p_name=="visible_layers") { r_ret=get_visible_layers(); } else if (p_name=="h_offset") { r_ret=get_h_offset(); } else if (p_name=="v_offset") { r_ret=get_v_offset(); } else if (p_name=="environment") { r_ret=get_environment(); } else return false; return true; }
bool Camera::_get(const StringName& p_name,Variant &r_ret) const { if (p_name=="projection") { r_ret= mode; } else if (p_name=="fov") r_ret= fov; else if (p_name=="size") r_ret= size; else if (p_name=="near") r_ret= near; else if (p_name=="far") r_ret= far; else if (p_name=="vaspect") r_ret= vaspect; else if (p_name=="current") { if (is_inside_scene() && get_scene()->is_editor_hint()) { r_ret=current; } else { r_ret=is_current(); } } else if (p_name=="visible_layers") { r_ret=get_visible_layers(); } else if (p_name=="environment") { r_ret=get_environment(); } else return false; return true; }
String OS_Unix::get_data_dir() const { String an = get_safe_application_name(); if (an != "") { if (has_environment("HOME")) { bool use_godot = ProjectSettings::get_singleton()->get("application/config/use_shared_user_dir"); if (use_godot) return get_environment("HOME") + "/.godot/app_userdata/" + an; else return get_environment("HOME") + "/." + an; } } return ProjectSettings::get_singleton()->get_resource_path(); }
int config_set_environment(struct compilation_configuration_tag* config, const char* index, const char* value) { type_environment_t* chosen_env = get_environment(value); if (chosen_env != NULL) { config->type_environment = chosen_env; } return 0; }
static rc_t populate_tool_ctx( tool_ctx_t * tool_ctx, const Args * args ) { rc_t rc = ArgsParamValue( args, 0, ( const void ** )&( tool_ctx -> accession_path ) ); if ( rc != 0 ) ErrMsg( "ArgsParamValue() -> %R", rc ); else { tool_ctx -> lookup_filename[ 0 ] = 0; tool_ctx -> index_filename[ 0 ] = 0; tool_ctx -> dflt_output[ 0 ] = 0; get_user_input( tool_ctx, args ); encforce_constrains( tool_ctx ); get_environment( tool_ctx ); rc = make_temp_dir( &tool_ctx -> temp_dir, tool_ctx -> requested_temp_path, tool_ctx -> dir ); } if ( rc == 0 ) rc = handle_accession( tool_ctx ); if ( rc == 0 ) rc = handle_lookup_path( tool_ctx ); if ( rc == 0 && tool_ctx -> output_dirname != NULL ) { if ( !dir_exists( tool_ctx -> dir, "%s", tool_ctx -> output_dirname ) ) rc = create_this_dir_2( tool_ctx -> dir, tool_ctx -> output_dirname, true ); } if ( rc == 0 ) { if ( tool_ctx -> output_filename == NULL ) { if ( tool_ctx -> output_dirname == NULL ) rc = make_output_filename_from_accession( tool_ctx ); else rc = make_output_filename_from_dir_and_accession( tool_ctx ); } else { if ( tool_ctx -> output_dirname == NULL ) rc = adjust_output_filename( tool_ctx ); else rc = adjust_output_filename_by_dir( tool_ctx ); } } if ( rc == 0 ) rc = Make_FastDump_Cleanup_Task ( &( tool_ctx -> cleanup_task ) ); /* cleanup_task.c */ if ( rc == 0 ) rc = Add_Directory_to_Cleanup_Task ( tool_ctx -> cleanup_task, get_temp_dir( tool_ctx -> temp_dir ) ); return rc; }
sexpr environment::update_symbol(const std::string& name, const sexpr& expr) { auto env = get_environment(name); if (env) env->symbols[name] = expr; else this->symbols[name] = expr; return expr; }
bool Ioss::ParallelUtils::get_environment(const std::string &name, int &value, bool sync_parallel) const { std::string str_value; bool success = get_environment(name, str_value, sync_parallel); if (success) { value = std::atoi(str_value.c_str()); } return success; }
button::button(const variant& v, game_logic::formula_callable* e) : widget(v,e), down_(false) { variant label_var = v["label"]; label_ = label_var.is_map() ? widget_factory::create(label_var, e) : new label(label_var.as_string_default("Button"), graphics::color_white()); ASSERT_LOG(v.has_key("on_click"), "Button must be supplied with an on_click handler"); // create delegate for onclick ASSERT_LOG(get_environment() != 0, "You must specify a callable environment"); click_handler_ = get_environment()->create_formula(v["on_click"]); onclick_ = boost::bind(&button::click, this); button_resolution_ = v["resolution"].as_string_default("normal") == "normal" ? BUTTON_SIZE_NORMAL_RESOLUTION : BUTTON_SIZE_DOUBLE_RESOLUTION; button_style_ = v["style"].as_string_default("default") == "default" ? BUTTON_STYLE_DEFAULT : BUTTON_STYLE_NORMAL; hpadding_ = v["hpad"].as_int(10); vpadding_ = v["vpad"].as_int(4); if(v.has_key("padding")) { ASSERT_LOG(v["padding"].num_elements() == 2, "Incorrect number of padding elements specifed." << v["padding"].num_elements()); hpadding_ = v["padding"][0].as_int(); vpadding_ = v["padding"][1].as_int(); } setup(); }
String OS_Unix::get_data_dir() const { String an = Globals::get_singleton()->get("application/name"); if (an!="") { if (has_environment("HOME")) { bool use_godot = Globals::get_singleton()->get("application/use_shared_user_dir"); if (use_godot) return get_environment("HOME")+"/.godot/app_userdata/"+an; else return get_environment("HOME")+"/."+an; } } return Globals::get_singleton()->get_resource_path(); }
String OS_Unix::get_locale() const { if (!has_environment("LANG")) return "en"; String locale = get_environment("LANG"); int tp = locale.find("."); if (tp!=-1) locale=locale.substr(0,tp); return locale; }
void syscall_env( struct syscall_packet *scp ) { struct process *proc = NULL; scp->rc = SMK_UNKNOWN_SYSCALL; switch (scp->opcode) { case OP( ENV, ONE ): proc = checkout_process( getpid(), WRITER ); assert( proc != NULL ); scp->rc = set_environment( current_process(), scp->name, scp->ptr, scp->size ); commit_process( proc ); break; case OP( ENV, TWO ): proc = checkout_process( getpid(), READER ); assert( proc != NULL ); scp->rc = get_environment( current_process(), scp->name, scp->ptr, &(scp->size) ); commit_process( proc ); break; case OP( ENV, THREE ): proc = checkout_process( getpid(), READER ); assert( proc != NULL ); scp->rc = get_environment_size( current_process(), scp->name, &(scp->size) ); commit_process( proc ); break; case OP( ENV, FOUR ): proc = checkout_process( getpid(), READER ); assert( proc != NULL ); scp->rc = get_environment_information( current_process(), scp->id, scp->name, &(scp->size) ); commit_process( proc ); break; case OP( ENV, FIVE ): proc = checkout_process( getpid(), WRITER ); assert( proc != NULL ); scp->rc = remove_environment( current_process(), scp->name ); commit_process( proc ); break; } }
static int deadpool_init() { if(!pool) { get_environment(); get_config(); if(config->tordns_enabled) { pool = init_pool( config->tordns_cache_size, config->tordns_deadpool_range->localip, config->tordns_deadpool_range->localnet, config->defaultserver.address, config->defaultserver.port ); if(!pool) { show_msg(MSGERR, "failed to initialize deadpool: tordns disabled\n"); } } } return 0; }
static int setting_get_environment(const TCHAR *service_name, void *param, const TCHAR *name, void *default_value, value_t *value, const TCHAR *additional) { HKEY key = (HKEY) param; if (! param) return -1; TCHAR *env = 0; unsigned long envlen; if (get_environment((TCHAR *) service_name, key, (TCHAR *) name, &env, &envlen)) return -1; if (! envlen) return 0; TCHAR *formatted; unsigned long newlen; if (format_double_null(env, envlen, &formatted, &newlen)) return -1; int ret; if (additional) { /* Find named environment variable. */ TCHAR *s; size_t len = _tcslen(additional); for (s = env; *s; s++) { /* Look for <additional>=<string> NULL NULL */ if (! _tcsnicmp(s, additional, len) && s[len] == _T('=')) { /* Strip <key>= */ s += len + 1; ret = value_from_string(name, value, s); HeapFree(GetProcessHeap(), 0, env); return ret; } /* Skip this string. */ for ( ; *s; s++); } HeapFree(GetProcessHeap(), 0, env); return 0; } HeapFree(GetProcessHeap(), 0, env); ret = value_from_string(name, value, formatted); if (newlen) HeapFree(GetProcessHeap(), 0, formatted); return ret; }
int execute_command(char * cmd, char ** args, int in_background) { pid_t pid = fork(); if(pid == -1) { perror("fork"); return -1; } else if(!pid) { if( -1 == execvpe(cmd, args, get_environment()) ) { fprintf(stderr, "%s: command not recognized\n", cmd); return -1; } } else { if(in_background) { add_job( pid, cmd ); } else { int status; if(-1 == waitpid( pid, &status, 0 ) ) { fprintf(stderr, "Error calling %s\n", cmd); } } return 0; } }
grid::grid(const variant& v, game_logic::formula_callable* e) : scrollable_widget(v, e), row_height_(v["row_height"].as_int(0)), selected_row_(-1), allow_selection_(false), must_select_(false), swallow_clicks_(false), hpad_(0), show_background_(false), max_height_(-1), allow_highlight_(true), set_h_(0), set_w_(0), default_selection_(v["default_select"].as_int(-1)), draw_selection_highlight_(v["draw_selection_highlighted"].as_bool(false)) { ASSERT_LOG(get_environment() != 0, "You must specify a callable environment"); if(v.has_key("on_select")) { const variant on_select_value = v["on_select"]; if(on_select_value.is_function()) { ASSERT_LOG(on_select_value.min_function_arguments() <= 1 && on_select_value.max_function_arguments() >= 1, "on_select grid function should take 1 argument: " << v.debug_location()); static const variant fml("fn(selection)"); ffl_on_select_.reset(new game_logic::formula(fml)); game_logic::map_formula_callable* callable = new game_logic::map_formula_callable; callable->add("fn", on_select_value); select_arg_.reset(callable); } else { ffl_on_select_ = get_environment()->create_formula(on_select_value); } on_select_ = boost::bind(&grid::select_delegate, this, _1); } if(v.has_key("on_mouseover")) { allow_selection_ = true; on_mouseover_ = boost::bind(&grid::mouseover_delegate, this, _1); const variant on_mouseover_value = v["on_mouseover"]; if(on_mouseover_value.is_function()) { ASSERT_LOG(on_mouseover_value.min_function_arguments() <= 1 && on_mouseover_value.max_function_arguments() >= 1, "on_mouseover grid function should take 1 argument: " << v.debug_location()); static const variant fml("fn(selection)"); ffl_on_mouseover_.reset(new game_logic::formula(fml)); game_logic::map_formula_callable* callable = new game_logic::map_formula_callable; callable->add("fn", on_mouseover_value); mouseover_arg_.reset(callable); } else { ffl_on_mouseover_ = get_environment()->create_formula(v["on_mouseover"]); } } ncols_ = v["columns"].as_int(1); if(v.has_key("column_widths")) { if(v["column_widths"].is_list()) { ASSERT_LOG(v["column_widths"].num_elements() == ncols_, "List of column widths must have " << ncols_ << " elements"); std::vector<int> li = v["column_widths"].as_list_int(); col_widths_.assign(li.begin(), li.end()); } else if(v["column_widths"].is_int()) { col_widths_.assign(ncols_, v["column_widths"].as_int()); } else { ASSERT_LOG(false, "grid: column_widths must be an int or list of ints"); } } else { col_widths_.assign(ncols_, 0); } col_aligns_.resize(ncols_); if(v.has_key("column_alignments")) { if(v["column_alignments"].is_list()) { // XXX this could be a list of strings as well. int col = 0; foreach(const variant& c, v["column_alignments"].as_list()) { if(c.is_int()) { set_align(col, static_cast<COLUMN_ALIGN>(c.as_int())); } else if(c.is_string()) { const std::string& s = c.as_string(); if(s == "center" || s == "centre") { set_align(col, ALIGN_CENTER); } else if(s == "right") { set_align(col, ALIGN_RIGHT); } else if(s == "left") { set_align(col, ALIGN_LEFT); } else { ASSERT_LOG(false, "grid: column_alignments must be \"left\", \"right\" or \"center\""); } } else { ASSERT_LOG(false, "grid: column alignment members must be an integer or a string."); } col++; } } else if(v["column_alignments"].is_int()) {
int poll(POLL_SIGNATURE) { int nevents = 0; int rc = 0, i; int setevents = 0; int monitoring = 0; struct connreq *conn, *nextconn; /* If we're not currently managing any requests we can just * leave here */ if (!requests) return(realpoll(ufds, nfds, timeout)); get_environment(); show_msg(MSGDEBUG, "Intercepted call to poll with %d fds, " "0x%08x timeout %d\n", nfds, ufds, timeout); for (conn = requests; conn != NULL; conn = conn->next) conn->selectevents = 0; /* Record what events on our sockets the caller was interested * in */ for (i = 0; i < nfds; i++) { if (!(conn = find_socks_request(ufds[i].fd, 0))) continue; show_msg(MSGDEBUG, "Have event checks for socks enabled socket %d\n", conn->sockid); conn->selectevents = ufds[i].events; monitoring = 1; } if (!monitoring) return(realpoll(ufds, nfds, timeout)); /* This is our poll loop. In it we repeatedly call poll(). We * pass select the same event list as provided by the caller except we * modify the events for the sockets we're managing to get events * we're interested in (while negotiating with the socks server). When * events we're interested in happen we go off and process the result * ourselves, without returning the events to the caller. The loop * ends when an event which isn't one we need to handle occurs or * the poll times out */ do { /* Enable our sockets for the events WE want to hear about */ for (i = 0; i < nfds; i++) { if (!(conn = find_socks_request(ufds[i].fd, 0))) continue; /* We always want to know about socket exceptions but they're * always returned (i.e they don't need to be in the list of * wanted events to be returned by the kernel */ ufds[i].events = 0; /* If we're waiting for a connect or to be able to send * on a socket we want to get write events */ if ((conn->state == SENDING) || (conn->state == CONNECTING)) ufds[i].events |= POLLOUT; /* If we're waiting to receive data we want to get * read events */ if (conn->state == RECEIVING) ufds[i].events |= POLLIN; } nevents = realpoll(ufds, nfds, timeout); /* If there were no events we must have timed out or had an error */ if (nevents <= 0) break; /* Loop through all the sockets we're monitoring and see if * any of them have had events */ for (conn = requests; conn != NULL; conn = nextconn) { nextconn = conn->next; if ((conn->state == FAILED) || (conn->state == DONE)) continue; /* Find the socket in the poll list */ for (i = 0; ((i < nfds) && (ufds[i].fd != conn->sockid)); i++) /* Empty Loop */; if (i == nfds) continue; show_msg(MSGDEBUG, "Checking socket %d for events\n", conn->sockid); if (!ufds[i].revents) { show_msg(MSGDEBUG, "No events on socket\n"); continue; } /* Clear any read or write events on the socket, we'll reset * any that are necessary later. */ setevents = ufds[i].revents; if (setevents & POLLIN) { show_msg(MSGDEBUG, "Socket had read event\n"); ufds[i].revents &= ~POLLIN; nevents--; } if (setevents & POLLOUT) { show_msg(MSGDEBUG, "Socket had write event\n"); ufds[i].revents &= ~POLLOUT; nevents--; } if (setevents & (POLLERR | POLLNVAL | POLLHUP)) show_msg(MSGDEBUG, "Socket had error event\n"); /* Now handle this event */ if (setevents & (POLLERR | POLLNVAL | POLLHUP)) { conn->state = FAILED; } else { rc = handle_request(conn); } /* If the connection hasn't failed or completed there is nothing * to report to the client */ if ((conn->state != FAILED) && (conn->state != DONE)) continue; /* Ok, the connection is completed, for good or for bad. We now * hand back the relevant events to the caller. We don't delete the * connection though since the caller should call connect() to * check the status, we delete it then */ if (conn->state == FAILED) { /* Damn, the connection failed. Just copy back the error events * from the poll call, error events are always valid even if not * requested by the client */ /* We should use setsockopt to set the SO_ERROR errno for this * socket, but this isn't allowed for some silly reason which * leaves us a bit hamstrung. * We don't delete the request so that hopefully we can * return the error on the socket if they call connect() on it */ } else { /* The connection is done, if the client polled for * writing we can go ahead and signal that now (since the socket must * be ready for writing), otherwise we'll just let the select loop * come around again (since we can't flag it for read, we don't know * if there is any data to be read and can't be bothered checking) */ if (conn->selectevents & WRITE) { setevents |= POLLOUT; nevents++; } } } } while (nevents == 0); show_msg(MSGDEBUG, "Finished intercepting poll(), %d events\n", nevents); /* Now restore the events polled in each of the blocks */ for (i = 0; i < nfds; i++) { if (!(conn = find_socks_request(ufds[i].fd, 1))) continue; ufds[i].events = conn->selectevents; } return(nevents); }
int select(SELECT_SIGNATURE) { int nevents = 0; int rc = 0; int setevents = 0; int monitoring = 0; struct connreq *conn, *nextconn; fd_set mywritefds, myreadfds, myexceptfds; /* If we're not currently managing any requests we can just * leave here */ if (!requests) return(realselect(n, readfds, writefds, exceptfds, timeout)); get_environment(); show_msg(MSGDEBUG, "Intercepted call to select with %d fds, " "0x%08x 0x%08x 0x%08x, timeout %08x\n", n, readfds, writefds, exceptfds, timeout); for (conn = requests; conn != NULL; conn = conn->next) { if ((conn->state == FAILED) || (conn->state == DONE)) continue; conn->selectevents = 0; show_msg(MSGDEBUG, "Checking requests for socks enabled socket %d\n", conn->sockid); conn->selectevents |= (writefds ? (FD_ISSET(conn->sockid, writefds) ? WRITE : 0) : 0); conn->selectevents |= (readfds ? (FD_ISSET(conn->sockid, readfds) ? READ : 0) : 0); conn->selectevents |= (exceptfds ? (FD_ISSET(conn->sockid, exceptfds) ? EXCEPT : 0) : 0); if (conn->selectevents) { show_msg(MSGDEBUG, "Socket %d was set for events\n", conn->sockid); monitoring = 1; } } if (!monitoring) return(realselect(n, readfds, writefds, exceptfds, timeout)); /* This is our select loop. In it we repeatedly call select(). We * pass select the same fdsets as provided by the caller except we * modify the fdsets for the sockets we're managing to get events * we're interested in (while negotiating with the socks server). When * events we're interested in happen we go off and process the result * ourselves, without returning the events to the caller. The loop * ends when an event which isn't one we need to handle occurs or * the select times out */ do { /* Copy the clients fd events, we'll change them as we wish */ if (readfds) memcpy(&myreadfds, readfds, sizeof(myreadfds)); else FD_ZERO(&myreadfds); if (writefds) memcpy(&mywritefds, writefds, sizeof(mywritefds)); else FD_ZERO(&mywritefds); if (exceptfds) memcpy(&myexceptfds, exceptfds, sizeof(myexceptfds)); else FD_ZERO(&myexceptfds); /* Now enable our sockets for the events WE want to hear about */ for (conn = requests; conn != NULL; conn = conn->next) { if ((conn->state == FAILED) || (conn->state == DONE) || (conn->selectevents == 0)) continue; /* We always want to know about socket exceptions */ FD_SET(conn->sockid, &myexceptfds); /* If we're waiting for a connect or to be able to send * on a socket we want to get write events */ if ((conn->state == SENDING) || (conn->state == CONNECTING)) FD_SET(conn->sockid,&mywritefds); else FD_CLR(conn->sockid,&mywritefds); /* If we're waiting to receive data we want to get * read events */ if (conn->state == RECEIVING) FD_SET(conn->sockid,&myreadfds); else FD_CLR(conn->sockid,&myreadfds); } nevents = realselect(n, &myreadfds, &mywritefds, &myexceptfds, timeout); /* If there were no events we must have timed out or had an error */ if (nevents <= 0) break; /* Loop through all the sockets we're monitoring and see if * any of them have had events */ for (conn = requests; conn != NULL; conn = nextconn) { nextconn = conn->next; if ((conn->state == FAILED) || (conn->state == DONE)) continue; show_msg(MSGDEBUG, "Checking socket %d for events\n", conn->sockid); /* Clear all the events on the socket (if any), we'll reset * any that are necessary later. */ setevents = 0; if (FD_ISSET(conn->sockid, &mywritefds)) { nevents--; setevents |= WRITE; show_msg(MSGDEBUG, "Socket had write event\n"); FD_CLR(conn->sockid, &mywritefds); } if (FD_ISSET(conn->sockid, &myreadfds)) { nevents--; setevents |= READ; show_msg(MSGDEBUG, "Socket had write event\n"); FD_CLR(conn->sockid, &myreadfds); } if (FD_ISSET(conn->sockid, &myexceptfds)) { nevents--; setevents |= EXCEPT; show_msg(MSGDEBUG, "Socket had except event\n"); FD_CLR(conn->sockid, &myexceptfds); } if (!setevents) { show_msg(MSGDEBUG, "No events on socket %d\n", conn->sockid); continue; } if (setevents & EXCEPT) { conn->state = FAILED; } else { rc = handle_request(conn); } /* If the connection hasn't failed or completed there is nothing * to report to the client */ if ((conn->state != FAILED) && (conn->state != DONE)) continue; /* Ok, the connection is completed, for good or for bad. We now * hand back the relevant events to the caller. We don't delete the * connection though since the caller should call connect() to * check the status, we delete it then */ if (conn->state == FAILED) { /* Damn, the connection failed. Whatever the events the socket * was selected for we flag */ if (conn->selectevents & EXCEPT) { FD_SET(conn->sockid, &myexceptfds); nevents++; } if (conn->selectevents & READ) { FD_SET(conn->sockid, &myreadfds); nevents++; } if (conn->selectevents & WRITE) { FD_SET(conn->sockid, &mywritefds); nevents++; } /* We should use setsockopt to set the SO_ERROR errno for this * socket, but this isn't allowed for some silly reason which * leaves us a bit hamstrung. * We don't delete the request so that hopefully we can * return the error on the socket if they call connect() on it */ } else { /* The connection is done, if the client selected for * writing we can go ahead and signal that now (since the socket must * be ready for writing), otherwise we'll just let the select loop * come around again (since we can't flag it for read, we don't know * if there is any data to be read and can't be bothered checking) */ if (conn->selectevents & WRITE) { FD_SET(conn->sockid, &mywritefds); nevents++; } } } } while (nevents == 0); show_msg(MSGDEBUG, "Finished intercepting select(), %d events\n", nevents); /* Now copy our event blocks back to the client blocks */ if (readfds) memcpy(readfds, &myreadfds, sizeof(myreadfds)); if (writefds) memcpy(writefds, &mywritefds, sizeof(mywritefds)); if (exceptfds) memcpy(exceptfds, &myexceptfds, sizeof(myexceptfds)); return(nevents); }
int connect(CONNECT_SIGNATURE) { struct sockaddr_in *connaddr; struct sockaddr_in peer_address; struct sockaddr_in server_address; int gotvalidserver = 0, rc, namelen = sizeof(peer_address); int sock_type = -1; int sock_type_len = sizeof(sock_type); unsigned int res = -1; struct serverent *path; struct connreq *newconn; get_environment(); /* If the real connect doesn't exist, we're stuffed */ if (realconnect == NULL) { show_msg(MSGERR, "Unresolved symbol: connect\n"); return(-1); } show_msg(MSGDEBUG, "Got connection request\n"); connaddr = (struct sockaddr_in *) __addr; /* Get the type of the socket */ getsockopt(__fd, SOL_SOCKET, SO_TYPE, (void *) &sock_type, &sock_type_len); /* If this isn't an INET socket for a TCP stream we can't */ /* handle it, just call the real connect now */ if ((connaddr->sin_family != AF_INET) || (sock_type != SOCK_STREAM)) { show_msg(MSGDEBUG, "Connection isn't a TCP stream ignoring\n"); return(realconnect(__fd, __addr, __len)); } /* If we haven't initialized yet, do it now */ get_config(); /* Are we already handling this connect? */ if ((newconn = find_socks_request(__fd, 1))) { if (memcmp(&newconn->connaddr, connaddr, sizeof(*connaddr))) { /* Ok, they're calling connect on a socket that is in our * queue but this connect() isn't to the same destination, * they're obviously not trying to check the status of * they're non blocking connect, they must have close()d * the other socket and created a new one which happens * to have the same fd as a request we haven't had the chance * to delete yet, so we delete it here. */ show_msg(MSGDEBUG, "Call to connect received on old " "tsocks request for socket %d but to " "new destination, deleting old request\n", newconn->sockid); kill_socks_request(newconn); } else { /* Ok, this call to connect() is to check the status of * a current non blocking connect(). */ if (newconn->state == FAILED) { show_msg(MSGDEBUG, "Call to connect received on failed " "request %d, returning %d\n", newconn->sockid, newconn->err); errno = newconn->err; rc = -1; } else if (newconn->state == DONE) { show_msg(MSGERR, "Call to connect received on completed " "request %d\n", newconn->sockid, newconn->err); rc = 0; } else { show_msg(MSGDEBUG, "Call to connect received on current request %d\n", newconn->sockid); rc = handle_request(newconn); errno = rc; } if ((newconn->state == FAILED) || (newconn->state == DONE)) kill_socks_request(newconn); return((rc ? -1 : 0)); } } /* If the socket is already connected, just call connect */ /* and get its standard reply */ if (!getpeername(__fd, (struct sockaddr *) &peer_address, &namelen)) { show_msg(MSGDEBUG, "Socket is already connected, defering to " "real connect\n"); return(realconnect(__fd, __addr, __len)); } show_msg(MSGDEBUG, "Got connection request for socket %d to " "%s\n", __fd, inet_ntoa(connaddr->sin_addr)); /* If the address is local call realconnect */ if (!(is_local(config, &(connaddr->sin_addr)))) { show_msg(MSGDEBUG, "Connection for socket %d is local\n", __fd); return(realconnect(__fd, __addr, __len)); } /* Ok, so its not local, we need a path to the net */ pick_server(config, &path, &(connaddr->sin_addr), ntohs(connaddr->sin_port)); show_msg(MSGDEBUG, "Picked server %s for connection\n", (path->address ? path->address : "(Not Provided)")); if (path->address == NULL) { if (path == &(config->defaultserver)) show_msg(MSGERR, "Connection needs to be made " "via default server but " "the default server has not " "been specified\n"); else show_msg(MSGERR, "Connection needs to be made " "via path specified at line " "%d in configuration file but " "the server has not been " "specified for this path\n", path->lineno); } else if ((res = resolve_ip(path->address, 0, HOSTNAMES)) == -1) { show_msg(MSGERR, "The SOCKS server (%s) listed in the configuration " "file which needs to be used for this connection " "is invalid\n", path->address); } else { /* Construct the addr for the socks server */ server_address.sin_family = AF_INET; /* host byte order */ server_address.sin_addr.s_addr = res; server_address.sin_port = htons(path->port); bzero(&(server_address.sin_zero), 8); /* Complain if this server isn't on a localnet */ if (is_local(config, &server_address.sin_addr)) { show_msg(MSGERR, "SOCKS server %s (%s) is not on a local subnet!\n", path->address, inet_ntoa(server_address.sin_addr)); } else gotvalidserver = 1; } /* If we haven't found a valid server we return connection refused */ if (!gotvalidserver || !(newconn = new_socks_request(__fd, connaddr, &server_address, path))) { errno = ECONNREFUSED; return(-1); } else { /* Now we call the main function to handle the connect. */ rc = handle_request(newconn); /* If the request completed immediately it mustn't have been * a non blocking socket, in this case we don't need to know * about this socket anymore. */ if ((newconn->state == FAILED) || (newconn->state == DONE)) kill_socks_request(newconn); errno = rc; return((rc ? -1 : 0)); } }
widget::widget(const variant& v, game_logic::formula_callable* e) : environ_(e), w_(0), h_(0), x_(0), y_(0), zorder_(0), true_x_(0), true_y_(0), disabled_(false), disabled_opacity_(v["disabled_opacity"].as_int(127)), tooltip_displayed_(false), id_(v["id"].as_string_default()), align_h_(HALIGN_LEFT), align_v_(VALIGN_TOP) { if(v.has_key("width")) { w_ = v["width"].as_int(); } if(v.has_key("height")) { h_ = v["height"].as_int(); } if(v.has_key("wh")) { std::vector<int> iv = v["wh"].as_list_int(); ASSERT_LOG(iv.size() == 2, "WH attribute must be 2 integer elements."); w_ = iv[0]; h_ = iv[1]; } if(v.has_key("rect")) { std::vector<int> r = v["rect"].as_list_int(); ASSERT_LOG(r.size() == 4, "Four values must be supplied to the rect attribute"); set_loc(r[0], r[1]); set_dim(r[2], r[3]); } if(v.has_key("draw_area")) { std::vector<int> r = v["draw_area"].as_list_int(); ASSERT_LOG(r.size() == 4, "Four values must be supplied to the rect attribute"); set_loc(r[0], r[1]); set_dim(r[2], r[3]); } if(v.has_key("x")) { true_x_ = x_ = v["x"].as_int(); } if(v.has_key("y")) { true_y_ = y_ = v["y"].as_int(); } if(v.has_key("xy")) { std::vector<int> iv = v["xy"].as_list_int(); ASSERT_LOG(iv.size() == 2, "XY attribute must be 2 integer elements."); true_x_ = x_ = iv[0]; true_y_ = y_ = iv[1]; } zorder_ = v["zorder"].as_int(0); if(v.has_key("on_process")) { on_process_ = boost::bind(&widget::process_delegate, this); ffl_on_process_ = get_environment()->create_formula(v["on_process"]); } if(v.has_key("tooltip")) { if(v["tooltip"].is_string()) { set_tooltip(v["tooltip"].as_string(), v["tooltip_size"].as_int(18)); } else if(v["tooltip"].is_map()) { set_tooltip(v["tooltip"]["text"].as_string(), v["tooltip"]["size"].as_int(18)); } else { ASSERT_LOG(false, "Specify the tooltip as a string, e.g. \"tooltip\":\"Text to display on mouseover\", " "or a map, e.g. \"tooltip\":{\"text\":\"Text to display.\", \"size\":14}"); } } visible_ = v["visible"].as_bool(true); if(v.has_key("align_h")) { std::string align = v["align_h"].as_string(); if(align == "left") { align_h_ = HALIGN_LEFT; } else if(align == "middle" || align == "center" || align == "centre") { align_h_ = HALIGN_CENTER; } else if(align == "right") { align_h_ = HALIGN_RIGHT; } else { ASSERT_LOG(false, "Invalid align_h attribute given: " << align); } } if(v.has_key("align_v")) { std::string align = v["align_v"].as_string(); if(align == "top") { align_v_ = VALIGN_TOP; } else if(align == "middle" || align == "center" || align == "centre") { align_v_ = VALIGN_CENTER; } else if(align == "bottom") { align_v_ = VALIGN_BOTTOM; } else { ASSERT_LOG(false, "Invalid align_v attribute given: " << align); } } disabled_ = !v["enabled"].as_bool(true); recalc_loc(); }
int get_parameters(nssm_service_t *service, STARTUPINFO *si) { unsigned long ret; /* Try to open the registry */ HKEY key = open_registry(service->name, KEY_READ); if (! key) return 1; /* Don't expand parameters when retrieving for the GUI. */ bool expand = si ? true : false; /* Try to get environment variables - may fail */ get_environment(service->name, key, NSSM_REG_ENV, &service->env, &service->envlen); /* Environment variables to add to existing rather than replace - may fail. */ get_environment(service->name, key, NSSM_REG_ENV_EXTRA, &service->env_extra, &service->env_extralen); /* Set environment if we are starting the service. */ if (si) set_service_environment(service); /* Try to get executable file - MUST succeed */ if (get_string(key, NSSM_REG_EXE, service->exe, sizeof(service->exe), expand, false, true)) { RegCloseKey(key); return 3; } /* Try to get flags - may fail and we don't care */ if (get_string(key, NSSM_REG_FLAGS, service->flags, sizeof(service->flags), expand, false, true)) { log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_NO_FLAGS, NSSM_REG_FLAGS, service->name, service->exe, 0); ZeroMemory(service->flags, sizeof(service->flags)); } /* Try to get startup directory - may fail and we fall back to a default */ if (get_string(key, NSSM_REG_DIR, service->dir, sizeof(service->dir), expand, true, true) || ! service->dir[0]) { _sntprintf_s(service->dir, _countof(service->dir), _TRUNCATE, _T("%s"), service->exe); strip_basename(service->dir); if (service->dir[0] == _T('\0')) { /* Help! */ ret = GetWindowsDirectory(service->dir, sizeof(service->dir)); if (! ret || ret > sizeof(service->dir)) { log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_NO_DIR_AND_NO_FALLBACK, NSSM_REG_DIR, service->name, 0); RegCloseKey(key); return 4; } } log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_NO_DIR, NSSM_REG_DIR, service->name, service->dir, 0); } /* Try to get processor affinity - may fail. */ TCHAR buffer[512]; if (get_string(key, NSSM_REG_AFFINITY, buffer, sizeof(buffer), false, false, false) || ! buffer[0]) service->affinity = 0LL; else if (affinity_string_to_mask(buffer, &service->affinity)) { log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_BOGUS_AFFINITY_MASK, service->name, buffer); service->affinity = 0LL; } else { DWORD_PTR affinity, system_affinity; if (GetProcessAffinityMask(GetCurrentProcess(), &affinity, &system_affinity)) { _int64 effective_affinity = service->affinity & system_affinity; if (effective_affinity != service->affinity) { TCHAR *system = 0; if (! affinity_mask_to_string(system_affinity, &system)) { TCHAR *effective = 0; if (! affinity_mask_to_string(effective_affinity, &effective)) { log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_EFFECTIVE_AFFINITY_MASK, service->name, buffer, system, effective, 0); } HeapFree(GetProcessHeap(), 0, effective); } HeapFree(GetProcessHeap(), 0, system); } } } /* Try to get priority - may fail. */ unsigned long priority; if (get_number(key, NSSM_REG_PRIORITY, &priority, false) == 1) { if (priority == (priority & priority_mask())) service->priority = priority; else log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_BOGUS_PRIORITY, service->name, NSSM_REG_PRIORITY, 0); } /* Try to get hook I/O sharing - may fail. */ unsigned long hook_share_output_handles; if (get_number(key, NSSM_REG_HOOK_SHARE_OUTPUT_HANDLES, &hook_share_output_handles, false) == 1) { if (hook_share_output_handles) service->hook_share_output_handles = true; else service->hook_share_output_handles = false; } else hook_share_output_handles = false; /* Try to get file rotation settings - may fail. */ unsigned long rotate_files; if (get_number(key, NSSM_REG_ROTATE, &rotate_files, false) == 1) { if (rotate_files) service->rotate_files = true; else service->rotate_files = false; } else service->rotate_files = false; if (get_number(key, NSSM_REG_ROTATE_ONLINE, &rotate_files, false) == 1) { if (rotate_files) service->rotate_stdout_online = service->rotate_stderr_online = true; else service->rotate_stdout_online = service->rotate_stderr_online = false; } else service->rotate_stdout_online = service->rotate_stderr_online = false; /* Log timestamping requires a logging thread.*/ unsigned long timestamp_log; if (get_number(key, NSSM_REG_TIMESTAMP_LOG, ×tamp_log, false) == 1) { if (timestamp_log) service->timestamp_log = true; else service->timestamp_log = false; } else service->timestamp_log = false; /* Hook I/O sharing and online rotation need a pipe. */ service->use_stdout_pipe = service->rotate_stdout_online || service->timestamp_log || hook_share_output_handles; service->use_stderr_pipe = service->rotate_stderr_online || service->timestamp_log || hook_share_output_handles; if (get_number(key, NSSM_REG_ROTATE_SECONDS, &service->rotate_seconds, false) != 1) service->rotate_seconds = 0; if (get_number(key, NSSM_REG_ROTATE_BYTES_LOW, &service->rotate_bytes_low, false) != 1) service->rotate_bytes_low = 0; if (get_number(key, NSSM_REG_ROTATE_BYTES_HIGH, &service->rotate_bytes_high, false) != 1) service->rotate_bytes_high = 0; override_milliseconds(service->name, key, NSSM_REG_ROTATE_DELAY, &service->rotate_delay, NSSM_ROTATE_DELAY, NSSM_EVENT_BOGUS_THROTTLE); /* Try to get force new console setting - may fail. */ if (get_number(key, NSSM_REG_NO_CONSOLE, &service->no_console, false) != 1) service->no_console = 0; /* Change to startup directory in case stdout/stderr are relative paths. */ TCHAR cwd[PATH_LENGTH]; GetCurrentDirectory(_countof(cwd), cwd); SetCurrentDirectory(service->dir); /* Try to get stdout and stderr */ if (get_io_parameters(service, key)) { log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GET_OUTPUT_HANDLES_FAILED, service->name, 0); RegCloseKey(key); SetCurrentDirectory(cwd); return 5; } /* Change back in case the startup directory needs to be deleted. */ SetCurrentDirectory(cwd); /* Try to get mandatory restart delay */ override_milliseconds(service->name, key, NSSM_REG_RESTART_DELAY, &service->restart_delay, 0, NSSM_EVENT_BOGUS_RESTART_DELAY); /* Try to get throttle restart delay */ override_milliseconds(service->name, key, NSSM_REG_THROTTLE, &service->throttle_delay, NSSM_RESET_THROTTLE_RESTART, NSSM_EVENT_BOGUS_THROTTLE); /* Try to get service stop flags. */ unsigned long type = REG_DWORD; unsigned long stop_method_skip; unsigned long buflen = sizeof(stop_method_skip); bool stop_ok = false; ret = RegQueryValueEx(key, NSSM_REG_STOP_METHOD_SKIP, 0, &type, (unsigned char *) &stop_method_skip, &buflen); if (ret != ERROR_SUCCESS) { if (ret != ERROR_FILE_NOT_FOUND) { if (type != REG_DWORD) { log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_BOGUS_STOP_METHOD_SKIP, service->name, NSSM_REG_STOP_METHOD_SKIP, NSSM, 0); } else log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, NSSM_REG_STOP_METHOD_SKIP, error_string(ret), 0); } } else stop_ok = true; /* Try all methods except those requested to be skipped. */ service->stop_method = ~0; if (stop_ok) service->stop_method &= ~stop_method_skip; /* Try to get kill delays - may fail. */ override_milliseconds(service->name, key, NSSM_REG_KILL_CONSOLE_GRACE_PERIOD, &service->kill_console_delay, NSSM_KILL_CONSOLE_GRACE_PERIOD, NSSM_EVENT_BOGUS_KILL_CONSOLE_GRACE_PERIOD); override_milliseconds(service->name, key, NSSM_REG_KILL_WINDOW_GRACE_PERIOD, &service->kill_window_delay, NSSM_KILL_WINDOW_GRACE_PERIOD, NSSM_EVENT_BOGUS_KILL_WINDOW_GRACE_PERIOD); override_milliseconds(service->name, key, NSSM_REG_KILL_THREADS_GRACE_PERIOD, &service->kill_threads_delay, NSSM_KILL_THREADS_GRACE_PERIOD, NSSM_EVENT_BOGUS_KILL_THREADS_GRACE_PERIOD); /* Try to get process tree settings - may fail. */ unsigned long kill_process_tree; if (get_number(key, NSSM_REG_KILL_PROCESS_TREE, &kill_process_tree, false) == 1) { if (kill_process_tree) service->kill_process_tree = true; else service->kill_process_tree = false; } else service->kill_process_tree = true; /* Try to get default exit action. */ bool default_action; service->default_exit_action = NSSM_EXIT_RESTART; TCHAR action_string[ACTION_LEN]; if (! get_exit_action(service->name, 0, action_string, &default_action)) { for (int i = 0; exit_action_strings[i]; i++) { if (! _tcsnicmp((const TCHAR *) action_string, exit_action_strings[i], ACTION_LEN)) { service->default_exit_action = i; break; } } } /* Close registry */ RegCloseKey(key); return 0; }
widget::widget(const variant& v, game_logic::formula_callable* e) : environ_(e), w_(0), h_(0), x_(0), y_(0), zorder_(0), true_x_(0), true_y_(0), disabled_(false), disabled_opacity_(v["disabled_opacity"].as_int(127)), tooltip_displayed_(false), id_(v["id"].as_string_default()), align_h_(HALIGN_LEFT), align_v_(VALIGN_TOP), tooltip_display_delay_(v["tooltip_delay"].as_int(500)), tooltip_ticks_(INT_MAX), resolution_(v["frame_size"].as_int(0)), display_alpha_(v["alpha"].as_int(256)), pad_w_(0), pad_h_(0), claim_mouse_events_(v["claim_mouse_events"].as_bool(true)), draw_with_object_shader_(v["draw_with_object_shader"].as_bool(true)) { set_alpha(display_alpha_ < 0 ? 0 : (display_alpha_ > 256 ? 256 : display_alpha_)); if(v.has_key("width")) { w_ = v["width"].as_int(); } if(v.has_key("height")) { h_ = v["height"].as_int(); } if(v.has_key("wh")) { std::vector<int> iv = v["wh"].as_list_int(); ASSERT_LOG(iv.size() == 2, "WH attribute must be 2 integer elements."); w_ = iv[0]; h_ = iv[1]; } if(v.has_key("rect")) { std::vector<int> r = v["rect"].as_list_int(); ASSERT_LOG(r.size() == 4, "Four values must be supplied to the rect attribute"); set_loc(r[0], r[1]); set_dim(r[2], r[3]); } if(v.has_key("draw_area")) { std::vector<int> r = v["draw_area"].as_list_int(); ASSERT_LOG(r.size() == 4, "Four values must be supplied to the rect attribute"); set_loc(r[0], r[1]); set_dim(r[2], r[3]); } if(v.has_key("x")) { true_x_ = x_ = v["x"].as_int(); } if(v.has_key("y")) { true_y_ = y_ = v["y"].as_int(); } if(v.has_key("xy")) { std::vector<int> iv = v["xy"].as_list_int(); ASSERT_LOG(iv.size() == 2, "XY attribute must be 2 integer elements."); true_x_ = x_ = iv[0]; true_y_ = y_ = iv[1]; } zorder_ = v["zorder"].as_int(0); if(v.has_key("on_process")) { on_process_ = boost::bind(&widget::process_delegate, this); ffl_on_process_ = get_environment()->create_formula(v["on_process"]); } if(v.has_key("tooltip")) { if(v["tooltip"].is_string()) { SDL_Color color = v.has_key("tooltip_color") ? graphics::color(v["tooltip_color"]).as_sdl_color() : graphics::color_yellow(); set_tooltip(v["tooltip"].as_string(), v["tooltip_size"].as_int(18), color, v["tooltip_font"].as_string_default()); } else if(v["tooltip"].is_map()) { SDL_Color color = v["tooltip"].has_key("color") ? graphics::color(v["tooltip"]["color"]).as_sdl_color() : graphics::color_yellow(); set_tooltip(v["tooltip"]["text"].as_string(), v["tooltip"]["size"].as_int(18), color, v["tooltip"]["font"].as_string_default()); } else { ASSERT_LOG(false, "Specify the tooltip as a string, e.g. \"tooltip\":\"Text to display on mouseover\", " "or a map, e.g. \"tooltip\":{\"text\":\"Text to display.\", \"size\":14}"); } } visible_ = v["visible"].as_bool(true); if(v.has_key("align_h")) { std::string align = v["align_h"].as_string(); if(align == "left") { align_h_ = HALIGN_LEFT; } else if(align == "middle" || align == "center" || align == "centre") { align_h_ = HALIGN_CENTER; } else if(align == "right") { align_h_ = HALIGN_RIGHT; } else { ASSERT_LOG(false, "Invalid align_h attribute given: " << align); } } if(v.has_key("align_v")) { std::string align = v["align_v"].as_string(); if(align == "top") { align_v_ = VALIGN_TOP; } else if(align == "middle" || align == "center" || align == "centre") { align_v_ = VALIGN_CENTER; } else if(align == "bottom") { align_v_ = VALIGN_BOTTOM; } else { ASSERT_LOG(false, "Invalid align_v attribute given: " << align); } } disabled_ = !v["enabled"].as_bool(true); if(v.has_key("frame")) { set_frame_set(v["frame"].as_string()); } if(v.has_key("frame_padding")) { ASSERT_LOG(v["frame_padding"].is_list() && v["frame_padding"].num_elements() == 2, "'pad' must be two element list"); set_padding(v["frame_padding"][0].as_int(), v["frame_padding"][1].as_int()); } if(v.has_key("frame_pad_width")) { set_padding(v["frame_pad_width"].as_int(), get_pad_height()); } if(v.has_key("frame_pad_height")) { set_padding(get_pad_width(), v["frame_pad_height"].as_int()); } recalc_loc(); }