/* xapm.c -- * Created: Tue Jan 9 21:23:09 1996 by r.faith@ieee.org * Revised: Sun Apr 21 16:37:44 1996 by r.faith@ieee.org * Copyright 1996 Rickard E. Faith (r.faith@ieee.org) * * Modified: Fri Mar 26 11:26:00 1999 by bill.mair@bm-soft.com * Added support for IBM ThinkPad charging options * Added option display of AC/Battery useage * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include #include #include #include #include #include "apm.h" typedef struct _instance_variables { Pixel highColor; Pixel lowColor; Pixel criticalColor; Pixel chargingColor; Pixel foreground; int highValue; int lowValue; String geometry; int delay; Boolean displayPercent; } instance_variable_rec; static XtAppContext app_context; static Widget scrollbar; static Widget topLevel; static Widget command; static XtIntervalId timerId; static instance_variable_rec iv; static int debug; /* Bill Mair, 26.03.1999 ----> */ #define IBM_THINKPAD 0 /* ThinkPads use the battery_flags to indicate charging */ #define SHOW_AC_BAT_STATUS 1 #define DEBUG_UPDATE 0 #if IBM_THINKPAD == 1 #define TP_CHARGE_FLAG 0x08 /* This works on the TP770X but may be different on other TPs */ #endif #if SHOW_AC_BAT_STATUS == 1 #define CHAR_COUNT 5 #else #define CHAR_COUNT 4 #endif /* <---- Bill Mair, 26.03.1999 */ static void update(XtPointer client_data, XtIntervalId * id) { apm_info i; char buf[128]; static int pixel = -1; static int lpixel = -1; static int bpixel = -1; static int lastPercentage = -1; static int lastMinutes = -1; static int lastDisplay = -1; static int count = 0; #if SHOW_AC_BAT_STATUS == 1 static int lastACStatus = -1; #endif apm_read(&i); #if DEBUG_UPDATE == 1 /* BM: Added this to display all of the APM flags */ if (debug) { printf("\nxapm update\n"); printf(" apm_flags: %d\n", i.apm_flags); printf(" ac_line_status: %d\n", i.ac_line_status); printf(" battery_status: %d\n", i.battery_status); printf(" battery_flags: %d\n", i.battery_flags); printf(" battery_percentage: %d\n", i.battery_percentage); printf(" battery_time: %d\n", i.battery_time); printf(" using_minutes: %d\n", i.using_minutes); } #endif if (iv.displayPercent) { if (lastDisplay != iv.displayPercent || i.battery_percentage != lastPercentage #if SHOW_AC_BAT_STATUS == 1 || i.ac_line_status != lastACStatus #endif ) { /* lastPercentage updated at end */ #if SHOW_AC_BAT_STATUS == 1 sprintf(buf, "%s%d%%", i.ac_line_status ? "P" : "B", i.battery_percentage); #else sprintf(buf, "%d%%", i.battery_percentage); #endif XtVaSetValues(command, XtNlabel, buf, NULL); } } else { /* int minutes = i.using_minutes ? i.battery_time : i.battery_time / 60;*/ int minutes = i.battery_percentage * 2 ; if (lastDisplay != iv.displayPercent || lastMinutes != minutes #if SHOW_AC_BAT_STATUS == 1 || i.ac_line_status != lastACStatus #endif ) { lastMinutes = minutes; #if SHOW_AC_BAT_STATUS == 1 sprintf(buf, "%s%s", i.ac_line_status ? "P" : "B", apm_time_nosec(minutes * 60)); #else sprintf(buf, "%s", apm_time_nosec(minutes * 60)); #endif XtVaSetValues(command, XtNlabel, buf, NULL); } } lastDisplay = iv.displayPercent; #if SHOW_AC_BAT_STATUS == 1 lastACStatus = i.ac_line_status; #endif if (i.battery_percentage <= iv.lowValue) { if (pixel != iv.criticalColor) XtVaSetValues(scrollbar, XtNforeground, pixel = iv.criticalColor, NULL); if (bpixel != iv.criticalColor) XtVaSetValues(scrollbar, XtNborderColor, bpixel = iv.criticalColor, NULL); } else if (i.battery_percentage <= iv.highValue) { if (pixel != iv.lowColor) XtVaSetValues(scrollbar, XtNforeground, pixel = iv.lowColor, NULL); if (bpixel != iv.foreground) XtVaSetValues(scrollbar, XtNborderColor, bpixel = iv.foreground, NULL); } else { if (pixel != iv.highColor) XtVaSetValues(scrollbar, XtNforeground, pixel = iv.highColor, NULL); if (i.battery_percentage == 100) { if (bpixel != iv.highColor) XtVaSetValues(scrollbar, XtNborderColor, bpixel = iv.highColor, NULL); } else { if (bpixel != iv.foreground) XtVaSetValues(scrollbar, XtNborderColor, bpixel = iv.foreground, NULL); } } if (debug) printf("scrollbar color = %d\n", pixel); if (i.battery_status == 3 #if IBM_THINKPAD == 1 || (i.battery_flags & TP_CHARGE_FLAG) #endif ) { if (lpixel != iv.chargingColor) XtVaSetValues(command, XtNforeground, lpixel = iv.chargingColor, NULL); } else { if (i.battery_percentage < iv.lowValue && count++ % 2) { if (lpixel != iv.criticalColor) XtVaSetValues(command, XtNforeground, lpixel = iv.criticalColor, NULL); } else { if (lpixel != iv.foreground) XtVaSetValues(command, XtNforeground, lpixel = iv.foreground, NULL); } } if (debug) printf("command color = %d, status = %d\n", lpixel, i.battery_status); if (i.battery_percentage != lastPercentage) XawScrollbarSetThumb(scrollbar, 0.0, i.battery_percentage < 0 ? 0.0 : i.battery_percentage / 100.0); lastPercentage = i.battery_percentage; timerId = XtAppAddTimeOut(app_context, 1000 * iv.delay + 500, update, app_context); } static void press(Widget w, XtPointer client_data, XtPointer call_data) { iv.displayPercent = !iv.displayPercent; XtRemoveTimeOut(timerId); timerId = XtAppAddTimeOut(app_context, 0, update, app_context); if (debug) printf("displayPercent = %d\n", iv.displayPercent); } static XrmOptionDescRec options[] = { {"-highcolor", "*highColor", XrmoptionSepArg, NULL}, {"-lowcolor", "*lowColor", XrmoptionSepArg, NULL}, {"-criticalcolor", "*criticalColor", XrmoptionSepArg, NULL}, {"-chargingcolor", "*chargingColor", XrmoptionSepArg, NULL}, {"-highvalue", "*highValue", XrmoptionSepArg, NULL}, {"-lowvalue", "*lowValue", XrmoptionSepArg, NULL}, {"-delay", "*delay", XrmoptionSepArg, NULL}, {"-percent", "*percent", XrmoptionNoArg, (XtPointer) "true"}, }; #define offset(field) XtOffsetOf( instance_variable_rec, field ) static XtResource resources[] = { {"highColor", XtCForeground, XtRPixel, sizeof(Pixel), offset(highColor), XtRString, "green"}, {"lowColor", XtCForeground, XtRPixel, sizeof(Pixel), offset(lowColor), XtRString, "yellow"}, {"criticalColor", XtCForeground, XtRPixel, sizeof(Pixel), offset(criticalColor), XtRString, "red"}, {"chargingColor", XtCForeground, XtRPixel, sizeof(Pixel), offset(chargingColor), XtRString, "blue"}, {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), offset(foreground), XtRString, XtDefaultForeground}, {"highValue", XtCValue, XtRInt, sizeof(int), offset(highValue), XtRImmediate, (XtPointer) 50}, {"lowValue", XtCValue, XtRInt, sizeof(int), offset(lowValue), XtRImmediate, (XtPointer) 10}, {"geometry", XtCString, XtRString, sizeof(String), offset(geometry), XtRString, (XtPointer) "10x100"}, {"delay", XtCValue, XtRInt, sizeof(int), offset(delay), XtRImmediate, (XtPointer) 1}, {"percent", XtCValue, XtRBoolean, sizeof(Boolean), offset(displayPercent), XtRImmediate, (XtPointer) FALSE}, }; int main(int argc, char **argv) { Cursor cursor; int c; Widget form; XFontStruct *fs; int fontWidth, fontHeight; int x = 0, y = 0, height = 10, width = 100; switch (apm_exists()) { case 1: fprintf(stderr, "No APM support in kernel\n"); exit(1); case 2: fprintf(stderr, "Old APM support in kernel\n"); exit(2); } topLevel = XtVaAppInitialize(&app_context, "XApm", options, XtNumber(options), &argc, argv, NULL, NULL); XtGetApplicationResources(topLevel, &iv, resources, XtNumber(resources), NULL, 0); if (iv.delay < 1) iv.delay = 1; XParseGeometry(iv.geometry, &x, &y, &width, &height); while ((c = getopt(argc, argv, "DV")) != -1) switch (c) { case 'D': ++debug; break; case 'V': fprintf(stderr, "apmd version %s\n", VERSION); exit(0); break; } if (debug) { printf("highColor = %ld\n", iv.highColor); printf("lowColor = %ld\n", iv.lowColor); printf("criticalColor = %ld\n", iv.criticalColor); printf("chargingColor = %ld\n", iv.chargingColor); printf("foreground = %ld\n", iv.foreground); printf("highValue = %d\n", iv.highValue); printf("lowValue = %d\n", iv.lowValue); printf("geometry = %s\n", iv.geometry); } cursor = XCreateFontCursor(XtDisplay(topLevel), XC_top_left_arrow); form = XtVaCreateManagedWidget("form", formWidgetClass, topLevel, XtNorientation, XtorientHorizontal, XtNborderWidth, 0, XtNdefaultDistance, 2, NULL); command = XtVaCreateManagedWidget("command", commandWidgetClass, form, XtNleft, XtChainLeft, XtNhighlightThickness, 0, XtNinternalHeight, 0, XtNinternalWidth, 0, XtNborderWidth, 0, XtNlabel, "", XtNresize, FALSE, NULL); XtVaGetValues(command, XtNfont, &fs, NULL); fontWidth = fs->max_bounds.width; fontHeight = fs->max_bounds.ascent + fs->max_bounds.descent; XtVaSetValues(command, XtNwidth, fontWidth * CHAR_COUNT, NULL); if (debug) { int tmp = (width > fontWidth * CHAR_COUNT - 6) ? width - fontWidth * CHAR_COUNT - 6 : fontWidth * CHAR_COUNT; printf("width = %d, using %d + %d = %d\n", width, fontWidth * CHAR_COUNT, tmp, fontWidth * CHAR_COUNT + tmp); } scrollbar = XtVaCreateManagedWidget("scrollbar", scrollbarWidgetClass, form, XtNhorizDistance, 3, XtNfromHoriz, command, XtNorientation, XtorientHorizontal, XtNscrollHCursor, cursor, XtNthickness, fontHeight, XtNlength, /* the following lines commented to make the bar minimal (width > fontWidth * CHAR_COUNT - 6) ? width - fontWidth * CHAR_COUNT - 6 : fontWidth * CHAR_COUNT, */ 1, NULL); XawScrollbarSetThumb(scrollbar, 0.0, 0.0); XtVaSetValues(scrollbar, XtNtranslations, XtParseTranslationTable(""), NULL); XtAddCallback(command, XtNcallback, press, NULL); XtRealizeWidget(topLevel); timerId = XtAppAddTimeOut(app_context, 0, update, app_context); XtAppMainLoop(app_context); return 0; }