static int gui_update() { int i, count; if (gui->need_update==1) { GuiWidget *cur_widget; cur_widget = (GuiWidget*)stack_get(gui->win_stack, 0); widget_update(cur_widget); count = stack_count(gui->win_stack); for (i=1; i<count -1; i++) { cur_widget = (GuiWidget *) stack_get(gui->win_stack, i); if (cur_widget && window_get_update(cur_widget) == 1) { widget_update(cur_widget); window_set_update(cur_widget, 0); } } widget_update(GET_TOP_WINDOW); SDL_Flip(screen); gui->need_update = 0; return 1; } return 0; }
void widget_enable ( widget *widget ) { if ( widget && !widget->enabled ) { widget->enabled = TRUE; widget_update ( widget ); widget_update ( widget->parent ); } }
void widget_disable ( widget *widget ) { if ( widget && widget->enabled ) { widget->enabled = FALSE; widget_update ( widget ); widget_update ( widget->parent ); } }
Save_Widget::Save_Widget() : _plugin (0), _codec_widget(0) { // Create widgets. Group_Box * codec_group = new Group_Box(label_codec_group); _codec_widget = new Radio_Button_Group(label_codec()); // Layout. Layout_Item::create_group(List<Layout_Item *>() << _codec_widget); Vertical_Layout * layout = new Vertical_Layout(this); layout->spacing(Style::global()->spacing_large()); layout->add(codec_group); codec_group->layout()->add(_codec_widget); layout->add_stretch(); // Initialize. plugin_update(); widget_update(); // Callbacks. _codec_widget->signal.set(this, codec_callback); }
Save_Widget::Save_Widget() : _plugin (0), _compression_widget(0) { //DJV_DEBUG("Save_Widget::Save_Widget"); // Create widgets. Group_Box * group = new Group_Box(label_compression_group); _compression_widget = new Radio_Button_Group(label_compression()); // Layout. Vertical_Layout * layout = new Vertical_Layout(this); layout->margin(Style::global()->margin_large()); layout->spacing(Style::global()->spacing_large()); layout->add(group); group->layout()->add(_compression_widget); layout->add_stretch(); // Initialize. plugin_update(); widget_update(); // Callbacks. _compression_widget->signal.set(this, compression_callback); }
void Magnify_Dialog::set(const View_Widget * in, const V2i & pick) { _view = in; _pick = pick; widget_update(); }
void File_Browser::set(const File & in) { if (in == _value) { return; } //DJV_DEBUG("File_Browser::set"); //DJV_DEBUG_PRINT("in = " << in); const String directory = _value.path(); _value = in; if (_seq && _value.is_seq_valid()) { _value.type(File::SEQ); } if (_value.path() != directory) { _directory_prev = directory; directory_update(); } widget_update(); }
// set the default text to display void textbox_text ( textbox *tb, const char *text ) { tb->update = TRUE; g_free ( tb->text ); const gchar *last_pointer = NULL; if ( g_utf8_validate ( text, -1, &last_pointer ) ) { tb->text = g_strdup ( text ); } else { if ( last_pointer != NULL ) { // Copy string up to invalid character. tb->text = g_strndup ( text, ( last_pointer - text ) ); } else { tb->text = g_strdup ( "Invalid UTF-8 string." ); } } __textbox_update_pango_text ( tb ); if ( tb->flags & TB_AUTOWIDTH ) { textbox_moveresize ( tb, tb->widget.x, tb->widget.y, tb->widget.w, tb->widget.h ); if ( WIDGET ( tb )->parent ) { widget_update ( WIDGET ( tb )->parent ); } } tb->cursor = MAX ( 0, MIN ( ( int ) g_utf8_strlen ( tb->text, -1 ), tb->cursor ) ); widget_queue_redraw ( WIDGET ( tb ) ); }
static void box_resize ( widget *widget, short w, short h ) { box *b = (box *) widget; if ( b->widget.w != w || b->widget.h != h ) { b->widget.w = w; b->widget.h = h; widget_update ( widget ); } }
void Magnify_Dialog::update(const View_Widget * in) { if (in != _view || ! shown() || ! visible()) { return; } widget_update(); }
void Display_Profile_Dialog::set( const View_Widget * in, const Display_Profile & value) { _view = in; _value = value; widget_update(); }
Save_Widget::Save_Widget() : _plugin (0), _color_profile_widget(0), _black_widget (0), _white_widget (0), _gamma_widget (0) { // Create color profile widgets. Group_Box * color_profile_group = new Group_Box(label_color_profile_group); _color_profile_widget = new Radio_Button_Group(label_color_profile()); Group_Box * film_print_group = new Group_Box(label_film_print_group); _black_widget = new Int_Edit_Slider(0, 1023); _white_widget = new Int_Edit_Slider(0, 1023); _gamma_widget = new Float_Edit_Slider(0.01, 4.0); // Layout. Vertical_Layout * layout = new Vertical_Layout(this); layout->margin(Style::global()->margin_large()); layout->spacing(Style::global()->spacing_large()); layout->add(color_profile_group); color_profile_group->layout()->add(_color_profile_widget); color_profile_group->layout()->add(film_print_group); Form_Widget * form_widget = new Form_Widget; film_print_group->layout()->add(form_widget); form_widget->add_row(label_film_print_black, _black_widget); form_widget->add_row(label_film_print_white, _white_widget); form_widget->add_row(label_film_print_gamma, _gamma_widget); layout->add_stretch(); // Initialize. _black_widget->default_value(Save::Options().film_print.black); _white_widget->default_value(Save::Options().film_print.white); _gamma_widget->default_value(Save::Options().film_print.gamma); plugin_update(); widget_update(); // Callbacks. _color_profile_widget->signal.set(this, color_profile_callback); _black_widget->signal.set(this, black_callback); _white_widget->signal.set(this, white_callback); _gamma_widget->signal.set(this, gamma_callback); }
Text_Display::Text_Display(const String & in) : _value(in), _widget(0) { debug_path("Text_Display"); add(_widget = new Widget); widget_update(); }
void Display_Profile_Dialog::update( const View_Widget * in, const Display_Profile & value) { if (in != _view) { return; } _value = value; widget_update(); }
void Text_Display::set(const String & in) { if (in == _value) { return; } //DJV_DEBUG("Text_Display::set"); //DJV_DEBUG_PRINT("in = " << in); _value = in; widget_update(); }
Application_Message_Dialog::Application_Message_Dialog() : Dialog("Messages"), _show (true), _widget (0), _show_widget (0), _clear_widget(0), _close_widget(0) { // Create widgets. _widget = new Multiline_Text_Display; _show_widget = new Check_Button("&Show"); _clear_widget = new Push_Button("&Clear"); _close_widget = new Push_Button("Clos&e"); // Layout. Vertical_Layout * layout = new Vertical_Layout(this); layout->add(_widget); layout->stretch(_widget); Horizontal_Layout * layout_h = new Horizontal_Layout(layout); layout_h->margin(0); layout_h->add(_show_widget); layout_h->add_stretch(); layout_h->add(_clear_widget); layout_h->add(_close_widget); layout_h->add_spacer(Layout::window_handle_size()); // Preferences. Prefs prefs(Prefs::prefs_global(), "application_message_dialog"); Prefs::get_(&prefs, "show", &_show); // Initialize. widget_update(); dialog_update(); size(size_hint()); // Callbacks. _show_widget->signal.set(this, show_callback); _clear_widget->signal.set(this, clear_callback); _close_widget->signal.set(this, close_callback); }
void File_Browser::seq(Seq::COMPRESS in) { if (in == _seq) { return; } _seq = in; _prefs->seq(_seq); directory_update(); widget_update(); menu_update(); }
void Application_Message_Dialog::set(const String & in) { _list.push_front(in); if (_list.size() > 100) { _list.pop_back(); } widget_update(); if (_show) { show(); } }
void File_Browser::show() { //DJV_DEBUG("File_Browser::show"); if (! shown()) { //_value = File_Util::path_absolute("."); directory_update(); widget_update(); _value_widget->take_focus(); } Dialog::show(); }
Magnify_Dialog::Magnify_Dialog() : Dialog("Magnify"), _view (0), _zoom (ZOOM_200), _widget (0), _zoom_widget (0), _close_widget(0) { // Create widgets. _widget = new Magnify_Widget; _zoom_widget = new Choice_Widget(label_zoom()); _close_widget = new Push_Button(label_close); // Layout. Vertical_Layout * layout = new Vertical_Layout(this); layout->add(_widget); layout->stretch(_widget); Horizontal_Layout * layout_h = new Horizontal_Layout(layout); layout_h->margin(0); layout_h->add(_zoom_widget); layout_h->add_spacer(-1, true); layout_h->add(_close_widget); layout_h->add_spacer(Layout::window_handle_size()); // Preferences. Prefs prefs(Prefs::prefs(), "magnify_dialog"); Prefs::get_(&prefs, "zoom", &_zoom); // Initialize. widget_update(); size(Vector_Util::max(size_hint(), V2i(300, 300))); // Callbacks. _zoom_widget->signal.set(this, zoom_callback); _close_widget->signal.set(this, close_callback); }
void* widget_main (struct widget *widget) { struct widget_config config = widget_config_defaults; widget_init_config_string(widget->config, "date_format", config.date_format); widget_init_config_string(widget->config, "time_format", config.time_format); widget_init_config_integer(widget->config, "refresh_interval", config.refresh_interval); widget_epoll_init(widget); while (true) { widget_update(widget, config); widget_epoll_wait_goto(widget, config.refresh_interval, cleanup); } cleanup: widget_epoll_cleanup(widget); widget_clean_exit(widget); }
void box_add ( box *box, widget *child, gboolean expand ) { if ( box == NULL ) { return; } // Make sure box is width/heigh enough. if ( box->type == ROFI_ORIENTATION_VERTICAL ) { int width = box->widget.w; width = MAX ( width, child->w + widget_padding_get_padding_width ( WIDGET ( box ) ) ); box->widget.w = width; } else { int height = box->widget.h; height = MAX ( height, child->h + widget_padding_get_padding_height ( WIDGET ( box ) ) ); box->widget.h = height; } child->expand = rofi_theme_get_boolean ( child, "expand", expand ); g_assert ( child->parent == WIDGET ( box ) ); box->children = g_list_append ( box->children, (void *) child ); widget_update ( WIDGET ( box ) ); }
void Magnify_Dialog::zoom_callback(int in) { _zoom = static_cast<ZOOM>(in); widget_update(); }
void Display_Profile_Dialog::widget_callback(const Display_Profile & in) { _value = in; widget_update(); }
Display_Profile_Dialog::Display_Profile_Dialog() : Dialog("Display Profile"), signal (this), _view (0), _lut_widget (0), _brightness_widget(0), _contrast_widget (0), _saturation_widget(0), _gamma_widget (0), _soft_clip_widget (0), _close_widget (0) { // Create LUT widgets. Group_Box * lut_group = new Group_Box(label_lut); _lut_widget = new File_Edit; // Create color widgets. Group_Box * color_group = new Group_Box(label_color); _brightness_widget = new Float_Edit_Slider; _brightness_widget->default_value(_value.color.brightness); _brightness_widget->range(0.0, 4.0); _contrast_widget = new Float_Edit_Slider; _contrast_widget->default_value(_value.color.contrast); _contrast_widget->range(0.0, 4.0); _saturation_widget = new Float_Edit_Slider; _saturation_widget->default_value(_value.color.saturation); _saturation_widget->range(0.0, 4.0); // Create levels widgets. Group_Box * levels_group = new Group_Box(label_levels); _levels_in_widget[0] = new Float_Edit_Slider; _levels_in_widget[0]->default_value(_value.levels.in_low); _levels_in_widget[0]->range(0.0, 1.0); _levels_in_widget[1] = new Float_Edit_Slider; _levels_in_widget[1]->default_value(_value.levels.in_high); _levels_in_widget[1]->range(0.0, 1.0); _gamma_widget = new Float_Edit_Slider; _gamma_widget->default_value(_value.levels.gamma); _gamma_widget->range(0.0, 4.0); _levels_out_widget[0] = new Float_Edit_Slider; _levels_out_widget[0]->default_value(_value.levels.out_low); _levels_out_widget[0]->range(0.0, 1.0); _levels_out_widget[1] = new Float_Edit_Slider; _levels_out_widget[1]->default_value(_value.levels.out_high); _levels_out_widget[1]->range(0.0, 1.0); _soft_clip_widget = new Float_Edit_Slider; _soft_clip_widget->default_value(_value.soft_clip); _soft_clip_widget->range(0.0, 1.0); // Create dialog widgets. _close_widget = new Push_Button(label_close); // Layout. Vertical_Layout * layout = new Vertical_Layout(this); layout->add(lut_group); lut_group->layout()->add(_lut_widget); layout->add(color_group); Form_Widget * form_widget = new Form_Widget; color_group->layout()->add(form_widget); form_widget->add_row(label_brightness, _brightness_widget); form_widget->add_row(label_contrast, _contrast_widget); form_widget->add_row(label_saturation, _saturation_widget); layout->add(levels_group); form_widget = new Form_Widget; levels_group->layout()->add(form_widget); form_widget->add_row(label_levels_in, _levels_in_widget[0]); form_widget->add_row(String(), _levels_in_widget[1]); form_widget->add_row(label_gamma, _gamma_widget); form_widget->add_row(label_levels_out, _levels_out_widget[0]); form_widget->add_row(String(), _levels_out_widget[1]); form_widget->add_row(label_soft_clip, _soft_clip_widget); layout->add_spacer(-1, true); Horizontal_Layout * layout_h = new Horizontal_Layout(layout); layout_h->margin(0); layout_h->add_stretch(); layout_h->add(_close_widget); layout_h->add_spacer(Layout::window_handle_size()); // Initialize. widget_update(); size(size_hint()); // Callbacks. _lut_widget->signal.set(this, lut_callback); _brightness_widget->signal.set(this, brightness_callback); _contrast_widget->signal.set(this, contrast_callback); _saturation_widget->signal.set(this, saturation_callback); _levels_in_widget[0]->signal.set(this, levels_in0_callback); _levels_in_widget[1]->signal.set(this, levels_in1_callback); _gamma_widget->signal.set(this, gamma_callback); _levels_out_widget[0]->signal.set(this, levels_out0_callback); _levels_out_widget[1]->signal.set(this, levels_out1_callback); _soft_clip_widget->signal.set(this, soft_clip_callback); _close_widget->signal.set(this, close_callback); }
void Application_Message_Dialog::clear_callback(bool) { _list.clear(); widget_update(); }
int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv ) { { box *b = box_create ( "box", BOX_HORIZONTAL ); //box_set_padding ( b, 5 ); widget_resize ( WIDGET (b), 100, 20); widget *wid1 = g_malloc0(sizeof(widget)); box_add ( b , WIDGET( wid1 ), TRUE, 0 ); // Widget not enabled. no width allocated. TASSERTE ( wid1->h, 0); TASSERTE ( wid1->w, 0 ); widget_enable ( WIDGET ( wid1 ) ); widget_update ( WIDGET ( b ) ) ; // Widget enabled. so width allocated. TASSERTE ( wid1->h, 20); TASSERTE ( wid1->w, 100 ); widget *wid2 = g_malloc0(sizeof(widget)); widget_enable ( WIDGET ( wid2 ) ); box_add ( b , WIDGET( wid2 ), TRUE, 1 ); TASSERTE ( wid1->h, 20); TASSERTE ( wid1->w, 49); TASSERTE ( wid2->h, 20); TASSERTE ( wid2->w, 49); widget *wid3 = g_malloc0(sizeof(widget)); widget_enable ( WIDGET ( wid3 ) ); box_add ( b , WIDGET( wid3 ), FALSE, 2 ); TASSERTE ( wid1->h, 20); TASSERTE ( wid1->w, 48); TASSERTE ( wid2->h, 20); TASSERTE ( wid2->w, 48); widget_resize ( WIDGET (wid3) , 20, 10 ); // TODO should this happen automagically? widget_update ( WIDGET ( b ) ) ; TASSERTE ( wid1->h, 20); TASSERTE ( wid1->w, 38); TASSERTE ( wid2->h, 20); TASSERTE ( wid2->w, 38); TASSERTE ( wid3->h, 20); TASSERTE ( wid3->w, 20); widget_resize ( WIDGET (b ), 200, 20 ); TASSERTE ( wid1->h, 20); TASSERTE ( wid1->w, 88); TASSERTE ( wid2->h, 20); TASSERTE ( wid2->w, 88); TASSERTE ( wid3->h, 20); TASSERTE ( wid3->w, 20); // TASSERTE ( box_get_fixed_pixels ( b ) , 24 ); widget *wid4 = g_malloc0(sizeof(widget)); widget_enable ( WIDGET ( wid4 ) ); widget_resize ( WIDGET ( wid4 ), 20, 20 ); box_add ( b , WIDGET( wid4 ), FALSE, 5 ); TASSERTE ( wid4->x, 200-20); widget *wid5 = g_malloc0(sizeof(widget)); widget_enable ( WIDGET ( wid5 ) ); widget_resize ( WIDGET ( wid5 ), 20, 20 ); box_add ( b , WIDGET( wid5 ), TRUE, 6 ); TASSERTE ( wid5->x, 149); widget_free ( WIDGET ( b ) ); } { box *b = box_create ( "box", BOX_VERTICAL ); widget_resize ( WIDGET (b), 20, 100); //box_set_padding ( b, 5 ); widget *wid1 = g_malloc0(sizeof(widget)); box_add ( b , WIDGET( wid1 ), TRUE, 0 ); // Widget not enabled. no width allocated. TASSERTE ( wid1->h, 0); TASSERTE ( wid1->w, 0 ); widget_enable ( WIDGET ( wid1 ) ); widget_update ( WIDGET ( b ) ) ; // Widget enabled. so width allocated. TASSERTE ( wid1->h, 100); TASSERTE ( wid1->w, 20 ); widget *wid2 = g_malloc0(sizeof(widget)); widget_enable ( WIDGET ( wid2 ) ); box_add ( b , WIDGET( wid2 ), TRUE, 1 ); TASSERTE ( wid1->w, 20); TASSERTE ( wid1->h, 49); TASSERTE ( wid2->w, 20); TASSERTE ( wid2->h, 49); widget *wid3 = g_malloc0(sizeof(widget)); widget_enable ( WIDGET ( wid3 ) ); box_add ( b , WIDGET( wid3 ), FALSE, 2 ); TASSERTE ( wid1->w, 20); TASSERTE ( wid1->h, 48); TASSERTE ( wid2->w, 20); TASSERTE ( wid2->h, 48); widget_resize ( WIDGET (wid3) , 10, 20 ); // TODO should this happen automagically? widget_update ( WIDGET ( b ) ) ; TASSERTE ( wid1->w, 20); TASSERTE ( wid1->h, 48); TASSERTE ( wid2->w, 20); TASSERTE ( wid2->h, 48); TASSERTE ( wid3->w, 20); TASSERTE ( wid3->h, 0); widget_resize ( WIDGET (b ), 20, 200 ); TASSERTE ( wid1->w, 20); TASSERTE ( wid1->h, 98); TASSERTE ( wid2->w, 20); TASSERTE ( wid2->h, 98); TASSERTE ( wid3->w, 20); // has no height, gets no height. TASSERTE ( wid3->h, 0); // TASSERTE ( box_get_fixed_pixels ( b ) , 4 ); widget *wid4 = g_malloc0(sizeof(widget)); widget_enable ( WIDGET ( wid4 ) ); widget_resize ( WIDGET ( wid4 ), 20, 20 ); box_add ( b , WIDGET( wid4 ), FALSE, 5 ); TASSERTE ( wid4->y, 200); widget *wid5 = g_malloc0(sizeof(widget)); widget_enable ( WIDGET ( wid5 ) ); widget_resize ( WIDGET ( wid5 ), 20, 20 ); box_add ( b , WIDGET( wid5 ), TRUE, 6 ); TASSERTE ( wid5->y, 136); widget_free ( WIDGET ( b ) ); } { box *b = box_create ( "box", BOX_VERTICAL ); widget_resize ( WIDGET (b), 20, 100); //box_set_padding ( b, 5 ); widget *wid1 = g_malloc0(sizeof(widget)); widget_enable(wid1); wid1->clicked = test_widget_clicked; box_add ( b , WIDGET( wid1 ), TRUE, 0 ); widget *wid2 = g_malloc0(sizeof(widget)); widget_enable(wid2); box_add ( b , WIDGET( wid2 ), TRUE, 1 ); xcb_button_press_event_t xce; xce.event_x = 10; xce.event_y = 60; TASSERTE ( widget_clicked ( WIDGET(b), &xce ), 0); xce.event_y = 50; TASSERTE ( widget_clicked ( WIDGET(b), &xce ), 0); xce.event_y = 48; TASSERTE ( widget_clicked ( WIDGET(b), &xce ), 1); widget_disable ( wid2 ); xce.event_y = 60; TASSERTE ( widget_clicked ( WIDGET(b), &xce ), 1); widget_disable ( wid1 ); widget_enable ( wid2 ); TASSERTE ( widget_clicked ( WIDGET(b), &xce ), 0); widget_free ( WIDGET ( b ) ); } }
void Save_Widget::set(Image_Io_Base * in) { _plugin = in; widget_update(); }
void* widget_main (struct widget *widget) { unsigned short i; int xcb_fd; int screen_nbr = 0; xcb_connection_t *conn = xcb_connect(NULL, NULL); xcb_ewmh_connection_t *ewmh = malloc(sizeof(xcb_ewmh_connection_t)); struct epoll_event xcb_event; widget_epoll_init(widget); if (xcb_connection_has_error(conn)) { LOG_ERR("could not connect to display %s", getenv("DISPLAY")); goto cleanup; } xcb_intern_atom_cookie_t *ewmh_cookie = xcb_ewmh_init_atoms(conn, ewmh); xcb_ewmh_init_atoms_replies(ewmh, ewmh_cookie, NULL); uint32_t values[] = { XCB_EVENT_MASK_PROPERTY_CHANGE }; xcb_generic_event_t *evt; xcb_generic_error_t *err = xcb_request_check(ewmh->connection, xcb_change_window_attributes_checked(ewmh->connection, ewmh->screens[screen_nbr]->root, XCB_CW_EVENT_MASK, values)); if (err != NULL) { LOG_ERR("could not request EWMH property change notifications"); goto cleanup; } xcb_fd = xcb_get_file_descriptor(ewmh->connection); xcb_event.data.fd = xcb_fd; xcb_event.events = EPOLLIN | EPOLLET; if (epoll_ctl(efd, EPOLL_CTL_ADD, xcb_fd, &xcb_event) == -1) { LOG_ERR("failed to add fd to epoll instance: %s", strerror(errno)); return 0; } widget_update(widget, ewmh, screen_nbr); while (true) { while ((nfds = epoll_wait(efd, events, MAX_EVENTS, -1)) > 0) { for (i = 0; i < nfds; i++) { if (events[i].data.fd == widget->bar->efd) { goto cleanup; } } while ((evt = xcb_poll_for_event(ewmh->connection)) != NULL) { xcb_property_notify_event_t *pne; switch (XCB_EVENT_RESPONSE_TYPE(evt)) { case XCB_PROPERTY_NOTIFY: pne = (xcb_property_notify_event_t*)evt; if (pne->atom == ewmh->_NET_DESKTOP_NAMES) { widget_update(widget, ewmh, screen_nbr); } else if (pne->atom == ewmh->_NET_NUMBER_OF_DESKTOPS) { widget_update(widget, ewmh, screen_nbr); } else if (pne->atom == ewmh->_NET_CURRENT_DESKTOP) { widget_update(widget, ewmh, screen_nbr); } default: break; } free(evt); } } } cleanup: if (ewmh != NULL) { xcb_ewmh_connection_wipe(ewmh); } if (conn != NULL) { xcb_disconnect(conn); } widget_epoll_cleanup(widget); widget_clean_exit(widget); }
static int widget_update (struct widget *widget, struct widget_config config) { CURL *curl; CURLcode status; char *data; long code; /* connect and handle IMAP responses */ curl = curl_easy_init(); data = malloc(CURL_BUF_SIZE); if (!curl || !data) { return 0; } write_result_t write_result = { .data = data, .pos = 0 }; curl_easy_setopt(curl, CURLOPT_USERNAME, config.username); curl_easy_setopt(curl, CURLOPT_PASSWORD, config.password); curl_easy_setopt(curl, CURLOPT_URL, config.address); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "SEARCH UNSEEN"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, candybar_curl_write_response); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_result); if (config.ssl_verify) { curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); } status = curl_easy_perform(curl); if (status != CURLE_OK) { LOG_ERR("unable to request data from %s (this error may be temporary): %s", config.address, curl_easy_strerror(status)); return 0; } curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); if (code != 0) { LOG_ERR("server responded with code %ld", code); return 0; } curl_easy_cleanup(curl); curl_global_cleanup(); data[write_result.pos] = '\0'; /* count unread message IDs */ /* the server responds with a string like "* SEARCH 1 2 3 4" where the numbers are message IDs */ char *str, *saveptr, *delim = " *"; int unread = -1; str = strtok_r(data, delim, &saveptr); while (str != NULL) { str = strtok_r(NULL, delim, &saveptr); unread++; } free(data); widget_data_callback(widget, widget_data_arg_number(unread), widget_data_arg_string(config.username)); return 0; } static const char* next (const char *ch, int space) { while (*ch && !isspace(*ch) == !space) { ++ch; } return ch; } static int parse_cmdline_arguments (const char *password_command, struct Process *proc) { const char *start = next(password_command, 1); if (!*start) { return -1; } const char *end = next(start, 0); if (!*end) { proc->path = strdup(start); } else { proc->path = strndup(start, end - start); } proc->argv = calloc(1024, sizeof(char*)); proc->argv[0] = proc->path; int argv_idx = 1; while ((start = next(end, 1))) { end = next(start, 0); if (!*end) { proc->argv[argv_idx++] = strdup(start); break; } else { proc->argv[argv_idx++] = strndup(start, end - start); } } return 1; } void* widget_main (struct widget *widget) { struct widget_config config = widget_config_defaults; widget_init_config_string(widget->config, "address", config.address); widget_init_config_string(widget->config, "username", config.username); widget_init_config_string(widget->config, "password", config.password); widget_init_config_string(widget->config, "password_command", config.password_command); widget_init_config_boolean(widget->config, "ssl_verify", config.ssl_verify); widget_init_config_integer(widget->config, "refresh_interval", config.refresh_interval); if (!config.username) { LOG_INFO("email_imap: username not set, disabling widget"); return 0; } struct Buffer buffer; memset(&buffer, 0, sizeof(buffer)); if (strlen(config.password_command)) { struct Process proc; memset(&proc, 0, sizeof(proc)); proc.stderr_cb = write_stderr; proc.stdout_cb = write_stdout; proc.user_data = &buffer; if (parse_cmdline_arguments(config.password_command, &proc) == -1) { LOG_ERR("email_imap: cannot parse password_command: \"%s\"", config.password_command); return 0; } const int ret = process(&proc); free_process(&proc); if (ret != 0) { LOG_ERR("email_imap: process error: %s => %d: %s/%s\n", proc.path, ret, proc.error, buffer.stderr_buffer); return 0; } config.password = buffer.stdout_buffer; } widget_epoll_init(widget); while (true) { widget_update(widget, config); widget_epoll_wait_goto(widget, config.refresh_interval, cleanup); } cleanup: widget_epoll_cleanup(widget); widget_clean_exit(widget); free_buffer(&buffer); }