diff options
Diffstat (limited to 'src/bar.c')
-rw-r--r-- | src/bar.c | 607 |
1 files changed, 0 insertions, 607 deletions
diff --git a/src/bar.c b/src/bar.c deleted file mode 100644 index 8af3308..0000000 --- a/src/bar.c +++ /dev/null @@ -1,607 +0,0 @@ -/* Functionality for a bar across the bottom of the screen listing the - * windows currently managed. - * - * Copyright (C) 2000, 2001, 2002, 2003, 2004 Shawn Betts <sabetts@vcn.bc.ca> - * - * This file is part of ratpoison. - * - * ratpoison is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * ratpoison is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - */ - -#include <X11/X.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> - -#ifdef USE_XFT_FONT -#include <X11/Xft/Xft.h> -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "ratpoison.h" - -#include "assert.h" - -/* Possible values for bar_is_raised status. */ -#define BAR_IS_HIDDEN 0 -#define BAR_IS_WINDOW_LIST 1 -#define BAR_IS_MESSAGE 2 - -/* A copy of the last message displayed in the message bar. */ -static char *last_msg = NULL; -static int last_mark_start = 0; -static int last_mark_end = 0; - -static void marked_message_internal (char *msg, int mark_start, int mark_end); - -/* Reset the alarm to auto-hide the bar in BAR_TIMEOUT seconds. */ -static void -reset_alarm (void) -{ - alarm (defaults.bar_timeout); - alarm_signalled = 0; -} - -/* Hide the bar from sight. */ -int -hide_bar (rp_screen *s) -{ - if (s->bar_is_raised) - { - s->bar_is_raised = 0; - XUnmapWindow (dpy, s->bar_window); - - /* Possibly restore colormap. */ - if (current_window()) - { - XUninstallColormap (dpy, s->def_cmap); - XInstallColormap (dpy, current_window()->colormap); - } - - return 1; - } - - return 0; -} - -/* Show window listing in bar. */ -int -show_bar (rp_screen *s, char *fmt) -{ - if (!s->bar_is_raised) - { - s->bar_is_raised = BAR_IS_WINDOW_LIST; - XMapRaised (dpy, s->bar_window); - update_window_names (s, fmt); - - /* Switch to the default colormap */ - if (current_window()) - XUninstallColormap (dpy, current_window()->colormap); - XInstallColormap (dpy, s->def_cmap); - - reset_alarm(); - return 1; - } - - /* If the bar is raised we still need to display the window - names. */ - update_window_names (s, fmt); - return 0; -} - -int -bar_x (rp_screen *s, int width) -{ - int x = 0; - - switch (defaults.bar_location) - { - case NorthWestGravity: - case WestGravity: - case SouthWestGravity: - x = s->left + (defaults.bar_in_padding ? 0 : defaults.padding_left); - break; - case NorthGravity: - case CenterGravity: - case SouthGravity: - x = s->left + (s->width - width - defaults.bar_border_width * 2) / 2 - - (defaults.bar_in_padding ? 0 : defaults.padding_left); - break; - case NorthEastGravity: - case EastGravity: - case SouthEastGravity: - x = s->left + s->width - width - defaults.bar_border_width * 2 - - (defaults.bar_in_padding ? 0 : defaults.padding_right); - break; - } - - return x; -} - -int -bar_y (rp_screen *s, int height) -{ - int y = 0; - - switch (defaults.bar_location) - { - case NorthEastGravity: - case NorthGravity: - case NorthWestGravity: - y = s->top + (defaults.bar_in_padding ? 0 : defaults.padding_top); - break; - case EastGravity: - case CenterGravity: - case WestGravity: - y = s->top + (s->height - height - - defaults.bar_border_width * 2) / 2 - - (defaults.bar_in_padding ? 0 : defaults.padding_top); - break; - case SouthEastGravity: - case SouthGravity: - case SouthWestGravity: - y = s->top + (s->height - height - - defaults.bar_border_width * 2) - - (defaults.bar_in_padding ? 0 : defaults.padding_top); - break; - } - - return y; -} - -void -update_bar (rp_screen *s) -{ - if (s->bar_is_raised == BAR_IS_WINDOW_LIST) { - update_window_names (s, defaults.window_fmt); - return; - } - - if (s->bar_is_raised == BAR_IS_HIDDEN) - return; - - redraw_last_message(); -} - -/* Note that we use marked_message_internal to avoid resetting the - alarm. */ -void -update_window_names (rp_screen *s, char *fmt) -{ - struct sbuf *bar_buffer; - int mark_start = 0; - int mark_end = 0; - - if (s->bar_is_raised != BAR_IS_WINDOW_LIST) return; - - bar_buffer = sbuf_new (0); - - if(defaults.window_list_style == STYLE_ROW) - { - get_window_list (fmt, NULL, bar_buffer, &mark_start, &mark_end); - marked_message_internal (sbuf_get (bar_buffer), mark_start, mark_end); - } - else - { - get_window_list (fmt, "\n", bar_buffer, &mark_start, &mark_end); - marked_message_internal (sbuf_get (bar_buffer), mark_start, mark_end); - } - - -/* marked_message (sbuf_get (bar_buffer), mark_start, mark_end); */ - sbuf_free (bar_buffer); -} - -void -message (char *s) -{ - marked_message (s, 0, 0); -} - -void -marked_message_printf (int mark_start, int mark_end, char *fmt, ...) -{ - char *buffer; - va_list ap; - - va_start (ap, fmt); - buffer = xvsprintf (fmt, ap); - va_end (ap); - - marked_message (buffer, mark_start, mark_end); - free (buffer); -} - -static int -count_lines (char* msg, int len) -{ - int ret = 1; - int i; - - if (len < 1) - return 1; - - for(i=0; i<len; i++) - { - if (msg[i] == '\n') ret++; - } - - return ret; -} - - -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, msg + start, i - start); - if(current_width > ret) - { - ret = current_width; - } - - /* Update the start of the new line. */ - start = i + 1; - } - } - - return ret; -} - -static int -pos_in_line (char* msg, int pos) -{ - int ret; - int i; - - if(pos <= 0) - return 0; - - /* Go backwards until we hit the beginning of the string or a new - line. */ - ret = 0; - for(i=pos-1; i>=0; ret++, i--) - { - if(msg[i]=='\n') - break; - } - - return ret; -} - -static int -line_beginning (char* msg, int pos) -{ - int ret = 0; - int i; - - if(pos <= 0) - return 0; - - /* Go backwards until we hit a new line or the beginning of the - string. */ - for(i=pos-1; i>=0; --i) - { - if (msg[i]=='\n') - { - ret = i + 1; - break; - } - } - - return ret; -} - -static void -draw_partial_string (rp_screen *s, char *msg, int line_no, int start, int end, int style) -{ - int line_height = FONT_HEIGHT (s); - - rp_draw_string (s, s->bar_window, style, - defaults.bar_x_padding, - defaults.bar_y_padding + FONT_ASCENT(s) - + line_no * line_height, - msg + start, end - start + 1); -} - -static void -draw_string (rp_screen *s, char *msg, int mark_start, int mark_end) -{ - size_t i; - int line_no; - int start; - int style = STYLE_NORMAL, update = 0; - - /* Walk through the string, print each line. */ - start = 0; - line_no = 0; -/* if (mark_start == 0 && mark_end == 0) */ -/* mark_start = mark_end = -1; */ - - for(i=0; i < strlen(msg); ++i) - { - if (i == (size_t)mark_start) - { - style = STYLE_INVERSE; - update = 1; - } - if (i == (size_t)mark_end) - { - style = STYLE_NORMAL; - update = 1; - } - if (msg[i] == '\n') - update = 2; - - if (update) - { - draw_partial_string (s, msg, line_no, start, update == 2 ? i-1:i, style); - start = i; - if (update == 2) - { - line_no++; - start++; - } - update = 0; - } - } - - /* Print the last line. */ - draw_partial_string (s, msg, line_no, start, strlen (msg)-1, style); - XSync (dpy, False); -} - -/* Move the marks if they are outside the string or if the start is - after the end. */ -static void -correct_mark (int msg_len, int *mark_start, int *mark_end) -{ - /* Make sure the marks are inside the string. */ - if (*mark_start < 0) - *mark_start = 0; - - if (*mark_end < 0) - *mark_end = 0; - - if (*mark_start > msg_len) - *mark_start = msg_len; - - if (*mark_end > msg_len) - *mark_end = msg_len; - - /* Make sure the marks aren't reversed. */ - if (*mark_start > *mark_end) - { - int tmp; - tmp = *mark_start; - *mark_start = *mark_end; - *mark_end = tmp; - } - -} - -/* Raise the bar and put it in the right spot */ -static void -prepare_bar (rp_screen *s, int width, int height) -{ - width = width < s->width ? width : s->width; - height = height < s->height ? height : s->height; - XMoveResizeWindow (dpy, s->bar_window, - bar_x (s, width), bar_y (s, height), - width, height); - - /* Map the bar if needed */ - if (!s->bar_is_raised) - { - s->bar_is_raised = BAR_IS_MESSAGE; - XMapRaised (dpy, s->bar_window); - - /* Switch to the default colormap */ - if (current_window()) - XUninstallColormap (dpy, current_window()->colormap); - XInstallColormap (dpy, s->def_cmap); - } - - XRaiseWindow (dpy, s->bar_window); - XClearWindow (dpy, s->bar_window); - XSync (dpy, False); -} - -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, &msg[start_line_beginning], - start_pos_in_line) + defaults.bar_x_padding; - - end = rp_text_width (s, &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); -} - -static void -draw_box (rp_screen *s, int x, int y, int width, int height) -{ - XGCValues lgv; - GC lgc; - unsigned long mask; - - lgv.foreground = s->fg_color; - mask = GCForeground; - lgc = XCreateGC(dpy, s->root, mask, &lgv); - - XFillRectangle (dpy, s->bar_window, lgc, - x, y, width, height); - XFreeGC (dpy, lgc); -} - -static void -draw_mark (rp_screen *s, char *msg, int mark_start, int mark_end) -{ - int x, y, width, height; - - /* when this happens, there is no mark. */ - if (mark_end == 0 || mark_start == mark_end) - return; - - get_mark_box (msg, mark_start, mark_end, - &x, &y, &width, &height); - draw_box (s, x, y, width, height); -} - -static void -update_last_message (char *msg, int mark_start, int mark_end) -{ - free (last_msg); - last_msg = xstrdup (msg); - last_mark_start = mark_start; - last_mark_end = mark_end; -} - -void -marked_message (char *msg, int mark_start, int mark_end) -{ - /* Schedule the bar to be hidden after some amount of time. */ - reset_alarm (); - marked_message_internal (msg, mark_start, mark_end); -} - -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); - - /* 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); -} - -/* Use this just to update the bar. show_last_message will draw it and - leave it up for a period of time. */ -void -redraw_last_message (void) -{ - char *msg; - - if (last_msg == NULL) return; - - /* A little kludge to avoid last_msg in marked_message from being - strdup'd right after freeing the pointer. Note: in this case - marked_message's msg arg would have been the same as - last_msg. */ - msg = xstrdup (last_msg); - marked_message_internal (msg, last_mark_start, last_mark_end); - free (msg); -} - -void -show_last_message (void) -{ - redraw_last_message(); - reset_alarm(); -} - -/* Free any memory associated with the bar. */ -void -free_bar (void) -{ - free (last_msg); - last_msg = NULL; -} |