void ring_bell (void) { #ifdef VISUAL_BELL GC lgc; XGCValues gcv; XWindowAttributes attr; rp_screen *s = current_screen (); XGetWindowAttributes (dpy, s->input_window, &attr); gcv.function = GXxor; gcv.foreground = s->fg_color ^ s->bg_color; lgc = XCreateGC (dpy, s->input_window, GCFunction | GCForeground, &gcv); XFillRectangle (dpy, s->input_window, lgc, 0, 0, attr.width, attr.height); XFlush (dpy); usleep (15000); XFillRectangle (dpy, s->input_window, lgc, 0, 0, attr.width, attr.height); XFlush (dpy); XFreeGC (dpy, lgc); #else XBell (dpy, 0); #endif }
static void marked_message_internal (char *msg, int mark_start, int mark_end) { rp_screen *s = current_screen (); int num_lines; int width; int height; PRINT_DEBUG (("msg = %s\n", msg?msg:"NULL")); PRINT_DEBUG (("mark_start = %d, mark_end = %d\n", mark_start, mark_end)); /* Calculate the width and height of the window. */ num_lines = count_lines (msg, strlen(msg)); width = defaults.bar_x_padding * 2 + max_line_length(msg); height = FONT_HEIGHT (s) * num_lines + defaults.bar_y_padding * 2; prepare_bar (s, width, height, num_lines > 1 ? 1 : 0); if (defaults.bar_sticky) /* Sticky bar is only showing the current window title, don't mark it */ mark_start = mark_end = -1; else { /* Draw the mark over the designated part of the string. */ correct_mark (strlen (msg), &mark_start, &mark_end); draw_mark (s, msg, mark_start, mark_end); } draw_string (s, msg, mark_start, mark_end); /* Keep a record of the message. */ update_last_message (msg, mark_start, mark_end); }
static int max_line_length (char* msg) { rp_screen *s = current_screen (); size_t i; size_t start; int ret = 0; /* Count each line and keep the length of the longest one. */ for(start=0, i=0; i <= strlen(msg); i++) { if(msg[i] == '\n' || msg[i] == '\0') { int current_width; /* Check if this line is the longest so far. */ current_width = rp_text_width (s, defaults.font, msg + start, i - start); if(current_width > ret) { ret = current_width; } /* Update the start of the new line. */ start = i + 1; } } return ret; }
/* Lifted the code from rxvt. */ static char * get_primary_selection(void) { long nread; unsigned long bytes_after; XTextProperty ct; struct sbuf *s = sbuf_new(0); for (nread = 0, bytes_after = 1; bytes_after > 0; nread += ct.nitems) { if ((XGetWindowProperty(dpy, current_screen()->input_window, rp_selection, (nread / 4), 4096, True, AnyPropertyType, &ct.encoding, &ct.format, &ct.nitems, &bytes_after, &ct.value) != Success)) { XFree(ct.value); sbuf_free(s); return NULL; } if (ct.value == NULL) continue; /* Accumulate the data. FIXME: ct.value may not be NULL terminated. */ sbuf_nconcat (s, ct.value, ct.nitems); XFree(ct.value); } return sbuf_free_struct (s); }
/* The same as read_key, but handle focusing the key_window and reverting focus. */ int read_single_key (KeySym *keysym, unsigned int *modifiers, char *keysym_name, int len) { Window focus; int revert; int nbytes; XGetInputFocus (dpy, &focus, &revert); set_window_focus (current_screen()->key_window); nbytes = read_key (keysym, modifiers, keysym_name, len); set_window_focus (focus); return nbytes; }
char * get_selection (void) { Atom property; XEvent ev; rp_screen *s = current_screen (); int loops = 1000; /* Just insert our text, if we own the selection. */ if (selection.text) { return xstrdup (selection.text); } else { /* be a good icccm citizen */ XDeleteProperty (dpy, s->input_window, rp_selection); /* TODO: we shouldn't use CurrentTime here, use the time of the XKeyEvent, should we fake it? */ XConvertSelection (dpy, XA_PRIMARY, XA_STRING, rp_selection, s->input_window, CurrentTime); /* This seems like a hack. */ while (!XCheckTypedWindowEvent (dpy, s->input_window, SelectionNotify, &ev)) { if (loops == 0) { PRINT_ERROR (("selection request timed out\n")); return NULL; } usleep (10000); loops--; } PRINT_DEBUG (("SelectionNotify event\n")); property = ev.xselection.property; if (property != None) return get_primary_selection (); else return get_cut_buffer (); } }
void ring_bell (void) { #ifdef VISUAL_BELL GC lgc; XGCValues gcv; XWindowAttributes attr; rp_screen *s = current_screen (); XGetWindowAttributes (dpy, s->input_window, &attr); gcv.function = GXxor; gcv.foreground = s->fg_color ^ s->bg_color; lgc = XCreateGC (dpy, s->input_window, GCFunction | GCForeground, &gcv); XFillRectangle (dpy, s->input_window, lgc, 0, 0, attr.width, attr.height); XFlush (dpy); #ifdef HAVE_USLEEP usleep (15000); #else { struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 15000; select (0, NULL, NULL, NULL, &tv); } #endif XFillRectangle (dpy, s->input_window, lgc, 0, 0, attr.width, attr.height); XFlush (dpy); XFreeGC (dpy, lgc); #else XBell (dpy, 0); #endif }
static void skin_render_viewport(struct skin_element* viewport, struct gui_wps *gwps, struct skin_viewport* skin_viewport, unsigned long refresh_type) { struct screen *display = gwps->display; char linebuf[MAX_LINE]; skin_render_func func = skin_render_line; struct skin_element* line = viewport; struct skin_draw_info info = { .gwps = gwps, .buf = linebuf, .buf_size = sizeof(linebuf), .line_number = 0, .no_line_break = false, .line_scrolls = false, .refresh_type = refresh_type, .skin_vp = skin_viewport, .offset = 0 }; struct align_pos * align = &info.align; bool needs_update; #ifdef HAVE_LCD_BITMAP /* Set images to not to be displayed */ struct skin_token_list *imglist = gwps->data->images; while (imglist) { struct gui_img *img = (struct gui_img *)imglist->token->value.data; img->display = -1; imglist = imglist->next; } #endif while (line) { linebuf[0] = '\0'; info.no_line_break = false; info.line_scrolls = false; info.force_redraw = false; info.cur_align_start = info.buf; align->left = info.buf; align->center = NULL; align->right = NULL; if (line->type == LINE_ALTERNATOR) func = skin_render_alternator; else if (line->type == LINE) func = skin_render_line; needs_update = func(line, &info); #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) if (skin_viewport->vp.fg_pattern != skin_viewport->start_fgcolour || skin_viewport->vp.bg_pattern != skin_viewport->start_bgcolour) { /* 2bit lcd drivers need lcd_set_viewport() to be called to change * the colour, 16bit doesnt. But doing this makes static text * get the new colour also */ needs_update = true; display->set_viewport(&skin_viewport->vp); } #endif /* only update if the line needs to be, and there is something to write */ if (refresh_type && needs_update) { if (info.line_scrolls) { /* if the line is a scrolling one we don't want to update too often, so that it has the time to scroll */ if ((refresh_type & SKIN_REFRESH_SCROLL) || info.force_redraw) write_line(display, align, info.line_number, true); } else write_line(display, align, info.line_number, false); } if (!info.no_line_break) info.line_number++; line = line->next; } #ifdef HAVE_LCD_BITMAP wps_display_images(gwps, &skin_viewport->vp); #endif } void skin_render(struct gui_wps *gwps, unsigned refresh_mode) { struct wps_data *data = gwps->data; struct screen *display = gwps->display; struct skin_element* viewport = data->tree; struct skin_viewport* skin_viewport; int old_refresh_mode = refresh_mode; #ifdef HAVE_LCD_CHARCELLS int i; for (i = 0; i < 8; i++) { if (data->wps_progress_pat[i] == 0) data->wps_progress_pat[i] = display->get_locked_pattern(); } #endif viewport = data->tree; skin_viewport = (struct skin_viewport *)viewport->data; if (skin_viewport->label && viewport->next && !strcmp(skin_viewport->label,VP_DEFAULT_LABEL)) refresh_mode = 0; for (viewport = data->tree; viewport; viewport = viewport->next) { /* SETUP */ skin_viewport = (struct skin_viewport*)viewport->data; unsigned vp_refresh_mode = refresh_mode; #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1) skin_viewport->vp.fg_pattern = skin_viewport->start_fgcolour; skin_viewport->vp.bg_pattern = skin_viewport->start_bgcolour; #endif /* dont redraw the viewport if its disabled */ if (skin_viewport->hidden_flags&VP_NEVER_VISIBLE) { /* don't draw anything into this one */ vp_refresh_mode = 0; } else if ((skin_viewport->hidden_flags&VP_DRAW_HIDDEN)) { skin_viewport->hidden_flags |= VP_DRAW_WASHIDDEN; continue; } else if (((skin_viewport->hidden_flags& (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE)) == (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE))) { vp_refresh_mode = SKIN_REFRESH_ALL; skin_viewport->hidden_flags = VP_DRAW_HIDEABLE; } display->set_viewport(&skin_viewport->vp); if ((vp_refresh_mode&SKIN_REFRESH_ALL) == SKIN_REFRESH_ALL) { display->clear_viewport(); } /* render */ if (viewport->children_count) skin_render_viewport(viewport->children[0], gwps, skin_viewport, vp_refresh_mode); refresh_mode = old_refresh_mode; } /* Restore the default viewport */ display->set_viewport(NULL); display->update(); } #ifdef HAVE_LCD_BITMAP static __attribute__((noinline)) void skin_render_playlistviewer(struct playlistviewer* viewer, struct gui_wps *gwps, struct skin_viewport* skin_viewport, unsigned long refresh_type) { struct screen *display = gwps->display; char linebuf[MAX_LINE]; skin_render_func func = skin_render_line; struct skin_element* line; struct skin_draw_info info = { .gwps = gwps, .buf = linebuf, .buf_size = sizeof(linebuf), .line_number = 0, .no_line_break = false, .line_scrolls = false, .refresh_type = refresh_type, .skin_vp = skin_viewport, .offset = viewer->start_offset }; struct align_pos * align = &info.align; bool needs_update; int cur_pos, start_item, max; int nb_lines = viewport_get_nb_lines(viewer->vp); #if CONFIG_TUNER if (current_screen() == GO_TO_FM) { cur_pos = radio_current_preset(); start_item = cur_pos + viewer->start_offset; max = start_item+radio_preset_count(); } else #endif { struct cuesheet *cue = skin_get_global_state()->id3 ? skin_get_global_state()->id3->cuesheet : NULL; cur_pos = playlist_get_display_index(); max = playlist_amount()+1; if (cue) max += cue->track_count; start_item = MAX(0, cur_pos + viewer->start_offset); } if (max-start_item > nb_lines) max = start_item + nb_lines; line = viewer->line; while (start_item < max) { linebuf[0] = '\0'; info.no_line_break = false; info.line_scrolls = false; info.force_redraw = false; info.cur_align_start = info.buf; align->left = info.buf; align->center = NULL; align->right = NULL; if (line->type == LINE_ALTERNATOR) func = skin_render_alternator; else if (line->type == LINE) func = skin_render_line; needs_update = func(line, &info); /* only update if the line needs to be, and there is something to write */ if (refresh_type && needs_update) { if (info.line_scrolls) { /* if the line is a scrolling one we don't want to update too often, so that it has the time to scroll */ if ((refresh_type & SKIN_REFRESH_SCROLL) || info.force_redraw) write_line(display, align, info.line_number, true); } else write_line(display, align, info.line_number, false); } info.line_number++; info.offset++; start_item++; } }
char * get_more_input (char *prompt, char *preinput, int history_id, completion_fn compl_fn) { /* Emacs 21 uses a 513 byte string to store the keysym name. */ char keysym_buf[513]; rp_screen *s = current_screen (); KeySym ch; unsigned int modifier; rp_input_line *line; char *final_input; edit_status status; Window focus; int revert, done = 0; history_reset(); /* Create our line structure */ line = input_line_new (prompt, preinput, history_id, compl_fn); /* We don't want to draw overtop of the program bar. */ hide_bar (s); /* Switch to the default colormap. */ if (current_window()) XUninstallColormap (dpy, current_window()->colormap); XInstallColormap (dpy, s->def_cmap); XMapWindow (dpy, s->input_window); XRaiseWindow (dpy, s->input_window); XClearWindow (dpy, s->input_window); /* Switch focus to our input window to read the next key events. */ XGetInputFocus (dpy, &focus, &revert); set_window_focus (s->input_window); XSync (dpy, False); update_input_window (s, line); while (!done) { read_key (&ch, &modifier, keysym_buf, sizeof (keysym_buf)); modifier = x11_mask_to_rp_mask (modifier); PRINT_DEBUG (("ch = %ld, modifier = %d, keysym_buf = %s", ch, modifier, keysym_buf)); status = execute_edit_action (line, ch, modifier, keysym_buf); switch (status) { case EDIT_COMPLETE: case EDIT_DELETE: case EDIT_INSERT: case EDIT_MOVE: /* If the text changed (and we didn't just complete something) then set the virgin bit. */ if (status != EDIT_COMPLETE) line->compl->virgin = 1; /* In all cases, we need to redisplay the input string. */ update_input_window (s, line); break; case EDIT_NO_OP: ring_bell (); break; case EDIT_ABORT: final_input = NULL; done = 1; break; case EDIT_DONE: final_input = xstrdup (line->buffer); done = 1; break; default: PRINT_ERROR (("Unhandled status %d; this is a *BUG*\n", status)); exit (EXIT_FAILURE); } } /* Clean up our line structure */ input_line_free (line); /* Revert focus. */ set_window_focus (focus); XUnmapWindow (dpy, s->input_window); /* Possibly restore colormap. */ if (current_window()) { XUninstallColormap (dpy, s->def_cmap); XInstallColormap (dpy, current_window()->colormap); } return final_input; }
static void get_mark_box (char *msg, size_t mark_start, size_t mark_end, int *x, int *y, int *width, int *height) { rp_screen *s = current_screen (); int start, end; int mark_end_is_new_line = 0; int start_line; int end_line; int start_pos_in_line; int end_pos_in_line; int start_line_beginning; int end_line_beginning; /* If the mark_end is on a new line or the end of the string, then back it up one character. */ if (msg[mark_end-1] == '\n' || mark_end == strlen (msg)) { mark_end--; mark_end_is_new_line = 1; } start_line = count_lines(msg, mark_start); end_line = count_lines(msg, mark_end); start_pos_in_line = pos_in_line(msg, mark_start); end_pos_in_line = pos_in_line(msg, mark_end); start_line_beginning = line_beginning(msg, mark_start); end_line_beginning = line_beginning(msg, mark_end); PRINT_DEBUG (("start_line = %d, end_line = %d\n", start_line, end_line)); PRINT_DEBUG (("start_line_beginning = %d, end_line_beginning = %d\n", start_line_beginning, end_line_beginning)); if (mark_start == 0 || start_pos_in_line == 0) start = 0; else start = rp_text_width (s, defaults.font, &msg[start_line_beginning], start_pos_in_line) + defaults.bar_x_padding; end = rp_text_width (s, defaults.font, &msg[end_line_beginning], end_pos_in_line) + defaults.bar_x_padding * 2; if (mark_end != strlen (msg)) end -= defaults.bar_x_padding; /* A little hack to highlight to the end of the line, if the mark_end is at the end of a line. */ if (mark_end_is_new_line) { *width = max_line_length(msg) + defaults.bar_x_padding * 2; } else { *width = end - start; } *x = start; *y = (start_line - 1) * FONT_HEIGHT (s) + defaults.bar_y_padding; *height = (end_line - start_line + 1) * FONT_HEIGHT (s); }