mirror of
https://github.com/morgant/mlvwm.git
synced 2025-02-16 12:30:25 +00:00
1614 lines
42 KiB
C
1614 lines
42 KiB
C
/****************************************************************************/
|
||
/* This module is all original code */
|
||
/* by TakaC Hasegawa (tac.hasegawa@gmail.com) */
|
||
/* Copyright 1996, TakaC Hasegawa */
|
||
/* You may use this code for any purpose, as long as the original */
|
||
/* copyright remains in the source code and all documentation */
|
||
/****************************************************************************/
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <ctype.h>
|
||
|
||
#include "mlvwm.h"
|
||
#include "screen.h"
|
||
#include "menus.h"
|
||
#include "event.h"
|
||
#include "functions.h"
|
||
#include "misc.h"
|
||
#include "add_window.h"
|
||
#include "borders.h"
|
||
|
||
#include <X11/Xatom.h>
|
||
#include <X11/Xresource.h>
|
||
|
||
#include <X11/extensions/shape.h>
|
||
|
||
void RedrawMenu( MenuLabel *m, Bool onoroff )
|
||
{
|
||
GC tmp_f_GC, tmp_b_GC;
|
||
int width, offset;
|
||
unsigned long gcm;
|
||
XGCValues gcv;
|
||
Pixel fore_pixel, back_pixel;
|
||
|
||
if( Scr.flags&SYSTEM8 ){
|
||
gcm = GCForeground;
|
||
if( !XGetGCValues( dpy, Scr.MenuBlueGC, gcm, &gcv ) ){
|
||
fprintf( stderr, "Sorry Can not get GC Values Blue\n");
|
||
gcv.foreground = WhitePixel( dpy, Scr.screen );
|
||
}
|
||
fore_pixel = gcv.foreground;
|
||
if( !XGetGCValues( dpy, Scr.MenuSelectBlueGC, gcm, &gcv ) ){
|
||
fprintf( stderr, "Sorry Can not get GC Values SelectBlue\n");
|
||
gcv.foreground = WhitePixel( dpy, Scr.screen );
|
||
}
|
||
back_pixel = gcv.foreground;
|
||
}
|
||
else{
|
||
fore_pixel = WhitePixel( dpy, Scr.screen );
|
||
back_pixel = BlackPixel( dpy, Scr.screen );
|
||
}
|
||
|
||
if( onoroff )
|
||
XSetWindowBackground( dpy, m->LabelWin, back_pixel );
|
||
else
|
||
XSetWindowBackground( dpy, m->LabelWin, fore_pixel );
|
||
XClearWindow( dpy, m->LabelWin );
|
||
|
||
if( m->LabelStr )
|
||
StrWidthHeight( MENUBARFONT, &width, NULL, &offset,
|
||
m->LabelStr, strlen(m->LabelStr));
|
||
|
||
if( onoroff ){
|
||
tmp_f_GC = Scr.WhiteGC;
|
||
tmp_b_GC = Scr.BlackGC;
|
||
}
|
||
else{
|
||
tmp_f_GC = Scr.BlackGC;
|
||
tmp_b_GC = Scr.WhiteGC;
|
||
}
|
||
if( !(m->flags&ACTIVE) && Scr.d_depth>1 )
|
||
tmp_f_GC = Scr.Gray3GC;
|
||
if( !m->xpm ){
|
||
if( m->LabelStr ){
|
||
XDRAWSTRING( dpy, m->LabelWin, MENUBARFONT, tmp_f_GC,
|
||
(m->LabelWidth-width)/2,
|
||
(MENUB_H-2)/2-offset,
|
||
m->LabelStr, strlen(m->LabelStr) );
|
||
/* Mask String for Mono Display */
|
||
if( !(m->flags&ACTIVE) && Scr.d_depth<2 ){
|
||
if( onoroff ) gcv.function = GXand;
|
||
else gcv.function = GXor;
|
||
gcm = GCFunction;
|
||
XChangeGC( dpy, Scr.BlackGC, gcm, &gcv );
|
||
XSetFillStyle( dpy, Scr.BlackGC, FillTiled );
|
||
XFillRectangle( dpy, m->LabelWin, Scr.BlackGC, 0, 0,
|
||
m->LabelWidth, MENUB_H);
|
||
XSetFillStyle( dpy, Scr.BlackGC, FillSolid );
|
||
gcv.function = GXcopy;
|
||
XChangeGC( dpy, Scr.BlackGC, gcm, &gcv );
|
||
}
|
||
}
|
||
}
|
||
else{
|
||
if( m->xpm->kind==PIXMAP ){
|
||
XSetClipMask( dpy, tmp_f_GC, m->xpm->mask );
|
||
XSetClipOrigin( dpy, tmp_f_GC,
|
||
(m->LabelWidth-m->xpm->width)/2,
|
||
(MENUB_H-2-m->xpm->height)/2 );
|
||
XCopyArea( dpy, m->xpm->icon, m->LabelWin, tmp_f_GC, 0, 0,
|
||
m->xpm->width, m->xpm->height,
|
||
(m->LabelWidth-m->xpm->width)/2,
|
||
(MENUB_H-2-m->xpm->height)/2 );
|
||
XSetClipMask( dpy, tmp_f_GC, None );
|
||
}
|
||
else{
|
||
XCopyArea( dpy, onoroff?m->xpm->mask:m->xpm->icon, m->LabelWin,
|
||
tmp_f_GC, 0, 0,
|
||
m->xpm->width, m->xpm->height,
|
||
(m->LabelWidth-m->xpm->width)/2,
|
||
(MENUB_H-2-m->xpm->height)/2 );
|
||
}
|
||
}
|
||
}
|
||
|
||
void RedrawMenuBar( void )
|
||
{
|
||
int lp;
|
||
|
||
if( Scr.flags&SYSTEM8 )
|
||
DrawShadowBox( 0, 0, Scr.MyDisplayWidth, MENUB_H, Scr.MenuBar, 1,
|
||
Scr.WhiteGC, Scr.Gray1GC, SHADOW_ALL );
|
||
if(Scr.flags&ROUNDEDCORNERS){
|
||
XFillRectangle( dpy, Scr.MenuBar, Scr.BlackGC, 0, 0, 7, 7 );
|
||
XFillRectangle( dpy, Scr.MenuBar,
|
||
Scr.BlackGC, Scr.MyDisplayWidth-7, 0, 7, 7 );
|
||
if( Scr.flags&SYSTEM8 && !(Scr.flags&STARTING) ){
|
||
XDrawArc( dpy, Scr.MenuBar, Scr.WhiteGC, 0, 0,
|
||
14, 14, 180*64, -(90*64) );
|
||
XDrawArc( dpy, Scr.MenuBar, Scr.Gray1GC, Scr.MyDisplayWidth-15, 0,
|
||
14, 14, 0, 90*64 );
|
||
XFillArc( dpy, Scr.MenuBar, Scr.MenuBlueGC, 0, 0,
|
||
14, 14, 180*64, -(90*64) );
|
||
XFillArc( dpy, Scr.MenuBar, Scr.MenuBlueGC, Scr.MyDisplayWidth-15, 0,
|
||
14, 14, 0, 90*64 );
|
||
}
|
||
else{
|
||
XFillArc( dpy, Scr.MenuBar, Scr.WhiteGC, 0, 0,
|
||
14, 14, 180*64, -(90*64) );
|
||
XFillArc( dpy, Scr.MenuBar, Scr.WhiteGC, Scr.MyDisplayWidth-15, 0,
|
||
14, 14, 0, 90*64 );
|
||
}
|
||
|
||
XMapWindow( dpy, Scr.lbCorner );
|
||
XMapWindow( dpy, Scr.rbCorner );
|
||
}
|
||
if( !(Scr.flags&SYSTEM8) )
|
||
XDrawLine( dpy, Scr.MenuBar, Scr.BlackGC,
|
||
0, MENUB_H-1, Scr.MyDisplayWidth, MENUB_H-1 );
|
||
}
|
||
|
||
void DrawStringMenuBar( char *str )
|
||
{
|
||
static int width=0;
|
||
int offset;
|
||
|
||
if( width!=0 ){
|
||
XFillRectangle( dpy, Scr.MenuBar, Scr.WhiteGC,
|
||
(Scr.MyDisplayWidth-width)/2, 0, width, MENUB_H-1 );
|
||
}
|
||
if( strlen( str )!=0 ){
|
||
StrWidthHeight( MENUBARFONT, &width, NULL, &offset,
|
||
str, strlen(str));
|
||
XDRAWSTRING( dpy, Scr.MenuBar, MENUBARFONT, Scr.BlackGC,
|
||
(Scr.MyDisplayWidth-width)/2,
|
||
MENUB_H/2-offset, str, strlen(str) );
|
||
}
|
||
else
|
||
XClearWindow( dpy, Scr.MenuBar );
|
||
RedrawMenuBar();
|
||
XSync( dpy, 0 );
|
||
}
|
||
|
||
/* X ɸ<><C9B8><EFBFBD>δؿ<CEB4><D8BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѳ<EFBFBD>ǽ */
|
||
Bool isRect( int px, int py, int x, int y, int width, int height )
|
||
{
|
||
if( px>x && px<x+width && py>y && py<y+height ) return True;
|
||
else return False;
|
||
}
|
||
|
||
void DrawCheckMark( MenuLabel *ml, GC gc, int topy )
|
||
{
|
||
XPoint check[] = {{3,5},{7,9},{16,0},{16,1},{7,10},{3,6}};
|
||
int lp;
|
||
|
||
for( lp=0; lp<6; lp++ )
|
||
check[lp].y += (topy+ml->ItemHeight/2-5);
|
||
XDrawLines( dpy, ml->PullWin, gc, check, 6, CoordModeOrigin );
|
||
}
|
||
|
||
void DrawSubMenuMark( MenuLabel *ml, GC gc, int topy )
|
||
{
|
||
XPoint mark[] = {{15, -7}, {15, 7}, {7,0}};
|
||
int lp;
|
||
|
||
for( lp=0; lp<3; lp++ ){
|
||
mark[lp].x = ml->MenuWidth-mark[lp].x;
|
||
mark[lp].y += (topy+ml->ItemHeight/2);
|
||
}
|
||
XFillPolygon( dpy, ml->PullWin, gc, mark, 3, Convex, CoordModeOrigin );
|
||
}
|
||
|
||
MenuLabel *DrawMenuItem( MenuLabel *ml, int sel, Bool on )
|
||
{
|
||
GC r_tmpGC, s_tmpGC;
|
||
int label_p, top_y, lp, width, offset;
|
||
Pixmap icon;
|
||
MenuItem *mi;
|
||
unsigned long gcm;
|
||
XGCValues gcv;
|
||
char dots[] = { 2, 2 };
|
||
|
||
for( lp=0, mi = ml->m_item; lp<sel-1; lp++, mi=mi->next );
|
||
if( !(mi->mode&SELECTON) && on ) return NULL;
|
||
|
||
top_y = ml->ItemHeight*(sel-1);
|
||
label_p = ml->ItemHeight==0?20:20+ml->ItemHeight+5;
|
||
|
||
if( on ){
|
||
r_tmpGC = Scr.flags&SYSTEM8?Scr.MenuSelectBlueGC:Scr.BlackGC;
|
||
s_tmpGC = Scr.WhiteGC;
|
||
}
|
||
else{
|
||
r_tmpGC = Scr.flags&SYSTEM8?Scr.MenuBlueGC:Scr.WhiteGC;
|
||
s_tmpGC = Scr.BlackGC;
|
||
}
|
||
|
||
if( mi->mode&STRGRAY && Scr.d_depth>2 )
|
||
s_tmpGC = Scr.Gray3GC;
|
||
XFillRectangle( dpy, ml->PullWin, r_tmpGC,
|
||
0+(Scr.flags&SYSTEM8?1:0), top_y,
|
||
ml->MenuWidth-(Scr.flags&SYSTEM8?2:0), ml->ItemHeight );
|
||
|
||
/** Draw Check Mark. **/
|
||
if( mi->mode & CHECKON )
|
||
DrawCheckMark( ml, s_tmpGC, top_y );
|
||
/** Draw Submenu Mark **/
|
||
if( mi->submenu )
|
||
DrawSubMenuMark( ml, s_tmpGC, top_y );
|
||
/** Draw Icon. **/
|
||
if( mi->xpm ){
|
||
if( mi->mode&STRGRAY || mi->mode&ICONGRAY)
|
||
icon = mi->xpm->lighticon;
|
||
else
|
||
icon = mi->xpm->icon;
|
||
if( mi->xpm->kind==PIXMAP ){
|
||
XSetClipMask( dpy, s_tmpGC, mi->xpm->mask );
|
||
XSetClipOrigin( dpy, s_tmpGC,
|
||
20+(ml->IconWidth-mi->xpm->width)/2,
|
||
top_y+(ml->ItemHeight-mi->xpm->height)/2);
|
||
XCopyArea( dpy, icon, ml->PullWin, s_tmpGC, 0, 0,
|
||
mi->xpm->width, mi->xpm->height,
|
||
20+(ml->IconWidth-mi->xpm->width)/2,
|
||
top_y+(ml->ItemHeight-mi->xpm->height)/2);
|
||
XSetClipMask( dpy, s_tmpGC, None );
|
||
}
|
||
else{
|
||
XCopyArea( dpy, on?mi->xpm->mask:mi->xpm->icon,
|
||
ml->PullWin, s_tmpGC, 0, 0,
|
||
mi->xpm->width, mi->xpm->height,
|
||
20+(ml->IconWidth-mi->xpm->width)/2,
|
||
top_y+(ml->ItemHeight-mi->xpm->height)/2);
|
||
if( mi->mode&ICONGRAY ){
|
||
if( on ) gcv.function = GXand;
|
||
else gcv.function = GXor;
|
||
gcm = GCFunction;
|
||
XChangeGC( dpy, Scr.BlackGC, gcm, &gcv );
|
||
XSetFillStyle( dpy, Scr.BlackGC, FillTiled );
|
||
XFillRectangle( dpy, ml->PullWin, Scr.BlackGC, 21, top_y,
|
||
mi->xpm->width, ml->ItemHeight );
|
||
XSetFillStyle( dpy, Scr.BlackGC, FillSolid );
|
||
gcv.function = GXcopy;
|
||
XChangeGC( dpy, Scr.BlackGC, gcm, &gcv );
|
||
}
|
||
}
|
||
}
|
||
/** Draw Label String. **/
|
||
if( mi->label ){
|
||
StrWidthHeight( MENUFONT, &width, NULL, &offset,
|
||
mi->label, strlen(mi->label));
|
||
XDRAWSTRING( dpy, ml->PullWin, MENUFONT, s_tmpGC,
|
||
(mi->xpm!=NULL?label_p:20),
|
||
top_y+ml->ItemHeight/2-offset,
|
||
mi->label, strlen(mi->label) );
|
||
/* Mask String for Mono Display */
|
||
if( mi->mode&STRGRAY && Scr.d_depth<2 ){
|
||
if( on ) gcv.function = GXand;
|
||
else gcv.function = GXor;
|
||
gcm = GCFunction;
|
||
XChangeGC( dpy, Scr.BlackGC, gcm, &gcv );
|
||
XSetFillStyle( dpy, Scr.BlackGC, FillTiled );
|
||
XFillRectangle( dpy, ml->PullWin, Scr.BlackGC, 0, top_y,
|
||
ml->MenuWidth, ml->ItemHeight );
|
||
XSetFillStyle( dpy, Scr.BlackGC, FillSolid );
|
||
gcv.function = GXcopy;
|
||
XChangeGC( dpy, Scr.BlackGC, gcm, &gcv );
|
||
}
|
||
}
|
||
if( mi->label && mi->label[0]=='\0' ){
|
||
if( Scr.d_depth>1 ){
|
||
if( Scr.flags&SYSTEM8 ){
|
||
XDrawLine( dpy, ml->PullWin, Scr.Gray2GC,
|
||
2, top_y+ml->ItemHeight/2,
|
||
ml->MenuWidth-3, top_y+ml->ItemHeight/2);
|
||
XDrawLine( dpy, ml->PullWin, Scr.WhiteGC,
|
||
3, top_y+ml->ItemHeight/2+1,
|
||
ml->MenuWidth-2, top_y+ml->ItemHeight/2+1);
|
||
}
|
||
else
|
||
XDrawLine( dpy, ml->PullWin, Scr.Gray2GC,
|
||
0, top_y+ml->ItemHeight/2,
|
||
ml->MenuWidth, top_y+ml->ItemHeight/2);
|
||
}
|
||
else{
|
||
gcm = GCLineStyle;
|
||
gcv.line_style = LineOnOffDash;
|
||
XChangeGC( dpy, Scr.BlackGC, gcm, &gcv );
|
||
XSetDashes( dpy, Scr.BlackGC, 0, dots, 2 );
|
||
XDrawLine( dpy, ml->PullWin, Scr.BlackGC,
|
||
0, top_y+ml->ItemHeight/2,
|
||
ml->MenuWidth, top_y+ml->ItemHeight/2);
|
||
gcm = GCLineStyle;
|
||
gcv.line_style = FillSolid;
|
||
XChangeGC( dpy, Scr.BlackGC, gcm, &gcv );
|
||
}
|
||
}
|
||
|
||
return mi->submenu;
|
||
}
|
||
|
||
void SortMenuItem( MenuLabel *m, MenuItem *start )
|
||
{
|
||
MenuItem *fence, *lastSwap, *i, *j, *k;
|
||
|
||
for(fence = NULL; fence != start; fence = lastSwap )
|
||
for(j = (lastSwap = i = start)->next;
|
||
(k = j->next) != fence;
|
||
i = j, j = k ){
|
||
if ( strcmp( j->label, k->label ) > 0 ){
|
||
i->next = k;
|
||
j->next = k->next;
|
||
lastSwap = k->next = j;
|
||
}
|
||
}
|
||
}
|
||
|
||
/*****************************************************************
|
||
MenuLabel *m Menu Label of Target
|
||
int left left side position of menu
|
||
int right right side position of menu
|
||
int y Height of menu
|
||
Bool side True left(Tear off right)
|
||
False right(Tear off left)
|
||
*****************************************************************/
|
||
Bool MapMenu( MenuLabel *m, int left, int right, int y, Bool side )
|
||
{
|
||
int lp, items=0;
|
||
int label_w, local_mw=0, height;
|
||
MenuItem *mi;
|
||
|
||
if( m->LabelWin!=None ) RedrawMenu( m, True );
|
||
|
||
if( m == &Scr.IconMenu && Scr.iconAnchor->next )
|
||
SortMenuItem( &Scr.IconMenu, Scr.iconAnchor );
|
||
|
||
m->MenuWidth = 0;
|
||
m->MenuHeight = 0;
|
||
m->ItemHeight = 0;
|
||
m->IconWidth = 0;
|
||
m->SelectNum = -1;
|
||
|
||
for( mi = m->m_item; mi; mi=mi->next ){
|
||
StrWidthHeight( MENUFONT, &label_w, &height, NULL,
|
||
mi->label, strlen(mi->label));
|
||
m->ItemHeight = max( height, m->ItemHeight );
|
||
if( mi->iconname && !(mi->xpm) )
|
||
mi->xpm = ReadIcon( mi->iconname, NULL, False );
|
||
if( mi->xpm ){
|
||
m->ItemHeight = max( mi->xpm->height, m->ItemHeight );
|
||
m->IconWidth = max( mi->xpm->width, m->IconWidth );
|
||
local_mw = 20+mi->xpm->width+5+label_w+10;
|
||
}
|
||
else
|
||
local_mw = 20+label_w+10;
|
||
if( mi->submenu ) local_mw += 15;
|
||
m->MenuWidth = max( local_mw, m->MenuWidth );
|
||
if( (mi->label && mi->label[0]) || mi->next )
|
||
items++;
|
||
}
|
||
|
||
m->ItemHeight+=2;
|
||
m->MenuHeight = m->ItemHeight*items;
|
||
|
||
if( side )
|
||
m->MenuX = left;
|
||
else
|
||
m->MenuX = right-m->MenuWidth;
|
||
|
||
if( m->MenuX+m->MenuWidth > Scr.MyDisplayWidth ){
|
||
m->MenuX = right-m->MenuWidth;
|
||
side = False;
|
||
}
|
||
if( m->MenuX < 0 ){
|
||
m->MenuX = 0;
|
||
side = True;
|
||
}
|
||
m->MenuY = y+m->MenuHeight<Scr.MyDisplayHeight ?
|
||
y : Scr.MyDisplayHeight-m->MenuHeight;
|
||
m->MenuY = m->MenuY<MENUB_H-1 ? MENUB_H-1 : m->MenuY;
|
||
if( Scr.flags&SYSTEM8 ){
|
||
m->MenuWidth+=2;
|
||
m->MenuHeight+=1;
|
||
}
|
||
XMoveResizeWindow( dpy, m->PullWin, m->MenuX, m->MenuY,
|
||
m->MenuWidth+2, m->MenuHeight+2 );
|
||
{
|
||
XRectangle rect[5];
|
||
int point=0;
|
||
|
||
rect[point].x = -1; rect[point].y = -1;
|
||
rect[point].width = m->MenuWidth+1;
|
||
rect[point].height = m->MenuHeight+1;
|
||
point++;
|
||
for( lp=1; lp<3; lp++ ){
|
||
rect[point].x = m->MenuWidth+lp-1; rect[point].y = lp-1;
|
||
rect[point].width = 1; rect[point].height = m->MenuHeight+2-lp+1;
|
||
point++;
|
||
}
|
||
for( lp=1; lp<3; lp++ ){
|
||
rect[point].x = lp-1; rect[point].y = m->MenuHeight+lp-1;
|
||
rect[point].width = m->MenuWidth+2-lp+1; rect[point].height = 1;
|
||
point++;
|
||
}
|
||
XShapeCombineRectangles(dpy,m->PullWin,ShapeBounding,
|
||
0,0,rect,point,ShapeSet,Unsorted);
|
||
}
|
||
|
||
XMapRaised( dpy, m->PullWin );
|
||
|
||
return side;
|
||
}
|
||
|
||
void UnmapMenu( MenuLabel *m, int mode )
|
||
{
|
||
if( mode&UNMAP_WINDOW ){
|
||
XUnmapWindow( dpy, m->PullWin );
|
||
m->SelectNum = -1;
|
||
}
|
||
if( mode&UNMAP_LABEL )
|
||
RedrawMenu( m, False );
|
||
XSync( dpy, 0 );
|
||
}
|
||
|
||
void ExecMenu( MenuLabel *m, int selected )
|
||
{
|
||
int lp;
|
||
MenuItem *tmp_item;
|
||
|
||
for( lp=0, tmp_item = m->m_item; lp<selected-1;
|
||
lp++,tmp_item=tmp_item->next );
|
||
if( !(tmp_item->mode&SELECTON) || !(tmp_item->action ))
|
||
return;
|
||
|
||
for( lp=0; lp<Scr.flush_times; lp++ ){
|
||
DrawMenuItem( m, selected, False ); XFlush( dpy );
|
||
sleep_a_little( Scr.flush_time );
|
||
DrawMenuItem( m, selected, True ); XFlush( dpy );
|
||
sleep_a_little( Scr.flush_time );
|
||
}
|
||
|
||
DrawMenuItem( m, selected, True );
|
||
XFlush( dpy );
|
||
UnmapMenu( m, UNMAP_WINDOW );
|
||
ExecuteFunction( tmp_item->action );
|
||
UnmapMenu( m, UNMAP_LABEL );
|
||
}
|
||
|
||
void DrawMenuItemAll( MenuLabel *ml )
|
||
{
|
||
int lp;
|
||
MenuItem *tmp_item;
|
||
|
||
for( lp=0, tmp_item=ml->m_item; tmp_item; lp++,tmp_item=tmp_item->next )
|
||
DrawMenuItem( ml, lp+1, lp+1==ml->SelectNum?True:False );
|
||
for( lp=0; lp<2; lp++ ){
|
||
XDrawLine( dpy, ml->PullWin, Scr.BlackGC,
|
||
lp, ml->MenuHeight+lp, ml->MenuWidth+1, ml->MenuHeight+lp );
|
||
XDrawLine( dpy, ml->PullWin, Scr.BlackGC,
|
||
ml->MenuWidth+lp, lp, ml->MenuWidth+lp, ml->MenuHeight);
|
||
}
|
||
if( Scr.flags&SYSTEM8 ){
|
||
XDrawLine( dpy, ml->PullWin, Scr.WhiteGC,
|
||
0, 0, 0, ml->MenuHeight );
|
||
XDrawLine( dpy, ml->PullWin, Scr.Gray2GC,
|
||
0, ml->MenuHeight-1, ml->MenuWidth-1, ml->MenuHeight-1 );
|
||
XDrawLine( dpy, ml->PullWin, Scr.Gray2GC,
|
||
ml->MenuWidth-1, 0, ml->MenuWidth-1, ml->MenuHeight-1 );
|
||
}
|
||
}
|
||
|
||
Bool ChoiseMenu( MenuLabel *m, Window *entwin, int ignore, Bool side )
|
||
{
|
||
Bool isEnd = False, finishall=False, Release=False, ChildSide=True;
|
||
XEvent Event;
|
||
MenuLabel *mapped=NULL, *tmp_menu;
|
||
|
||
while( !isEnd && !finishall){
|
||
XMaskEvent( dpy, ExposureMask | ButtonReleaseMask | ButtonPressMask|
|
||
EnterWindowMask | PointerMotionMask | ButtonMotionMask,
|
||
&Event );
|
||
// XNextEvent( dpy, &Event );
|
||
switch( Event.type ){
|
||
case Expose:
|
||
if( XFindContext( dpy, Event.xany.window, MenuContext,
|
||
(caddr_t *)&tmp_menu )!=XCNOENT ){
|
||
if( Event.xexpose.count==0 ) DrawMenuItemAll( tmp_menu );
|
||
}
|
||
else handle_expose( &Event );
|
||
break;
|
||
case EnterNotify:
|
||
if( XFindContext( dpy, Event.xcrossing.window, MenuContext,
|
||
(caddr_t *)&tmp_menu )!=XCNOENT ){
|
||
if( tmp_menu==mapped ){
|
||
finishall = ChoiseMenu( mapped, entwin, ignore, ChildSide );
|
||
if( *entwin!=m->PullWin ) isEnd = True;
|
||
}
|
||
else if( tmp_menu!=m || Event.xcrossing.window==m->LabelWin ){
|
||
isEnd = True;
|
||
*entwin = Event.xcrossing.window;
|
||
if( m->SelectNum != -1 ){
|
||
DrawMenuItem( m, m->SelectNum, False );
|
||
m->SelectNum = -1;
|
||
if( mapped ){
|
||
UnmapMenu( mapped, UNMAP_ALL );
|
||
mapped = NULL;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if( Event.xcrossing.window == Scr.MenuBar &&
|
||
Event.xcrossing.detail!=NotifyNonlinearVirtual ){
|
||
isEnd = True;
|
||
*entwin = Scr.MenuBar;
|
||
}
|
||
break;
|
||
case ButtonRelease:
|
||
if( ignore ){
|
||
isEnd = True;
|
||
finishall = True;
|
||
Release = True;
|
||
}
|
||
else ignore++;
|
||
break;
|
||
case MotionNotify:
|
||
if(isRect( Event.xbutton.x, Event.xbutton.y, 0, 0,
|
||
m->MenuWidth, m->MenuHeight ) &&
|
||
Event.xany.window == m->PullWin ){
|
||
if( m->SelectNum != (Event.xbutton.y-3)/m->ItemHeight+1 ){
|
||
if( m->SelectNum != -1 ){
|
||
DrawMenuItem( m, m->SelectNum, False);
|
||
if( mapped ){
|
||
UnmapMenu( mapped, UNMAP_ALL );
|
||
mapped = NULL;
|
||
}
|
||
}
|
||
m->SelectNum = (Event.xbutton.y-3)/m->ItemHeight+1;
|
||
mapped=DrawMenuItem( m, m->SelectNum, True );
|
||
if( mapped ){
|
||
ChildSide = MapMenu( mapped,
|
||
m->MenuX+m->MenuWidth-5, m->MenuX+5,
|
||
(m->MenuY==MENUB_H-1 && m->SelectNum==1) ?
|
||
m->MenuY+m->ItemHeight/2 :
|
||
m->MenuY+m->ItemHeight*(m->SelectNum-1),
|
||
side );
|
||
}
|
||
}
|
||
}
|
||
else if( m->SelectNum != -1 ){
|
||
DrawMenuItem( m, m->SelectNum, False );
|
||
m->SelectNum = -1;
|
||
if( mapped ){
|
||
UnmapMenu( mapped, UNMAP_ALL );
|
||
mapped = NULL;
|
||
}
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
if( mapped ){
|
||
UnmapMenu( mapped, UNMAP_ALL );
|
||
DrawMenuItemAll( m );
|
||
}
|
||
if( Release && m->SelectNum!=-1 ){
|
||
UnGrabEvent();
|
||
ExecMenu( m, m->SelectNum );
|
||
if( !GrabEvent( DEFAULT ) ){
|
||
XBell( dpy, 30 );
|
||
return finishall;
|
||
}
|
||
}
|
||
|
||
return finishall;
|
||
}
|
||
|
||
void press_menu( MenuLabel *m )
|
||
{
|
||
Bool isEnd = False, Side=True;
|
||
XEvent Event;
|
||
MenuLabel *mapped, *tmp_menu;
|
||
int x, y, JunkX, JunkY;
|
||
unsigned int JunkMask;
|
||
Window JunkRoot, JunkChild, entwin;
|
||
int ignore;
|
||
|
||
if( m!=NULL )
|
||
Side=MapMenu( m, m->LabelX, m->LabelX+m->LabelWidth, MENUB_H-1, True );
|
||
|
||
if( !GrabEvent( DEFAULT ) ){
|
||
XBell( dpy, 30 );
|
||
return;
|
||
}
|
||
|
||
if( Scr.flags&ONECLICKMENU ) ignore=0;
|
||
else ignore=1;
|
||
|
||
mapped = m;
|
||
while( !isEnd ){
|
||
XMaskEvent( dpy, ExposureMask | ButtonReleaseMask | ButtonPressMask|
|
||
EnterWindowMask | PointerMotionMask | ButtonMotionMask,
|
||
&Event );
|
||
// XNextEvent( dpy, &Event );
|
||
switch( Event.type ){
|
||
case Expose:
|
||
if( mapped && Event.xany.window==mapped->PullWin &&
|
||
Event.xexpose.count==0 )
|
||
DrawMenuItemAll( mapped );
|
||
else
|
||
handle_expose( &Event );
|
||
break;
|
||
case ButtonRelease:
|
||
if( ignore ) isEnd = True;
|
||
else ignore++;
|
||
break;
|
||
case EnterNotify:
|
||
if( XFindContext( dpy, Event.xcrossing.window,
|
||
MenuContext, (caddr_t *)&tmp_menu )
|
||
!=XCNOENT ){
|
||
if( mapped != tmp_menu ){
|
||
if( mapped ) UnmapMenu( mapped, UNMAP_ALL );
|
||
mapped = tmp_menu;
|
||
Side = MapMenu( mapped, mapped->LabelX,
|
||
mapped->LabelX+mapped->LabelWidth,
|
||
MENUB_H-1, True );
|
||
}
|
||
else if( Event.xcrossing.window==mapped->PullWin ){
|
||
isEnd = ChoiseMenu( mapped, &entwin, ignore, Side );
|
||
if( entwin == Scr.MenuBar ){
|
||
UnmapMenu( mapped, UNMAP_ALL );
|
||
mapped = NULL;
|
||
}
|
||
}
|
||
}
|
||
if( Event.xcrossing.window==Scr.MenuBar &&
|
||
Event.xcrossing.detail!=NotifyVirtual ){
|
||
if( mapped!=NULL ){
|
||
XQueryPointer( dpy, mapped->PullWin,
|
||
&JunkRoot, &JunkChild,
|
||
&x, &y,&JunkX, &JunkY,&JunkMask);
|
||
if( !isRect( x, y, 0, 0,
|
||
mapped->MenuWidth, mapped->MenuHeight ) &&
|
||
!isRect( x-mapped->LabelX, y, 0, 0,
|
||
mapped->LabelWidth, MENUB_H )){
|
||
UnmapMenu( mapped, UNMAP_ALL );
|
||
mapped = NULL;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
if( mapped ) UnmapMenu( mapped, UNMAP_ALL );
|
||
UnGrabEvent();
|
||
}
|
||
|
||
Bool SwallowMenu( MenuLabel *ml )
|
||
{
|
||
XEvent ev;
|
||
XClassHint class;
|
||
XSizeHints hints;
|
||
MlvwmWindow *tmp_win;
|
||
Bool done=True;
|
||
char *name, *comm, *fullpath;
|
||
long supplied=0;
|
||
Atom *protocols = NULL, *ap;
|
||
int n, lp;
|
||
XWindowAttributes attr;
|
||
XTextProperty text_prop;
|
||
#ifdef USE_LOCALE
|
||
int num;
|
||
char **list;
|
||
#endif
|
||
|
||
stripquote( ml->action, &comm );
|
||
if( comm==NULL ){
|
||
ml->flags &= ~SWALLOW;
|
||
|
||
return False;
|
||
}
|
||
if( (fullpath=LookUpFiles( getenv("PATH"), comm, X_OK ))==NULL ){
|
||
ml->flags &= ~SWALLOW;
|
||
DrawErrMsgOnMenu( "Swallow Falied(Can't Exec) ", comm );
|
||
return False;
|
||
}
|
||
free( fullpath );
|
||
free( comm );
|
||
ExecuteFunction( ml->action );
|
||
|
||
do{
|
||
XMaskEvent( dpy, SubstructureRedirectMask |
|
||
StructureNotifyMask | SubstructureNotifyMask, &ev );
|
||
if( ev.type==MapRequest ){
|
||
if( XGetWMName( dpy, ev.xmaprequest.window, &text_prop) != 0 ){
|
||
#ifdef USE_LOCALE
|
||
if(text_prop.value)
|
||
text_prop.nitems = strlen(text_prop.value);
|
||
if(XmbTextPropertyToTextList(dpy, &text_prop, &list, &num)
|
||
>= Success
|
||
&& num > 0 && *list)
|
||
name = *list;
|
||
else
|
||
name = NoName;
|
||
#else
|
||
name = (char *)text_prop.value;
|
||
#endif
|
||
}
|
||
else
|
||
name = NoName;
|
||
|
||
XGetClassHint(dpy, ev.xmaprequest.window, &class);
|
||
if( !strcmp( name, ml->name ) ||
|
||
!strcmp( class.res_name, ml->name ) ||
|
||
!strcmp( class.res_class, ml->name ) ){
|
||
done = False;
|
||
XGetWindowAttributes( dpy, ev.xmaprequest.window, &attr );
|
||
|
||
if(!XGetWMNormalHints( dpy, ev.xmaprequest.window, &hints,
|
||
&supplied ))
|
||
hints.flags = 0;
|
||
if((USSize | PSize ) & hints.flags ){
|
||
ml->LabelWidth = hints.width;
|
||
ml->LabelHeight = hints.height;
|
||
}
|
||
else{
|
||
ml->LabelWidth = attr.width;
|
||
ml->LabelHeight = attr.height;
|
||
}
|
||
ml->LabelWin = ev.xmaprequest.window;
|
||
ml->flags &= ~CANDELETE;
|
||
if(XGetWMProtocols (dpy, ml->LabelWin, &protocols, &n)){
|
||
for( lp=0, ap=protocols; lp<n; lp++, ap++)
|
||
if(*ap == (Atom)_XA_WM_DELETE_WINDOW)
|
||
ml->flags |= CANDELETE;
|
||
}
|
||
if (protocols) XFree ((char *) protocols);
|
||
}
|
||
else
|
||
HandleEvents( ev );
|
||
if( name!=NoName ) XFree( name );
|
||
}
|
||
else
|
||
HandleEvents( ev );
|
||
if( ev.type==MapNotify &&
|
||
XFindContext(dpy, ev.xany.window, MlvwmContext, (caddr_t *)&tmp_win)
|
||
!=XCNOENT)
|
||
DrawStringMenuBar( tmp_win->name );
|
||
}
|
||
while( done );
|
||
return True;
|
||
}
|
||
|
||
void CreateMenuLabel( MenuLabel *ml )
|
||
{
|
||
unsigned long valuemask;
|
||
XSetWindowAttributes attributes;
|
||
int width;
|
||
|
||
if( ml->flags&SWALLOW ){
|
||
if( SwallowMenu( ml ) ){
|
||
XSetWindowBorderWidth( dpy, ml->LabelWin, 0 );
|
||
// XResizeWindow( dpy, ml->LabelWin, ml->LabelWidth, MENUB_H-2 );
|
||
XReparentWindow( dpy, ml->LabelWin, Scr.MenuBar, 0, 0 );
|
||
ml->LabelWidth += 6;
|
||
}
|
||
}
|
||
else{
|
||
if( ml->xpm ){
|
||
ml->LabelWidth = ml->xpm->width+16;
|
||
ml->LabelHeight = ml->xpm->height;
|
||
}
|
||
else{
|
||
ml->LabelHeight = 0;
|
||
if( ml->LabelStr ){
|
||
StrWidthHeight( MENUBARFONT, &width, NULL, NULL,
|
||
ml->LabelStr, strlen(ml->LabelStr));
|
||
ml->LabelWidth = width+16;
|
||
}
|
||
else
|
||
ml->LabelWidth = 16;
|
||
}
|
||
valuemask = CWCursor | CWEventMask | CWBackPixel;
|
||
attributes.background_pixel = WhitePixel( dpy, Scr.screen );
|
||
attributes.cursor = Scr.MlvwmCursors[DEFAULT];
|
||
attributes.event_mask = (ButtonPressMask | ButtonReleaseMask |
|
||
EnterWindowMask | ExposureMask |
|
||
OwnerGrabButtonMask | PointerMotionMask);
|
||
ml->LabelWin = XCreateWindow( dpy, Scr.MenuBar, 0, 1,
|
||
ml->LabelWidth, MENUB_H-2, 0,
|
||
CopyFromParent, InputOutput,
|
||
CopyFromParent,
|
||
valuemask, &attributes );
|
||
XSaveContext( dpy, ml->LabelWin, MenuContext, (caddr_t)ml );
|
||
|
||
valuemask = CWCursor | CWEventMask | CWBackPixel;
|
||
attributes.background_pixel = WhitePixel( dpy, Scr.screen );
|
||
attributes.cursor = Scr.MlvwmCursors[DEFAULT];
|
||
attributes.event_mask = (SubstructureRedirectMask | ExposureMask |
|
||
SubstructureNotifyMask | PointerMotionMask |
|
||
EnterWindowMask | LeaveWindowMask );
|
||
ml->PullWin = XCreateWindow( dpy, Scr.Root, 0, 0, 10, 10 , 1,
|
||
CopyFromParent, InputOutput,
|
||
CopyFromParent,
|
||
valuemask, &attributes );
|
||
XSaveContext( dpy, ml->PullWin, MenuContext, (caddr_t)ml );
|
||
}
|
||
}
|
||
|
||
void AddMenuItem( MenuLabel *ml, char *label, char *action, char *icon, Icon *miniicon, MenuLabel *submenu, int mode )
|
||
{
|
||
MenuItem *tmpitem, *newitem;
|
||
|
||
newitem = calloc( 1, sizeof( MenuItem ) );
|
||
|
||
if( ml->m_item == NULL )
|
||
ml->m_item = newitem;
|
||
else{
|
||
for( tmpitem=ml->m_item; tmpitem->next; tmpitem=tmpitem->next );
|
||
tmpitem->next = newitem;
|
||
}
|
||
newitem->label = strdup( label );
|
||
newitem->action = action ? strdup( action ) : action ;
|
||
newitem->iconname = icon ? strdup( icon ) : icon ;
|
||
newitem->mode = mode;
|
||
newitem->submenu = submenu;
|
||
newitem->xpm = miniicon;
|
||
}
|
||
|
||
void DelMenuItem( MenuLabel *ml, char *action )
|
||
{
|
||
MenuItem *mi, *prev;
|
||
|
||
for( mi=ml->m_item, prev=NULL;
|
||
strcmp( mi->action, action )!=0 && mi;
|
||
prev=mi, mi=mi->next );
|
||
if( !mi ) return;
|
||
|
||
free( mi->label );
|
||
if( mi->action ) free( mi->action );
|
||
if( mi->iconname ) free( mi->iconname );
|
||
if( prev ) prev->next = mi->next;
|
||
free( mi );
|
||
}
|
||
|
||
void CreateMenuItems( void )
|
||
{
|
||
MenuLabel *tmpmenu;
|
||
|
||
Scr.IconMenu.flags = ACTIVE | STICKLABEL;
|
||
Scr.IconMenu.xpm = Scr.SystemIcon;
|
||
Scr.IconMenu.name = strdup( "ICON" );
|
||
Scr.IconMenu.LabelStr = NULL;
|
||
CreateMenuLabel( &Scr.IconMenu );
|
||
|
||
for(tmpmenu=Scr.MenuLabelRoot;tmpmenu!=NULL;tmpmenu=tmpmenu->next)
|
||
CreateMenuLabel( tmpmenu );
|
||
}
|
||
|
||
char *SetItemGrayString( char *str, char **action, int *mode, char **icon, MenuLabel **submenu )
|
||
{
|
||
*mode |= STRGRAY;
|
||
|
||
return str+4;
|
||
}
|
||
|
||
char *SetItemBlackString( char *str, char **action, int *mode, char **icon, MenuLabel **submenu )
|
||
{
|
||
*mode &= ~STRGRAY;
|
||
|
||
return str+5;
|
||
}
|
||
|
||
char *SetItemCheckMark( char *str, char **action, int *mode, char **icon, MenuLabel **submenu )
|
||
{
|
||
*mode |= CHECKON;
|
||
|
||
return str+5;
|
||
}
|
||
|
||
char *SetItemNonCheckMark( char *str, char **action, int *mode, char **icon, MenuLabel **submenu )
|
||
{
|
||
*mode &= ~CHECKON;
|
||
|
||
return str+8;
|
||
}
|
||
|
||
char *SetItemSelect( char *str, char **action, int *mode, char **icon, MenuLabel **submenu )
|
||
{
|
||
*mode |= SELECTON;
|
||
|
||
return str+6;
|
||
}
|
||
|
||
char *SetItemNonSelect( char *str, char **action, int *mode, char **icon, MenuLabel **submenu )
|
||
{
|
||
*mode &= ~SELECTON;
|
||
|
||
return str+9;
|
||
}
|
||
|
||
char *SetItemIcon( char *str, char **action, int *mode, char **icon, MenuLabel **submenu )
|
||
{
|
||
char *name, *stop, tmp[5], *path;
|
||
|
||
if( *icon )
|
||
free( *icon );
|
||
|
||
if( (stop = strchr( str, ',' ))!=NULL )
|
||
*stop = '\0';
|
||
name = calloc( strlen(str)-4, 1 );
|
||
sscanf( str, "%s%s", tmp, name );
|
||
|
||
*icon = name;
|
||
if((path = LookUpFiles( Scr.IconPath, name, R_OK ))==NULL )
|
||
DrawErrMsgOnMenu( "Can't Find file ", name );
|
||
else
|
||
free( path );
|
||
|
||
if( stop!=NULL )
|
||
stop++;
|
||
else
|
||
stop = str+strlen(str);
|
||
|
||
return stop;
|
||
}
|
||
|
||
char *SetItemAction( char *str, char **action, int *mode, char **icon, MenuLabel **submenu )
|
||
{
|
||
char *stop, *top;
|
||
|
||
if( *action ) free( *action );
|
||
top = SkipSpace( str+6 );
|
||
if( (stop = strchr( str, ',' ))!=NULL )
|
||
*stop = '\0';
|
||
else
|
||
str[strlen(str)-1]='\0';
|
||
*action = strdup( top );
|
||
|
||
if( stop!=NULL )
|
||
stop++;
|
||
else
|
||
stop = str+strlen(str);
|
||
|
||
return stop;
|
||
}
|
||
|
||
char *SetSubMenu( char *str, char **action, int *mode, char **icon, MenuLabel **submenu )
|
||
{
|
||
char *stop, *top;
|
||
MenuLabel *tmp_l;
|
||
|
||
top = SkipSpace( str+7 );
|
||
if( (stop = strchr( str, ',' ))!=NULL )
|
||
*stop = '\0';
|
||
else
|
||
str[strlen(str)-1]='\0';
|
||
|
||
for( tmp_l=Scr.MenuLabelRoot;
|
||
tmp_l && strcmp( top, tmp_l->name ); tmp_l=tmp_l->next );
|
||
|
||
if( tmp_l )
|
||
*submenu = tmp_l;
|
||
else
|
||
DrawErrMsgOnMenu( "Configuration Error(SubMenu)! ", str );
|
||
|
||
if( stop!=NULL )
|
||
stop++;
|
||
else
|
||
stop = str+strlen(str);
|
||
|
||
return stop;
|
||
}
|
||
|
||
menu_item_func MenuItemFunc[]={
|
||
{"Gray", SetItemGrayString },
|
||
{"Black", SetItemBlackString },
|
||
{"Check", SetItemCheckMark },
|
||
{"NonCheck", SetItemNonCheckMark },
|
||
{"Select", SetItemSelect },
|
||
{"NonSelect", SetItemNonSelect },
|
||
{"SubMenu", SetSubMenu },
|
||
{"Icon", SetItemIcon },
|
||
{"Action", SetItemAction },
|
||
{NULL, 0}
|
||
};
|
||
|
||
|
||
char *SetLabelIconName( MenuLabel *ml, char *str )
|
||
{
|
||
char *name, *stop, tmp[5];
|
||
|
||
if( (stop = strchr( str, ',' ))!=NULL )
|
||
*stop = '\0';
|
||
name = calloc( strlen(str)-4, 1 );
|
||
sscanf( str, "%s%s", tmp, name );
|
||
ml->xpm = ReadIcon( name, NULL, True );
|
||
free( name );
|
||
|
||
if( stop!=NULL )
|
||
stop++;
|
||
else
|
||
stop = str+strlen(str);
|
||
|
||
return stop;
|
||
}
|
||
|
||
char *SetLabelStick( MenuLabel *ml, char *str )
|
||
{
|
||
ml->flags |= STICKLABEL;
|
||
|
||
return str+5;
|
||
}
|
||
|
||
char *SetLabelNonStick( MenuLabel *ml, char *str )
|
||
{
|
||
ml->flags &= ~STICKLABEL;
|
||
|
||
return str+8;
|
||
}
|
||
|
||
char *SetLabelRight( MenuLabel *ml, char *str )
|
||
{
|
||
ml->flags &= ~LEFTSIDE;
|
||
|
||
return str+5;
|
||
}
|
||
|
||
char *SetLabelLeft( MenuLabel *ml, char *str )
|
||
{
|
||
ml->flags |= LEFTSIDE;
|
||
|
||
return str+5;
|
||
}
|
||
|
||
char *SetMenuLabelLabel( MenuLabel *ml, char *str )
|
||
{
|
||
char *top;
|
||
|
||
top = stripquote( str+6, &(ml->LabelStr) );
|
||
|
||
return top;
|
||
}
|
||
|
||
char *SetSwallowAction( MenuLabel *ml, char *str )
|
||
{
|
||
char *stop, *top;
|
||
|
||
top = SkipSpace( str+6 );
|
||
if( (stop = strchr( str, ',' ))!=NULL )
|
||
*stop = '\0';
|
||
else
|
||
str[strlen(str)-1]='\0';
|
||
ml->action = strdup( top );
|
||
|
||
if( stop!=NULL )
|
||
stop++;
|
||
else
|
||
stop = str+strlen(str);
|
||
|
||
return stop;
|
||
}
|
||
|
||
menu_func MenuLabelFunc[]={
|
||
{"Action", SetSwallowAction},
|
||
{"Icon", SetLabelIconName},
|
||
{"Label", SetMenuLabelLabel },
|
||
{"Left", SetLabelLeft},
|
||
{"Right", SetLabelRight},
|
||
{"Stick", SetLabelStick},
|
||
{"NonStick", SetLabelNonStick},
|
||
{NULL, 0}
|
||
};
|
||
|
||
void SetSwallow( char *line, FILE *fp )
|
||
{
|
||
char str[256], *top;
|
||
MenuLabel *tmpmenu, *last_m;
|
||
int lp;
|
||
|
||
tmpmenu = calloc( 1, sizeof( MenuLabel ) );
|
||
|
||
if( Scr.MenuLabelRoot==NULL ) Scr.MenuLabelRoot = tmpmenu;
|
||
else{
|
||
for( last_m=Scr.MenuLabelRoot;
|
||
last_m->next!=NULL;
|
||
last_m=(MenuLabel *)last_m->next );
|
||
last_m->next = tmpmenu;
|
||
}
|
||
top = stripquote( line, &(tmpmenu->name) );
|
||
tmpmenu->flags = SWALLOW | ACTIVE | STICKLABEL;
|
||
|
||
while( *top!='\n' && *top!='\0' ){
|
||
for( ; !isalpha( *top ) && *top!='\n' && *top!='\0'; top++ );
|
||
if( *top=='\n' || *top=='\0' ) break;
|
||
for( lp=0; MenuLabelFunc[lp].label!=NULL; lp++ ){
|
||
if( !strncmp( top, MenuLabelFunc[lp].label,
|
||
strlen(MenuLabelFunc[lp].label) )){
|
||
top=MenuLabelFunc[lp].action( tmpmenu, top );
|
||
break;
|
||
}
|
||
}
|
||
if( !MenuLabelFunc[lp].label ){
|
||
DrawErrMsgOnMenu( "Configuration Error(Swallow)! ", str );
|
||
for( ; *top!=',' && *top!='\n' && *top!='\0'; top++ );
|
||
}
|
||
}
|
||
}
|
||
|
||
void SetMenu( char *line, FILE *fp )
|
||
{
|
||
char str[256], *top, tmp[5];
|
||
MenuLabel *tmpmenu, *last_m, *submenu;
|
||
int mode;
|
||
char *action, *label;
|
||
char *icon;
|
||
int lp;
|
||
|
||
tmpmenu = calloc( 1, sizeof( MenuLabel ) );
|
||
|
||
if( Scr.MenuLabelRoot==NULL ) Scr.MenuLabelRoot = tmpmenu;
|
||
else{
|
||
for( last_m=Scr.MenuLabelRoot;
|
||
last_m->next!=NULL;
|
||
last_m=(MenuLabel *)last_m->next );
|
||
last_m->next = tmpmenu;
|
||
}
|
||
|
||
if( (top = strchr( line, ',' ))!=NULL )
|
||
*top = '\0';
|
||
tmpmenu->name = calloc( strlen(line)-4, 1 );
|
||
sscanf( line, "%s%s", tmp, tmpmenu->name );
|
||
if( top ) top++;
|
||
else top = line+strlen( line );
|
||
|
||
tmpmenu->flags = LEFTSIDE;
|
||
|
||
while( *top!='\n' && *top!='\0' ){
|
||
for( ; !isalpha( *top ) && *top!='\n' && *top!='\0'; top++ );
|
||
if( *top=='\n' || *top=='\0' ) break;
|
||
for( lp=0; MenuLabelFunc[lp].label!=NULL; lp++ ){
|
||
if( !strncmp( top, MenuLabelFunc[lp].label,
|
||
strlen(MenuLabelFunc[lp].label) )){
|
||
top=MenuLabelFunc[lp].action( tmpmenu, top );
|
||
break;
|
||
}
|
||
}
|
||
if( !MenuLabelFunc[lp].label ){
|
||
DrawErrMsgOnMenu( "Configuration Error(Menu)! ", str );
|
||
for( ; *top!=',' && *top!='\n' && *top!='\0'; top++ );
|
||
}
|
||
}
|
||
|
||
while( fgetline( str, 256, fp )!=NULL && strncmp( str, "END", 3) ){
|
||
if( str[0]=='#' ) continue;
|
||
mode = SELECTON;
|
||
label = NULL;
|
||
action = NULL;
|
||
icon = NULL;
|
||
submenu = NULL;
|
||
|
||
top = stripquote( str, &label );
|
||
if( !label ){
|
||
DrawErrMsgOnMenu( "Configuration Error! ", str );
|
||
continue;
|
||
}
|
||
while( *top!='\n' && *top!='\0' ){
|
||
for( ; !isalpha( *top ) && *top!='\n' && *top!='\0'; top++ );
|
||
if( *top=='\n' || *top=='\0' ) break;
|
||
for( lp=0; MenuItemFunc[lp].label!=NULL; lp++ ){
|
||
if( !strncmp( top, MenuItemFunc[lp].label,
|
||
strlen(MenuItemFunc[lp].label) )){
|
||
top = MenuItemFunc[lp].action( top, &action,
|
||
&mode, &icon, &submenu );
|
||
break;
|
||
}
|
||
}
|
||
if( !MenuItemFunc[lp].label ){
|
||
DrawErrMsgOnMenu( "Configuration Error(MenuItem)! ", str );
|
||
for( ; *top!=',' && *top!='\n' && *top!='\0'; top++ );
|
||
}
|
||
}
|
||
AddMenuItem( tmpmenu, label, action, icon, NULL, submenu, mode );
|
||
if( label ) free( label );
|
||
if( action ) free( action );
|
||
if( icon ) free( icon );
|
||
if( mode&SELECTON ) tmpmenu->flags |= ACTIVE;
|
||
}
|
||
}
|
||
|
||
void SetMenuBar( char *line, FILE *fp )
|
||
{
|
||
char str[256], *top, tmp[8];
|
||
Menu *tmp_m, *last_m;
|
||
MenuLink **tmp_link;
|
||
MenuLabel *tmp_l;
|
||
|
||
tmp_m = calloc( 1, sizeof( Menu ) );
|
||
|
||
if( Scr.MenuRoot==NULL ) Scr.MenuRoot = tmp_m;
|
||
else{
|
||
for( last_m=Scr.MenuRoot;
|
||
last_m->next!=NULL;
|
||
last_m=last_m->next );
|
||
last_m->next = tmp_m;
|
||
}
|
||
if( (top = strchr( line, ',' ))!=NULL )
|
||
*top = '\0';
|
||
tmp_m->name = calloc( strlen(line)-7, 1 );
|
||
sscanf( line, "%s%s", tmp, tmp_m->name );
|
||
|
||
if( top ) top++;
|
||
else top = line+strlen( line );
|
||
tmp_link = &tmp_m->link;
|
||
|
||
for( tmp_l=Scr.MenuLabelRoot; tmp_l; tmp_l=tmp_l->next ){
|
||
if( tmp_l->flags&STICKLABEL ){
|
||
*tmp_link = calloc( 1, sizeof( MenuLink ) );
|
||
(*tmp_link)->link = tmp_l;
|
||
tmp_link = &(*tmp_link)->next;
|
||
}
|
||
}
|
||
while( fgetline( str, 256, fp )!=NULL && strncmp( str, "END", 3) ){
|
||
if( str[0]=='#' ) continue;
|
||
str[ strlen(str)-1] = '\0';
|
||
for( tmp_l=Scr.MenuLabelRoot;
|
||
tmp_l && strcmp( str, tmp_l->name ); tmp_l=tmp_l->next );
|
||
if( tmp_l ){
|
||
*tmp_link = calloc( 1, sizeof( MenuLink ) );
|
||
(*tmp_link)->link = tmp_l;
|
||
tmp_link = &(*tmp_link)->next;
|
||
}
|
||
else
|
||
DrawErrMsgOnMenu( "MenuBar Falied(Can't find) ", str );
|
||
}
|
||
}
|
||
|
||
Window PixmapWin (char **data_xpm, Window root, int x, int y)
|
||
{
|
||
static XpmAttributes attributes;
|
||
|
||
Pixmap pixmap;
|
||
Pixmap shapemask;
|
||
Window w;
|
||
XSetWindowAttributes attr;
|
||
|
||
XpmCreatePixmapFromData( dpy, root, data_xpm,
|
||
&pixmap, &shapemask, &attributes );
|
||
x = x<0? x + Scr.MyDisplayWidth - attributes.width : x-1;
|
||
y = y<0? y + Scr.MyDisplayHeight - attributes.height : y-1;
|
||
|
||
attr.background_pixel = BlackPixel( dpy, DefaultScreen(dpy) );
|
||
attr.override_redirect = True;
|
||
w = XCreateWindow( dpy, root, x, y,
|
||
attributes.width, attributes.height, 1,
|
||
CopyFromParent, InputOutput, CopyFromParent,
|
||
CWBackPixel | CWOverrideRedirect, &attr );
|
||
XShapeCombineMask( dpy, w, ShapeBounding, 0, 0, shapemask, ShapeSet );
|
||
|
||
XFreePixmap( dpy, pixmap );
|
||
XFreePixmap( dpy, shapemask );
|
||
return w;
|
||
}
|
||
|
||
void CreateMenuBar( void )
|
||
{
|
||
static char *lbot_xpm[] = {
|
||
"5 5 2 1",
|
||
" c none s none",
|
||
"# c black",
|
||
"# ",
|
||
"# ",
|
||
"## ",
|
||
"### ",
|
||
"#####"
|
||
};
|
||
static char *rbot_xpm[] = {
|
||
"5 5 2 1",
|
||
" c none s none",
|
||
"# c black",
|
||
" #",
|
||
" #",
|
||
" ##",
|
||
" ###",
|
||
"#####"
|
||
};
|
||
unsigned long valuemask;
|
||
XSetWindowAttributes attributes;
|
||
|
||
valuemask = CWCursor | CWBackPixel | CWEventMask;
|
||
attributes.cursor = Scr.MlvwmCursors[DEFAULT];
|
||
attributes.background_pixel = WhitePixel( dpy, Scr.screen );
|
||
attributes.event_mask = (SubstructureRedirectMask | ButtonPressMask |
|
||
EnterWindowMask | ExposureMask |
|
||
OwnerGrabButtonMask | ButtonReleaseMask );
|
||
Scr.MenuBar = XCreateWindow( dpy, Scr.Root, 0, 0,
|
||
Scr.MyDisplayWidth, MENUB_H ,0,
|
||
CopyFromParent, InputOutput, CopyFromParent,
|
||
valuemask, &attributes );
|
||
XMapWindow( dpy, Scr.MenuBar );
|
||
Scr.lbCorner = PixmapWin( lbot_xpm, Scr.Root, 0, -1 );
|
||
Scr.rbCorner = PixmapWin( rbot_xpm, Scr.Root, -1, -1 );
|
||
|
||
RedrawMenuBar( );
|
||
}
|
||
|
||
void MapMenuBar( MlvwmWindow *win )
|
||
{
|
||
int left, right;
|
||
MenuLabel *tmpml;
|
||
MenuLink *mlink;
|
||
styles *style;
|
||
static Bool Mapped=False;
|
||
|
||
if( Scr.flags&STARTING ) return;
|
||
left = 10;
|
||
right = Scr.MyDisplayWidth-Scr.IconMenu.LabelWidth-10;
|
||
|
||
XMoveWindow( dpy, Scr.IconMenu.LabelWin, right, 1 );
|
||
Scr.IconMenu.LabelX = right;
|
||
right--;
|
||
|
||
if( Scr.MenuRoot==NULL ){
|
||
if( Mapped ) return;
|
||
|
||
for( tmpml=Scr.MenuLabelRoot; tmpml; tmpml=tmpml->next ){
|
||
if( tmpml->flags&LEFTSIDE ){
|
||
tmpml->LabelX = left;
|
||
left += tmpml->LabelWidth+1;
|
||
}
|
||
else{
|
||
tmpml->LabelX = right-tmpml->LabelWidth-1;
|
||
right = tmpml->LabelX;
|
||
}
|
||
if( tmpml->LabelHeight )
|
||
XMoveWindow( dpy, tmpml->LabelWin,
|
||
tmpml->LabelX+3, (MENUB_H-tmpml->LabelHeight)/2 );
|
||
else
|
||
XMoveWindow( dpy, tmpml->LabelWin, tmpml->LabelX, 1 );
|
||
}
|
||
XMapSubwindows( dpy, Scr.MenuBar );
|
||
Mapped = True;
|
||
|
||
return;
|
||
}
|
||
if((!win || (style = lookupstyles( win->name, &win->class ))==NULL) ||
|
||
!(style->menubar) )
|
||
if( (style = lookupstyles( "*", NULL ))==NULL )
|
||
return;
|
||
if( !(style->menubar) ) return;
|
||
if( Scr.ActiveMenu==style->menubar ) return;
|
||
|
||
XGrabServer (dpy);
|
||
for( mlink=style->menubar->link; mlink; mlink=mlink->next ){
|
||
if( mlink->link->flags&LEFTSIDE ){
|
||
mlink->link->LabelX = left;
|
||
left += mlink->link->LabelWidth+1;
|
||
}
|
||
else{
|
||
mlink->link->LabelX = right-mlink->link->LabelWidth-1;
|
||
right = mlink->link->LabelX;
|
||
}
|
||
if( mlink->link->flags&SWALLOW )
|
||
XMoveWindow( dpy, mlink->link->LabelWin,
|
||
mlink->link->LabelX+3, (MENUB_H-mlink->link->LabelHeight)/2 );
|
||
else
|
||
XMoveWindow( dpy, mlink->link->LabelWin, mlink->link->LabelX, 1 );
|
||
}
|
||
|
||
if( Scr.ActiveMenu )
|
||
for( mlink=Scr.ActiveMenu->link; mlink; mlink=mlink->next )
|
||
if( !(mlink->link->flags&STICKLABEL) )
|
||
XUnmapWindow( dpy, mlink->link->LabelWin );
|
||
|
||
XMapWindow( dpy, Scr.IconMenu.LabelWin );
|
||
for( mlink=style->menubar->link; mlink; mlink=mlink->next ){
|
||
XMapWindow( dpy, mlink->link->LabelWin );
|
||
RedrawMenu( mlink->link, False );
|
||
}
|
||
Scr.ActiveMenu = style->menubar;
|
||
XSync( dpy, 0 );
|
||
XUngrabServer (dpy);
|
||
}
|
||
|
||
void ChangeMenuLabel( MenuLabel *ml, char *newl, Icon *miniicon )
|
||
{
|
||
if( newl==NULL && ml->xpm==miniicon ) return;
|
||
if( ml->LabelStr && !strcmp(ml->LabelStr, newl )){
|
||
if( ml->LabelStr )
|
||
free( ml->LabelStr );
|
||
ml->LabelStr = newl;
|
||
}
|
||
ml->xpm = miniicon;
|
||
RedrawMenu( ml, False );
|
||
}
|
||
|
||
void ChangeMenuItemLabel( char *name, char *oldl, char *newl, char *action, int mm, int sm )
|
||
{
|
||
MenuItem *tmpitem;
|
||
MenuLabel *tmplabel;
|
||
|
||
if( oldl==NULL || *oldl=='\0' ) return;
|
||
if( !strcmp( name, "ICON" ) ) tmplabel = &(Scr.IconMenu);
|
||
else{
|
||
for( tmplabel = Scr.MenuLabelRoot;
|
||
tmplabel && strcmp( name, tmplabel->name );
|
||
tmplabel=tmplabel->next );
|
||
if( tmplabel==NULL ) return;
|
||
}
|
||
for( tmpitem = tmplabel->m_item;
|
||
tmpitem && (strcmp( oldl, tmpitem->label ) ||
|
||
(action==NULL?False:strcmp(tmpitem->action, action)));
|
||
tmpitem=tmpitem->next );
|
||
if( tmpitem==NULL ) return;
|
||
switch( sm ){
|
||
case M_COPY: tmpitem->mode = mm; break;
|
||
case M_AND: tmpitem->mode &= mm; break;
|
||
case M_OR: tmpitem->mode |= mm; break;
|
||
}
|
||
if( oldl==newl || !strcmp( oldl, newl ) ) return;
|
||
if( tmpitem->label!=NULL )
|
||
free( tmpitem->label );
|
||
tmpitem->label = strdup( newl );
|
||
}
|
||
|
||
void FreeMenuItems( MenuLabel *ml, Bool FreeIcon )
|
||
{
|
||
MenuItem *tmpitem, *next;
|
||
|
||
tmpitem = ml->m_item;
|
||
while( tmpitem!=NULL ){
|
||
next = tmpitem->next;
|
||
if( tmpitem->label ) free( tmpitem->label );
|
||
if( tmpitem->action ) free( tmpitem->action );
|
||
if( FreeIcon && tmpitem->xpm ){
|
||
XFreePixmap( dpy, tmpitem->xpm->icon );
|
||
XFreePixmap( dpy, tmpitem->xpm->lighticon );
|
||
if( tmpitem->xpm->mask!=None )
|
||
XFreePixmap( dpy, tmpitem->xpm->mask );
|
||
free( tmpitem->xpm );
|
||
free( tmpitem->iconname );
|
||
}
|
||
free( tmpitem );
|
||
tmpitem = next;
|
||
}
|
||
}
|
||
|
||
void FreeMenuLabels( MenuLabel *ml, Bool all )
|
||
{
|
||
Bool cont=True;
|
||
XWindowAttributes winattrs;
|
||
unsigned long eventMask;
|
||
XEvent ev;
|
||
|
||
FreeMenuItems( ml, all );
|
||
free( ml->name );
|
||
if( ml->LabelStr ) free( ml->LabelStr );
|
||
if( ml->xpm ){
|
||
XFreePixmap( dpy, ml->xpm->icon );
|
||
XFreePixmap( dpy, ml->xpm->lighticon );
|
||
if( ml->xpm->mask!=None ) XFreePixmap( dpy, ml->xpm->mask );
|
||
free( ml->xpm );
|
||
}
|
||
if( !(ml->flags&SWALLOW) ){
|
||
if( ml->action )
|
||
free( ml->action );
|
||
if( ml->LabelWin!=None )
|
||
XDestroyWindow( dpy, ml->LabelWin );
|
||
if( ml->PullWin!=None )
|
||
XDestroyWindow( dpy, ml->PullWin );
|
||
}
|
||
else{
|
||
if( XGetWindowAttributes(dpy, ml->LabelWin, &winattrs) ){
|
||
eventMask = winattrs.your_event_mask;
|
||
XMoveWindow( dpy, ml->LabelWin, ml->LabelX, -MENUB_H );
|
||
XMapWindow( dpy, ml->LabelWin );
|
||
XSelectInput(dpy, ml->LabelWin, eventMask | StructureNotifyMask);
|
||
|
||
if( ml->flags&CANDELETE )
|
||
send_clientmessage( ml->LabelWin, _XA_WM_DELETE_WINDOW,
|
||
CurrentTime);
|
||
else
|
||
XKillClient( dpy, ml->LabelWin );
|
||
do{
|
||
XMaskEvent( dpy, StructureNotifyMask|SubstructureNotifyMask,
|
||
&ev );
|
||
if( (ev.type==UnmapNotify || ev.type==DestroyNotify) &&
|
||
(ev.xany.window==ml->LabelWin ||
|
||
ev.xunmap.window==ml->LabelWin) ){
|
||
cont = False;
|
||
XUnmapWindow( dpy, ev.xany.window );
|
||
}
|
||
else
|
||
HandleEvents( ev );
|
||
}
|
||
while( cont );
|
||
}
|
||
free( ml->action );
|
||
}
|
||
if( all ) free( ml );
|
||
}
|
||
|
||
void FreeMenu( void )
|
||
{
|
||
Menu *tmpm, *nextm;
|
||
MenuLink *tmplink, *nextlink;
|
||
MenuLabel *tmpml, *nextl;
|
||
|
||
tmpm = Scr.MenuRoot;
|
||
while( tmpm ){
|
||
nextm = tmpm->next;
|
||
tmplink = tmpm->link;
|
||
while( tmplink ){
|
||
nextlink = tmplink->next;
|
||
free( tmplink );
|
||
tmplink = nextlink;
|
||
}
|
||
free( tmpm->name );
|
||
free( tmpm );
|
||
tmpm = nextm;
|
||
}
|
||
|
||
tmpml = Scr.MenuLabelRoot;
|
||
while( tmpml ){
|
||
nextl = tmpml->next;
|
||
FreeMenuLabels( tmpml, True );
|
||
tmpml = nextl;
|
||
}
|
||
ChangeMenuLabel( &(Scr.IconMenu), NULL, Scr.SystemIcon );
|
||
FreeMenuLabels( &Scr.IconMenu, False );
|
||
XUnmapWindow( dpy, Scr.MenuBar );
|
||
}
|
||
|
||
void FreeShortCut( void )
|
||
{
|
||
ShortCut *now, *next;
|
||
|
||
now = Scr.ShortCutRoot;
|
||
for( ;now!=NULL; now = next ){
|
||
next = now->next;
|
||
free( now->action );
|
||
free( now );
|
||
}
|
||
}
|
||
|
||
void KeepOnTop( void )
|
||
{
|
||
MlvwmWindow *tmp;
|
||
|
||
if( Scr.flags&STARTING ) return;
|
||
for (tmp = Scr.MlvwmRoot.next; tmp != NULL; tmp = tmp->next)
|
||
if( tmp->flags&ONTOP )
|
||
RaiseMlvwmWindow( tmp );
|
||
XRaiseWindow( dpy, Scr.MenuBar );
|
||
XRaiseWindow( dpy, Scr.lbCorner );
|
||
XRaiseWindow( dpy, Scr.rbCorner );
|
||
}
|
||
|
||
void CreateSimpleMenu( void )
|
||
{
|
||
Scr.MenuLabelRoot = calloc( 1, sizeof( MenuLabel ) );
|
||
Scr.MenuLabelRoot->flags = LEFTSIDE | ACTIVE;
|
||
Scr.MenuLabelRoot->name = strdup( "Default" );
|
||
Scr.MenuLabelRoot->LabelStr = strdup( "File" );
|
||
|
||
Scr.MenuLabelRoot->m_item = calloc( 1, sizeof( MenuItem ) );
|
||
Scr.MenuLabelRoot->m_item->mode = SELECTON;
|
||
Scr.MenuLabelRoot->m_item->label = strdup( "Quit" );
|
||
Scr.MenuLabelRoot->m_item->action = strdup( "Exit" );
|
||
|
||
Scr.MenuRoot = calloc( 1, sizeof(Menu) );
|
||
Scr.MenuRoot->link = calloc( 1, sizeof(MenuLink) );
|
||
Scr.MenuRoot->link->link = Scr.MenuLabelRoot;
|
||
if( !Scr.style_list ){
|
||
Scr.style_list = calloc( 1, sizeof( styles ) );
|
||
Scr.style_list->name = strdup("*");
|
||
Scr.style_list->flags = NORMALWIN;
|
||
Scr.style_list->maxmizescale = 90;
|
||
Scr.style_list->menubar = Scr.MenuRoot;
|
||
}
|
||
}
|