Пример #1
0
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
}
Пример #2
0
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);
}
Пример #3
0
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;
}
Пример #4
0
/* 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);
}
Пример #5
0
/* 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;
}
Пример #6
0
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 ();
    }
}
Пример #7
0
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
}
Пример #8
0
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++;
    }
}
Пример #9
0
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;
}
Пример #10
0
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);
}