e16/src/menus.c

2039 lines
50 KiB
C
Raw Blame History

/*
* Copyright (C) 1999 Carsten Haitzler, Geoff Harrison and various contributors
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in
* all copies of the Software, its documentation and marketing & publicity
* materials, and acknowledgment shall be given in the documentation, materials
* and software packages that this Software was used.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "E.h"
static MenuStyle *task_menu_style = NULL;
static MenuStyle *desk_menu_style = NULL;
static MenuStyle *group_menu_style = NULL;
static void FileMenuUpdate(int val, void *data);
static void FillFlatFileMenu(Menu * m, MenuStyle * ms, char *name, char *file, Menu * parent);
void
ShowTaskMenu(void)
{
EDBUG(5, "ShowTaskMenu");
EDBUG_RETURN_;
}
void
ShowAllTaskMenu(void)
{
static MenuStyle *ms = NULL;
static Menu *m = NULL;
EDBUG(5, "ShowAllTaskMenu");
XUngrabPointer(disp, CurrentTime);
if (!task_menu_style)
{
ms = FindItem("TASK_MENU", 0, LIST_FINDBY_NAME, LIST_TYPE_MENU_STYLE);
if (!ms)
ms = FindItem("DEFAULT", 0, LIST_FINDBY_NAME, LIST_TYPE_MENU_STYLE);
if (!ms)
EDBUG_RETURN_;
}
task_menu_style = ms;
mode.cur_menu_mode = 1;
m = NULL;
m = RefreshAllTaskMenu(all_task_menu);
all_task_menu = m;
if (m)
{
if (!FindEwinByMenu(m))
ShowMenu(m, 0);
mode.cur_menu[0] = m;
mode.cur_menu_depth = 1;
ShowMenuMasker(m);
}
else
{
mode.cur_menu[0] = NULL;
mode.cur_menu_depth = 0;
HideMenuMasker();
}
EDBUG_RETURN_;
}
void
ShowDeskMenu(void)
{
static MenuStyle *ms = NULL;
static Menu *m = NULL;
EDBUG(5, "ShowDeskMenu");
XUngrabPointer(disp, CurrentTime);
if (!desk_menu_style)
{
ms = FindItem("DESK_MENU", 0, LIST_FINDBY_NAME, LIST_TYPE_MENU_STYLE);
if (!ms)
ms = FindItem("DEFAULT", 0, LIST_FINDBY_NAME, LIST_TYPE_MENU_STYLE);
if (!ms)
EDBUG_RETURN_;
}
desk_menu_style = ms;
mode.cur_menu_mode = 1;
m = NULL;
m = RefreshDeskMenu(desk_menu);
desk_menu = m;
if (m)
{
if (!FindEwinByMenu(m))
ShowMenu(m, 0);
mode.cur_menu[0] = m;
mode.cur_menu_depth = 1;
ShowMenuMasker(m);
}
else
{
mode.cur_menu[0] = NULL;
mode.cur_menu_depth = 0;
HideMenuMasker();
}
EDBUG_RETURN_;
}
Menu *
RefreshTaskMenu(int desk)
{
char was = 0;
int lx = 0, ly = 0;
EWin *ewin;
EDBUG(5, "RefreshTaskMenu");
if (task_menu[desk])
{
ewin = FindEwinByMenu(task_menu[desk]);
if ((task_menu[desk]->win) && (ewin))
{
lx = ewin->x;
ly = ewin->y;
was = 1;
}
DestroyMenu(task_menu[desk]);
}
task_menu[desk] = NULL;
if (!task_menu_style)
{
EDBUG_RETURN(NULL);
}
task_menu[desk] = CreateMenuFromDesktopEWins("MENU", task_menu_style, desk);
if ((was) && (task_menu[desk]))
{
ShowMenu(task_menu[desk], 1);
ewin = FindEwinByMenu(task_menu[desk]);
if (ewin)
{
MoveEwin(ewin, lx, ly);
ShowEwin(ewin);
}
mode.cur_menu[0] = task_menu[desk];
mode.cur_menu_depth = 1;
ShowMenuMasker(task_menu[desk]);
}
EDBUG_RETURN(task_menu[desk]);
}
Menu *
RefreshAllTaskMenu(Menu * m)
{
char was = 0;
int lx = 0, ly = 0;
EWin *ewin;
EDBUG(5, "RefreshAllTaskMenu");
if (m)
{
ewin = FindEwinByMenu(m);
if ((m->win) && (ewin))
{
lx = ewin->x;
ly = ewin->y;
was = 1;
}
DestroyMenu(m);
}
m = NULL;
if (!task_menu_style)
{
EDBUG_RETURN(NULL);
}
m = CreateMenuFromAllEWins("MENU", task_menu_style);
if ((was) && (m))
{
ShowMenu(m, 1);
ewin = FindEwinByMenu(m);
if (ewin)
{
MoveEwin(ewin, lx, ly);
ShowEwin(ewin);
}
mode.cur_menu[0] = m;
mode.cur_menu_depth = 1;
ShowMenuMasker(m);
}
EDBUG_RETURN(m);
}
Menu *
RefreshDeskMenu(Menu * m)
{
char was = 0;
int lx = 0, ly = 0;
EWin *ewin;
EDBUG(5, "RefreshDeskMenu");
if (m)
{
ewin = FindEwinByMenu(m);
if ((m->win) && (ewin))
{
lx = ewin->x;
ly = ewin->y;
was = 1;
}
DestroyMenu(m);
}
m = NULL;
if (!desk_menu_style)
{
EDBUG_RETURN(NULL);
}
m = CreateMenuFromDesktops("MENU", desk_menu_style);
if ((was) && (m))
{
ShowMenu(m, 1);
ewin = FindEwinByMenu(m);
if (ewin)
{
MoveEwin(ewin, lx, ly);
ShowEwin(ewin);
}
mode.cur_menu[0] = m;
mode.cur_menu_depth = 1;
ShowMenuMasker(m);
}
EDBUG_RETURN(m);
}
void
HideMenu(Menu * m)
{
EWin *ewin;
/* XEvent ev; */
EDBUG(5, "HideMenu");
if (m->win)
EUnmapWindow(disp, m->win);
ewin = FindEwinSpawningMenu(m);
if (ewin)
ewin->shownmenu = 0;
ewin = FindEwinByMenu(m);
if (ewin)
{
HideEwin(ewin);
/* FASTER ????
* ev.xunmap.window = m->win;
* HandleUnmap(&ev);
*/
}
if (m->sel_item)
{
m->sel_item->state = STATE_NORMAL;
DrawMenuItem(m, m->sel_item, 1);
m->sel_item = NULL;
}
m->stuck = 0;
EDBUG_RETURN_;
}
void
ShowMenu(Menu * m, char noshow)
{
EWin *ewin;
int x, y, wx = 0, wy = 0; /* wx, wy added to stop menus from appearing offscreen */
unsigned int w, h, mw, mh;
EDBUG(5, "ShowMenu");
if ((m->num <= 0) || (!m->style))
EDBUG_RETURN_;
if (m->stuck)
{
Button *button;
EWin *ewin99;
if ((button = FindButton(mode.context_win)))
{
button->state = STATE_NORMAL;
DrawButton(button);
}
else if ((ewin99 = FindEwinByDecoration(mode.context_win)))
{
int i99;
for (i99 = 0; i99 < ewin99->border->num_winparts; i99++)
{
if (mode.context_win == ewin99->bits[i99].win)
{
ewin99->bits[i99].state = STATE_NORMAL;
ChangeEwinWinpart(ewin99, i99);
i99 = ewin99->border->num_winparts;
}
}
}
EDBUG_RETURN_;
}
if (!m->win)
RealizeMenu(m);
ewin = FindEwinByMenu(m);
if (ewin)
{
if ((mode.button) && FindItem((char *)mode.button, 0, LIST_FINDBY_POINTER,
LIST_TYPE_BUTTON))
{
fprintf(stderr, "setting back to normal\n");
mode.button->state = STATE_NORMAL;
DrawButton(mode.button);
}
RaiseEwin(ewin);
EDBUG_RETURN_;
}
GetWinXY(m->items[0]->win, &x, &y);
GetWinWH(m->items[0]->win, &w, &h);
GetWinWH(m->win, &mw, &mh);
wx = 0;
wy = 0;
if (mode.menusonscreen)
{
Border *b;
b = (Border *) FindItem(m->style->border_name, 0, LIST_FINDBY_NAME,
LIST_TYPE_BORDER);
if (b)
{
if (mode.x - x - ((int)mw / 2) > (int)root.w)
wx = 0 + (int)b->border.left;
else if (mode.x + ((int)mw / 2) > (int)root.w)
wx = root.w - (int)mw - (int)b->border.right;
else
wx = mode.x - x - ((int)w / 2);
if ((wx - ((int)w / 2)) < 0)
wx = (int)b->border.left;
if (mode.y + (int)mh > (int)root.h)
wy = (int)root.h - (int)mh - (int)b->border.bottom;
else
wy = mode.y - y - ((int)h / 2);
if ((wy - ((int)h / 2) - (int)b->border.top) < 0)
wy = (int)b->border.top;
}
}
if ((mode.x >= 0) && (mode.y >= 0))
{
if (mode.menusonscreen)
EMoveWindow(disp, m->win, wx, wy);
else
EMoveWindow(disp, m->win, mode.x - x - (w / 2), mode.y - y - (h / 2));
}
else if ((mode.x >= 0) && (mode.y < 0))
{
if (((-mode.y) + (int)mh) > (int)root.h)
mode.y = -((-mode.y) - mode.context_h - mh);
if (mode.menusonscreen)
EMoveWindow(disp, m->win, wx, -mode.y);
else
EMoveWindow(disp, m->win, mode.x - x - (w / 2), -mode.y);
}
else if ((mode.x < 0) && (mode.y >= 0))
{
if (((-mode.x) + (int)mw) > (int)root.w)
mode.x = -((-mode.x) - mode.context_w - mw);
if (mode.menusonscreen)
EMoveWindow(disp, m->win, -mode.x, wy);
else
EMoveWindow(disp, m->win, -mode.x, mode.y - y - (h / 2));
}
else
{
if (((-mode.x) + (int)mw) > (int)root.w)
mode.x = -((-mode.x) - mode.context_w - mw);
if (((-mode.y) + (int)mh) > (int)root.h)
mode.y = -((-mode.y) - mode.context_h - mh);
EMoveWindow(disp, m->win, -mode.x, -mode.y);
}
ewin = AddInternalToFamily(m->win, 1, m->style->border_name, 0, m);
if (ewin)
{
DesktopRemoveEwin(ewin);
ewin->layer = 99;
DesktopAddEwinToTop(ewin);
if (ewin->desktop != 0)
MoveEwin(ewin, ewin->x - desks.desk[ewin->desktop].x,
ewin->y - desks.desk[ewin->desktop].y);
RestackEwin(ewin);
if (mode.menuslide)
InstantShadeEwin(ewin);
ICCCM_Cmap(NULL);
if (!noshow)
{
ShowEwin(ewin);
if (mode.menuslide)
UnShadeEwin(ewin);
}
ewin->menu = m;
ewin->dialog = NULL;
}
m->stuck = 0;
if (!FindMenu(m->win))
AddItem(m, m->name, m->win, LIST_TYPE_MENU);
{
Button *button;
EWin *ewin99;
if ((button = FindButton(mode.context_win)))
{
button->state = STATE_NORMAL;
DrawButton(button);
}
else if ((ewin99 = FindEwinByDecoration(mode.context_win)))
{
int i99;
for (i99 = 0; i99 < ewin99->border->num_winparts; i99++)
{
if (mode.context_win == ewin99->bits[i99].win)
{
ewin99->bits[i99].state = STATE_NORMAL;
ChangeEwinWinpart(ewin99, i99);
i99 = ewin99->border->num_winparts;
}
}
}
}
EDBUG_RETURN_;
}
MenuStyle *
CreateMenuStyle(void)
{
MenuStyle *ms;
EDBUG(5, "CreateMenuStyle");
ms = Emalloc(sizeof(MenuStyle));
ms->name = NULL;
ms->tclass = NULL;
ms->bg_iclass = NULL;
ms->item_iclass = NULL;
ms->sub_iclass = NULL;
ms->use_item_bg = 0;
ms->iconpos = ICON_LEFT;
ms->maxx = 0;
ms->maxy = 0;
ms->border_name = NULL;
ms->ref_count = 0;
EDBUG_RETURN(ms);
}
MenuItem *
CreateMenuItem(char *text, ImageClass * iclass, int action_id,
char *action_params, Menu * child)
{
MenuItem *mi;
EDBUG(5, "CreateMenuItem");
mi = Emalloc(sizeof(MenuItem));
mi->icon_iclass = iclass;
if (iclass)
iclass->ref_count++;
mi->text = duplicate(text);
mi->act_id = action_id;
if (action_params)
{
mi->params = duplicate(action_params);
}
else
{
mi->params = NULL;
}
mi->child = child;
mi->state = STATE_NORMAL;
mi->win = 0;
mi->pmap[0] = 0;
mi->pmap[1] = 0;
mi->pmap[2] = 0;
mi->mask[0] = 0;
mi->mask[1] = 0;
mi->mask[2] = 0;
mi->icon_win = 0;
mi->icon_w = 0;
mi->icon_h = 0;
mi->text_w = 0;
mi->text_h = 0;
mi->text_x = 0;
mi->text_y = 0;
EDBUG_RETURN(mi);
}
Menu *
CreateMenu(void)
{
Menu *m;
EDBUG(5, "CreateMenu");
m = Emalloc(sizeof(Menu));
m->name = NULL;
m->title = NULL;
m->style = NULL;
m->num = 0;
m->items = NULL;
m->win = 0;
m->pmap = 0;
m->mask = 0;
m->stuck = 0;
m->parent = NULL;
m->sel_item = NULL;
m->data = NULL;
m->ref_menu = NULL;
m->last_change = 0;
EDBUG_RETURN(m);
}
void
DestroyMenu(Menu * m)
{
int i, j;
char s[4096];
EDBUG(5, "DestroyMenu");
if (!m)
EDBUG_RETURN_;
HideMenu(m);
if (m->win)
EDestroyWindow(disp, m->win);
Esnprintf(s, sizeof(s), "__.%s", m->name);
RemoveTimerEvent(s);
RemoveItem((char *)m, m->win, LIST_FINDBY_POINTER, LIST_TYPE_MENU);
if (m->name)
Efree(m->name);
for (i = 0; i < m->num; i++)
{
if (m->items[i])
{
if (m->items[i]->child)
{
if (FindItem((char *)m->items[i]->child, 0,
LIST_FINDBY_POINTER, LIST_TYPE_MENU))
DestroyMenu(m->items[i]->child);
}
if (m->items[i]->text)
Efree(m->items[i]->text);
if (m->items[i]->params)
Efree(m->items[i]->params);
for (j = 0; j < 3; j++)
{
if (m->items[i]->pmap[j])
Imlib_free_pixmap(id, m->items[i]->pmap[j]);
if (m->items[i]->mask[j])
Imlib_free_pixmap(id, m->items[i]->mask[j]);
}
if (m->items[i]->icon_iclass)
m->items[i]->icon_iclass->ref_count--;
if (m->items[i])
Efree(m->items[i]);
}
}
if (m->items)
Efree(m->items);
if (m->data)
Efree(m->data);
Efree(m);
EDBUG_RETURN_;
}
/* NB - this doesnt free imageclasses if we created them for the menu
* FIXME: so it will leak if we create new imageclasses and stop using
* old ones for menu icons. we need to add some ref counting in menu icon
* imageclasses to knw to free them when not used
*/
void
EmptyMenu(Menu * m)
{
int i, j;
EDBUG(5, "EmptyMenu");
for (i = 0; i < m->num; i++)
{
if (m->items[i])
{
if (m->items[i]->child)
DestroyMenu(m->items[i]->child);
if (m->items[i]->text)
Efree(m->items[i]->text);
if (m->items[i]->params)
Efree(m->items[i]->params);
for (j = 0; j < 3; j++)
{
if (m->items[i]->pmap[j])
Imlib_free_pixmap(id, m->items[i]->pmap[j]);
if (m->items[i]->mask[j])
Imlib_free_pixmap(id, m->items[i]->mask[j]);
}
if (m->items[i]->win)
EDestroyWindow(disp, m->items[i]->win);
if (m->items[i])
Efree(m->items[i]);
}
}
if (m->items)
Efree(m->items);
m->items = NULL;
m->num = 0;
EDBUG_RETURN_;
}
void
RepackMenu(Menu * m)
{
EWin *ewin;
unsigned int w, h;
EDBUG(5, "RepackMenu");
ewin = FindEwinByMenu(m);
if (m->win)
RealizeMenu(m);
if (ewin)
{
GetWinWH(m->win, &w, &h);
ewin->client.height.min = h;
ewin->client.height.max = h;
ewin->client.width.min = w;
ewin->client.width.max = w;
ResizeEwin(ewin, w, h);
RaiseEwin(ewin);
}
EDBUG_RETURN_;
}
void
AddItemToMenu(Menu * menu, MenuItem * item)
{
EDBUG(5, "AddItemToMenu");
menu->num++;
menu->items = Erealloc(menu->items, sizeof(MenuItem *) * menu->num);
menu->items[menu->num - 1] = item;
EDBUG_RETURN_;
}
void
AddTitleToMenu(Menu * menu, char *title)
{
EDBUG(5, "AddTitleToMenu");
if (menu->title)
Efree(menu->title);
menu->title = duplicate(title);
EDBUG_RETURN_;
}
void
RealizeMenu(Menu * m)
{
int i, maxh = 0, maxw = 0, maxx1, maxx2, w, h, x, y, r,
mmw, mmh;
unsigned int iw, ih;
ImlibImage *im;
XSetWindowAttributes att;
XTextProperty xtp;
char pq, has_i, has_s;
EDBUG(5, "RealizeMenu");
if (!m->style)
EDBUG_RETURN_;
if (!m->win)
m->win = ECreateWindow(root.win, 0, 0, 1, 1, 0);
if (m->title)
{
xtp.encoding = XA_STRING;
xtp.format = 8;
xtp.value = (unsigned char *)(m->title);
xtp.nitems = strlen((char *)(xtp.value));
XSetWMName(disp, m->win, &xtp);
}
maxh = 0;
maxx1 = 0;
maxx2 = 0;
has_i = 0;
has_s = 0;
att.event_mask = PointerMotionMask;
XChangeWindowAttributes(disp, m->win, CWEventMask, &att);
att.event_mask = ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
LeaveWindowMask | PointerMotionMask;
for (i = 0; i < m->num; i++)
{
if (m->items[i]->child)
has_s = 1;
else
has_i = 1;
m->items[i]->win = ECreateWindow(m->win, 0, 0, 1, 1, 0);
XChangeWindowAttributes(disp, m->items[i]->win, CWEventMask, &att);
EMapWindow(disp, m->items[i]->win);
if ((m->style) && (m->style->tclass) && (m->items[i]->text))
{
TextSize(m->style->tclass, 0, 0, 0, m->items[i]->text, &w, &h, 17);
if (h > maxh)
maxh = h;
if (w > maxx1)
maxx1 = w;
m->items[i]->text_w = w;
m->items[i]->text_h = h;
}
if (m->items[i]->icon_iclass)
{
im = ELoadImage(m->items[i]->icon_iclass->norm.normal->im_file);
if (im)
{
m->items[i]->icon_win = ECreateWindow(m->items[i]->win, 0, 0,
im->rgb_width,
im->rgb_height, 0);
EMapWindow(disp, m->items[i]->icon_win);
XChangeWindowAttributes(disp, m->items[i]->icon_win, CWEventMask, &att);
m->items[i]->icon_w = im->rgb_width;
m->items[i]->icon_h = im->rgb_height;
if (im->rgb_height > maxh)
maxh = im->rgb_height;
if (im->rgb_width > maxx2)
maxx2 = im->rgb_width;
Imlib_destroy_image(id, im);
}
else
m->items[i]->icon_iclass = NULL;
}
}
if (((has_i) && (has_s)) || ((!has_i) && (!has_s)))
{
if (m->style->item_iclass->padding.top > m->style->sub_iclass->padding.top)
maxh += m->style->item_iclass->padding.top;
else
maxh += m->style->sub_iclass->padding.top;
if (m->style->item_iclass->padding.bottom > m->style->sub_iclass->padding.bottom)
maxh += m->style->item_iclass->padding.bottom;
else
maxh += m->style->sub_iclass->padding.bottom;
maxw = maxx1 + maxx2;
if (m->style->item_iclass->padding.left > m->style->sub_iclass->padding.left)
maxw += m->style->item_iclass->padding.left;
else
maxw += m->style->sub_iclass->padding.left;
if (m->style->item_iclass->padding.right > m->style->sub_iclass->padding.right)
maxw += m->style->item_iclass->padding.right;
else
maxw += m->style->sub_iclass->padding.right;
}
else if (has_i)
{
maxh += m->style->item_iclass->padding.top;
maxh += m->style->item_iclass->padding.bottom;
maxw = maxx1 + maxx2;
maxw += m->style->item_iclass->padding.left;
maxw += m->style->item_iclass->padding.right;
}
else if (has_s)
{
maxh += m->style->sub_iclass->padding.top;
maxh += m->style->sub_iclass->padding.bottom;
maxw = maxx1 + maxx2;
maxw += m->style->sub_iclass->padding.left;
maxw += m->style->sub_iclass->padding.right;
}
x = 0;
y = 0;
if ((m->style->bg_iclass) && (!m->style->use_item_bg))
{
x = m->style->bg_iclass->padding.left;
y = m->style->bg_iclass->padding.top;
}
r = 0;
mmw = 0;
mmh = 0;
pq = queue_up;
queue_up = 0;
for (i = 0; i < m->num; i++)
{
EMoveResizeWindow(disp, m->items[i]->win, x, y, maxw, maxh);
if (m->style->iconpos == ICON_LEFT)
{
m->items[i]->text_x = m->style->item_iclass->padding.left + maxx2;
m->items[i]->text_w = maxx1;
m->items[i]->text_y = (maxh - m->items[i]->text_h) / 2;
if (m->items[i]->icon_win)
EMoveWindow(disp, m->items[i]->icon_win,
m->style->item_iclass->padding.left +
((maxx2 - m->items[i]->icon_w) / 2),
((maxh - m->items[i]->icon_h) / 2));
}
else
{
m->items[i]->text_x = m->style->item_iclass->padding.left;
m->items[i]->text_w = maxx1;
m->items[i]->text_y = (maxh - m->items[i]->text_h) / 2;
if (m->items[i]->icon_win)
EMoveWindow(disp, m->items[i]->icon_win, maxw -
m->style->item_iclass->padding.right - maxx2 +
((maxx2 - w) / 2), ((maxh - h) / 2));
}
if (m->items[i]->icon_iclass)
{
iw = 0;
ih = 0;
GetWinWH(m->items[i]->icon_win, &iw, &ih);
IclassApply(m->items[i]->icon_iclass, m->items[i]->icon_win, iw, ih,
0, 0, STATE_NORMAL, 0);
}
if (x + maxw > mmw)
mmw = x + maxw;
if (y + maxh > mmh)
mmh = y + maxh;
if ((m->style->maxx) || (m->style->maxy))
{
if (m->style->maxy)
{
y += maxh;
r++;
if (r >= m->style->maxy)
{
r = 0;
x += maxw;
y = 0;
}
}
else
{
x += maxw;
r++;
if (r >= m->style->maxx)
{
r = 0;
y += maxh;
x = 0;
}
}
}
else
y += maxh;
}
if ((m->style->bg_iclass) && (!m->style->use_item_bg))
{
mmw += m->style->bg_iclass->padding.right;
mmh += m->style->bg_iclass->padding.bottom;
}
EResizeWindow(disp, m->win, mmw, mmh);
if (!m->style->use_item_bg)
{
IclassApplyCopy(m->style->bg_iclass, m->win, mmw, mmh, 0, 0,
STATE_NORMAL, &(m->pmap), &(m->mask));
ESetWindowBackgroundPixmap(disp, m->win, m->pmap);
EShapeCombineMask(disp, m->win, ShapeBounding,
0, 0, m->mask, ShapeSet);
for (i = 0; i < m->num; i++)
DrawMenuItem(m, m->items[i], 0);
}
else
{
for (i = 0; i < m->num; i++)
DrawMenuItem(m, m->items[i], 0);
PropagateShapes(m->win);
}
queue_up = pq;
EDBUG_RETURN_;
}
void
DrawMenuItem(Menu * m, MenuItem * mi, char shape)
{
GC gc;
XGCValues gcv;
unsigned int w, h;
int x, y;
char pq;
Pixmap pmap, mask;
EDBUG(5, "DrawMenuItem");
pq = queue_up;
queue_up = 0;
if (!mi->pmap[(int)(mi->state)])
{
if (mi->text)
{
GetWinWH(mi->win, &w, &h);
GetWinXY(mi->win, &x, &y);
if (!m->style->use_item_bg)
{
mi->pmap[(int)(mi->state)] = ECreatePixmap(disp, mi->win, w, h, id->x.depth);
gc = XCreateGC(disp, m->pmap, 0, &gcv);
XCopyArea(disp, m->pmap, mi->pmap[(int)(mi->state)], gc, x, y, w, h, 0, 0);
mi->mask[(int)(mi->state)] = None;
if ((mi->state != STATE_NORMAL) || (mi->child))
{
pmap = 0;
mask = 0;
if (mi->child)
IclassApplyCopy(m->style->sub_iclass, mi->win, w, h, 0, 0, mi->state,
&pmap, &mask);
else
IclassApplyCopy(m->style->item_iclass, mi->win, w, h, 0, 0, mi->state,
&pmap, &mask);
if (mask)
{
XSetClipMask(disp, gc, mask);
XSetClipOrigin(disp, gc, 0, 0);
}
XCopyArea(disp, pmap, mi->pmap[(int)(mi->state)], gc, 0, 0, w, h, 0, 0);
Imlib_free_pixmap(id, pmap);
if (mask)
Imlib_free_pixmap(id, mask);
}
XFreeGC(disp, gc);
}
else
{
if (mi->child)
IclassApplyCopy(m->style->sub_iclass, mi->win, w, h, 0, 0, mi->state,
&(mi->pmap[(int)(mi->state)]), &(mi->mask[(int)(mi->state)]));
else
IclassApplyCopy(m->style->item_iclass, mi->win, w, h, 0, 0, mi->state,
&(mi->pmap[(int)(mi->state)]), &(mi->mask[(int)(mi->state)]));
}
}
}
if ((m->style->tclass) && (mi->text))
{
TextDraw(m->style->tclass, mi->pmap[(int)(mi->state)], 0, 0, mi->state,
mi->text, mi->text_x, mi->text_y, mi->text_w, mi->text_h, 17,
m->style->tclass->justification);
}
if (mi->text)
{
ESetWindowBackgroundPixmap(disp, mi->win, mi->pmap[(int)(mi->state)]);
EShapeCombineMask(disp, mi->win, ShapeBounding,
0, 0, mi->mask[(int)(mi->state)], ShapeSet);
XClearWindow(disp, mi->win);
}
else
{
GetWinWH(mi->win, &w, &h);
GetWinXY(mi->win, &x, &y);
if (!m->style->use_item_bg)
{
if ((mi->state != STATE_NORMAL) || (mi->child))
IclassApply(m->style->item_iclass, mi->win, w, h, 0, 0, mi->state, 0);
else
{
ESetWindowBackgroundPixmap(disp, mi->win, ParentRelative);
EShapeCombineMask(disp, mi->win, ShapeBounding,
0, 0, None, ShapeSet);
XClearWindow(disp, mi->win);
}
}
else
{
if (mi->child)
IclassApply(m->style->sub_iclass, mi->win, w, h, 0, 0, mi->state, 0);
else
IclassApply(m->style->item_iclass, mi->win, w, h, 0, 0, mi->state, 0);
}
}
if ((shape) && (m->style->use_item_bg))
PropagateShapes(m->win);
queue_up = pq;
EDBUG_RETURN_;
}
Menu *
CreateMenuFromDirectory(char *name, MenuStyle * ms, char *dir)
{
Progressbar *p = NULL;
Menu *m, *mm;
int i, num;
char **list, s[4096], ss[4096], *ext, cs[4096];
MenuItem *mi;
struct stat st;
const char *chmap =
#ifndef __EMX__
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
#else
"0123456789abcdefghijklmnopqrstuvwxyz<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-_";
#endif
FILE *f;
EDBUG(5, "CreateMenuFromDirectory");
m = CreateMenu();
m->name = duplicate(name);
m->style = ms;
if (stat(dir, &st) >= 0)
{
int aa, bb, cc;
#ifdef __EMX__
aa = (int)st.st_inode;
#else
list = ls(dir, &num);
aa = (int)num;
#endif
bb = (int)st.st_dev;
cc = 0;
if (st.st_mtime > st.st_ctime)
cc = st.st_mtime;
else
cc = st.st_ctime;
Esnprintf(cs, sizeof(cs),
"%s/cached/img/.%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
UserEDir(),
chmap[(aa >> 0) & 0x3f],
chmap[(aa >> 6) & 0x3f],
chmap[(aa >> 12) & 0x3f],
chmap[(aa >> 18) & 0x3f],
chmap[(aa >> 24) & 0x3f],
chmap[(aa >> 28) & 0x3f],
chmap[(bb >> 0) & 0x3f],
chmap[(bb >> 6) & 0x3f],
chmap[(bb >> 12) & 0x3f],
chmap[(bb >> 18) & 0x3f],
chmap[(bb >> 24) & 0x3f],
chmap[(bb >> 28) & 0x3f],
chmap[(cc >> 0) & 0x3f],
chmap[(cc >> 6) & 0x3f],
chmap[(cc >> 12) & 0x3f],
chmap[(cc >> 18) & 0x3f],
chmap[(cc >> 24) & 0x3f],
chmap[(cc >> 28) & 0x3f]);
/* cached dir listing - use it */
if (exists(cs))
{
#ifndef __EMX__
f = fopen(cs, "r");
#else
f = fopen(cs, "rt");
#endif
while (fgets(s, sizeof(s), f))
{
s[strlen(s) - 1] = 0;
word(s, 1, ss);
if (!strcmp(ss, "BG"))
{
Background *bg;
char ok = 1;
char s2[4096], s3[512];
word(s, 3, s3);
bg = (Background *) FindItem(s3, 0, LIST_FINDBY_NAME, LIST_TYPE_BACKGROUND);
if (!bg)
{
ImlibImage *im;
word(s, 2, s2);
Esnprintf(ss, sizeof(ss), "%s/%s", dir, s2);
im = Imlib_load_image(id, ss);
if (im)
{
ImlibImage *im2;
ImlibColor icl;
char tile = 1, keep_asp = 0;
int width, height, scalex = 0,
scaley = 0;
int scr_asp, im_asp, w2,
h2;
int maxw = 48, maxh = 48;
int justx = 512, justy = 512;
Esnprintf(s2, sizeof(s2), "%s/cached/img/%s", UserEDir(), s3);
width = im->rgb_width;
height = im->rgb_height;
h2 = maxh;
w2 = (im->rgb_width * h2) / im->rgb_height;
if (w2 > maxw)
{
w2 = maxw;
h2 = (im->rgb_height * w2) / im->rgb_width;
}
im2 = Imlib_clone_scaled_image(id, im, w2, h2);
Imlib_save_image_to_ppm(id, im2, s2);
Imlib_changed_image(id, im2);
Imlib_changed_image(id, im);
Imlib_kill_image(id, im2);
Imlib_kill_image(id, im);
scr_asp = (root.w << 16) / root.h;
im_asp = (width << 16) / height;
if (width == height)
{
justx = 0;
justy = 0;
scalex = 0;
scaley = 0;
tile = 1;
keep_asp = 0;
}
else if ((!(IN_RANGE(scr_asp, im_asp, 16000))) &&
((width < 480) && (height < 360)))
{
justx = 0;
justy = 0;
scalex = 0;
scaley = 0;
tile = 1;
keep_asp = 0;
}
else if (IN_RANGE(scr_asp, im_asp, 16000))
{
justx = 0;
justy = 0;
scalex = 1024;
scaley = 1024;
tile = 0;
keep_asp = 0;
}
else if (im_asp > scr_asp)
{
justx = 512;
justy = 512;
scalex = 1024;
scaley = 0;
tile = 0;
keep_asp = 1;
}
else
{
justx = 512;
justy = 512;
scalex = 0;
scaley = 1024;
tile = 0;
keep_asp = 1;
}
icl.r = 0;
icl.g = 0;
icl.b = 0;
bg = CreateDesktopBG(s3, &icl, ss, tile, keep_asp,
justx, justy, scalex, scaley,
NULL, 0, 0, 0, 0, 0);
AddItem(bg, bg->name, 0, LIST_TYPE_BACKGROUND);
}
else
ok = 0;
}
if (ok)
{
ImageClass *ic = NULL;
char stmp[4096];
ic = CreateIclass();
ic->name = duplicate("`");
ic->norm.normal = CreateImageState();
Esnprintf(stmp, sizeof(stmp), "cached/img/%s", s3);
ic->norm.normal->im_file = duplicate(stmp);
ic->norm.normal->unloadable = 1;
IclassPopulate(ic);
AddItem(ic, ic->name, 0, LIST_TYPE_ICLASS);
mi = CreateMenuItem(NULL, ic, ACTION_BACKGROUND_SET, s3, NULL);
AddItemToMenu(m, mi);
}
}
else if (!strcmp(ss, "EXE"))
{
word(s, 2, ss);
Esnprintf(s, sizeof(s), "%s/%s", dir, ss);
mi = CreateMenuItem(NULL, NULL, ACTION_EXEC, s, NULL);
AddItemToMenu(m, mi);
}
else if (!strcmp(ss, "DIR"))
{
char tmp[4096];
word(s, 2, tmp);
Esnprintf(s, sizeof(s), "%s/%s:%s", dir, tmp, name);
Esnprintf(ss, sizeof(ss), "%s/%s", dir, tmp);
mm = CreateMenuFromDirectory(s, ms, ss);
mm->parent = m;
AddItem(mm, mm->name, mm->win, LIST_TYPE_MENU);
mi = CreateMenuItem(tmp, NULL, 0, NULL, mm);
AddItemToMenu(m, mi);
}
}
fclose(f);
EDBUG_RETURN(m);
}
}
list = ls(dir, &num);
Esnprintf(s, sizeof(s), "Scanning %s", dir);
if (!init_win_ext)
p = CreateProgressbar(s, 600, 16);
if (p)
ShowProgressbar(p);
f = fopen(cs, "w");
for (i = 0; i < num; i++)
{
if (p)
SetProgressbar(p, (i * 100) / num);
Esnprintf(ss, sizeof(ss), "%s/%s", dir, list[i]);
/* skip "dot" files and dirs - senisble */
if ((*(list[i]) != '.') && (stat(ss, &st) >= 0))
{
ext = FileExtension(ss);
if (S_ISDIR(st.st_mode))
{
Esnprintf(s, sizeof(s), "%s/%s:%s", dir, list[i], name);
Esnprintf(ss, sizeof(ss), "%s/%s", dir, list[i]);
mm = CreateMenuFromDirectory(s, ms, ss);
mm->parent = m;
AddItem(mm, mm->name, mm->win, LIST_TYPE_MENU);
mi = CreateMenuItem(list[i], NULL, 0, NULL, mm);
AddItemToMenu(m, mi);
if (f)
fprintf(f, "DIR %s\n", list[i]);
}
/* that's it - people are stupid and have executable images and just */
/* don't get it - so I'm disablign this to save people from their own */
/* stupidity */
/* else if (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
* {
* mi = CreateMenuItem(list[i], NULL, ACTION_EXEC, ss, NULL);
* AddItemToMenu(m, mi);
* if (f)
* fprintf(f, "EXE %s\n", list[i]);
* }
*/
else if ((!strcmp(ext, "jpg")) || (!strcmp(ext, "JPG")) ||
(!strcmp(ext, "jpeg")) || (!strcmp(ext, "Jpeg")) ||
(!strcmp(ext, "JPEG")) || (!strcmp(ext, "Jpg")) ||
(!strcmp(ext, "gif")) || (!strcmp(ext, "Gif")) ||
(!strcmp(ext, "GIF")) || (!strcmp(ext, "png")) ||
(!strcmp(ext, "Png")) || (!strcmp(ext, "PNG")) ||
(!strcmp(ext, "tif")) || (!strcmp(ext, "Tif")) ||
(!strcmp(ext, "TIFF")) || (!strcmp(ext, "tiff")) ||
(!strcmp(ext, "Tiff")) || (!strcmp(ext, "TIFF")) ||
(!strcmp(ext, "xpm")) || (!strcmp(ext, "Xpm")) ||
(!strcmp(ext, "XPM")) || (!strcmp(ext, "ppm")) ||
(!strcmp(ext, "PPM")) || (!strcmp(ext, "pgm")) ||
(!strcmp(ext, "PGM")) || (!strcmp(ext, "pnm")) ||
(!strcmp(ext, "PNM")) || (!strcmp(ext, "bmp")) ||
(!strcmp(ext, "Bmp")) || (!strcmp(ext, "BMP")))
{
Background *bg;
char ok = 1;
char s2[4096], s3[512];
int aa, bb, cc;
aa = (int)st.st_nlink;
bb = (int)st.st_dev;
cc = 0;
if (st.st_mtime > st.st_ctime)
cc = st.st_mtime;
else
cc = st.st_ctime;
Esnprintf(s3, sizeof(s3),
".%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
chmap[(aa >> 0) & 0x3f],
chmap[(aa >> 6) & 0x3f],
chmap[(aa >> 12) & 0x3f],
chmap[(aa >> 18) & 0x3f],
chmap[(aa >> 24) & 0x3f],
chmap[(aa >> 28) & 0x3f],
chmap[(bb >> 0) & 0x3f],
chmap[(bb >> 6) & 0x3f],
chmap[(bb >> 12) & 0x3f],
chmap[(bb >> 18) & 0x3f],
chmap[(bb >> 24) & 0x3f],
chmap[(bb >> 28) & 0x3f],
chmap[(cc >> 0) & 0x3f],
chmap[(cc >> 6) & 0x3f],
chmap[(cc >> 12) & 0x3f],
chmap[(cc >> 18) & 0x3f],
chmap[(cc >> 24) & 0x3f],
chmap[(cc >> 28) & 0x3f]);
bg = (Background *) FindItem(s3, 0, LIST_FINDBY_NAME, LIST_TYPE_BACKGROUND);
if (!bg)
{
ImlibImage *im;
im = Imlib_load_image(id, ss);
if (im)
{
ImlibImage *im2;
ImlibColor icl;
char tile = 1, keep_asp = 0;
int width, height, scalex = 0,
scaley = 0;
int scr_asp, im_asp, w2, h2;
int maxw = 48, maxh = 48;
Esnprintf(s2, sizeof(s2), "%s/cached/img/%s", UserEDir(), s3);
width = im->rgb_width;
height = im->rgb_height;
h2 = maxh;
w2 = (im->rgb_width * h2) / im->rgb_height;
if (w2 > maxw)
{
w2 = maxw;
h2 = (im->rgb_height * w2) / im->rgb_width;
}
im2 = Imlib_clone_scaled_image(id, im, w2, h2);
Imlib_save_image_to_ppm(id, im2, s2);
Imlib_changed_image(id, im2);
Imlib_changed_image(id, im);
Imlib_kill_image(id, im2);
Imlib_kill_image(id, im);
scr_asp = (root.w << 16) / root.h;
im_asp = (width << 16) / height;
if (width == height)
{
scalex = 0;
scaley = 0;
tile = 1;
keep_asp = 0;
}
else if ((!(IN_RANGE(scr_asp, im_asp, 16000))) &&
((width < 480) && (height < 360)))
{
scalex = 0;
scaley = 0;
tile = 1;
keep_asp = 0;
}
else if (IN_RANGE(scr_asp, im_asp, 16000))
{
scalex = 1024;
scaley = 1024;
tile = 0;
keep_asp = 0;
}
else if (im_asp > scr_asp)
{
scalex = 1024;
scaley = 0;
tile = 0;
keep_asp = 1;
}
else
{
scalex = 0;
scaley = 1024;
tile = 0;
keep_asp = 1;
}
icl.r = 0;
icl.g = 0;
icl.b = 0;
bg = CreateDesktopBG(s3, &icl, ss, tile, keep_asp,
512, 512, scalex, scaley,
NULL, 0, 0, 0, 0, 0);
AddItem(bg, bg->name, 0, LIST_TYPE_BACKGROUND);
}
else
ok = 0;
}
if (ok)
{
ImageClass *ic = NULL;
char stmp[4096];
ic = CreateIclass();
ic->name = duplicate("`");
ic->norm.normal = CreateImageState();
Esnprintf(stmp, sizeof(stmp), "cached/img/%s", s3);
ic->norm.normal->im_file = duplicate(stmp);
ic->norm.normal->unloadable = 1;
IclassPopulate(ic);
AddItem(ic, ic->name, 0, LIST_TYPE_ICLASS);
mi = CreateMenuItem(NULL, ic, ACTION_BACKGROUND_SET, s3, NULL);
AddItemToMenu(m, mi);
}
if (f)
fprintf(f, "BG %s %s\n", list[i], s3);
}
}
}
if (f)
fclose(f);
if (p)
FreeProgressbar(p);
if (list)
freestrlist(list, num);
EDBUG_RETURN(m);
}
Menu *
CreateMenuFromFlatFile(char *name, MenuStyle * ms, char *file, Menu * parent)
{
Menu *m;
char s[4096], *ff = NULL;
static int calls = 0;
EDBUG(5, "CreateMenuFromFlatFile");
calls++;
if (calls > 255)
{
calls--;
EDBUG_RETURN(NULL);
}
ff = FindFile(file);
if (!ff)
EDBUG_RETURN(NULL);
if (canread(ff))
{
m = CreateMenu();
m->name = duplicate(name);
m->style = ms;
m->last_change = moddate(ff);
if (parent)
FillFlatFileMenu(m, m->style, m->name, ff, parent);
else
FillFlatFileMenu(m, m->style, m->name, ff, m);
m->data = ff;
m->ref_menu = parent;
Esnprintf(s, sizeof(s), "__.%s", m->name);
DoIn(s, 2.0, FileMenuUpdate, 0, m);
calls--;
EDBUG_RETURN(m);
}
Efree(ff);
calls--;
EDBUG_RETURN(NULL);
}
static void
FillFlatFileMenu(Menu * m, MenuStyle * ms, char *name, char *file, Menu * parent)
{
FILE *f;
char first = 1;
char s[4096];
#ifndef __EMX__
f = fopen(file, "r");
#else
f = fopen(file, "rt");
#endif
while (fgets(s, 4096, f))
{
s[strlen(s) - 1] = 0;
if (first)
{
char *wd;
wd = field(s, 0);
if (wd)
{
AddTitleToMenu(m, wd);
Efree(wd);
}
first = 0;
}
else
{
char *txt = NULL, *icon = NULL, *act = NULL;
char *params = NULL, *tmp = NULL, wd[4096];
MenuItem *mi;
ImageClass *icc = NULL;
Menu *mm;
int count = 0;
txt = field(s, 0);
icon = field(s, 1);
act = field(s, 2);
params = field(s, 3);
tmp = NULL;
if (icon)
{
Esnprintf(wd, sizeof(wd), "__FM.%s", icon);
icc = FindItem(wd, 0, LIST_FINDBY_NAME, LIST_TYPE_ICLASS);
if (!icc)
{
icc = CreateIclass();
icc->name = duplicate(wd);
icc->norm.normal = CreateImageState();
icc->norm.normal->im_file = icon;
IclassPopulate(icc);
AddItem(icc, icc->name, 0, LIST_TYPE_ICLASS);
}
else
{
Efree(icon);
}
}
if ((act) && (!strcmp(act, "exec")) && (params))
{
word(params, 1, wd);
tmp = pathtoexec(wd);
if (tmp)
{
Efree(tmp);
mi = CreateMenuItem(txt, icc, ACTION_EXEC, params, NULL);
AddItemToMenu(m, mi);
if (txt)
Efree(txt);
if (params)
Efree(params);
}
}
else if ((act) && (!strcmp(act, "menu")) && (params))
{
Esnprintf(wd, sizeof(wd), "__FM.%s.%i", name, count);
count++;
mm = CreateMenuFromFlatFile(wd, ms, params, parent);
if (mm)
{
mm->parent = m;
AddItem(mm, mm->name, mm->win, LIST_TYPE_MENU);
mi = CreateMenuItem(txt, icc, 0, NULL, mm);
AddItemToMenu(m, mi);
}
if (txt)
Efree(txt);
}
else
{
mi = CreateMenuItem(txt, icc, 0, NULL, NULL);
AddItemToMenu(m, mi);
if (txt)
Efree(txt);
if (params)
Efree(params);
}
if (act)
Efree(act);
}
}
fclose(f);
}
static void
FileMenuUpdate(int val, void *data)
{
Menu *m, *mm;
time_t lastmod = 0;
char s[4096];
m = (Menu *) data;
if (!m)
return;
if (!FindItem((char *)m, m->win, LIST_FINDBY_POINTER, LIST_TYPE_MENU))
return;
/* if the menu is up dont update */
if (((mode.cur_menu_mode) || (clickmenu)) && (mode.cur_menu_depth > 0))
{
Esnprintf(s, sizeof(s), "__.%s", m->name);
DoIn(s, 2.0, FileMenuUpdate, 0, m);
return;
}
mm = m;
if (m->ref_menu)
mm = m->ref_menu;
if (!exists(m->data))
{
HideMenu(m);
EmptyMenu(m);
return;
}
if (m->data)
lastmod = moddate(m->data);
if (lastmod > m->last_change)
{
m->last_change = lastmod;
if (m == mm)
{
Esnprintf(s, sizeof(s), "__.%s", m->name);
DoIn(s, 2.0, FileMenuUpdate, 0, m);
}
EmptyMenu(mm);
FillFlatFileMenu(mm, mm->style, mm->name, mm->data, mm);
RepackMenu(mm);
return;
}
Esnprintf(s, sizeof(s), "__.%s", m->name);
DoIn(s, 2.0, FileMenuUpdate, 0, m);
val = 0;
}
Menu *
CreateMenuFromGnome(char *name, MenuStyle * ms, char *dir)
{
Menu *m, *mm;
int i, num;
char **list, s[4096], ss[4096];
MenuItem *mi;
FILE *f;
char *lang, name_buf[20];
EDBUG(5, "CreateMenuFromGnome");
if ((lang = getenv("LANG")) != NULL)
Esnprintf(name_buf, sizeof(name_buf), "Name[%s]=", lang);
else
name_buf[0] = '\0';
m = CreateMenu();
m->name = duplicate(name);
m->style = ms;
list = ls(dir, &num);
for (i = 0; i < num; i++)
{
if ((strcmp(list[i], ".")) && (strcmp(list[i], "..")))
{
Esnprintf(ss, sizeof(ss), "%s/%s", dir, list[i]);
if (isdir(ss))
{
Esnprintf(s, sizeof(s), "%s/%s:%s", dir, list[i], name);
mm = CreateMenuFromGnome(s, ms, ss);
mm->parent = m;
AddItem(mm, mm->name, mm->win, LIST_TYPE_MENU);
name = list[i];
if (name_buf[0])
{
Esnprintf(s, sizeof(s), "%s/.directory", ss);
if ((f = fopen(s, "r")) != NULL)
{
while (fgets(s, sizeof(s), f))
{
if (!strncmp(s, name_buf, strlen(name_buf)))
{
if (s[strlen(s) - 1] == '\n')
s[strlen(s) - 1] = 0;
name = &(s[strlen(name_buf)]);
break;
}
}
fclose(f);
}
}
mi = CreateMenuItem(name, NULL, 0, NULL, mm);
AddItemToMenu(m, mi);
}
else
{
#ifndef __EMX__
f = fopen(ss, "r");
#else
f = fopen(ss, "rt");
#endif
if (f)
{
char *iname = NULL, *exec = NULL, *texec = NULL,
*tmp;
char *en_name = NULL;
while (fgets(s, sizeof(s), f))
{
if (s[strlen(s) - 1] == '\n')
s[strlen(s) - 1] = 0;
if (!strncmp(s, "Name=", strlen("Name=")))
en_name = duplicate(&(s[strlen("Name=")]));
else if (name_buf[0] &&
!strncmp(s, name_buf, strlen(name_buf)))
iname = duplicate(&(s[strlen(name_buf)]));
else if (!strncmp(s, "TryExec=", strlen("TryExec=")))
texec = duplicate(&(s[strlen("TryExec=")]));
else if (!strncmp(s, "Exec=", strlen("Exec=")))
exec = duplicate(&(s[strlen("Exec=")]));
}
if (iname)
{
if (en_name)
Efree(en_name);
}
else
{
if (en_name)
iname = en_name;
}
fclose(f);
if ((iname) && (exec))
{
tmp = NULL;
if (texec)
tmp = pathtoexec(texec);
if ((tmp) || (!texec))
{
if (tmp)
Efree(tmp);
mi = CreateMenuItem(iname, NULL, ACTION_EXEC, exec, NULL);
AddItemToMenu(m, mi);
}
}
if (iname)
Efree(iname);
if (exec)
Efree(exec);
if (texec)
Efree(texec);
}
}
}
}
if (list)
freestrlist(list, num);
EDBUG_RETURN(m);
}
Menu *
CreateMenuFromThemes(char *name, MenuStyle * ms)
{
Menu *m;
char **lst;
int i, num;
char ss[4096], *s;
MenuItem *mi;
EDBUG(5, "CreateMenuFromThemes");
m = CreateMenu();
m->name = duplicate(name);
m->style = ms;
lst = ListThemes(&num);
if (lst)
{
for (i = 0; i < num; i++)
{
s = fullfileof(lst[i]);
Esnprintf(ss, sizeof(ss), "restart_theme %s", s);
Efree(s);
s = fileof(lst[i]);
mi = CreateMenuItem(s, NULL, ACTION_EXIT, ss, NULL);
AddItemToMenu(m, mi);
Efree(s);
}
freestrlist(lst, i);
}
EDBUG_RETURN(m);
}
int
BorderNameCompare(Border * b1, Border * b2)
{
if (b1 && b2)
return strcmp(b1->name, b2->name);
return 0;
}
Menu *
CreateMenuFromBorders(char *name, MenuStyle * ms)
{
Menu *m;
Border **lst;
int i, num;
MenuItem *mi;
EDBUG(5, "CreateMenuFromBorders");
m = CreateMenu();
m->name = duplicate(name);
m->style = ms;
lst = (Border **) ListItemType(&num, LIST_TYPE_BORDER);
if (lst)
Quicksort((void **)lst, 0, num - 1,
(int (*)(void *, void *))&BorderNameCompare);
for (i = 0; i < num; i++)
{
/* if its not internal (ie doesnt start with _ ) */
if (lst[i]->name[0] != '_')
{
mi = CreateMenuItem(lst[i]->name, NULL, ACTION_SET_WINDOW_BORDER, lst[i]->name, NULL);
AddItemToMenu(m, mi);
}
}
if (lst)
Efree(lst);
EDBUG_RETURN(m);
}
Menu *
CreateMenuFromAllEWins(char *name, MenuStyle * ms)
{
Menu *m;
EWin **lst;
int i, num;
char s[256];
MenuItem *mi;
EDBUG(5, "CreateMenuFromEWins");
m = CreateMenu();
m->name = duplicate(name);
m->style = ms;
lst = (EWin **) ListItemType(&num, LIST_TYPE_EWIN);
if (lst)
{
for (i = 0; i < num; i++)
{
if ((!lst[i]->menu) && (!lst[i]->pager) && (!lst[i]->skipwinlist) && (lst[i]->client.title) && (!lst[i]->ibox))
{
Esnprintf(s, sizeof(s), "%i", (int)(lst[i]->client.win));
mi = CreateMenuItem(lst[i]->client.title, NULL, ACTION_FOCUS_SET, s, NULL);
AddItemToMenu(m, mi);
}
}
Efree(lst);
}
EDBUG_RETURN(m);
}
Menu *
CreateMenuFromDesktopEWins(char *name, MenuStyle * ms, int desk)
{
Menu *m;
EWin **lst;
int i, num;
char s[256];
MenuItem *mi;
EDBUG(5, "CreateMenuFromEWins");
m = CreateMenu();
m->name = duplicate(name);
m->style = ms;
lst = (EWin **) ListItemType(&num, LIST_TYPE_EWIN);
if (lst)
{
for (i = 0; i < num; i++)
{
if (((lst[i]->desktop == desk) || (lst[i]->sticky)) &&
(!lst[i]->menu) && (!lst[i]->pager) && (!lst[i]->skipwinlist) && (lst[i]->client.title) && (!lst[i]->ibox))
{
Esnprintf(s, sizeof(s), "%i", (int)(lst[i]->client.win));
mi = CreateMenuItem(lst[i]->client.title, NULL, ACTION_FOCUS_SET, s, NULL);
AddItemToMenu(m, mi);
}
}
Efree(lst);
}
EDBUG_RETURN(m);
desk = 0;
}
Menu *
CreateMenuFromDesktops(char *name, MenuStyle * ms)
{
Menu *m, *mm;
EWin **lst;
int j, i, num;
char s[256];
MenuItem *mi;
EDBUG(5, "CreateMenuFromEWins");
m = CreateMenu();
m->name = duplicate(name);
m->style = ms;
lst = (EWin **) ListItemType(&num, LIST_TYPE_EWIN);
for (j = 0; j < mode.numdesktops; j++)
{
mm = CreateMenu();
mm->name = duplicate("__SUBMENUDESK_E");
mm->style = ms;
Esnprintf(s, sizeof(s), "%i", j);
mi = CreateMenuItem("Go to this Desktop", NULL, ACTION_GOTO_DESK, s, NULL);
AddItemToMenu(mm, mi);
for (i = 0; i < num; i++)
{
if (((lst[i]->desktop == j) || (lst[i]->sticky)) &&
(!lst[i]->menu) && (!lst[i]->pager) && (!lst[i]->skipwinlist) && (lst[i]->client.title) && (!lst[i]->ibox))
{
Esnprintf(s, sizeof(s), "%i", (int)(lst[i]->client.win));
mi = CreateMenuItem(lst[i]->client.title, NULL, ACTION_FOCUS_SET, s, NULL);
AddItemToMenu(mm, mi);
}
}
mm->parent = m;
Esnprintf(s, sizeof(s), "Desktop %i", j);
mi = CreateMenuItem(s, NULL, 0, NULL, mm);
AddItemToMenu(m, mi);
}
if (lst)
Efree(lst);
EDBUG_RETURN(m);
}
void
ShowMenuMasker(Menu * m)
{
EWin *ewin;
ewin = FindEwinByMenu(m);
if ((ewin) && (!mode.menu_cover_win))
{
Window parent;
Window wl[2];
parent = desks.desk[ewin->desktop].win;
mode.menu_cover_win = ECreateEventWindow(parent, 0, 0, root.w, root.h);
wl[0] = ewin->win;
wl[1] = mode.menu_cover_win;
XSelectInput(disp, mode.menu_cover_win, ButtonPressMask |
ButtonReleaseMask | EnterWindowMask | LeaveWindowMask);
XRestackWindows(disp, wl, 2);
EMapWindow(disp, mode.menu_cover_win);
}
}
void
HideMenuMasker(void)
{
if (mode.menu_cover_win)
EDestroyWindow(disp, mode.menu_cover_win);
mode.menu_cover_win = 0;
}
Menu *
CreateMenuFromGroups(char *name, MenuStyle * ms)
{
Menu *m, *mm;
Group **lst;
int i, j, num;
char s[256];
MenuItem *mi;
EDBUG(5, "CreateMenuFromEWins");
m = CreateMenu();
m->name = duplicate(name);
m->style = ms;
lst = (Group **) ListItemType(&num, LIST_TYPE_GROUP);
if (lst)
{
for (i = 0; i < num; i++)
{
mm = CreateMenu();
mm->name = duplicate("__SUBMENUGROUP_E");
mm->style = ms;
Esnprintf(s, sizeof(s), "%i", lst[i]->members[0]->client.win);
mi = CreateMenuItem("Show/Hide this group", NULL, ACTION_SHOW_HIDE_GROUP, s, NULL);
AddItemToMenu(mm, mi);
mi = CreateMenuItem("Iconify this group", NULL, ACTION_ICONIFY, s, NULL);
AddItemToMenu(mm, mi);
for (j = 0; j < lst[i]->num_members; j++)
{
Esnprintf(s, sizeof(s), "%i", lst[i]->members[j]->client.win);
mi = CreateMenuItem(lst[i]->members[j]->client.title, NULL, ACTION_FOCUS_SET, s, NULL);
AddItemToMenu(mm, mi);
}
mm->parent = m;
Esnprintf(s, sizeof(s), "Group %i", i);
mi = CreateMenuItem(s, NULL, 0, NULL, mm);
AddItemToMenu(m, mi);
}
Efree(lst);
}
EDBUG_RETURN(m);
}
Menu *
RefreshGroupMenu(Menu * m)
{
char was = 0;
int lx = 0, ly = 0;
EWin *ewin;
EDBUG(5, "RefreshGroupMenu");
if (m)
{
ewin = FindEwinByMenu(m);
if ((m->win) && (ewin))
{
lx = ewin->x;
ly = ewin->y;
was = 1;
}
DestroyMenu(m);
}
m = NULL;
if (!group_menu_style)
{
EDBUG_RETURN(NULL);
}
m = CreateMenuFromGroups("MENU", group_menu_style);
if ((was) && (m))
{
ShowMenu(m, 1);
ewin = FindEwinByMenu(m);
if (ewin)
{
MoveEwin(ewin, lx, ly);
ShowEwin(ewin);
}
mode.cur_menu[0] = m;
mode.cur_menu_depth = 1;
ShowMenuMasker(m);
}
EDBUG_RETURN(m);
}
void
ShowGroupMenu(void)
{
static MenuStyle *ms = NULL;
static Menu *m = NULL;
EDBUG(5, "ShowGroupMenu");
XUngrabPointer(disp, CurrentTime);
if (!group_menu_style)
{
ms = FindItem("GROUP_MENU", 0, LIST_FINDBY_NAME, LIST_TYPE_MENU_STYLE);
if (!ms)
ms = FindItem("DEFAULT", 0, LIST_FINDBY_NAME, LIST_TYPE_MENU_STYLE);
if (!ms)
EDBUG_RETURN_;
}
group_menu_style = ms;
mode.cur_menu_mode = 1;
m = NULL;
m = RefreshGroupMenu(group_menu);
group_menu = m;
if (m)
{
if (!FindEwinByMenu(m))
ShowMenu(m, 0);
mode.cur_menu[0] = m;
mode.cur_menu_depth = 1;
ShowMenuMasker(m);
}
else
{
mode.cur_menu[0] = NULL;
mode.cur_menu_depth = 0;
HideMenuMasker();
}
EDBUG_RETURN_;
}