1 /*--------------------------------*/
2 /* a simple dockapp library */
3 /* made from scratch */
4 /*--------------------------------*/
7 functions were written by following People:
13 --- built-in Dock module for WindowMaker
16 --- wmgeneral (taken from wmppp)
17 Martijn Pieterse (pieterse@xs4all.nl)
30 #include <sys/types.h>
34 #include <X11/extensions/shape.h>
38 /* Return a cons cell produced from (head . tail) */
41 list_cons(void* head
, LinkedList
* tail
)
45 cell
= (LinkedList
*)malloc(sizeof(LinkedList
));
51 /* Return the length of a list, list_length(NULL) returns zero */
54 list_length(LinkedList
* list
)
65 /* Return the Nth element of LIST, where N count from zero. If N
66 larger than the list length, NULL is returned */
69 list_nth(int index
, LinkedList
* list
)
81 /* Remove the element at the head by replacing it by its successor */
84 list_remove_head(LinkedList
** list
)
89 LinkedList
* tail
= (*list
)->tail
; /* fetch next */
90 *(*list
) = *tail
; /* copy next to list head */
91 free(tail
); /* free next */
93 else /* only one element in list */
101 list_remove_elem(LinkedList
* list
, void* elem
)
106 if (list
->head
== elem
) {
111 list
->tail
= list_remove_elem(list
->tail
, elem
);
118 /* Return element that has ELEM as car */
121 list_find(LinkedList
* list
, void* elem
)
125 if (list
->head
== elem
)
132 /* Free list (backwards recursive) */
135 list_free(LinkedList
* list
)
139 list_free(list
->tail
);
144 /* Map FUNCTION over all elements in LIST */
147 list_mapcar(LinkedList
* list
, void(*function
)(void*))
151 (*function
)(list
->head
);
158 *----------------------------------------------------------------------
160 * Divides a command line into a argv/argc pair.
161 *----------------------------------------------------------------------
176 static DFA mtable
[9][6] = {
177 {{3,1},{0,0},{4,0},{1,0},{8,0},{6,0}},
178 {{1,1},{1,1},{2,0},{3,0},{5,0},{1,1}},
179 {{1,1},{1,1},{1,1},{1,1},{5,0},{1,1}},
180 {{3,1},{5,0},{4,0},{1,0},{5,0},{6,0}},
181 {{3,1},{3,1},{3,1},{3,1},{5,0},{3,1}},
182 {{-1,-1},{0,0},{0,0},{0,0},{0,0},{0,0}}, /* final state */
183 {{6,1},{6,1},{7,0},{6,1},{5,0},{3,0}},
184 {{6,1},{6,1},{6,1},{6,1},{5,0},{6,1}},
185 {{-1,-1},{0,0},{0,0},{0,0},{0,0},{0,0}}, /* final state */
189 next_token(char *word
, char **next
)
195 t
= ret
= malloc(strlen(word
)+1);
209 else if (*ptr
==' ' || *ptr
=='\t')
214 if (mtable
[state
][ctype
].output
) {
218 state
= mtable
[state
][ctype
].nstate
;
220 if (mtable
[state
][0].output
<0) {
242 parse_command(char *command
, char ***argv
, int *argc
)
244 LinkedList
*list
= NULL
;
250 token
= next_token(line
, &line
);
252 list
= list_cons(token
, list
);
254 } while (token
!=NULL
&& line
!=NULL
);
256 count
= list_length(list
);
257 *argv
= malloc(sizeof(char*)*count
);
260 (*argv
)[--i
] = list
->head
;
261 list_remove_head(&list
);
267 execCommand(char *command
)
273 parse_command(command
, &argv
, &argc
);
279 if ((pid
=fork())==0) {
283 args
= malloc(sizeof(char*)*(argc
+1));
286 for (i
=0; i
<argc
; i
++) {
290 execvp(argv
[0], args
);
306 XSizeHints mysizehints
;
308 Pixel back_pix
, fore_pix
;
327 #define MAX_MOUSE_REGION (8)
328 MOUSE_REGION mouse_region
[MAX_MOUSE_REGION
];
330 /***********************/
331 /* Function Prototypes */
332 /***********************/
334 static void GetXPM(XpmIcon
*, char **);
335 static Pixel
GetColor(char *);
336 void RedrawWindow(void);
337 void AddMouseRegion(int, int, int, int, int);
338 int CheckMouseRegion(int, int);
340 /*******************************************************************************\
342 \*******************************************************************************/
344 void parse_rcfile(const char *filename
, rckeys
*keys
) {
348 char *tokens
= " :\t\n";
352 fp
= fopen(filename
, "r");
354 while (fgets(temp
, 128, fp
)) {
356 while (key
>= 0 && keys
[key
].label
) {
357 if ((p
= strstr(temp
, keys
[key
].label
))) {
358 p
+= strlen(keys
[key
].label
);
359 p
+= strspn(p
, tokens
);
360 if ((i
= strcspn(p
, "#\n"))) p
[i
] = 0;
361 free(*keys
[key
].var
);
362 *keys
[key
].var
= strdup(p
);
372 /*******************************************************************************\
374 \*******************************************************************************/
376 static void GetXPM(XpmIcon
*wmgen
, char *pixmap_bytes
[]) {
378 XWindowAttributes attributes
;
381 /* For the colormap */
382 XGetWindowAttributes(display
, Root
, &attributes
);
384 wmgen
->attributes
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
386 err
= XpmCreatePixmapFromData(display
, Root
, pixmap_bytes
, &(wmgen
->pixmap
),
387 &(wmgen
->mask
), &(wmgen
->attributes
));
389 if (err
!= XpmSuccess
) {
390 fprintf(stderr
, "Not enough free colorcells.\n");
395 /*******************************************************************************\
397 \*******************************************************************************/
399 static Pixel
GetColor(char *name
) {
402 XWindowAttributes attributes
;
404 XGetWindowAttributes(display
, Root
, &attributes
);
407 if (!XParseColor(display
, attributes
.colormap
, name
, &color
)) {
408 fprintf(stderr
, "wm.app: can't parse %s.\n", name
);
409 } else if (!XAllocColor(display
, attributes
.colormap
, &color
)) {
410 fprintf(stderr
, "wm.app: can't allocate %s.\n", name
);
415 /*******************************************************************************\
417 \*******************************************************************************/
419 static int flush_expose(Window w
) {
424 while (XCheckTypedWindowEvent(display
, w
, Expose
, &dummy
))
430 /*******************************************************************************\
432 \*******************************************************************************/
434 void RedrawWindow(void) {
436 flush_expose(iconwin
);
437 XCopyArea(display
, wmgen
.pixmap
, iconwin
, NormalGC
,
438 0,0, wmgen
.attributes
.width
, wmgen
.attributes
.height
, 0,0);
440 XCopyArea(display
, wmgen
.pixmap
, win
, NormalGC
,
441 0,0, wmgen
.attributes
.width
, wmgen
.attributes
.height
, 0,0);
444 /*******************************************************************************\
446 \*******************************************************************************/
448 void RedrawWindowXY(int x
, int y
) {
450 flush_expose(iconwin
);
451 XCopyArea(display
, wmgen
.pixmap
, iconwin
, NormalGC
,
452 x
,y
, wmgen
.attributes
.width
, wmgen
.attributes
.height
, 0,0);
454 XCopyArea(display
, wmgen
.pixmap
, win
, NormalGC
,
455 x
,y
, wmgen
.attributes
.width
, wmgen
.attributes
.height
, 0,0);
458 /*******************************************************************************\
460 \*******************************************************************************/
462 void AddMouseRegion(int index
, int left
, int top
, int right
, int bottom
) {
464 if (index
< MAX_MOUSE_REGION
) {
465 mouse_region
[index
].enable
= 1;
466 mouse_region
[index
].top
= top
;
467 mouse_region
[index
].left
= left
;
468 mouse_region
[index
].bottom
= bottom
;
469 mouse_region
[index
].right
= right
;
473 /*******************************************************************************\
474 |* CheckMouseRegion *|
475 \*******************************************************************************/
477 int CheckMouseRegion(int x
, int y
) {
484 for (i
=0; i
<MAX_MOUSE_REGION
&& !found
; i
++) {
485 if (mouse_region
[i
].enable
&&
486 x
<= mouse_region
[i
].right
&&
487 x
>= mouse_region
[i
].left
&&
488 y
<= mouse_region
[i
].bottom
&&
489 y
>= mouse_region
[i
].top
)
492 if (!found
) return -1;
496 /*******************************************************************************\
498 \*******************************************************************************/
500 void copyXPMArea(int x
, int y
, int sx
, int sy
, int dx
, int dy
) {
502 XCopyArea(display
, wmgen
.pixmap
, wmgen
.pixmap
, NormalGC
, x
, y
, sx
, sy
, dx
, dy
);
506 /*******************************************************************************\
508 \*******************************************************************************/
510 void copyXBMArea(int x
, int y
, int sx
, int sy
, int dx
, int dy
) {
512 XCopyArea(display
, wmgen
.mask
, wmgen
.pixmap
, NormalGC
, x
, y
, sx
, sy
, dx
, dy
);
516 /*******************************************************************************\
518 \*******************************************************************************/
520 void setMaskXY(int x
, int y
) {
522 XShapeCombineMask(display
, win
, ShapeBounding
, x
, y
, pixmask
, ShapeSet
);
523 XShapeCombineMask(display
, iconwin
, ShapeBounding
, x
, y
, pixmask
, ShapeSet
);
526 /*******************************************************************************\
528 \*******************************************************************************/
529 void openXwindow(int argc
, char *argv
[], char *pixmap_bytes
[], char *pixmask_bits
, int pixmask_width
, int pixmask_height
) {
531 unsigned int borderwidth
= 1;
532 XClassHint classHint
;
533 char *display_name
= NULL
;
534 char *wname
= argv
[0];
544 for (i
=1; argv
[i
]; i
++) {
545 if (!strcmp(argv
[i
], "-display"))
546 display_name
= argv
[i
+1];
549 if (!(display
= XOpenDisplay(display_name
))) {
550 fprintf(stderr
, "%s: can't open display %s\n",
551 wname
, XDisplayName(display_name
));
554 screen
= DefaultScreen(display
);
555 Root
= RootWindow(display
, screen
);
556 d_depth
= DefaultDepth(display
, screen
);
557 x_fd
= XConnectionNumber(display
);
559 /* Convert XPM to XImage */
560 GetXPM(&wmgen
, pixmap_bytes
);
562 /* Create a window to hold the stuff */
563 mysizehints
.flags
= USSize
| USPosition
;
567 back_pix
= GetColor("white");
568 fore_pix
= GetColor("black");
570 XWMGeometry(display
, screen
, Geometry
, NULL
, borderwidth
, &mysizehints
,
571 &mysizehints
.x
, &mysizehints
.y
,&mysizehints
.width
,&mysizehints
.height
, &dummy
);
573 mysizehints
.width
= 64;
574 mysizehints
.height
= 64;
576 win
= XCreateSimpleWindow(display
, Root
, mysizehints
.x
, mysizehints
.y
,
577 mysizehints
.width
, mysizehints
.height
, borderwidth
, fore_pix
, back_pix
);
579 iconwin
= XCreateSimpleWindow(display
, win
, mysizehints
.x
, mysizehints
.y
,
580 mysizehints
.width
, mysizehints
.height
, borderwidth
, fore_pix
, back_pix
);
583 XSetWMNormalHints(display
, win
, &mysizehints
);
584 classHint
.res_name
= wname
;
585 classHint
.res_class
= wname
;
586 XSetClassHint(display
, win
, &classHint
);
588 XSelectInput(display
, win
, ButtonPressMask
| ExposureMask
| ButtonReleaseMask
| PointerMotionMask
| StructureNotifyMask
);
589 XSelectInput(display
, iconwin
, ButtonPressMask
| ExposureMask
| ButtonReleaseMask
| PointerMotionMask
| StructureNotifyMask
);
591 if (XStringListToTextProperty(&wname
, 1, &name
) == 0) {
592 fprintf(stderr
, "%s: can't allocate window name\n", wname
);
596 XSetWMName(display
, win
, &name
);
598 /* Create GC for drawing */
600 gcm
= GCForeground
| GCBackground
| GCGraphicsExposures
;
601 gcv
.foreground
= fore_pix
;
602 gcv
.background
= back_pix
;
603 gcv
.graphics_exposures
= 0;
604 NormalGC
= XCreateGC(display
, Root
, gcm
, &gcv
);
608 pixmask
= XCreateBitmapFromData(display
, win
, pixmask_bits
, pixmask_width
, pixmask_height
);
610 XShapeCombineMask(display
, win
, ShapeBounding
, 0, 0, pixmask
, ShapeSet
);
611 XShapeCombineMask(display
, iconwin
, ShapeBounding
, 0, 0, pixmask
, ShapeSet
);
615 mywmhints
.initial_state
= WithdrawnState
;
616 mywmhints
.icon_window
= iconwin
;
617 mywmhints
.icon_x
= mysizehints
.x
;
618 mywmhints
.icon_y
= mysizehints
.y
;
619 mywmhints
.window_group
= win
;
620 mywmhints
.flags
= StateHint
| IconWindowHint
| IconPositionHint
| WindowGroupHint
;
622 XSetWMHints(display
, win
, &mywmhints
);
624 XSetCommand(display
, win
, argv
, argc
);
625 XMapWindow(display
, win
);
630 FILE *prefs_filehandle
;
631 char* p_strcpy (char *dest
, const char *src
, int maxlength
);
632 char* p_strcat (char *dest
, const char *src
, int maxlength
);
634 /*---------------------------------------------------------------------------*/
636 char* p_getdir_config (char *cdirectory
)
638 static char cfgdir
[MAX_PATH
];
641 p_strcpy (cfgdir
, getenv ("HOME"), MAX_PATH
);
642 p_strcat (cfgdir
, slash
, MAX_PATH
);
643 p_strcat (cfgdir
, cdirectory
, MAX_PATH
);
645 if(stat(cfgdir
, &cfg
) < 0)
646 mkdir(cfgdir
, S_IRUSR
| S_IWUSR
| S_IXUSR
);
651 /*---------------------------------------------------------------------------*/
653 char* p_getfilename_config (char *config_dir
, char *config_filename
)
655 static char filename
[MAX_PATH
];
657 p_strcpy (filename
, p_getdir_config(config_dir
), MAX_PATH
);
658 p_strcat (filename
, slash
, MAX_PATH
);
659 p_strcat (filename
, config_filename
, MAX_PATH
);
664 /*---------------------------------------------------------------------------*/
666 void* p_prefs_openfile (char *filename
, int openmode
)
668 prefs_filehandle
= NULL
;
670 if (openmode
== P_READ
)
671 prefs_filehandle
= fopen (filename
, "rb");
672 else if (openmode
== P_WRITE
)
673 prefs_filehandle
= fopen (filename
, "wb");
675 return prefs_filehandle
;
679 void p_prefs_closefile (void)
681 fclose (prefs_filehandle
);
684 /*---------------------------------------------------------------------------*/
686 void p_prefs_put_int (char *tagname
, int value
)
688 fprintf (prefs_filehandle
, "%s=%d\n", tagname
, value
);
692 void p_prefs_put_float (char *tagname
, float value
)
694 fprintf (prefs_filehandle
, "%s=%f\n", tagname
, value
);
698 void p_prefs_put_string (char *tagname
, char *value
)
700 fprintf (prefs_filehandle
, "%s=%s\n", tagname
, value
);
704 void p_prefs_put_lf (void)
706 fprintf (prefs_filehandle
, "\n");
710 void p_prefs_put_comment (char *comment
)
712 char text
[MAX_LINE_LEN
];
714 p_strcpy (text
, "# ", MAX_LINE_LEN
);
715 p_strcat (text
, comment
, MAX_LINE_LEN
);
716 fprintf (prefs_filehandle
, text
);
719 /*---------------------------------------------------------------------------*/
721 char* p_prefs_get_line_with_tag (char *tagname
)
723 static char prfline
[MAX_LINE_LEN
];
727 fseek (prefs_filehandle
, 0, SEEK_SET
);
729 while (!feof (prefs_filehandle
)) {
732 while (((c
= fgetc (prefs_filehandle
)) != crlf_char
) && c
!= EOF
&& i
< MAX_LINE_LEN
)
735 prfline
[i
] = null_char
;
737 if (prfline
[0] != '#')
738 if (!strncmp (tagname
, prfline
, strlen (tagname
))) break;
745 char* p_prefs_get_value_field (char *tagname
)
747 static char valuestr
[MAX_VALUE_LEN
];
753 if ((valpos
= strchr (p_prefs_get_line_with_tag (tagname
), '='))) {
754 while((c
= valpos
[i
+1]) != null_char
&& i
< MAX_VALUE_LEN
) valuestr
[i
++] = c
;
757 valuestr
[i
] = null_char
;
762 int p_prefs_get_int (char *tagname
)
764 return (atoi (p_prefs_get_value_field (tagname
)));
768 float p_prefs_get_float (char *tagname
)
770 return (atof (p_prefs_get_value_field (tagname
)));
774 char* p_prefs_get_string (char *tagname
)
776 return (p_prefs_get_value_field (tagname
));
779 /*---------------------------------------------------------------------------*/
780 /* following functions based on samba sources. */
781 /* safe_strcpy and safe_strcat routines written by Andrew Tridgell */
782 /*---------------------------------------------------------------------------*/
784 char* p_strcpy (char *dest
, const char *src
, int maxlength
)
789 printf ("ERROR: NULL dest in safe_strcpy\n");
800 if (len
> maxlength
) {
801 printf ("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
802 (int)(len
-maxlength
), src
);
806 memcpy(dest
, src
, len
);
811 /*---------------------------------------------------------------------------*/
813 char* p_strcat (char *dest
, const char *src
, int maxlength
)
815 int src_len
, dest_len
;
818 printf ("ERROR: NULL dest in safe_strcat\n");
826 src_len
= strlen(src
);
827 dest_len
= strlen(dest
);
829 if (src_len
+ dest_len
> maxlength
) {
830 printf ("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
831 (int)(src_len
+ dest_len
- maxlength
), src
);
832 src_len
= maxlength
- dest_len
;
835 memcpy(&dest
[dest_len
], src
, src_len
);
836 dest
[dest_len
+ src_len
] = 0;
840 /*---------------------------------------------------------------------------*/