/* ************************************************************************* * xfsm - (C) Copyright 1993-1999 Robert Gasch (Robert_Gasch@peoplesoft.com) http://www.peoplesoft.com/peoplepages/g/robert_gasch/src/ Permission to use, copy, modify and distribute this software for any purpose and without fee is hereby granted, provided that this copyright notice appear in all copies as well as supporting documentation. All work developed as a consequence of the use of this program should duly acknowledge such use. No representations are made about the suitability of this software for any purpose. This software is provided "as is" without express or implied warranty. See the GNU General Public Licence for more information. * ************************************************************************* */ #include "xfsm.h" #ifdef ULTRIX /* *** This defines the gt_names string which means that we have to *** */ /* *** include it here to avoid multiple definitions *** */ #include #endif extern Display *mydisplay; extern char* myname; extern char* title; extern XrmDatabase resourceDB; extern WinType main_win, menu[MENU_ITEMS], fs_win[MAXFS], detail_win; extern XGCValues gray_gc_val; extern XEvent myevent; extern unsigned long fg, bg, warncols[]; extern XWindowAttributes attribs; extern XSizeHints mainwin_hint, szhint; extern Pixmap warn_pix, popup_pix; extern int show_use, upd_interval, NFS, detail_open, detail_share_color, minimize, menu_border, show_biggest, fs_border, percent, absolute, available, bell, alwaysbeep, popup, fs_level[], fs_warn[], fs_bell[], verbose, gray, idx[], /* for compatability - xfsm */ root, /* for compatability - xfsm */ show_blocks; /* for compatability - xofm */ extern double b_blocks, b_bytes, b_disk, b_bsize, o_b_blocks, o_b_bsize, o_b_bytes, o_b_disk; extern unsigned long turns; extern float fs_perc[], res_space, warnvals[], warn_val; extern MyString hname; #ifdef XOFM extern Stats stats[]; #else /* xfsm */ extern struct statfs stats[]; extern StringInfo strinfo[]; #endif /* *** variables accessed only in util.c - make them static to make sure *** */ static char *Menu_Text[MENU_ITEMS]={ " Update Now ", " Quit "}; static int percent_width, lname; /* ************************************************************************ */ /* **** Here we adjust the main window if we add or loose an automount **** */ /* ****** file system. We also create or destroy any fs_win we need ******* */ /* ************************************************************************ */ void handle_NFS_change (ppnfs, OFS) int ppnfs, OFS; { int i; /* *** add a file system *** */ if (NFS > OFS) for (i = OFS; i < NFS; i++) { set_fs_win_size (i, ppnfs); create_window (main_win.win, &fs_win[i], getColorResource(resourceDB, catlist(myname, ".", FsName, ".foreground", (char*)NULL), "Xfsm.FileSystem.Foreground", fg), getColorResource ( resourceDB, catlist(myname, ".", FsName, ".background", (char*)NULL), "Xfsm.FileSystem.Background",bg)); if (gray) XChangeGC (mydisplay, fs_win[i].gc, GCFillStyle | GCStipple, &gray_gc_val); XMapRaised (mydisplay, fs_win[i].win); #ifdef DEBUG printf("LEVEL: clearing level info for new FS %d\n",i); #endif fs_level[i] = 0; fs_bell[i] = 0; fs_warn[i] = FALSE; } /* *** remove a file system *** */ else if (NFS < OFS) for (i = NFS; i < OFS; i++) { XFreeGC (mydisplay, fs_win[i].gc); XDestroyWindow (mydisplay, fs_win[i].win); fs_level[i] = 0; fs_bell[i] = 0; fs_warn[i] = FALSE; } /* *** did the number of file systems change *** */ if (NFS != OFS) { /* *** quick and dirty fix to force redisplaying *** */ /* *** of bars which may otherwise be associated *** */ /* *** with the wrong file system. On a decent *** */ /* *** machine this should be barley noticabel *** */ toggle_mode (); toggle_mode (); XResizeWindow (mydisplay, main_win.win, main_win.width, main_win.height); mainwin_hint.min_height = ((MIN_INTERVAL(main_win) * NFS) + BEGIN_NFS(main_win)); XSetNormalHints (mydisplay, main_win.win, &mainwin_hint); } /* *** check if the biggest file system changed *** */ if (HAS_BIGGEST_CHANGED) for (i = 0; i < NFS; i++) { set_fs_win_size (i, ppnfs); XResizeWindow (mydisplay, fs_win[i].win, fs_win[i].width, fs_win[i].height); XClearWindow (mydisplay, fs_win[i].win); redraw_fs_win (i); } redraw_main_win (); for (i = 0; i < NFS; i++) redraw_fs_win (i); } /* ************************************************************************ */ /* ************************ set the menu's position *********************** */ /* ************************************************************************ */ void fix_menu_pos (width) int width; { int i; for (i=0; i GB) sprintf (s, "%.1fGB ", b_disk/GB); else sprintf (s, "%.1fMB ", b_disk/MB); posx = main_win.width-XTextWidth(main_win.font_info, s, strlen (s)); posy = main_win.height-MENU_HEIGHT(menu[0]); XDrawImageString (mydisplay, main_win.win, main_win.gc, posx, posy, s, strlen (s)); } for (i = 0; i < NFS; i++) { if (minimize == MNL) XDrawImageString (mydisplay, main_win.win, main_win.gc, OFF_X+2, fs_win[i].y-2, FsName, strlen(FsName)); else { int n = strlen(FsName); /* *** find how much of the name we can write *** */ while (XTextWidth(main_win.font_info, FsName, n) > text_width) n--; XDrawImageString (mydisplay, main_win.win, main_win.gc, OFF_X + 2, fs_win[i].y - 2, FsName, n); } /* *** handle the exclamation mark after the FS name *** */ if (warn_val > 0) { if (fs_perc[i] >= warn_val) { if (bell && !fs_bell[i]) { should_bell=TRUE; if (!alwaysbeep) fs_bell[i] = 1; } XCopyArea (mydisplay, warn_pix, main_win.win, main_win.gc, 0, 0, warn_width, warn_height, (main_win.width-OFF_X)+2, fs_win[i].y-LETTER_HEIGHT(main_win)); } else { #ifdef DEBUG printf("LEVEL: clearing Warning Area %d - Warn_Val > 0\n",i); #endif fs_bell[i] = 0; XClearArea (mydisplay, main_win.win, (main_win.width - OFF_X) + 2, fs_win[i].y - LETTER_HEIGHT(main_win), warn_width, warn_height, FALSE); } } /* ** handle the color warning levels *** */ /* * EHR begin patch -- 1) warncols[0] as default color for bars * 2) enable popup when level changes * 3) change to table rep of warn levels & * bar colors * 4) change to have status set up in * get_fs_stat. This section just * sets up the screen as necessary. */ /* * Get Appropriate color. Note that fs_level is set in * the get_fs_stat routine. */ color=warncols[fs_level[i]]; #ifdef DEBUG printf("LEVEL: color set to %d\n", color); #endif /* * Set up the warning/popup. Note that fs_warn is set in * the get_fs_stat routine. */ if (popup && fs_warn[i]) { #ifdef DEBUG printf("LEVEL: popup processed for fs %d\n",i); #endif if (bell && !fs_bell[i]) { should_bell = TRUE; if (!alwaysbeep) fs_bell[i] = 1; } should_raise = TRUE; XCopyArea (mydisplay, popup_pix, main_win.win, main_win.gc, 0, 0, popup_width, popup_height, (main_win.width-OFF_X)+2, fs_win[i].y-LETTER_HEIGHT(main_win)); } else if (warn_val <= 0) { fs_bell[i] = 0; #ifdef DEBUG printf("LEVEL: clearing popup warning area %d\n",i); #endif XClearArea (mydisplay, main_win.win, (main_win.width - OFF_X) + 2, fs_win[i].y - LETTER_HEIGHT(main_win), popup_width, popup_height, FALSE); } XSetForeground (mydisplay, fs_win[i].gc, color); if (percent) write_percent (i); if (available) write_available (i); } /* *** make sure window is raised when should_raise==TRUE *** */ if (should_raise) { XWMHints wmhints; wmhints.initial_state = NormalState; wmhints.flags = StateHint; XSetWMHints(mydisplay, main_win.win, &wmhints); XMapRaised(mydisplay, main_win.win); } if (should_bell) XBell (mydisplay, 0); } /* *********************************************************************** */ /* *************************** redraw the bars *************************** */ /* *********************************************************************** */ void redraw_fs_win(i) int i; { /* *** now draw bar *** */ /* XClearWindow (mydisplay, fs_win[i].win); */ XFillRectangle (mydisplay, fs_win[i].win, fs_win[i].gc, 0, 0, (int)(fs_perc[i]*fs_win[i].width), fs_win[i].height); XClearArea(mydisplay, fs_win[i].win, (int)(fs_perc[i] * fs_win[i].width), 0, 0, 0, False); } /* *********************************************************************** */ /* ************************* write available space *********************** */ /* *********************************************************************** */ void write_available(i) int i; { char s[30]; long bsize=stats[i].f_bsize; sprintf (s, "%5.2f", #ifdef SCO ((double)(bsize)/(float)(MB))*(double)(stats[i].f_bfree)); #else ((double)(bsize)/(float)(MB))*(double)(stats[i].f_bavail)); #endif /* SCO */ XDrawImageString (mydisplay, main_win.win, main_win.gc, (main_win.width - OFF_Y - XTextWidth(main_win.font_info, s, strlen(s))), fs_win[i].y - 2, s, strlen (s)); } /* *********************************************************************** */ /* ************************* write the percentage ************************ */ /* *********************************************************************** */ void write_percent(i) int i; { char s[30]; if (fs_perc[i] < 0 ) strcpy (s, "N.A."); else sprintf (s, "%3d%%", (int)(fs_perc[i]*100 + 0.5)); XDrawImageString (mydisplay, main_win.win, main_win.gc, (main_win.width - OFF_Y - XTextWidth(main_win.font_info, s, strlen(s))), fs_win[i].y - 2, s, strlen (s)); } /* *********************************************************************** */ /* ************************* write the percentage ************************ */ /* *********************************************************************** */ void open_detail_win (argc, argv) int argc; char **argv; { XSizeHints szhint; XClassHint clshint; XWMHints wmhints; szhint.min_width = DETAIL_X; szhint.min_height = DETAIL_Y; szhint.max_width = szhint.min_width; szhint.max_height = szhint.min_height; szhint.x = detail_win.x; szhint.y = detail_win.y; szhint.width = detail_win.width; szhint.height = detail_win.height; szhint.flags = detail_win.flags | PMinSize | PMaxSize | PSize; clshint.res_name = "detailWin"; clshint.res_class = CLASS_NAME; wmhints.input = True; wmhints.initial_state = NormalState; wmhints.window_group = main_win.win; wmhints.flags = InputHint | StateHint | WindowGroupHint; create_window(DefaultRootWindow(mydisplay), &detail_win, getColorResource(resourceDB, catlist(myname, ".detailWin.foreground", (char*) NULL), "Xofm.DetailWin.Foreground", fg), getColorResource(resourceDB, catlist(myname, ".detailWin.background", (char*) NULL), "Xofm.DetailWin.Background", bg)); /* *** set up the properties for the window. *** */ XSetStandardProperties (mydisplay, detail_win.win, detail_win.text, detail_win.text, None, argv, argc, &szhint); XSetClassHint(mydisplay, detail_win.win, &clshint); XSetWMHints(mydisplay, detail_win.win, &wmhints); XMapRaised (mydisplay, detail_win.win); } /* *********************************************************************** */ /* *********************** create a single window ************************ */ /* *********************************************************************** */ void create_window (parent_win, this_win, foreg, backg) Window parent_win; WinTypePtr this_win; unsigned long foreg, backg; { /* *** Create Actual Window *** */ this_win->win = XCreateSimpleWindow (mydisplay, parent_win, this_win->x, this_win->y, this_win->width, this_win->height, this_win->line_thick, foreg, backg); if (!this_win->win) { fprintf (stderr, "Error creating Simple Window %s ... Exiting.\n", this_win->text); exit (1); } #ifdef DEBUG fprintf (stdout, "Created Simple Window %s (%d) %d %d %d %d\n", this_win->text, this_win->win, this_win->x, this_win->y, this_win->width, this_win->height, this_win->line_thick); #endif /* *** set Graphics Content creation and initialize *** */ this_win->gc = XCreateGC (mydisplay, this_win->win, 0, 0); if (! this_win->gc) { fprintf (stderr, "Error creating GC for %s ... Exiting.\n", this_win->text); exit (1); } #ifdef DEBUG fprintf (stdout, "Created GC %d\n", this_win->gc); #endif XSetBackground (mydisplay, this_win->gc, backg); XSetForeground (mydisplay, this_win->gc, foreg); if (this_win->font_info != 0) XSetFont(mydisplay, this_win->gc, this_win->font_info->fid); this_win->fg = foreg; this_win->bg = backg; /* *** specify which input we want this window to process *** */ XSelectInput (mydisplay, this_win->win, this_win->event_mask); } /* *********************************************************************** */ /* highlight menu item (window) in response to a mouse entering or leaving */ /* *********************************************************************** */ int highlight_menu (menu, menu_num,highlight) WinType menu[]; int menu_num; int highlight; { int i, state=NOGOOD; /* *** figure out which menu *** */ for (i = 0; i < menu_num; i++) if (myevent.xcrossing.window == menu[i].win) { state = i; i = menu_num; } /* *** check if menu is valid and change fg & bg *** */ if (state >= 0 && state < menu_num) { if (highlight) { #ifdef DEBUG fprintf(stdout, "Enter state in button %s\n", menu[state].text); #endif XSetBackground (mydisplay, menu[state].gc, fg); XSetForeground (mydisplay, menu[state].gc, bg); } else { #ifdef DEBUG fprintf (stdout, "Exit state in button %s\n", menu[state].text); #endif XSetBackground (mydisplay, menu[state].gc, bg); XSetForeground (mydisplay, menu[state].gc, fg); } for (i = 0; i < menu_num; ++i) XDrawImageString (mydisplay, menu[i].win, menu[i].gc, 1, LETTER_ASCENT(menu[i]), menu[i].text, strlen(menu[i].text)); return (state); } else return (NOGOOD); } /* *********************************************************************** */ /* ************** redraw the string in an exposed window ***************** */ /* *********************************************************************** */ int expose_win (menu, menu_num) WinType menu[]; int menu_num; { int i; for (i = 0; i < menu_num; i++) { if (myevent.xexpose.window == menu[i].win) { XDrawImageString (mydisplay, menu[i].win, menu[i].gc, 1, LETTER_ASCENT(menu[i]), menu[i].text, strlen(menu[i].text)); return (FALSE); } } return (TRUE); } /* *********************************************************************** */ /* *********************** destroy an entire menu *********************** */ /* *********************************************************************** */ void destroy_menu (menu, menu_num) WinType menu[]; int menu_num; { int i; for (i=0; i DisplayWidth(mydisplay, DefaultScreen(mydisplay))) { width = DisplayWidth(mydisplay, DefaultScreen(mydisplay))-1; if (verbose) fprintf (stderr, "Specified width too \ large ... adjusting to maximum size\n"); } main_win.width = width; main_win.flags = USPosition; geom_used=TRUE; } if (HeightValue & flags) { if (height < ((MIN_INTERVAL(main_win)*NFS)+BEGIN_NFS(main_win))) { height = ((MIN_INTERVAL(main_win)*NFS)+ BEGIN_NFS(main_win)); if (verbose) fprintf (stderr, "Specified height too \ small ... adjusting to minimum size\n"); } else if (height > DisplayHeight(mydisplay, DefaultScreen(mydisplay))) { height = DisplayHeight(mydisplay, DefaultScreen(mydisplay))-1; if (verbose) fprintf (stderr, "Specified height too \ large ... adjusting to maximum size\n"); } main_win.height = height; main_win.flags = USPosition; geom_used=TRUE; } } for (i = 0; i < MENU_ITEMS; i++) { strcpy(menu[i].text, Menu_Text[i]); menu[i].font_info = main_win.font_info; menu[i].width = SM_MENU_WIDTH(menu[i]); menu[i].height = MENU_HEIGHT(menu[i]); menu[i].x = ((main_win.width - menu[i].width) / 2); menu[i].y = MENU_Y + MENU_HEIGHT(menu[i]) * i; if (menu_border) menu[i].line_thick = 1; else menu[i].line_thick = 0; menu[i].event_mask = big_event_mask; } for (i = 0; i < MAXFS; i++) { fs_win[i].font_info = main_win.font_info; fs_win[i].line_thick = fs_border; fs_win[i].event_mask = fs_mask; } for (i = 0; i < NFS; i++) { fs_win[i].x = OFF_X; if (geom_used) { ppnfs = ((main_win.height-BEGIN_NFS(main_win)) / NFS); set_fs_win_size (i, ppnfs); } else if (minimize) { fs_win[i].y = ((MIN_INTERVAL(fs_win[i]) * i) + BEGIN_NFS(fs_win[i])); fs_win[i].height = MIN_MENU_HEIGHT; } else { fs_win[i].y = ((INTERVAL(fs_win[i]) * i) + BEGIN_NFS(fs_win[i])); fs_win[i].height = MENU_HEIGHT(fs_win[i]); } fs_win[i].width = main_win.width - OFF_X * 2; } sprintf (detail_win.text, "%s detail", hname); detail_win.x = OFF_X; detail_win.y = OFF_Y; detail_win.font_info = getFontResource(resourceDB, catlist(myname, ".detailWin.font", (char*) NULL), "Xfsm.DetailWin.Font", def_font); detail_win.width = DETAIL_X; detail_win.height = DETAIL_Y; detail_win.line_thick = border_width; detail_win.event_mask = small_event_mask; detail_win.flags = PPosition; if (XrmGetResource(resourceDB, catlist(myname, ".detailWin.geometry", (char*) NULL), "Xfsm.DetailWin.Geometry", &str_type, &value)) { flags = XParseGeometry(value.addr, &x, &y, &width, &height); if (XValue & flags) { if (XNegative & flags) x = DisplayWidth(mydisplay, DefaultScreen(mydisplay)) + x - detail_win.width - 2 * detail_win.line_thick; detail_win.x = x; detail_win.flags = USPosition; } if (YValue & flags) { if (YNegative & flags) y = DisplayHeight(mydisplay, DefaultScreen(mydisplay)) + y - detail_win.height - 2 * detail_win.line_thick; detail_win.y = y; detail_win.flags = USPosition; } } /* *** 4 spaces (3 digits + 1 %) + 1 space *** */ percent_width = XTextWidth(main_win.font_info, "9999%", 5); } /* ***************************************************************** */ /* ********** Returns the value of the given bool resource ********** */ /* ***************************************************************** */ Bool getBoolResource(db, str_name, str_class, deflt) XrmDatabase db; char* str_name; char* str_class; Bool deflt; { XrmString str_type; XrmValue value; if (XrmGetResource(db, str_name, str_class, &str_type, &value)) { return ((!strcmp(value.addr, "true")) || (!strcmp(value.addr, "True")) || (!strcmp(value.addr, "TRUE")) || (!strcmp(value.addr, "yes")) || (!strcmp(value.addr, "Yes")) || (!strcmp(value.addr, "YES")) || (!strcmp(value.addr, "on")) || (!strcmp(value.addr, "On")) || (!strcmp(value.addr, "ON")) || (!strcmp(value.addr, "1"))); } else return (deflt); } /* ***************************************************************** */ /* ********** Returns the value of the given int resource ********** */ /* ***************************************************************** */ int getIntResource(db, str_name, str_class, deflt) XrmDatabase db; char* str_name; char* str_class; int deflt; { XrmString str_type; XrmValue value; if (XrmGetResource(db, str_name, str_class, &str_type, &value)) return (atoi(value.addr)); else return (deflt); } /* ***************************************************************** */ /* ********** Returns the value of the given Font resource ********* */ /* ***************************************************************** */ XFontStruct* getFontResource(db, str_name, str_class, deflt) XrmDatabase db; char* str_name; char* str_class; XFontStruct* deflt; { XrmString str_type; XrmValue value; if (XrmGetResource(db, str_name, str_class, &str_type, &value)) { XFontStruct* font = XLoadQueryFont(mydisplay, value.addr); if (font == NULL) { fprintf(stderr, "Could not load font \"%s\".\n", value.addr); return (deflt); } else return (font); } else return (deflt); } /* ***************************************************************** */ /* ********** Returns the value of the given color resource ******** */ /* ***************************************************************** */ unsigned long getColorResource(db, str_name, str_class, deflt) XrmDatabase db; char* str_name; char* str_class; unsigned long deflt; { XrmString str_type; XrmValue value; if (XrmGetResource(db, str_name, str_class, &str_type, &value)) { XColor screen_def; if (XParseColor(mydisplay, DefaultColormapOfScreen (DefaultScreenOfDisplay(mydisplay)), value.addr, &screen_def) == 0 || XAllocColor(mydisplay, DefaultColormapOfScreen (DefaultScreenOfDisplay(mydisplay)), &screen_def) == 0) { fprintf(stderr, "Color specification \"%s\" invalid.\n", value.addr); return (deflt); } else return (screen_def.pixel); } else return (deflt); } /* ***************************************************************** */ /* ********** Returns the concatenation of the NULL ********** */ /* ********** terminated list of strings. ********** */ /* ***************************************************************** */ #ifdef __STDC__ #if NeedFunctionPrototypes char* catlist(char *str1, ...) #else char* catlist(str1) char* str1; #endif /* NeedFunctionPrototypes */ { static char blocks[2][64]; static int current = 0; va_list ap; char* c; strcpy(blocks[current], str1); va_start(ap, str1); while ((c = va_arg(ap, char*)) != NULL) strcat(blocks[current], c); va_end(ap); c = blocks[current]; current = (current + 1) % 2; return c; } #else char* catlist(va_alist) va_dcl { static char blocks[2][64]; static int current = 0; va_list ap; char* c; va_start(ap); blocks[current][0] = '\0'; while ((c = va_arg(ap, char*)) != NULL) strcat(blocks[current], c); va_end(ap); c = blocks[current]; current = (current + 1) % 2; return c; } #endif /* __STDC__ */ #if defined (DYNIX) || defined (MACH) /* *** for some reason DYNIX does not have strstr *** */ /* Copyright (C) 1991, 1992 Free Software Foundation, Inc. */ /* This file is part of the GNU C Library. */ /* Return the first ocurrence of NEEDLE in HAYSTACK. */ #ifdef __STDC__ char *strstr (const char* haystack, const char* needle) #else char *strstr (haystack, needle) char *haystack, *needle; #endif { char *needle_end = strchr(needle, '\0'); char *haystack_end = strchr(haystack, '\0'); size_t needle_len = needle_end - needle; size_t needle_last = needle_len - 1; char *begin; if (needle_len == 0) return (char *) haystack_end; if ((size_t) (haystack_end - haystack) < needle_len) return NULL; for (begin = &haystack[needle_last]; begin < haystack_end; ++begin) { char *n = &needle[needle_last]; char *h = begin; do if (*h != *n) goto loop; /* continue for loop */ while (--n >= needle && --h >= haystack); return (char *) h; loop:; } return NULL; } #endif /* DYNIX || MACH */ /* This routine clears the fs_warn[] flags for all of the currently active * file systems. This is done in a separate routine so that popup warnings * stay active until the "Update Now" button is pressed. Otherwise, every * update pass (default is 1 per minute) will clear the popup warning field. * When that happens, you can't tell what caused the popup if you've left it * on overnight!! So, we now only clear the popup warning field when pressing * the "Update Now" button. */ void clear_fs_warn_flags() { int i; for (i=0; i