/* FvwmIconBox Module --- Copyright 1994, Nobutaka Suzuki. * * No guarantees or warantees or anything are provided or implied in * any way whatsoever. Use this program at your own risk. Permission * to use this program for any purpose is given, as long as the * copyright is kept intact. * * The functions based on part of GoodStuff, FvwmScroll, FvwmWinList * and Fvwm are noted by a small copyright atop that function. * Full original copyright is described in COPYRIGHT. */ #define TRUE 1 #define FALSE 0 #define MARGIN1 8 #define MARGIN2 6 #define BAR_WIDTH 9 #define NONE 0 #define VERTICAL 1 #define HORIZONTAL 2 #define DEAD 0 #define DELETE 1 #include "../../configure.h" #ifdef ISC #include /* Saul */ #endif #include #include #include #include #include #include #if defined ___AIX || defined _AIX || defined __QNX__ || defined ___AIXV3 || defined AIXV3 || defined _SEQUENT_ #include #endif #include #include #include #include "../../fvwm/module.h" #include #include #include #include #include #ifdef SHAPE #include #endif /* SHAPE */ /* just as same as wild.c */ #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #include "FvwmIconBox.h" #include "../../version.h" char *MyName; XFontStruct *font; Display *dpy; /* which display are we talking to */ int x_fd,fd_width; Window Root; int screen; int d_depth; char *Back = "#5f9ea0"; char *Fore = "#82dfe3"; char *IconBack = "#cfcfcf"; char *IconFore = "black"; char *ActIconBack = "white"; char *ActIconFore = "black"; char *font_string = "fixed"; Pixel fore_pix, hilite_pix, back_pix, shadow_pix; Pixel icon_fore_pix, icon_back_pix, icon_hilite_pix, icon_shadow_pix; Pixel act_icon_fore_pix, act_icon_back_pix, act_icon_hilite_pix, act_icon_shadow_pix; GC NormalGC,ShadowGC,ReliefGC,IconShadowGC,IconReliefGC; Window main_win; Window holder_win; Window icon_win; Window h_scroll_bar; Window v_scroll_bar; Window l_button, r_button, t_button, b_button; Window Pressed = None; int Width, Height; int UWidth, UHeight; #define MW_EVENTS (KeyPressMask| ExposureMask | StructureNotifyMask|\ ButtonReleaseMask | ButtonPressMask ) #define SCROLL_EVENTS (ExposureMask | StructureNotifyMask|\ ButtonReleaseMask |ButtonPressMask | PointerMotionMask) #define BUTTON_EVENTS (ExposureMask | StructureNotifyMask|\ ButtonReleaseMask | ButtonPressMask |\ LeaveWindowMask | PointerMotionMask) struct icon_info *Hilite; int main_width, main_height; int num_icons = 0; int num_rows = 1; int num_columns = 6; int Lines = 6; int max_icon_width = 48,max_icon_height = 48; int ButtonWidth,ButtonHeight; int x= -100000,y= -100000,w= -1,h= -1,gravity = NorthWestGravity; int icon_win_x = 0, icon_win_y = 0, icon_win_width = 100, icon_win_height = 100; int ready = 0; int sorticons = 0; int interval = 8; int motion = NONE; int primary = LEFT, secondary = BOTTOM; int xneg = 0, yneg = 0; int ClickTime = 150; int hidesc = NONE; Pixmap IconwinPixmap = None; char *IconwinPixmapFile = NULL; int h_margin = MARGIN1*2 + BAR_WIDTH + MARGIN2 + 8; int v_margin = MARGIN1*2 + BAR_WIDTH + MARGIN2 + 8; int fd[2]; struct icon_info *Head = NULL; struct icon_info *Tail = NULL; struct iconfile *IconListHead = NULL; struct iconfile *IconListTail = NULL; struct iconfile *DefaultIcon = NULL; struct mousefunc *MouseActions = NULL; struct keyfunc *KeyActions = NULL; char *iconPath = NULL; char *pixmapPath = NULL; static Atom wm_del_win; Atom _XA_WM_PROTOCOLS; Atom _XA_WM_NAME; int UP = 0; int isendlist = 0; /************************************************************************ Main Based on main() from GoodStuff: Copyright 1993, Robert Nation. ************************************************************************/ void main(int argc, char **argv) { char *display_name = NULL; char *temp, *s; char set_mask_mesg[50]; temp = argv[0]; s=strrchr(argv[0], '/'); if (s != NULL) temp = s + 1; MyName = safemalloc(strlen(temp)+1); strcpy(MyName, temp); signal (SIGPIPE, DeadPipe); if((argc != 6)&&(argc != 7)) { fprintf(stderr,"%s Version %s should only be executed by fvwm!\n",MyName, VERSION); exit(1); } fd[0] = atoi(argv[1]); fd[1] = atoi(argv[2]); if (!(dpy = XOpenDisplay(display_name))) { fprintf(stderr,"%s: can't open display %s", MyName, XDisplayName(display_name)); exit (1); } x_fd = XConnectionNumber(dpy); fd_width = GetFdWidth(); screen= DefaultScreen(dpy); Root = RootWindow(dpy, screen); if(Root == None) { fprintf(stderr,"%s: Screen %d is not valid ", MyName, screen); exit(1); } d_depth = DefaultDepth(dpy, screen); sprintf(set_mask_mesg,"SET_MASK %lu\n", (unsigned long)(M_CONFIGURE_WINDOW| M_ADD_WINDOW| M_DESTROY_WINDOW| M_END_WINDOWLIST| M_ICONIFY| M_DEICONIFY| M_ICON_NAME| M_RES_NAME| M_RES_CLASS| M_WINDOW_NAME)); SendFvwmPipe(fd,set_mask_mesg,0); ParseOptions(argv[3]); CreateWindow(); SendFvwmPipe(fd,"Send_WindowList",0); Loop(); } /************************************************************************ Loop Based on Loop() from GoodStuff: Copyright 1993, Robert Nation. ************************************************************************/ void Loop(void) { Window root; struct icon_info *tmp, *exhilite; int x,y,border_width,depth; int i, hr = ICON_RELIEF/2; XEvent Event; int tw,th; int diffx, diffy; int oldw, oldh; while(1) { if(My_XNextEvent(dpy,&Event)) { switch(Event.type) { case Expose: if(Event.xexpose.count == 0){ if (Event.xany.window == main_win){ if(ready < 1) ready ++; RedrawWindow(-1); }else{ tmp = Head; while(tmp != NULL){ if (Event.xany.window == tmp->icon_pixmap_w){ RedrawIcon(tmp, 1); break; }else if(Event.xany.window == tmp->IconWin){ RedrawIcon(tmp, 2); break; } tmp = tmp->next; } } } break; case ConfigureNotify: XGetGeometry(dpy,main_win,&root,&x,&y, (unsigned int *)&tw,(unsigned int *)&th, (unsigned int *)&border_width, (unsigned int *)&depth); if (UP && (tw != main_width || th != main_height)){ main_width = tw; main_height= th; oldw = Width; oldh = Height; num_columns = (tw - h_margin - interval + 1) / UWidth; num_rows = (th - v_margin - interval + 1) / UHeight; Width = UWidth * num_columns + interval - 1; Height = UHeight * num_rows + interval -1; XMoveResizeWindow(dpy, holder_win, MARGIN1+2, MARGIN1+2, tw - h_margin, th - v_margin); if (hidesc != HORIZONTAL) XResizeWindow(dpy, h_scroll_bar, Width - BAR_WIDTH*2, BAR_WIDTH); if (hidesc != VERTICAL) XResizeWindow(dpy ,v_scroll_bar, BAR_WIDTH, Height - BAR_WIDTH*2); GetIconwinSize(&diffx, &diffy); i = 0; tmp = Head; while(tmp != NULL){ AdjustIconWindow(tmp, i++); tmp = tmp->next; } if (primary == BOTTOM || secondary == BOTTOM) icon_win_y -= Height - oldh; if (primary == RIGHT || secondary == RIGHT) icon_win_x -= Width - oldw; if (icon_win_x < 0) icon_win_x = 0; if (icon_win_y < 0) icon_win_y = 0; if (icon_win_x + Width > icon_win_width) icon_win_x = icon_win_width - Width; if (icon_win_y + Height > icon_win_height) icon_win_y = icon_win_height - Height; XMoveResizeWindow(dpy, icon_win, -icon_win_x, -icon_win_y, icon_win_width, icon_win_height); XClearWindow(dpy,main_win); RedrawWindow(-1); } break; case KeyPress: ExecuteKey(Event); break; case ButtonPress: if (hidesc != HORIZONTAL){ if (Event.xbutton.window == h_scroll_bar) motion = HORIZONTAL; else if (Event.xbutton.window == l_button){ Pressed = l_button; RedrawLeftButton(ShadowGC, ReliefGC); } else if (Event.xbutton.window == r_button){ Pressed = r_button; RedrawRightButton(ShadowGC, ReliefGC); } } if (hidesc != VERTICAL){ if (Event.xbutton.window == v_scroll_bar) motion = VERTICAL; else if (Event.xbutton.window == t_button){ Pressed = t_button; RedrawTopButton(ShadowGC, ReliefGC); } else if (Event.xbutton.window == b_button){ Pressed = b_button; RedrawBottomButton(ShadowGC, ReliefGC); } } if ((tmp = Search(Event.xbutton.window)) != NULL) ExecuteAction(Event.xbutton.x, Event.xbutton.y, tmp); break; case ButtonRelease: if (hidesc != HORIZONTAL){ if (Event.xbutton.window == h_scroll_bar && motion == HORIZONTAL) HScroll(Event.xbutton.x * icon_win_width / Width); else if (Event.xbutton.window == l_button && Pressed == l_button){ Pressed = None; RedrawLeftButton(ReliefGC, ShadowGC); HScroll(icon_win_x - UWidth); } else if (Event.xbutton.window == r_button && Pressed == r_button){ Pressed = None; RedrawRightButton(ReliefGC, ShadowGC); HScroll(icon_win_x + UWidth); } } if (hidesc != VERTICAL){ if (Event.xbutton.window == v_scroll_bar && motion == VERTICAL) VScroll(Event.xbutton.y * icon_win_height / Height); else if (Event.xbutton.window == t_button && Pressed == t_button){ Pressed = None; RedrawTopButton(ReliefGC, ShadowGC); VScroll(icon_win_y - UHeight); } else if (Event.xbutton.window == b_button && Pressed == b_button){ Pressed = None; RedrawBottomButton(ReliefGC, ShadowGC); VScroll(icon_win_y + UHeight); } } motion = NONE; break; case MotionNotify: if (motion == VERTICAL){ VScroll(Event.xbutton.y * icon_win_height / Height); }else if (motion == HORIZONTAL){ HScroll(Event.xbutton.x * icon_win_width / Width); } break; case EnterNotify: if ((tmp = Search(Event.xcrossing.window)) != NULL) if ((exhilite = Hilite) != tmp){ Hilite = tmp; if (exhilite != NULL) RedrawIcon(exhilite, 3); RedrawIcon(tmp, 3); } break; case LeaveNotify: if ((tmp = Search(Event.xcrossing.window)) != NULL && tmp == Hilite){ Hilite = NULL; RedrawIcon(tmp, 3); } if (hidesc != HORIZONTAL && Event.xbutton.window == l_button && Pressed == l_button){ Pressed = None; RedrawLeftButton(ReliefGC, ShadowGC); } else if (hidesc != HORIZONTAL && Event.xbutton.window == r_button && Pressed == r_button){ Pressed = None; RedrawRightButton(ReliefGC, ShadowGC); } else if (hidesc != VERTICAL && Event.xbutton.window == t_button && Pressed == t_button){ Pressed = None; RedrawTopButton(ReliefGC, ShadowGC); } else if (hidesc != VERTICAL && Event.xbutton.window == b_button && Pressed == b_button){ Pressed = None; RedrawBottomButton(ReliefGC, ShadowGC); } break; case ClientMessage: if ((Event.xclient.format==32) && (Event.xclient.data.l[0]==wm_del_win)) DeadPipe(1); break; case PropertyNotify: switch (Event.xproperty.atom){ case XA_WM_HINTS: if (Event.xproperty.state == PropertyDelete) break; tmp = Head; i=0; while(tmp != NULL){ if (Event.xproperty.window == tmp->id) break; tmp = tmp->next; ++i; } if (tmp == NULL || tmp->wmhints == NULL || !tmp->defaulticon) break; #ifdef SHAPE /* turn off "old" shape mask */ if (tmp->icon_maskPixmap != None) XShapeCombineMask(dpy, tmp->icon_pixmap_w, ShapeBounding, 0, 0, None, ShapeSet); #endif if (tmp->wmhints) XFree (tmp->wmhints); tmp->wmhints = XGetWMHints(dpy, tmp->id); if (tmp->wmhints && (tmp->wmhints->flags & IconPixmapHint)){ if (tmp->iconPixmap != None) XFreePixmap(dpy, tmp->iconPixmap); GetIconBitmap(tmp); #ifdef SHAPE if (tmp->icon_maskPixmap != None) XShapeCombineMask(dpy, tmp->icon_pixmap_w, ShapeBounding, hr, hr, tmp->icon_maskPixmap, ShapeSet); #endif AdjustIconWindow(tmp, i); RedrawIcon(tmp, 1); } break; } break; default: break; } } } return; } void HScroll(int x) { int oldx = icon_win_x; if (x + Width > icon_win_width) x = icon_win_width - Width; if (x < 0) x = 0; if (oldx != x){ icon_win_x = x; XMoveWindow(dpy,icon_win, -icon_win_x, -icon_win_y); if (hidesc != HORIZONTAL) RedrawHScrollbar(); } } void VScroll(int y) { int oldy = icon_win_y; if (y + Height > icon_win_height) y = icon_win_height - Height; if (y < 0) y = 0; if (oldy != y){ icon_win_y = y; XMoveWindow(dpy,icon_win, -icon_win_x, -icon_win_y); if (hidesc != VERTICAL) RedrawVScrollbar(); } } struct icon_info *Search(Window w) { struct icon_info *tmp; tmp = Head; while (tmp != NULL){ if (tmp->IconWin == w || tmp->icon_pixmap_w == w) return tmp; tmp = tmp->next; } return NULL; } /************************************************************************ * * Draw the window * ***********************************************************************/ void RedrawWindow(int newbutton) { XEvent dummy; if(ready < 1) return; while (XCheckTypedWindowEvent (dpy, main_win, Expose, &dummy)); RelieveWindow(main_win, MARGIN1, MARGIN1, Width + 4, Height + 4, ShadowGC,ReliefGC); if (hidesc != HORIZONTAL) RelieveWindow(main_win, MARGIN1, MARGIN1 + 4 + Height + MARGIN2, Width + 4, BAR_WIDTH+4, ShadowGC,ReliefGC); if (hidesc != VERTICAL) RelieveWindow(main_win, MARGIN1 + 4 + Width + MARGIN2, MARGIN1, BAR_WIDTH+4, Height + 4, ShadowGC,ReliefGC); RelieveWindow(main_win, 0, 0, Width + h_margin, Height + v_margin, ReliefGC, ShadowGC); /* scroll bar */ if (hidesc != HORIZONTAL) RedrawHScrollbar(); if (hidesc != VERTICAL) RedrawVScrollbar(); /* buttons */ if (hidesc != HORIZONTAL){ RedrawLeftButton(ReliefGC, ShadowGC); RedrawRightButton(ReliefGC, ShadowGC); } if (hidesc != VERTICAL){ RedrawTopButton(ReliefGC, ShadowGC); RedrawBottomButton(ReliefGC, ShadowGC); } /* icons */ RedrawIcons(); } void RedrawIcons(void) { struct icon_info *tmp; tmp = Head; while(tmp != NULL){ RedrawIcon(tmp, 3); tmp = tmp->next; } } void RedrawIcon(struct icon_info *item, int f) { unsigned long plane = 1; int hr, len; int diff, lm ,w, h, tw; char label[256]; hr = ICON_RELIEF/2; if (Hilite == item){ XSetForeground(dpy, NormalGC, act_icon_fore_pix); XSetBackground(dpy, NormalGC, act_icon_back_pix); XSetForeground(dpy, IconReliefGC, act_icon_hilite_pix); XSetForeground(dpy, IconShadowGC, act_icon_shadow_pix); XSetWindowBackground(dpy, item->icon_pixmap_w, act_icon_back_pix); XSetWindowBackground(dpy, item->IconWin, act_icon_back_pix); } /* icon pixmap */ if ((f & 1) && (item->flags & ICON_OURS)){ if (item->iconPixmap != None && item->icon_pixmap_w != None){ if (item->icon_depth != d_depth) XCopyPlane(dpy, item->iconPixmap, item->icon_pixmap_w, NormalGC, 0, 0, item->icon_w, item->icon_h, hr, hr, plane); else XCopyArea(dpy, item->iconPixmap, item->icon_pixmap_w, NormalGC, 0, 0, item->icon_w, item->icon_h, hr, hr); /* if (item->flags & ICONIFIED){ if (Hilite == item) XSetForeground(dpy, NormalGC, act_icon_back_pix); else XSetForeground(dpy, NormalGC, icon_back_pix); XSetFillStyle(dpy, NormalGC, FillStippled); XFillRectangle(dpy, item->icon_pixmap_w, NormalGC, hr, hr, item->icon_w, item->icon_h); XSetFillStyle(dpy, NormalGC, FillSolid); if (Hilite == item) XSetForeground(dpy, NormalGC, act_icon_fore_pix); else XSetForeground(dpy, NormalGC, icon_fore_pix); } */ } if (!(item->flags & SHAPED_ICON)){ if (item->icon_w > 0 && item->icon_h > 0) RelieveWindow(item->icon_pixmap_w, 0, 0, item->icon_w +ICON_RELIEF, item->icon_h + ICON_RELIEF, IconReliefGC, IconShadowGC); else RelieveWindow(item->icon_pixmap_w, 0, 0, max_icon_width +ICON_RELIEF, max_icon_height + ICON_RELIEF, IconReliefGC, IconShadowGC); } } else if (f & 1) XMapWindow(dpy, item->icon_pixmap_w); /* label */ if (f & 2){ w = max_icon_width + ICON_RELIEF; h = max_icon_height + ICON_RELIEF; if (item->flags & ICONIFIED){ sprintf(label, "(%s)", item->name); }else strcpy(label, item->name); len = strlen(label); tw = XTextWidth(font, label, len); diff = max_icon_width + ICON_RELIEF - tw; lm = diff/2; lm = lm > 4 ? lm : 4; if (Hilite == item){ XRaiseWindow(dpy, item->IconWin); XMoveResizeWindow(dpy, item->IconWin, item->x + min(0, (diff - 8))/2, item->y + h, max(tw + 8, w), 6 + font->ascent + font->descent); XClearWindow(dpy, item->IconWin); XDrawString(dpy, item->IconWin, NormalGC, lm, 3 + font->ascent, label, len); RelieveWindow(item->IconWin, 0, 0, max(tw + 8, w), 6 + font->ascent + font->descent, IconReliefGC, IconShadowGC); }else{ XMoveResizeWindow(dpy, item->IconWin, item->x, item->y + h, w, 6 + font->ascent + font->descent); XClearWindow(dpy, item->IconWin); XDrawString(dpy, item->IconWin, NormalGC, lm, 3 + font->ascent, label, len); RelieveWindow(item->IconWin, 0, 0, w, 6 + font->ascent + font->descent, IconReliefGC, IconShadowGC); } } if (Hilite == item){ XSetForeground(dpy, NormalGC, icon_fore_pix); XSetBackground(dpy, NormalGC, icon_back_pix); XSetForeground(dpy, IconReliefGC, icon_hilite_pix); XSetForeground(dpy, IconShadowGC, icon_shadow_pix); XSetWindowBackground(dpy, item->icon_pixmap_w, icon_back_pix); XSetWindowBackground(dpy, item->IconWin, icon_back_pix); } } /*********************************************************************** * RedrawHScrollbar * Based on part of Loop() of GrabWindow.c in FvwmScroll: * Copyright 1994, Robert Nation. ***********************************************************************/ void RedrawHScrollbar(void) { int x,width; x = (Width - BAR_WIDTH*2) * icon_win_x / icon_win_width; width = (Width - BAR_WIDTH*2) * Width / icon_win_width; XClearArea(dpy, h_scroll_bar, 0, 0, Width, BAR_WIDTH,False); RelieveWindow(h_scroll_bar, x, 0, width, BAR_WIDTH, ReliefGC, ShadowGC); } /*********************************************************************** * RedrawVScrollbar * Based on part of Loop() of GrabWindow.c in FvwmScroll: * Copyright 1994, Robert Nation. ***********************************************************************/ void RedrawVScrollbar(void) { int y, height; y = (Height - BAR_WIDTH*2) * icon_win_y / icon_win_height; height = (Height - BAR_WIDTH*2)* Height / icon_win_height; XClearArea(dpy, v_scroll_bar, 0, 0, BAR_WIDTH, Height,False); RelieveWindow(v_scroll_bar, 0, y, BAR_WIDTH, height, ReliefGC, ShadowGC); } void RedrawLeftButton(GC rgc, GC sgc) { XSegment seg[4]; int i=0; seg[i].x1 = 1; seg[i].y1 = BAR_WIDTH/2; seg[i].x2 = BAR_WIDTH - 2; seg[i++].y2 = 1; seg[i].x1 = 0; seg[i].y1 = BAR_WIDTH/2; seg[i].x2 = BAR_WIDTH - 1; seg[i++].y2 = 0; XDrawSegments(dpy, l_button, rgc, seg, i); i = 0; seg[i].x1 = 1; seg[i].y1 = BAR_WIDTH/2; seg[i].x2 = BAR_WIDTH - 2; seg[i++].y2 = BAR_WIDTH - 2; seg[i].x1 = 0; seg[i].y1 = BAR_WIDTH/2; seg[i].x2 = BAR_WIDTH - 1; seg[i++].y2 = BAR_WIDTH - 1; seg[i].x1 = BAR_WIDTH - 2; seg[i].y1 = 1; seg[i].x2 = BAR_WIDTH - 2; seg[i++].y2 = BAR_WIDTH - 2; seg[i].x1 = BAR_WIDTH - 1; seg[i].y1 = 0; seg[i].x2 = BAR_WIDTH - 1; seg[i++].y2 = BAR_WIDTH - 1; XDrawSegments(dpy, l_button, sgc, seg, i); } void RedrawRightButton(GC rgc, GC sgc) { XSegment seg[4]; int i=0; seg[i].x1 = 1; seg[i].y1 = 1; seg[i].x2 = 1; seg[i++].y2 = BAR_WIDTH - 2; seg[i].x1 = 0; seg[i].y1 = 0; seg[i].x2 = 0; seg[i++].y2 = BAR_WIDTH - 1; seg[i].x1 = 1; seg[i].y1 = 1; seg[i].x2 = BAR_WIDTH - 2; seg[i++].y2 = BAR_WIDTH/2; seg[i].x1 = 0; seg[i].y1 = 0; seg[i].x2 = BAR_WIDTH - 1; seg[i++].y2 = BAR_WIDTH/2; XDrawSegments(dpy, r_button, rgc, seg, i); i = 0; seg[i].x1 = 1; seg[i].y1 = BAR_WIDTH - 2; seg[i].x2 = BAR_WIDTH - 2; seg[i++].y2 = BAR_WIDTH/2; seg[i].x1 = 0; seg[i].y1 = BAR_WIDTH - 1; seg[i].x2 = BAR_WIDTH - 1; seg[i++].y2 = BAR_WIDTH/2; XDrawSegments(dpy, r_button, sgc, seg, i); } void RedrawTopButton(GC rgc, GC sgc) { XSegment seg[4]; int i=0; seg[i].x1 = BAR_WIDTH/2; seg[i].y1 = 1; seg[i].x2 = 1; seg[i++].y2 = BAR_WIDTH - 2; seg[i].x1 = BAR_WIDTH/2; seg[i].y1 = 0; seg[i].x2 = 0; seg[i++].y2 = BAR_WIDTH - 1; XDrawSegments(dpy, t_button, rgc, seg, i); i = 0; seg[i].x1 = BAR_WIDTH/2; seg[i].y1 = 1; seg[i].x2 = BAR_WIDTH - 2; seg[i++].y2 = BAR_WIDTH - 2; seg[i].x1 = BAR_WIDTH/2; seg[i].y1 = 0; seg[i].x2 = BAR_WIDTH - 1; seg[i++].y2 = BAR_WIDTH - 1; seg[i].x1 = 1; seg[i].y1 = BAR_WIDTH - 2; seg[i].x2 = BAR_WIDTH - 2; seg[i++].y2 = BAR_WIDTH - 2; seg[i].x1 = 0; seg[i].y1 = BAR_WIDTH - 1; seg[i].x2 = BAR_WIDTH - 1; seg[i++].y2 = BAR_WIDTH - 1; XDrawSegments(dpy, t_button, sgc, seg, i); } void RedrawBottomButton(GC rgc, GC sgc) { XSegment seg[4]; int i=0; seg[i].x1 = 1; seg[i].y1 = 1; seg[i].x2 = BAR_WIDTH/2; seg[i++].y2 = BAR_WIDTH - 2; seg[i].x1 = 0; seg[i].y1 = 0; seg[i].x2 = BAR_WIDTH/2; seg[i++].y2 = BAR_WIDTH - 1; seg[i].x1 = 1; seg[i].y1 = 1; seg[i].x2 = BAR_WIDTH - 2; seg[i++].y2 = 1; seg[i].x1 = 0; seg[i].y1 = 0; seg[i].x2 = BAR_WIDTH - 1; seg[i++].y2 = 0; XDrawSegments(dpy, b_button, rgc, seg, i); i = 0; seg[i].x1 = BAR_WIDTH - 2; seg[i].y1 = 1; seg[i].x2 = BAR_WIDTH/2; seg[i++].y2 = BAR_WIDTH - 2; seg[i].x1 = BAR_WIDTH - 1; seg[i].y1 = 0; seg[i].x2 = BAR_WIDTH/2; seg[i++].y2 = BAR_WIDTH - 1; XDrawSegments(dpy, b_button, sgc, seg, i); } /************************************************************************ RelieveWindow Original work from GoodStuff: Copyright 1993, Robert Nation. ************************************************************************/ FVWM_INLINE void RelieveWindow(Window win,int x,int y,int w,int h, GC rgc,GC sgc) { XSegment seg[4]; int i; i=0; seg[i].x1 = x; seg[i].y1 = y; seg[i].x2 = w+x-1; seg[i++].y2 = y; seg[i].x1 = x; seg[i].y1 = y; seg[i].x2 = x; seg[i++].y2 = h+y-1; seg[i].x1 = x+1; seg[i].y1 = y+1; seg[i].x2 = x+w-2; seg[i++].y2 = y+1; seg[i].x1 = x+1; seg[i].y1 = y+1; seg[i].x2 = x+1; seg[i++].y2 = y+h-2; XDrawSegments(dpy, win, rgc, seg, i); i=0; seg[i].x1 = x; seg[i].y1 = y+h-1; seg[i].x2 = w+x-1; seg[i++].y2 = y+h-1; seg[i].x1 = x+w-1; seg[i].y1 = y; seg[i].x2 = x+w-1; seg[i++].y2 = y+h-1; if(d_depth<2) XDrawSegments(dpy, win, ShadowGC, seg, i); else XDrawSegments(dpy, win, sgc, seg, i); i=0; seg[i].x1 = x+1; seg[i].y1 = y+h-2; seg[i].x2 = x+w-2; seg[i++].y2 = y+h-2; seg[i].x1 = x+w-2; seg[i].y1 = y+1; seg[i].x2 = x+w-2; seg[i++].y2 = y+h-2; XDrawSegments(dpy, win, sgc, seg, i); } /************************************************************************ * CreateWindow --Sizes and creates the window * Based on CreateWindow() from GoodStuff: * Copyright 1993, Robert Nation. ***********************************************************************/ XSizeHints mysizehints; XSetWindowAttributes attributes; void CreateWindow(void) { XGCValues gcv; unsigned long gcm; unsigned long mask; wm_del_win = XInternAtom(dpy,"WM_DELETE_WINDOW",False); _XA_WM_PROTOCOLS = XInternAtom (dpy, "WM_PROTOCOLS", False); /* load the font */ if ((font = XLoadQueryFont(dpy, font_string)) == NULL) { if ((font = XLoadQueryFont(dpy, "fixed")) == NULL) { fprintf(stderr,"%s: No fonts available\n",MyName); exit(1); } }; if (hidesc == HORIZONTAL) v_margin -= BAR_WIDTH + MARGIN2 + 4; if (hidesc == VERTICAL) h_margin -= BAR_WIDTH + MARGIN2 + 4; UWidth = max_icon_width + ICON_RELIEF + interval; UHeight = font->ascent + font->descent + max_icon_height + ICON_RELIEF + 6 + interval; Width = UWidth * num_columns + interval -1; Height = UHeight * num_rows + interval -1; mysizehints.flags = PWinGravity| PResizeInc | PMinSize; /* subtract one for the right/bottom border */ mysizehints.min_width = UWidth + interval - 1 + h_margin; main_width = mysizehints.width = Width + h_margin; mysizehints.min_height = UHeight + interval - 1 + v_margin; main_height = mysizehints.height = Height + v_margin; mysizehints.width_inc = UWidth; mysizehints.height_inc = UHeight; if(x > -100000) { if (xneg) { mysizehints.x = DisplayWidth(dpy,screen) + x - mysizehints.width-2; gravity = NorthEastGravity; } else mysizehints.x = x; if (yneg) { mysizehints.y = DisplayHeight(dpy,screen) + y - mysizehints.height-2; gravity = SouthWestGravity; } else mysizehints.y = y; if((xneg) && (yneg)) gravity = SouthEastGravity; mysizehints.flags |= USPosition; } mysizehints.win_gravity = gravity; #define BW 1 if(d_depth < 2) { back_pix = icon_back_pix = act_icon_fore_pix = GetColor("white"); fore_pix = icon_fore_pix = act_icon_back_pix = GetColor("black"); hilite_pix = icon_hilite_pix = act_icon_shadow_pix = icon_back_pix; shadow_pix = icon_shadow_pix = act_icon_hilite_pix = icon_fore_pix; } else { fore_pix = GetColor(Fore); back_pix = GetColor(Back); icon_back_pix = GetColor(IconBack); icon_fore_pix = GetColor(IconFore); icon_hilite_pix = GetHilite(icon_back_pix); icon_shadow_pix = GetShadow(icon_back_pix); act_icon_back_pix = GetColor(ActIconBack); act_icon_fore_pix = GetColor(ActIconFore); act_icon_hilite_pix = GetHilite(act_icon_back_pix); act_icon_shadow_pix = GetShadow(act_icon_back_pix); hilite_pix = GetHilite(back_pix); shadow_pix = GetShadow(back_pix); } main_win = XCreateSimpleWindow(dpy,Root,mysizehints.x,mysizehints.y, mysizehints.width,mysizehints.height, BW,fore_pix,back_pix); XSetWMProtocols(dpy,main_win,&wm_del_win,1); XSetWMNormalHints(dpy,main_win,&mysizehints); XSelectInput(dpy,main_win,MW_EVENTS); change_window_name(MyName); mysizehints.flags = PWinGravity| PResizeInc | PSize; mysizehints.width -= h_margin; mysizehints.height -= v_margin; holder_win = XCreateSimpleWindow(dpy,main_win,MARGIN1+2, MARGIN1+2, mysizehints.width, mysizehints.height, 0,fore_pix,back_pix); icon_win = XCreateSimpleWindow(dpy,holder_win,-icon_win_x,-icon_win_y, icon_win_width, icon_win_height, 0,fore_pix,back_pix); gcm = GCForeground|GCBackground; gcv.foreground = hilite_pix; gcv.background = back_pix; ReliefGC = XCreateGC(dpy, Root, gcm, &gcv); gcm = GCForeground|GCBackground; gcv.foreground = shadow_pix; gcv.background = back_pix; ShadowGC = XCreateGC(dpy, Root, gcm, &gcv); gcm = GCForeground|GCBackground; gcv.foreground = icon_hilite_pix; gcv.background = icon_back_pix; IconReliefGC = XCreateGC(dpy, Root, gcm, &gcv); gcm = GCForeground|GCBackground; gcv.foreground = icon_shadow_pix; gcv.background = icon_back_pix; IconShadowGC = XCreateGC(dpy, Root, gcm, &gcv); gcm = GCForeground|GCBackground|GCFont; gcv.foreground = fore_pix; gcv.background = back_pix; gcv.font = font->fid; NormalGC = XCreateGC(dpy, Root, gcm, &gcv); /* icon_win's background */ if (GetBackPixmap() == True){ XSetWindowBackgroundPixmap(dpy, icon_win, IconwinPixmap); /* special thanks to Dave Goldberg for his helpful information */ XFreePixmap(dpy, IconwinPixmap); } XSetForeground(dpy, NormalGC, icon_fore_pix); XSetBackground(dpy, NormalGC, icon_back_pix); /* scroll bars */ mask = CWWinGravity | CWBackPixel; attributes.background_pixel = back_pix; if (hidesc != HORIZONTAL){ attributes.win_gravity = SouthWestGravity; h_scroll_bar = XCreateWindow(dpy ,main_win, MARGIN1 + 2 + BAR_WIDTH, MARGIN1 + 6 + Height + MARGIN2, Width - BAR_WIDTH*2, BAR_WIDTH, 0, CopyFromParent, InputOutput, CopyFromParent, mask, &attributes); XSelectInput(dpy,h_scroll_bar,SCROLL_EVENTS); } if (hidesc != VERTICAL){ attributes.win_gravity = NorthEastGravity; v_scroll_bar = XCreateWindow(dpy ,main_win, MARGIN1 + 6 + Width + MARGIN2, MARGIN1 + 2 + BAR_WIDTH, BAR_WIDTH, Height - BAR_WIDTH*2, 0, CopyFromParent, InputOutput, CopyFromParent, mask, &attributes); XSelectInput(dpy,v_scroll_bar,SCROLL_EVENTS); } /* buttons */ if (hidesc != HORIZONTAL){ attributes.win_gravity = SouthWestGravity; l_button = XCreateWindow(dpy, main_win, MARGIN1 + 2, MARGIN1 + 6 + Height + MARGIN2, BAR_WIDTH, BAR_WIDTH, 0, CopyFromParent, InputOutput, CopyFromParent, mask, &attributes); attributes.win_gravity = SouthEastGravity; r_button = XCreateWindow(dpy, main_win, MARGIN1 + 2 + Width - BAR_WIDTH, MARGIN1 + 6 + Height + MARGIN2, BAR_WIDTH, BAR_WIDTH, 0, CopyFromParent, InputOutput, CopyFromParent, mask, &attributes); XSelectInput(dpy,l_button,BUTTON_EVENTS); XSelectInput(dpy,r_button,BUTTON_EVENTS); } if (hidesc != VERTICAL){ attributes.win_gravity = NorthEastGravity; t_button = XCreateWindow(dpy, main_win, MARGIN1 + 6 + Width + MARGIN2, MARGIN1 + 2, BAR_WIDTH, BAR_WIDTH, 0, CopyFromParent, InputOutput, CopyFromParent, mask, &attributes); attributes.win_gravity = SouthEastGravity; b_button = XCreateWindow(dpy, main_win, MARGIN1 + 6 + Width + MARGIN2, MARGIN1 + 2 + Height - BAR_WIDTH, BAR_WIDTH, BAR_WIDTH, 0, CopyFromParent, InputOutput, CopyFromParent, mask, &attributes); XSelectInput(dpy,t_button,BUTTON_EVENTS); XSelectInput(dpy,b_button,BUTTON_EVENTS); } } void GetIconwinSize(int *dx, int *dy) { *dx = icon_win_width; *dy = icon_win_height; if (primary == LEFT || primary == RIGHT){ icon_win_width = max(Width, UWidth * Lines + interval - 1); icon_win_height = max(Height, UHeight * (max(0, (num_icons-1))/Lines + 1) - 1 + interval); }else{ icon_win_width = max(Width, UWidth * (max(0,num_icons-1) / Lines + 1) + interval - 1); icon_win_height = max(Height, UHeight * Lines - 1 + interval); } *dx = icon_win_width - *dx; *dy = icon_win_height - *dy; } /************************************************************************ * GetShadow * Original work from GoodStuff: * Copyright 1993, Robert Nation. ***********************************************************************/ Pixel GetShadow(Pixel background) { XColor bg_color; XWindowAttributes attributes; XGetWindowAttributes(dpy,Root,&attributes); bg_color.pixel = background; XQueryColor(dpy,attributes.colormap,&bg_color); bg_color.red = (unsigned short)((bg_color.red*50)/100); bg_color.green = (unsigned short)((bg_color.green*50)/100); bg_color.blue = (unsigned short)((bg_color.blue*50)/100); if(!XAllocColor(dpy,attributes.colormap,&bg_color)) nocolor("alloc shadow",""); return bg_color.pixel; } /************************************************************************ * GetHilite * Original work from GoodStuff: * Copyright 1993, Robert Nation. ***********************************************************************/ Pixel GetHilite(Pixel background) { XColor bg_color, white_p; XWindowAttributes attributes; XGetWindowAttributes(dpy,Root,&attributes); bg_color.pixel = background; XQueryColor(dpy,attributes.colormap,&bg_color); white_p.pixel = GetColor("white"); XQueryColor(dpy,attributes.colormap,&white_p); bg_color.red = max((white_p.red/5), bg_color.red); bg_color.green = max((white_p.green/5), bg_color.green); bg_color.blue = max((white_p.blue/5), bg_color.blue); bg_color.red = min(white_p.red, (bg_color.red*140)/100); bg_color.green = min(white_p.green, (bg_color.green*140)/100); bg_color.blue = min(white_p.blue, (bg_color.blue*140)/100); if(!XAllocColor(dpy,attributes.colormap,&bg_color)) nocolor("alloc hilight",""); return bg_color.pixel; } /************************************************************************ * nocolor * Original work from GoodStuff: * Copyright 1993, Robert Nation. ***********************************************************************/ void nocolor(char *a, char *b) { fprintf(stderr,"%s: can't %s %s\n", MyName, a,b); } /************************************************************************ * GetColor * Original work from GoodStuff: * Copyright 1993, Robert Nation. ***********************************************************************/ Pixel GetColor(char *name) { XColor color; XWindowAttributes attributes; XGetWindowAttributes(dpy,Root,&attributes); color.pixel = 0; if (!XParseColor (dpy, attributes.colormap, name, &color)) { nocolor("parse",name); } else if(!XAllocColor (dpy, attributes.colormap, &color)) { nocolor("alloc",name); } return color.pixel; } /************************************************************************ SendFvwmPipe - Send a message back to fvwm Original work from FvwmWinList: Copyright 1994, Mike Finger. ************************************************************************/ void SendFvwmPipe(int *fd, char *message,unsigned long window) { int w; char *hold,*temp,*temp_msg; hold=message; while(1) { temp=strchr(hold,','); if (temp!=NULL) { temp_msg=malloc(temp-hold+1); strncpy(temp_msg,hold,(temp-hold)); temp_msg[(temp-hold)]='\0'; hold=temp+1; } else temp_msg=hold; if (!ExecIconBoxFunction(temp_msg)){ write(fd[0],&window, sizeof(unsigned long)); w=strlen(temp_msg); write(fd[0],&w,sizeof(int)); write(fd[0],temp_msg,w); /* keep going */ w=1; write(fd[0],&w,sizeof(int)); } if(temp_msg!=hold) free(temp_msg); else break; } } Bool ExecIconBoxFunction(char *msg) { if (mystrncasecmp(msg, "Next", 4) == 0){ Next(); return True; }else if (mystrncasecmp(msg, "Prev", 4) == 0){ Prev(); return True; }else if (mystrncasecmp(msg, "Left", 4) == 0){ HScroll(icon_win_x - UWidth); return True; }else if (mystrncasecmp(msg, "Right", 5) == 0){ HScroll(icon_win_x + UWidth); return True; }else if (mystrncasecmp(msg, "Up", 2) == 0){ VScroll(icon_win_y - UHeight); return True; }else if (mystrncasecmp(msg, "Down", 4) == 0){ VScroll(icon_win_y + UHeight); return True; } return False; } void Next(void) { struct icon_info *new, *old; int i; old = new = Hilite; if (new != NULL) new = new->next; if (new != NULL) Hilite = new; else new = Hilite = Head; if (new == NULL) return; if (old != NULL) RedrawIcon(old, 3); if (new != NULL) RedrawIcon(new, 3); i=0; if (new->x < icon_win_x){ while (new->x + UWidth * ++i < icon_win_x) ; HScroll(icon_win_x - UWidth*i); }else if (new->x > icon_win_x + Width){ while (new->x - UWidth * ++i > icon_win_x + Width) ; HScroll(icon_win_x + UWidth*i); } i=0; if (new->y < icon_win_y){ while (new->y + UHeight * ++i < icon_win_y) ; VScroll(icon_win_y - UHeight*i); }else if (new->y > icon_win_y + Height){ while (new->y - UHeight * ++i > icon_win_y + Height) ; VScroll(icon_win_y + UHeight*i); } } void Prev(void) { struct icon_info *new, *old; int i; old = new = Hilite; if (new != NULL) new = new->prev; if (new != NULL) Hilite = new; else new = Hilite = Tail; if (new == NULL) return; if (old != NULL) RedrawIcon(old, 3); if (new != NULL) RedrawIcon(new, 3); i=0; if (new->x < icon_win_x){ while (new->x + UWidth * ++i < icon_win_x) ; HScroll(icon_win_x - UWidth*i); }else if (new->x > icon_win_x + Width){ while (new->x - UWidth * ++i > icon_win_x + Width) ; HScroll(icon_win_x + UWidth*i); } i=0; if (new->y < icon_win_y){ while (new->y + UHeight * ++i < icon_win_y) ; VScroll(icon_win_y - UHeight*i); }else if (new->y > icon_win_y + Height){ while (new->y - UHeight * ++i > icon_win_y + Height) ; VScroll(icon_win_y + UHeight*i); } } /************************************************************************ * DeadPipe --Dead pipe handler * Based on DeadPipe() from GoodStuff: * Copyright 1993, Robert Nation. ***********************************************************************/ void DeadPipe(int nonsense) { struct icon_info *tmpi, *tmpi2; struct mousefunc *tmpm, *tmpm2; struct keyfunc *tmpk, *tmpk2; struct iconfile *tmpf, *tmpf2; tmpm = MouseActions; while(tmpm != NULL){ tmpm2 = tmpm; tmpm = tmpm->next; free(tmpm2->action); free(tmpm2); } tmpk = KeyActions; while(tmpk != NULL){ tmpk2 = tmpk; tmpk = tmpk->next; free(tmpk2->action); free(tmpk2->name); free(tmpk2); } tmpf = IconListHead; while(tmpf != NULL){ tmpf2 = tmpf; tmpf = tmpf->next; free(tmpf2->name); free(tmpf2->iconfile); free(tmpf2); } tmpi = Head; while(tmpi != NULL){ tmpi2 = tmpi; tmpi = tmpi->next; freeitem(tmpi2, DEAD); } XSync(dpy,0); exit(0); } /************************************************************************ * ParseOptions * Based on ParseConfig() from FvwmWinList: * Copyright 1994, Mike Finger. ***********************************************************************/ void ParseOptions(char *filename) { FILE *fd = (FILE *)0; char line[256]; char *tline,*orig_tline,*tmp; int Clength; fd = fopen(filename,"r"); if(fd == (FILE *)0) { fprintf(stderr,"%s: can't open config file %s",MyName,filename); exit(1); } tline = fgets(line,(sizeof line)-1,fd); orig_tline = tline; Clength = strlen(MyName); while(tline != (char *)0) { int g_x, g_y, flags; unsigned width,height; while(isspace(*tline))tline++; if(strlen(&tline[0])>1){ if (mystrncasecmp(tline,CatString3("*", MyName, "Geometry"),Clength+9)==0){ tmp = &tline[Clength+9]; while(((isspace(*tmp))&&(*tmp != '\n'))&&(*tmp != 0)) tmp++; tmp[strlen(tmp)-1] = 0; flags = XParseGeometry(tmp,&g_x,&g_y,&width,&height); if (flags & WidthValue) num_columns = width; if (flags & HeightValue) num_rows = height; if (flags & XValue) x = g_x; if (flags & YValue) y = g_y; if (flags & XNegative) xneg = 1; if (flags & YNegative) yneg = 1; } else if (mystrncasecmp(tline,CatString3("*", MyName, "MaxIconSize"),Clength+12)==0){ tmp = &tline[Clength+12]; while(((isspace(*tmp))&&(*tmp != '\n'))&&(*tmp != 0)) tmp++; tmp[strlen(tmp)-1] = 0; flags = XParseGeometry(tmp,&g_x,&g_y,&width,&height); if (flags & WidthValue) max_icon_width = width; if (flags & HeightValue) max_icon_height = height; }else if (mystrncasecmp(tline,CatString3("*",MyName,"Font"),Clength+5)==0) CopyString(&font_string,&tline[Clength+5]); else if (mystrncasecmp(tline,CatString3("*",MyName,"IconFore"),Clength+9)==0) CopyString(&IconFore,&tline[Clength+9]); else if (mystrncasecmp(tline,CatString3("*",MyName,"IconBack"),Clength+9)==0) CopyString(&IconBack,&tline[Clength+9]); else if (mystrncasecmp(tline,CatString3("*",MyName,"IconHiFore"),Clength+11)==0) CopyString(&ActIconFore,&tline[Clength+11]); else if (mystrncasecmp(tline,CatString3("*",MyName,"IconHiBack"),Clength+11)==0) CopyString(&ActIconBack,&tline[Clength+11]); else if (mystrncasecmp(tline,CatString3("*",MyName, "Fore"),Clength+5)==0) CopyString(&Fore,&tline[Clength+5]); else if (mystrncasecmp(tline,CatString3("*",MyName, "Back"),Clength+5)==0) CopyString(&Back,&tline[Clength+5]); else if (mystrncasecmp(tline,CatString3("*",MyName, "Pixmap"),Clength+7)==0) CopyString(&IconwinPixmapFile,&tline[Clength+7]); else if (mystrncasecmp(tline,CatString3("*",MyName, "Padding"),Clength+8)==0) interval = max(0,atoi(&tline[Clength+8])); else if (mystrncasecmp(tline,CatString3("*",MyName, "Lines"),Clength+6)==0) Lines = max(1,atoi(&tline[Clength+6])); else if (mystrncasecmp(tline,CatString3("*",MyName, "Placement"),Clength+10)==0) parseplacement(&tline[Clength+10]); else if (mystrncasecmp(tline,CatString3("*",MyName, "SortIcons"),Clength+10)==0) sorticons = 1; else if (mystrncasecmp(tline,CatString3("*",MyName, "Mouse"),Clength+6)==0) parsemouse(&tline[Clength + 6]); else if (mystrncasecmp(tline,CatString3("*",MyName, "Key"),Clength+4)==0) parsekey(&tline[Clength + 4]); else if (mystrncasecmp(tline,CatString3("*",MyName, "HideSC"),Clength+7)==0){ tmp = &tline[Clength+7]; while(((isspace(*tmp))&&(*tmp != '\n'))&&(*tmp != 0)) tmp++; if (mystrncasecmp(tmp, "Horizontal", 10) == 0) hidesc = HORIZONTAL; else if (mystrncasecmp(tmp, "Vertical", 8) == 0) hidesc = VERTICAL; }else if (mystrncasecmp(tline,CatString3("*",MyName, ""),Clength+1)==0) parseicon(&tline[Clength + 1]); else if (mystrncasecmp(tline,"IconPath",8)==0) CopyString(&iconPath,&tline[8]); else if (mystrncasecmp(tline,"PixmapPath",10)==0) CopyString(&pixmapPath,&tline[10]); else if (mystrncasecmp(tline,"ClickTime",9)==0) ClickTime = atoi(&tline[9]); } tline = fgets(line,(sizeof line)-1,fd); orig_tline = tline; } return; } void parseicon(char *tline) { int len; struct iconfile *tmp; char *ptr, *start, *end; tmp = (struct iconfile *)safemalloc(sizeof(struct iconfile)); /* windowname */ tmp->name = stripcpy(tline); if(tmp->name == NULL){ free(tmp); return; } /* skip windowname, based on strpcpy3 of configure.c */ while((*tline != '"')&&(tline != NULL)) tline++; if(*tline != 0) tline++; while((*tline != '"')&&(tline != NULL)) tline++; if(*tline == 0){ free(tmp); return; } tline++; /* file */ /* skip spaces */ while(isspace(*tline)&&(*tline != '\n')&&(*tline != 0)) tline++; start = tline; end = tline; while(!isspace(*end)&&(*end != '\n')&&(*end != 0)) end++; len = end - start; ptr = safemalloc(len+1); strncpy(ptr, start, len); ptr[len] = 0; tmp->iconfile = ptr; if (strcmp(tmp->name, "*") == 0) DefaultIcon = tmp; tmp->next = NULL; if (IconListHead == NULL) IconListHead = IconListTail = tmp; else{ IconListTail->next = tmp; IconListTail = tmp; } } void parseplacement(char *tline) { char p[240], s[240]; sscanf(tline, "%s %s", p, s); if (mystrncasecmp(p, "Left", 4) == 0) primary = LEFT; else if (mystrncasecmp(p, "Right", 5) == 0) primary = RIGHT; else if (mystrncasecmp(p, "Top", 3) == 0) primary = TOP; else if (mystrncasecmp(p, "Bottom", 6) == 0) primary = BOTTOM; if (mystrncasecmp(s, "Left", 4) == 0) secondary = LEFT; else if (mystrncasecmp(s, "Right", 5) == 0) secondary = RIGHT; else if (mystrncasecmp(s, "Top", 3) == 0) secondary = TOP; else if (mystrncasecmp(s, "Bottom", 6) == 0) secondary = BOTTOM; } void parsemouse(char *tline) { struct mousefunc *f = NULL; int len; char *ptr,*start,*end,*tmp; f = (struct mousefunc *)safemalloc(sizeof(struct mousefunc)); f->next = NULL; f->mouse = 0; /* skip spaces */ while(isspace(*tline)&&(*tline != '\n')&&(*tline != 0)) tline++; start = tline; end = tline; while((!isspace(*end))&&(*end!='\n')&&(*end!=0)) end++; if (mystrncasecmp(start, "1", 1) == 0) f->mouse = Button1; else if (mystrncasecmp(start, "2", 1) == 0) f->mouse = Button2; else if (mystrncasecmp(start, "3", 1) == 0) f->mouse = Button3; /* click or doubleclick */ tline = end; /* skip spaces */ while(isspace(*tline)&&(*tline != '\n')&&(*tline != 0)) tline++; start = tline; end = tline; while((!isspace(*end))&&(*end!='\n')&&(*end!=0)) end++; if (mystrncasecmp(start, "Click", 5) == 0) f->type = CLICK; else if (mystrncasecmp(start, "DoubleClick", 11) == 0) f->type = DOUBLE_CLICK; /* actions */ tline = end; /* skip spaces */ while(isspace(*tline)&&(*tline != '\n')&&(*tline != 0)) tline++; start = tline; end = tline; tmp = tline; while((*tmp!='\n')&&(*tmp!=0)){ if (!isspace(*tmp)) end = tmp; tmp++; } end++; len = end - start; ptr = safemalloc(len+1); strncpy(ptr, start, len); ptr[len] = 0; f->action = ptr; f->next = MouseActions; MouseActions = f; } /*********************************************************************** parsekey Based on part of AddFunckey() of configure.c in Fvwm. Copyright 1988, Evans and Sutherland Computer Corporation, Copyright 1989, Massachusetts Institute of Technology, Copyright 1993, Robert Nation. ***********************************************************************/ void parsekey(char *tline) { struct keyfunc *k; int nlen, alen; char *nptr, *aptr, *start, *end, *tmp; int i, kmin, kmax; KeySym keysym; /* skip spaces */ while(isspace(*tline)&&(*tline != '\n')&&(*tline != 0)) tline++; start = tline; end = tline; while((!isspace(*end))&&(*end!='\n')&&(*end!=0)) end++; nlen = end - start; nptr = safemalloc(nlen+1); strncpy(nptr, start, nlen); nptr[nlen] = 0; /* actions */ tline = end; /* skip spaces */ while(isspace(*tline)&&(*tline != '\n')&&(*tline != 0)) tline++; start = tline; end = tline; tmp = tline; while((*tmp!='\n')&&(*tmp!=0)){ if (!isspace(*tmp)) end = tmp; tmp++; } end++; alen = end - start; aptr = safemalloc(alen+1); strncpy(aptr, start, alen); aptr[alen] = 0; if ((keysym = XStringToKeysym(nptr)) == NoSymbol || XKeysymToKeycode(dpy, keysym) == 0){ free(nptr); free(aptr); return; } XDisplayKeycodes(dpy, &kmin, &kmax); for (i=kmin; i<=kmax; i++) if (XKeycodeToKeysym(dpy, i, 0) == keysym) { k = (struct keyfunc *)safemalloc(sizeof(struct keyfunc)); k->name = nptr; k->keycode = i; k->action = aptr; k->next = KeyActions; KeyActions = k; } } /*********************************************************************** * change_window_name * Original work from GoodStuff: * Copyright 1993, Robert Nation. ***********************************************************************/ void change_window_name(char *str) { XTextProperty name; if (XStringListToTextProperty(&str,1,&name) == 0) { fprintf(stderr,"%s: cannot allocate window name",MyName); return; } XSetWMName(dpy,main_win,&name); XSetWMIconName(dpy,main_win,&name); XFree(name.value); } /*********************************************************************** * My_XNextEvent * Original work from GoodStuff: * Copyright 1993, Robert Nation. ***********************************************************************/ int My_XNextEvent(Display *dpy, XEvent *event) { fd_set in_fdset; unsigned long header[3]; int body_length; int count,count2 = 0; static int miss_counter = 0; unsigned long *body; int total; char *cbody; if(XPending(dpy)) { XNextEvent(dpy,event); return 1; } FD_ZERO(&in_fdset); FD_SET(x_fd,&in_fdset); FD_SET(fd[1],&in_fdset); #ifdef __hpux select(fd_width,(int *)&in_fdset, 0, 0, NULL); #else select(fd_width,&in_fdset, 0, 0, NULL); #endif if(FD_ISSET(x_fd, &in_fdset)) { if(XPending(dpy)) { XNextEvent(dpy,event); miss_counter = 0; return 1; } else miss_counter++; if(miss_counter > 100) DeadPipe(0); } if(FD_ISSET(fd[1], &in_fdset)) { if(count = ReadFvwmPacket(fd[1],header,&body) > 0) { process_message(header[1],body); free(body); } } return 0; } /************************************************************************** * process_message * Based on ProcessMassage() from FvwmWinList: * Copyright 1994, Mike Finger. *************************************************************************/ int diffx, diffy; void process_message(unsigned long type, unsigned long *body) { struct icon_info *tmp; int isndeleted=0, i=0; Window iw; switch(type){ case M_CONFIGURE_WINDOW: if (isendlist) break; case M_ADD_WINDOW: if (AddItem(body[0], body[1], body[8]) == True && UP){ GetIconwinSize(&diffx, &diffy); if (diffy && (primary == BOTTOM || secondary == BOTTOM)) icon_win_y += diffy; if (diffx && (primary == RIGHT || secondary == RIGHT)) icon_win_x += diffx; XMoveResizeWindow(dpy, icon_win, -icon_win_x, -icon_win_y, icon_win_width, icon_win_height); } break; case M_DESTROY_WINDOW: if (DeleteItem(body[0]) && UP){ GetIconwinSize(&diffx, &diffy); if (diffy && (primary == BOTTOM || secondary == BOTTOM)) icon_win_y += diffy; if (diffx && (primary == RIGHT || secondary == RIGHT)) icon_win_x += diffx; if (icon_win_y < 0) icon_win_y = 0; if (icon_win_x < 0) icon_win_x = 0; if (icon_win_x + Width > icon_win_width) icon_win_x = icon_win_width - Width; if (icon_win_y + Height > icon_win_height) icon_win_y = icon_win_height - Height; XMoveResizeWindow(dpy, icon_win, -icon_win_x, -icon_win_y, icon_win_width, icon_win_height); tmp = Head; i = 0; while(tmp != NULL){ AdjustIconWindow(tmp, i++); tmp = tmp->next; } RedrawIcons(); if (hidesc != HORIZONTAL && diffx) RedrawHScrollbar(); if (hidesc != VERTICAL && diffy) RedrawVScrollbar(); } break; case M_WINDOW_NAME: UpdateItem(type, body[0], (char *)&body[3]); break; case M_RES_CLASS: UpdateItem(type, body[0], (char *)&body[3]); break; case M_RES_NAME: if ((tmp = UpdateItem(type, body[0], (char *)&body[3])) != NULL) isndeleted = LookInList(tmp); if (UP && isndeleted && tmp != NULL){ CreateIconWindow(tmp); ConfigureIconWindow(tmp); XMapWindow(dpy, tmp->icon_pixmap_w); XMapWindow(dpy, tmp->IconWin); tmp = Head; while(tmp != NULL){ AdjustIconWindow(tmp, i++); tmp = tmp->next; } RedrawIcons(); if (hidesc != HORIZONTAL) RedrawHScrollbar(); if (hidesc != VERTICAL) RedrawVScrollbar(); } break; case M_ICON_NAME: tmp = UpdateItem(type, body[0], (char *)&body[3]); iw = tmp == NULL ? None : tmp->IconWin; if (UP && tmp != NULL && sorticons){ /* SortIcon is specified */ if (SortItem(tmp) == True && iw != None){ tmp = Head; while(tmp != NULL){ AdjustIconWindow(tmp, i++); tmp = tmp->next; } RedrawIcons(); }else if (iw != None) RedrawIcon(tmp, 2); } else if (UP && iw != None) /* SortIcon is not specified */ RedrawIcon(tmp, 2); break; case M_ICONIFY: case M_DEICONIFY: if (UP && (tmp = SetFlag(body[0], type)) != NULL) RedrawIcon(tmp, 2); break; case M_END_WINDOWLIST: GetIconwinSize(&diffx, &diffy); tmp = Head; while(tmp != NULL){ CreateIconWindow(tmp); ConfigureIconWindow(tmp); tmp = tmp->next; } if (sorticons) SortItem(NULL); tmp = Head; i=0; while(tmp != NULL){ AdjustIconWindow(tmp, i++); tmp = tmp->next; } if (primary == BOTTOM || secondary == BOTTOM) icon_win_y = icon_win_height - Height; if (primary == RIGHT || secondary == RIGHT) icon_win_x = icon_win_width - Width; XMoveResizeWindow(dpy, icon_win, -icon_win_x, -icon_win_y, icon_win_width, icon_win_height); XMapWindow(dpy,main_win); XMapSubwindows(dpy, main_win); XMapWindow(dpy, icon_win); XMapSubwindows(dpy, icon_win); UP = 1; isendlist = 1; break; default: break; } } struct icon_info *SetFlag(unsigned long id, int t) { struct icon_info *tmp; tmp = Head; while(tmp != NULL){ if (tmp->id == id){ if (t == M_ICONIFY) tmp->flags |= ICONIFIED; else tmp->flags ^= ICONIFIED; return tmp; } tmp = tmp->next; } return NULL; } /************************************************************************ * send_clientmessage * Original work from GoodStuff: * Copyright 1993, Robert Nation. ***********************************************************************/ void send_clientmessage (Window w, Atom a, Time timestamp) { XClientMessageEvent ev; ev.type = ClientMessage; ev.window = w; ev.message_type = _XA_WM_PROTOCOLS; ev.format = 32; ev.data.l[0] = a; ev.data.l[1] = timestamp; XSendEvent (dpy, w, False, 0L, (XEvent *) &ev); } /************************************************************************ * AddItem * Skeleton based on AddItem() from FvwmWinList: * Copyright 1994, Mike Finger. ***********************************************************************/ Bool AddItem(unsigned long id, unsigned long fid, unsigned long flags) { struct icon_info *new, *tmp; tmp = Head; if (id == main_win || (flags & TRANSIENT)) return False; while (tmp != NULL){ if (tmp->id == id || (tmp->wmhints && (tmp->wmhints->flags & IconWindowHint) && tmp->wmhints->icon_window == id)) return False; tmp = tmp->next; } new = (struct icon_info *)safemalloc(sizeof(struct icon_info)); new->name = NULL; new->window_name = NULL; new->res_class = NULL; new->res_name = NULL; new->action = NULL; new->icon_file = NULL; new->icon_w = 0; new->icon_h = 0; new->IconWin = None; new->iconPixmap = None; new->icon_maskPixmap = None; new->icon_pixmap_w = None; new->icon_depth = 0; new->id = id; new->fid = fid; new->defaulticon = 1; new->flags = flags | ICON_OURS; new->wmhints = NULL; new->prev = NULL; new->next = Head; if (Head != NULL) Head->prev = new; else Tail = new; Head = new; num_icons++; return True; } /************************************************************************ * Deletetem * Skeleton based on DeleteItem() from FvwmWinList: * Copyright 1994, Mike Finger. ***********************************************************************/ Bool DeleteItem(unsigned long id) { struct icon_info *tmp; tmp = Head; if (tmp == NULL) return False; if (tmp->id == id){ if (Hilite == tmp) Hilite = NULL; if ((tmp->icon_pixmap_w != None) && (tmp->flags & ICON_OURS)) XDestroyWindow(dpy, tmp->icon_pixmap_w); if (tmp->IconWin != None) XDestroyWindow(dpy, tmp->IconWin); Head = tmp->next; if (Head != NULL) Head->prev = NULL; else Tail = NULL; freeitem(tmp, DELETE); num_icons--; return True; } tmp = tmp->next; while(tmp != NULL){ if (tmp->id == id){ if (Hilite == tmp) Hilite = NULL; if (Tail == tmp) Tail = tmp->prev; if ((tmp->icon_pixmap_w != None) && (tmp->flags & ICON_OURS)) XDestroyWindow(dpy, tmp->icon_pixmap_w); if (tmp->IconWin != None) XDestroyWindow(dpy, tmp->IconWin); tmp->prev->next = tmp->next; if (tmp->next != NULL) tmp->next->prev = tmp->prev; freeitem(tmp, DELETE); num_icons--; return True; } tmp = tmp->next; } return False; } /************************************************************************ * UpdateItem * Skeleton based on UpdateItem() from FvwmWinList: * Copyright 1994, Mike Finger. ***********************************************************************/ struct icon_info *UpdateItem(unsigned long type, unsigned long id, char *item) { struct icon_info *tmp; char *str; tmp = Head; while (tmp != NULL){ if (tmp->id == id){ str = (char *)safemalloc(strlen(item)+1); strcpy(str, item); switch (type){ case M_ICON_NAME: if (tmp->name != NULL) free(tmp->name); tmp->name = str; return tmp; case M_WINDOW_NAME: if (tmp->window_name != NULL) free(tmp->window_name); tmp->window_name = str; return tmp; case M_RES_CLASS: tmp->res_class = str; return tmp; case M_RES_NAME: tmp->res_name = str; return tmp; } } tmp = tmp->next; } return NULL; } Bool SortItem(struct icon_info *item) { struct icon_info *tmp, *i_min, *next, *prev, tmp2; if (item != NULL && (item->prev==NULL || strcmp(item->prev->name, item->name) <= 0) && (item->next==NULL || strcmp(item->next->name, item->name) >= 0)) return False; tmp = Head; while (tmp != NULL){ i_min = MinItem(tmp); tmp2 = *i_min; *i_min = *tmp; next = tmp->next; prev = tmp->prev; i_min->next = tmp2.next; i_min->prev = tmp2.prev; *tmp = tmp2; tmp->next = next; tmp->prev = prev; tmp = tmp->next; } return True; } struct icon_info *MinItem(struct icon_info *head) { struct icon_info *tmp, *i_min; if (head == NULL) return NULL; i_min = head; tmp = head->next; while (tmp != NULL){ if (strcmp(i_min->name, tmp->name) > 0) i_min = tmp; tmp = tmp->next; } return i_min; } /* void ShowItem(struct icon_info *head) { struct icon_info *tmp; fprintf(stderr, "The contents of item are as follows:\n"); tmp = head; while (tmp != NULL){ fprintf(stderr, "id:%x name:%s resname:%s class%s iconfile:%s\n", tmp->id, tmp->name == NULL ? "NULL" : tmp->name, tmp->res_name, tmp->res_class, tmp->icon_file); tmp = tmp->next; } } void ShowAction(void) { struct mousefunc *tmp; tmp = MouseActions; while (tmp != NULL){ fprintf(stderr, "mouse:%d type %d action:%s\n", tmp->mouse, tmp->type, tmp->action); tmp = tmp->next; } } void ShowKAction(void) { struct keyfunc *tmp; tmp = KeyActions; while (tmp != NULL){ fprintf(stderr, "key:%s keycode:%d action:%s\n", tmp->name, tmp->keycode, tmp->action); tmp = tmp->next; } } */ void freeitem(struct icon_info *item, int s) { if (item == NULL) return; if (!(item->flags & ICON_OURS) && s == DEAD){ XUnmapWindow(dpy, item->icon_pixmap_w); XReparentWindow(dpy, item->icon_pixmap_w, Root, 0, 0); } if (item->name != NULL) free(item->name); if (item->window_name != NULL) free(item->window_name); if (item->res_name != NULL) free(item->res_name); if (item->res_class != NULL) free(item->res_class); if (item->wmhints != NULL) XFree(item->wmhints); if (item->iconPixmap != None) XFreePixmap(dpy, item->iconPixmap); free(item); } /************************************************************************ IsClick Based on functions.c from Fvwm: Copyright 1988, Evans and Sutherland Computer Corporation, Copyright 1989, Massachusetts Institute of Technology, Copyright 1993, Robert Nation. ***********************************************************************/ Bool IsClick(int x,int y,unsigned EndMask, XEvent *d) { int xcurrent,ycurrent,total = 0; xcurrent = x; ycurrent = y; while((total < ClickTime)&& (x - xcurrent < 5)&&(x - xcurrent > -5)&& (y - ycurrent < 5)&&(y - ycurrent > -5)) { sleep_a_little(10000); total+=10; if(XCheckMaskEvent (dpy,EndMask, d)) return True; if(XCheckMaskEvent (dpy,ButtonMotionMask|PointerMotionMask, d)) { xcurrent = d->xmotion.x_root; ycurrent = d->xmotion.y_root; } } return False; } /************************************************************************ * ExecuteAction * Based on part of ComplexFunction() of functions.c from fvwm: Copyright 1988, Evans and Sutherland Computer Corporation, Copyright 1989, Massachusetts Institute of Technology, Copyright 1993, Robert Nation. ***********************************************************************/ void ExecuteAction(int x, int y, struct icon_info *item) { int type = NO_CLICK; XEvent *ev; XEvent d; struct mousefunc *tmp; /* Wait and see if we have a click, or a move */ /* wait 100 msec, see if the used releases the button */ if(IsClick(x,y,ButtonReleaseMask,&d)) { type = CLICK; ev = &d; } /* If it was a click, wait to see if its a double click */ if((type == CLICK) && (IsClick(x,y,ButtonPressMask, &d))) { type = ONE_AND_A_HALF_CLICKS; ev = &d; } if((type == ONE_AND_A_HALF_CLICKS) && (IsClick(x,y,ButtonReleaseMask, &d))) { type = DOUBLE_CLICK; ev = &d; } tmp = MouseActions; while (tmp != NULL){ if (tmp->mouse == d.xbutton.button && tmp->type == type){ SendFvwmPipe(fd, tmp->action, item->id); return; } tmp = tmp->next; } } void ExecuteKey(XEvent event) { struct icon_info *item; struct keyfunc *tmp; if ((item = Hilite) == NULL) if ((item = Head) == NULL) return; tmp = KeyActions; event.xkey.keycode = XKeysymToKeycode(dpy,XKeycodeToKeysym(dpy,event.xkey.keycode,0)); while (tmp != NULL){ if (tmp->keycode == event.xkey.keycode){ SendFvwmPipe(fd, tmp->action, item->id); return; } tmp = tmp->next; } } void ShowList(void) { struct iconfile *nptr; for (nptr = IconListHead; nptr != NULL; nptr = nptr->next) fprintf(stderr, "%s, %s,\n", nptr->name, nptr->iconfile); } /*********************************************************************** LookInList Based on part of LookInList() of add_window.c from fvwm: Copyright 1988, Evans and Sutherland Computer Corporation, Copyright 1989, Massachusetts Institute of Technology, Copyright 1993, Robert Nation. ***********************************************************************/ int LookInList(struct icon_info *item) { int isdefault=0; char *value=NULL; struct iconfile *nptr; for (nptr = IconListHead; nptr != NULL; nptr = nptr->next){ if (nptr == DefaultIcon) isdefault = 1; if (matchWildcards(nptr->name, item->res_class) == TRUE){ value = nptr->iconfile; if (nptr != DefaultIcon) isdefault = 0; } if (matchWildcards(nptr->name, item->res_name) == TRUE){ value = nptr->iconfile; if (nptr != DefaultIcon) isdefault = 0; } if (matchWildcards(nptr->name, item->window_name) == TRUE){ value = nptr->iconfile; if (nptr != DefaultIcon) isdefault = 0; } } if (!isdefault){ item->icon_file = value; item->defaulticon = 0; }else item->icon_file = DefaultIcon->iconfile; /* Icon is not shown if "-" is specified */ if (item->icon_file != NULL && (strcmp(item->icon_file, "-") == 0)){ DeleteItem(item->id); return 0; } return 1; } /*********************************************************************** strcpy Based on stripcpy2() of configure.c from Fvwm: Copyright 1988, Evans and Sutherland Computer Corporation, Copyright 1989, Massachusetts Institute of Technology, Copyright 1993, Robert Nation. ***********************************************************************/ char *stripcpy(char *source) { char *ptr; int count = 0; while((*source != '"')&&(*source != 0)) source++; if(*source == 0) return 0; source++; ptr = source; while((*ptr!='"')&&(*ptr != 0)){ ptr++; count++; } ptr = safemalloc(count+1); strncpy(ptr,source,count); ptr[count]=0; return ptr; }