--- /dev/null
+/* xacpi.c --
+ *
+ * This is a patched xapm working with acpi (which does not support
+ * apm anymore)
+ *
+ * xapm was written and (C) by Rickard E. Faith (r.faith@ieee.org)
+ *
+ * 2004/06/10 Patch for acpi by Francois Fleuret (francois.fleuret@epfl.ch)
+ * 2004/07/20 Patch from Bryan Cardillo (dillo@seas.upenn.edu)
+ *
+ * To compile:
+ *
+ * gcc -DNARROWPROTO -o xacpi -L /usr/X11R6/lib/ -lX11 -lXaw xacpi.c
+ *
+ * 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.
+ *
+ * $Id: xacpi.c,v 1.40 2004/12/03 07:52:30 fleuret Exp $
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <err.h>
+#include <time.h>
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/cursorfont.h>
+#include <X11/Xaw/Form.h>
+#include <X11/Xaw/Command.h>
+#include <X11/Xaw/Scrollbar.h>
+
+/* The acpi file readings can fail sometime, but we will immediately
+ retry. We display ERR in the window if we fail more than that
+ number of times . */
+
+#define NB_TOLERATED_FAILURES 1
+
+#define XACPI_VERSION "1.3"
+#define MIN_BAR_WIDTH 32
+
+#define DEFAULT_ACPI_DIR "/proc/acpi"
+#define DEFAULT_CPUFREQ_DIR "/sys/devices/system/cpu/cpu0/cpufreq"
+
+#define BUFFER_LEN 1024
+
+#define DEFAULT_DELAY 5
+#define DEFAULT_DATE_FORMAT "%a %b %e %H:%M:%S %Z %Y"
+
+typedef struct _instance_variables {
+ Pixel highColor, lowColor, criticalColor, chargingColor;
+ Pixel foreground;
+ int highValue, lowValue, criticalTemp;
+ String geometry;
+ int delay;
+ Boolean displayPercent, displayPercentAuto;
+ Boolean showBar, showTemperature;
+ Boolean showCpufreq;
+ String cpuFreqDir;
+ String dateFormat;
+ Boolean showDate;
+ Boolean fahrenheit;
+ String acpiDir;
+} instance_variable_rec;
+
+struct acpi_info {
+ int design_capacity, last_full_capacity, remaining_capacity;
+ int present_rate;
+ int ac_on_line;
+ int charging;
+ int battery_percentage, battery_time;
+ int temperature;
+ int cpufreq;
+};
+
+static XtAppContext app_context;
+static Widget scrollbar;
+static Widget topLevel;
+static Widget form;
+static Widget delay;
+static Widget temperature;
+static Widget cpufreq;
+static Widget date;
+static XtIntervalId timerId;
+static instance_variable_rec iv;
+static int debug;
+
+static int nb_failures;
+
+char *get_field_name(char *buffer, char *r) {
+ while(*r && *r != ':') *(buffer++) = *(r++);
+ while(*r == ' ' || *r == ':') r++;
+ *(buffer++) = '\0';
+ return r;
+}
+
+int get_int(char *r) {
+ char tmp[BUFFER_LEN];
+ char *t = tmp;
+ while(*r >= '0' && *r <= '9') *(t++) = *(r++);
+ *t = '\0';
+ return atoi(tmp);
+}
+
+char *goto_next_line(char *r) {
+ while(*r && *r != '\n') r++;
+ while(*r == '\n') r++;
+ if(*r) return r; else return 0;
+}
+
+/* We make the assumption that the file is shorter than BUFFER_LEN
+ bytes. */
+
+void read_proc_file(char *path, char *subdir, char *filename, char *content) {
+ char name[BUFFER_LEN];
+ size_t len;
+ FILE *file;
+
+ snprintf(name, BUFFER_LEN, "%s/%s/%s", path, subdir, filename);
+
+ file = fopen(name, "r");
+ if(file) {
+#ifdef DEBUG
+ printf("reading of [%s]\n", name);
+#endif
+ len = fread(content, 1, BUFFER_LEN - 1, file);
+ fclose(file);
+ } else {
+#ifdef DEBUG
+ printf("opening of [%s] failed\n", name);
+#endif
+ len = 0;
+ }
+
+ if(len == 0) {
+ err(1, "%s", name);
+#ifdef DEBUG
+ printf("reading of [%s] failed\n", name);
+#endif
+ }
+ else content[len] = '\0';
+}
+
+void check_acpi(char *acpi_dir) {
+ DIR *directory;
+
+ directory= opendir(acpi_dir);
+ if(directory) closedir(directory);
+ else err(1, "%s", acpi_dir);
+}
+
+void acpi_read(char *acpi_dir, char *cpu_dir, struct acpi_info *acpi) {
+ DIR *directory;
+ struct dirent *dir_entry;
+ char content[BUFFER_LEN], word[BUFFER_LEN], dir_name[BUFFER_LEN];
+
+ int error = 0;
+
+ memset(acpi, 0, sizeof(*acpi));
+
+ /* Read the battery information */
+
+ snprintf(dir_name, BUFFER_LEN, "%s/battery", acpi_dir);
+ directory = opendir(dir_name);
+ if (!(directory)) err(1, "%s", dir_name);
+
+ while((dir_entry = readdir(directory))) {
+ if(dir_entry->d_name[0] != '.') {
+ char *s;
+
+ read_proc_file(dir_name, dir_entry->d_name, "info", content);
+
+ s = content;
+ while(s) {
+ s = get_field_name(word, s);
+
+ if(strcmp(word, "ERROR") == 0) {
+#ifdef DEBUG
+ printf("Read \"ERROR\"\n");
+#endif
+ error = 1;
+ }
+
+ else if(strcmp(word, "design capacity") == 0 && s) acpi->design_capacity += get_int(s);
+ else if(strcmp(word, "last full capacity") == 0 && s) acpi->last_full_capacity += get_int(s);
+ s = goto_next_line(s);
+ }
+
+ read_proc_file(dir_name, dir_entry->d_name, "state", content);
+ s = content;
+ while(s) {
+ s = get_field_name(word, s);
+ if(strcmp(word, "ERROR") == 0) {
+#ifdef DEBUG
+ printf("Read \"ERROR\"\n");
+#endif
+ error = 1;
+ }
+
+ else if(strcmp(word, "present rate") == 0 && s) acpi->present_rate += get_int(s);
+ else if(strcmp(word, "remaining capacity") == 0 && s) acpi->remaining_capacity += get_int(s);
+ else if(strcmp(word, "charging state") == 0 && s) {
+ if(strncmp(s, "charging", 8) == 0) acpi->charging = 1;
+ else if(strncmp(s, "charged", 7) == 0) acpi->charging = 0;
+ else if(strncmp(s, "discharging", 11) == 0) acpi->charging = -1;
+ }
+ s = goto_next_line(s);
+ }
+ }
+ }
+
+ closedir(directory);
+
+ /* Read the AC line information */
+
+ snprintf(dir_name, BUFFER_LEN, "%s/ac_adapter", acpi_dir);
+ directory = opendir(dir_name);
+ if (!(directory)) err(1, "%s", dir_name);
+
+ while((dir_entry = readdir(directory))) {
+ if(dir_entry->d_name[0] != '.') {
+ char *s;
+ read_proc_file(dir_name, dir_entry->d_name, "state", content);
+ s = content;
+ while(s) {
+ s = get_field_name(word, s);
+ if(strcmp(word, "ERROR") == 0) {
+#ifdef DEBUG
+ printf("Read \"ERROR\"\n");
+#endif
+ error = 1;
+ }
+
+ else if(strcmp(word, "state") == 0 && s)
+ acpi->ac_on_line = (strncmp(s, "on-line", 7) == 0);
+ s = goto_next_line(s);
+ }
+ }
+ }
+
+ closedir(directory);
+
+ /* When required, read the temperature information */
+
+ if(temperature) {
+ snprintf(dir_name, BUFFER_LEN, "%s/thermal_zone", acpi_dir);
+ directory = opendir(dir_name);
+ if (!(directory)) err(1, "%s", dir_name);
+
+ acpi->temperature = -1;
+
+ while((dir_entry = readdir(directory))) {
+ if(dir_entry->d_name[0] != '.') {
+ char *s;
+ read_proc_file(dir_name, dir_entry->d_name, "temperature", content);
+ s = content;
+ while(s) {
+ s = get_field_name(word, s);
+ if(strcmp(word, "ERROR") == 0) {
+#ifdef DEBUG
+ printf("Read \"ERROR\"\n");
+#endif
+ error = 1;
+ }
+
+ else if(strcmp(word, "temperature") == 0 && s) {
+ int temp = get_int(s);
+ if(temp > acpi->temperature) acpi->temperature = temp;
+ }
+ s = goto_next_line(s);
+ }
+ }
+ }
+
+ closedir(directory);
+ }
+
+ /* When required, read the frequency information */
+
+ if(cpufreq) {
+ read_proc_file(cpu_dir, "", "scaling_cur_freq", content);
+ char *s = content;
+ acpi->cpufreq = get_int(s)/1000;
+ }
+
+ if(error) nb_failures++; else nb_failures = 0;
+
+ if(nb_failures == 0) {
+
+ // Bryan Cardillo preferes to see the percentage of the design
+ // capacity. I think it's kind of depressive to see that the
+ // battery gets worst and worst ...
+
+ /* if (acpi->charging == 0) { */
+ /* acpi->battery_percentage = (acpi->remaining_capacity * 100) / acpi->design_capacity; */
+ /* } else { */
+ acpi->battery_percentage = (acpi->remaining_capacity * 100) / acpi->last_full_capacity;
+ /* } */
+
+ if(acpi->present_rate) {
+ if(acpi->charging > 0)
+ acpi->battery_time = ((acpi->last_full_capacity - acpi->remaining_capacity) * 3600) / acpi->present_rate;
+ else if(acpi->charging < 0)
+ acpi->battery_time = (acpi->remaining_capacity * 3600) / acpi->present_rate;
+ }
+ } else if(nb_failures > NB_TOLERATED_FAILURES) {
+ acpi->battery_time = -1;
+ }
+}
+
+void put_date(char *buf, char *format) {
+ time_t t;
+ time(&t);
+ strftime(buf, BUFFER_LEN, format, localtime(&t));
+}
+
+static void update(XtPointer client_data, XtIntervalId * id) {
+ struct acpi_info acpi;
+ char buf[128];
+
+ static int current_bar_color = -1;
+ static int current_charging_color = -1;
+ static int current_temperature_color = -1;
+ static int blink_counter = 0;
+
+ static int lastPercentage = -1;
+ static int lastMinutes = -1;
+ static int lastDisplay = -1;
+ static int lastACStatus = -1;
+ static int lastTemperature = -1;
+ static int lastCpufreq = -1;
+
+ acpi_read(iv.acpiDir, iv.cpuFreqDir, &acpi);
+
+ if(nb_failures > NB_TOLERATED_FAILURES) {
+
+ XtVaSetValues(delay, XtNlabel, "ERR", NULL);
+
+ if(scrollbar && current_bar_color != iv.criticalColor) {
+ current_bar_color = iv.criticalColor;
+ XtVaSetValues(scrollbar, XtNforeground, current_bar_color, NULL);
+ XtVaSetValues(scrollbar, XtNborderColor, current_bar_color, NULL);
+ }
+
+ /* All this will have to be refreshed */
+
+ lastPercentage = -1;
+ lastMinutes = -1;
+ lastDisplay = -1;
+ blink_counter = 0;
+ lastACStatus = -1;
+ lastTemperature = -1;
+ lastCpufreq = -1;
+
+ }
+
+ /* We refresh only if there were no error during updating */
+
+ else if(nb_failures == 0) {
+
+ if(iv.displayPercentAuto && acpi.ac_on_line != lastACStatus){
+ lastDisplay = -1;
+ iv.displayPercent = acpi.ac_on_line;
+ }
+
+ if (iv.displayPercent) {
+ if (lastDisplay != iv.displayPercent
+ || acpi.battery_percentage != lastPercentage
+ || acpi.ac_on_line != lastACStatus) {
+
+ /* lastPercentage updated at end */
+
+ snprintf(buf, BUFFER_LEN, "%s%d%%", acpi.ac_on_line ? "L" : "B", acpi.battery_percentage);
+ XtVaSetValues(delay, XtNlabel, buf, NULL);
+ }
+ } else {
+
+ /* Negative value means we could not estimate it in acpi_read
+ because the charging speed was 0 */
+
+ if(acpi.battery_time < 0) {
+ snprintf(buf, BUFFER_LEN, "%s", acpi.ac_on_line ? "L" : "B???");
+ XtVaSetValues(delay, XtNlabel, buf, NULL);
+
+ } else {
+
+ int minutes = acpi.battery_time / 60;
+ if (lastDisplay != iv.displayPercent || lastMinutes != minutes
+ || acpi.ac_on_line != lastACStatus
+ ) {
+ lastMinutes = minutes;
+ snprintf(buf, BUFFER_LEN, "%s%lu:%02lu", acpi.ac_on_line ? "L" : "B", minutes/60, minutes%60);
+ XtVaSetValues(delay, XtNlabel, buf, NULL);
+ }
+
+ }
+ }
+
+ lastDisplay = iv.displayPercent;
+ lastACStatus = acpi.ac_on_line;
+
+ if(scrollbar) {
+ if (acpi.battery_percentage <= iv.lowValue) {
+ if (current_bar_color != iv.criticalColor) {
+ current_bar_color = iv.criticalColor;
+ XtVaSetValues(scrollbar, XtNforeground, current_bar_color, NULL);
+ XtVaSetValues(scrollbar, XtNborderColor, current_bar_color, NULL);
+ }
+ } else if (acpi.battery_percentage <= iv.highValue) {
+ if (current_bar_color != iv.lowColor) {
+ current_bar_color = iv.lowColor;
+ XtVaSetValues(scrollbar, XtNforeground, current_bar_color, NULL);
+ XtVaSetValues(scrollbar, XtNborderColor, current_bar_color, NULL);
+ }
+ } else {
+ if (current_bar_color != iv.highColor) {
+ current_bar_color = iv.highColor;
+ XtVaSetValues(scrollbar, XtNforeground, current_bar_color, NULL);
+ XtVaSetValues(scrollbar, XtNborderColor, current_bar_color, NULL);
+ }
+ }
+ }
+
+ if(temperature) {
+ int degrees = (iv.fahrenheit) ?
+ 32 + (acpi.temperature * 18) / 10 : acpi.temperature;
+
+ if (degrees != lastTemperature) {
+ if(iv.fahrenheit) {
+ snprintf(buf, BUFFER_LEN, "%dF", degrees);
+ } else {
+ snprintf(buf, BUFFER_LEN, "%dC", degrees);
+ }
+ XtVaSetValues(temperature, XtNlabel, buf, NULL);
+ }
+
+ if(degrees >= iv.criticalTemp) {
+ if (current_temperature_color != iv.criticalColor) {
+ current_temperature_color = iv.criticalColor;
+ XtVaSetValues(temperature, XtNforeground, current_temperature_color, NULL);
+ }
+ } else {
+ if (current_temperature_color != iv.foreground) {
+ current_temperature_color = iv.foreground;
+ XtVaSetValues(temperature, XtNforeground, current_temperature_color, NULL);
+ }
+ }
+
+ lastTemperature = degrees;
+ }
+
+ if(cpufreq && acpi.cpufreq != lastCpufreq) {
+ snprintf(buf, BUFFER_LEN, "%.1fGhz", ((float) acpi.cpufreq)/1000.0);
+ XtVaSetValues(cpufreq, XtNlabel, buf, NULL);
+ }
+
+ if(date) {
+ put_date(buf, iv.dateFormat);
+ XtVaSetValues(date, XtNlabel, buf, NULL);
+ }
+
+ if (acpi.charging > 0) {
+ if (current_charging_color != iv.chargingColor)
+ XtVaSetValues(delay, XtNforeground,
+ current_charging_color = iv.chargingColor, NULL);
+ } else {
+ if (acpi.battery_percentage < iv.lowValue && blink_counter++ % 2) {
+ if (current_charging_color != iv.criticalColor)
+ XtVaSetValues(delay,
+ XtNforeground, current_charging_color = iv.criticalColor, NULL);
+ } else {
+ if (current_charging_color != iv.foreground)
+ XtVaSetValues(delay,
+ XtNforeground, current_charging_color = iv.foreground, NULL);
+ }
+ }
+
+ if (scrollbar && acpi.battery_percentage != lastPercentage) {
+ XawScrollbarSetThumb(scrollbar, 0.0,
+ acpi.battery_percentage < 0 ? 0.0 : acpi.battery_percentage / 100.0);
+ lastPercentage = acpi.battery_percentage;
+ }
+ }
+
+ /* We come back in 0.5s if there was an error */
+
+ timerId = XtAppAddTimeOut(app_context,
+ ((nb_failures > 0 && nb_failures <= NB_TOLERATED_FAILURES)) ? 250 : (1000 * iv.delay + 500),
+ update, app_context);
+}
+
+static void press(Widget w, XtPointer client_data, XtPointer call_data){
+ if (w == delay) {
+ iv.displayPercent = !iv.displayPercent;
+ } else if (w == temperature) {
+ iv.fahrenheit = !iv.fahrenheit;
+ }
+ XtRemoveTimeOut(timerId);
+ timerId = XtAppAddTimeOut(app_context, 0, update, app_context);
+}
+
+static XrmOptionDescRec options[] = {
+ {"-highcolor", "*highColor", XrmoptionSepArg, NULL},
+ {"-lowcolor", "*lowColor", XrmoptionSepArg, NULL},
+ {"-criticalcolor", "*criticalColor", XrmoptionSepArg, NULL},
+ {"-criticaltemperature", "*criticalTemperature", XrmoptionSepArg, NULL},
+ {"-chargingcolor", "*chargingColor", XrmoptionSepArg, NULL},
+ {"-highvalue", "*highValue", XrmoptionSepArg, NULL},
+ {"-lowvalue", "*lowValue", XrmoptionSepArg, NULL},
+ {"-delay", "*delay", XrmoptionSepArg, NULL},
+ {"-percent", "*percent", XrmoptionNoArg, (XtPointer) "true"},
+ {"-percentauto", "*percentAuto", XrmoptionNoArg, (XtPointer) "true"},
+ {"-showbar", "*showBar", XrmoptionNoArg, (XtPointer) "true"},
+ {"-showtemp", "*showTemperature", XrmoptionNoArg, (XtPointer) "true"},
+ {"-showcpufreq", "*showCpuFreq", XrmoptionNoArg, (XtPointer) "true"},
+ {"-showdate", "*showDate", XrmoptionNoArg, (XtPointer) "true"},
+ {"-fahrenheit", "*fahrenheit", XrmoptionNoArg, (XtPointer) "true"},
+ {"-dateformat", "*dateFormat", XrmoptionSepArg, NULL},
+ {"-acpidir", "*acpiDir", XrmoptionSepArg, NULL},
+ {"-cpufreqdir", "*cpuFreqDir", XrmoptionSepArg, NULL},
+};
+
+#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},
+ {"criticalTemperature", XtCValue, XtRInt, sizeof(int),
+ offset(criticalTemp), XtRImmediate, (XtPointer) 0},
+ {"geometry", XtCString, XtRString, sizeof(String),
+ offset(geometry), XtRString, (XtPointer) "170x10"},
+ {"delay", XtCValue, XtRInt, sizeof(int),
+ offset(delay), XtRImmediate, (XtPointer) DEFAULT_DELAY},
+ {"percent", XtCValue, XtRBoolean, sizeof(Boolean),
+ offset(displayPercent), XtRImmediate, (XtPointer) FALSE},
+ {"percentAuto", XtCValue, XtRBoolean, sizeof(Boolean),
+ offset(displayPercentAuto), XtRImmediate, (XtPointer) FALSE},
+ {"showBar", XtCValue, XtRBoolean, sizeof(Boolean),
+ offset(showBar), XtRImmediate, (XtPointer) FALSE},
+ {"showTemperature", XtCValue, XtRBoolean, sizeof(Boolean),
+ offset(showTemperature), XtRImmediate, (XtPointer) FALSE},
+ {"showCpuFreq", XtCValue, XtRBoolean, sizeof(Boolean),
+ offset(showCpufreq), XtRImmediate, (XtPointer) FALSE},
+ {"showDate", XtCValue, XtRBoolean, sizeof(Boolean),
+ offset(showDate), XtRImmediate, (XtPointer) FALSE},
+ {"fahrenheit", XtCValue, XtRBoolean, sizeof(Boolean),
+ offset(fahrenheit), XtRImmediate, (XtPointer) FALSE},
+ {"dateFormat", XtCString, XtRString, sizeof(String),
+ offset(dateFormat), XtRString, (XtPointer) DEFAULT_DATE_FORMAT},
+ {"acpiDir", XtCString, XtRString, sizeof(String),
+ offset(acpiDir), XtRString, (XtPointer) DEFAULT_ACPI_DIR},
+ {"cpuFreqDir", XtCString, XtRString, sizeof(String),
+ offset(cpuFreqDir), XtRString, (XtPointer) DEFAULT_CPUFREQ_DIR},
+};
+
+static void quit(Widget w, XtPointer client_data, XtPointer call_data){
+ exit (0);
+}
+
+static XtActionsRec main_actions[] = { {"Quit", (XtActionProc) quit},
+};
+
+static String main_translations = "<Message>WM_PROTOCOLS:Quit()\n";
+
+int main(int argc, char **argv){
+ char c;
+
+ int x = 0, y = 0, height = 0, width = 0;
+ int current_width = 0, own_width;
+ XFontStruct *fs;
+ Atom wm_protocols[1];
+ Widget last;
+
+ nb_failures = 0;
+
+ topLevel = XtVaAppInitialize(&app_context, "XAcpi",
+ options, XtNumber(options),
+ &argc, argv, NULL, NULL);
+
+ XtGetApplicationResources(topLevel,
+ &iv,
+ resources,
+ XtNumber(resources),
+ NULL, 0);
+
+ if(iv.criticalTemp <= 0) {
+ if(iv.fahrenheit) iv.criticalTemp = 158;
+ else iv.criticalTemp = 70;
+ }
+
+ check_acpi(iv.acpiDir);
+
+ if (iv.delay < 1) iv.delay = DEFAULT_DELAY;
+
+ XParseGeometry(iv.geometry, &x, &y, &width, &height);
+
+ while ((c = getopt(argc, argv, "DVH")) != -1)
+ switch (c) {
+ case 'D':
+ ++debug;
+ break;
+ case 'V':
+ fprintf(stderr, "xacpi version " XACPI_VERSION ".\n");
+ fprintf(stderr, "$Id: xacpi.c,v 1.40 2004/12/03 07:52:30 fleuret Exp $.\n");
+ exit(0);
+ case 'H':
+ printf("Options:\n"
+ " -D\n"
+ " -V\n"
+ " -H\n"
+ " -highcolor <string: color>\n"
+ " -lowcolor <string: color>\n"
+ " -criticalcolor <string: color>\n"
+ " -chargingcolor <string: color>\n"
+ " -highvalue <int: percentage>\n"
+ " -lowvalue <int: percentage>\n"
+ " -delay <int: seconds>\n"
+ " -percent\n"
+ " -percentauto\n"
+ " -showbar\n"
+ " -showtemp\n"
+ " -showcpufreq\n"
+ " -showdate\n"
+ " -dateformat <string: format>\n"
+ " -fahrenheit\n"
+ " -acpidir <string: path>\n"
+ " -cpufreqdir <string: path>\n"
+ "\n"
+ "See man xacpi for more detailed information.\n");
+ exit(0);
+ break;
+ }
+
+ form = XtVaCreateManagedWidget("form",
+ formWidgetClass, topLevel,
+ XtNorientation, XtorientHorizontal,
+ XtNborderWidth, 0,
+ XtNdefaultDistance, 0,
+ NULL);
+
+ /* Add the date */
+
+ if(iv.showDate) {
+ date = XtVaCreateManagedWidget("date",
+ labelWidgetClass, form,
+ XtNinternalHeight, 0,
+ XtNinternalWidth, 0,
+ XtNborderWidth, 0,
+ XtNlabel, "",
+ XtNresize, FALSE,
+ NULL);
+
+ char buf[BUFFER_LEN];
+ put_date(buf, iv.dateFormat);
+ last = date;
+ XtVaGetValues(last, XtNfont, &fs, NULL);
+ own_width = ((strlen(buf) + 2) * fs->max_bounds.width);
+ XtVaSetValues(last, XtNwidth, own_width, NULL);
+ current_width += own_width;
+ } else date = 0;
+
+ /* Add the widget to display the remaining battery time */
+
+ delay = XtVaCreateManagedWidget("delay",
+ commandWidgetClass, form,
+ XtNleft, XtChainLeft,
+ XtNhighlightThickness, 0,
+ XtNinternalHeight, 0,
+ XtNinternalWidth, 0,
+ XtNborderWidth, 0,
+ XtNlabel, "",
+ XtNresize, FALSE,
+ NULL);
+
+
+ if(date) XtVaSetValues(delay, XtNfromHoriz, last, 0);
+ XtAddCallback(delay, XtNcallback, press, NULL);
+
+ last = delay;
+ XtVaGetValues(last, XtNfont, &fs, NULL);
+ own_width = 6 * fs->max_bounds.width;
+ XtVaSetValues(last, XtNwidth, own_width, NULL);
+ current_width += own_width;
+
+ /* Add the widget to display the colored bar */
+
+ if(iv.showBar) {
+
+ scrollbar = XtVaCreateManagedWidget("scrollbar",
+ scrollbarWidgetClass, form,
+ XtNhorizDistance, 3,
+ XtNfromHoriz, last,
+ XtNorientation, XtorientHorizontal,
+ NULL);
+
+ XawScrollbarSetThumb(scrollbar, 0.0, 0.0);
+
+ XtVaSetValues(scrollbar,
+ XtNtranslations, XtParseTranslationTable(""),
+ NULL);
+
+ last = scrollbar;
+ } else scrollbar = 0;
+
+ /* Add the widget to display the temperature */
+
+ if(iv.showTemperature) {
+ temperature = XtVaCreateManagedWidget("temperature",
+ commandWidgetClass, form,
+ XtNhorizDistance, 6,
+ XtNfromHoriz, last,
+ XtNhighlightThickness, 0,
+ XtNinternalHeight, 0,
+ XtNinternalWidth, 0,
+ XtNborderWidth, 0,
+ XtNlabel, iv.fahrenheit ? "000F " : "00C ",
+ XtNresize, FALSE,
+ NULL);
+ last = temperature;
+ XtVaGetValues(last, XtNfont, &fs, NULL);
+ own_width = (iv. fahrenheit ? 5 : 4) * fs->max_bounds.width;
+ XtVaSetValues(last, XtNwidth, own_width, NULL);
+ current_width += own_width;
+ XtAddCallback(temperature, XtNcallback, press, NULL);
+ } else temperature = 0;
+
+ /* Add the widget to display the cpu frequency */
+
+ if(iv.showCpufreq) {
+ cpufreq = XtVaCreateManagedWidget("cpufreq",
+ labelWidgetClass, form,
+ XtNhorizDistance, 6,
+ XtNfromHoriz, last,
+ XtNinternalHeight, 0,
+ XtNinternalWidth, 0,
+ XtNborderWidth, 0,
+ XtNlabel, "?.?Ghz",
+ XtNresize, FALSE,
+ NULL);
+ last = cpufreq;
+ XtVaGetValues(last, XtNfont, &fs, NULL);
+ own_width = 7 * fs->max_bounds.width;
+ XtVaSetValues(last, XtNwidth, own_width, NULL);
+ current_width += own_width;
+ } else cpufreq = 0;
+
+ /* Changed the bar length to the unused width */
+
+ if(scrollbar) {
+ if(width > current_width + MIN_BAR_WIDTH)
+ XtVaSetValues(scrollbar, XtNwidth, width - current_width, 0);
+ else {
+ XtVaSetValues(scrollbar, XtNwidth, MIN_BAR_WIDTH, 0);
+ }
+ }
+
+ XtRealizeWidget(topLevel);
+
+ /* Add code to handle WM_DELETE_WINDOW cleanly. */
+
+ XtAppAddActions(app_context, main_actions, XtNumber(main_actions));
+ XtOverrideTranslations(topLevel, XtParseTranslationTable(main_translations));
+ wm_protocols[0]
+ = XInternAtom(XtDisplay(topLevel), "WM_DELETE_WINDOW", False);
+ XSetWMProtocols(XtDisplay(topLevel), XtWindow(topLevel), wm_protocols, 1);
+
+ timerId = XtAppAddTimeOut(app_context, 0, update, app_context);
+ XtAppMainLoop(app_context);
+
+ return 0;
+}