// Copyright 2008 Curaga
// A small app to be swallowed into JWM tray, to show cpu,mem,swap usage
// What do you know, mixing C with fltk C++ works just fine

// Licensed under the GPLv2, as scanf did not work for me, so
// I benefited from Open Source and copied the fgets block from
// wmbluemem :)
// Thank You Mihai Drăghicioiu

// Changes from Softwaregurl:
// Moved letters after the values with percentages
// Gigabytes for swap and mem

#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Box.H>
#include <FL/filename.H>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char version[4]="1.6";

float timeout=1.5,mem=0,swap=0,cpu=0,used=0,oldused=0,cputotal=0,oldcputotal=0;
int arg_i=0, fontsize=10, mib=0, showswap=1;
char memind[2]="m", swapind[2]="m";
FILE *meminfo,*cpuinfo;

void checkup(){
  if((meminfo=fopen("/proc/meminfo","r"))==NULL){
    fprintf(stderr,"Error opening meminfo");
    exit(1);
  }
  if((cpuinfo=fopen("/proc/stat","r"))==NULL){
    fprintf(stderr,"Error opening stat");
    exit(1);
  }

 unsigned long memtotal,memfree,buffers,cache,swaptotal,swapfree;
 unsigned long user,nice,sys,idle,iowait,irq,softirq,virt,virt2;
 char buf[60],buf2[190];
 char *p;
 int i;

 fgets(buf, 60, meminfo); strtok(buf, " "); p = strtok(NULL, " ");
 memtotal = strtol(p, NULL, 10);
 fgets(buf, 60, meminfo); strtok(buf, " "); p = strtok(NULL, " ");
 memfree = strtol(p, NULL, 10);
 fgets(buf, 60, meminfo); strtok(buf, " "); p = strtok(NULL, " ");
 buffers = strtol(p, NULL, 10);
 fgets(buf, 60, meminfo); strtok(buf, " "); p = strtok(NULL, " ");
 cache = strtol(p, NULL, 10);
 for(i = 1; i < 35; i++){
   fgets(buf, 60, meminfo);
   p=strtok(buf, " ");
   if(strcmp("SwapTotal:",p)==0) break;
 }
 p = strtok(NULL, " ");
 swaptotal = strtol(p, NULL, 10);
 fgets(buf, 60, meminfo); strtok(buf, " "); p = strtok(NULL, " ");
 swapfree = strtol(p, NULL, 10);
 fclose(meminfo);

 fgets(buf2,190,cpuinfo); strtok(buf2, " ");
 p=strtok(NULL, " "); user=strtol(p, NULL, 10);
 p=strtok(NULL, " "); nice=strtol(p, NULL, 10);
 p=strtok(NULL, " "); sys=strtol(p, NULL, 10);
 p=strtok(NULL, " "); idle=strtol(p, NULL, 10);
 p=strtok(NULL, " "); iowait=strtol(p, NULL, 10);
 p=strtok(NULL, " "); irq=strtol(p, NULL, 10);
 p=strtok(NULL, " "); softirq=strtol(p, NULL,10);
 p=strtok(NULL, " "); virt=strtol(p, NULL, 10);
 p=strtok(NULL, " "); virt2=strtol(p, NULL, 10);
 fclose(cpuinfo);

 used=(float)(user+nice+sys+irq+softirq+virt+virt2);
 cputotal=used+(float)idle+(float)iowait;

 cpu=((used-oldused)/(cputotal-oldcputotal))*(float)100;

 if(mib==1){
 mem=(float)(memtotal-(memfree+buffers+cache))/(float)1024;
 swap=(float)(swaptotal-swapfree)/(float)1024;
 }
 if(mib==2){
 mem=(float)(memfree+buffers+cache)/(float)1024;
 swap=(float)swapfree/(float)1024;
 }
 if(mib==0){
 mem=((float)(memtotal-(memfree+buffers+cache))/ (float) memtotal)*(float)100;
 swap=((float)(swaptotal-swapfree)/(float)swaptotal)*(float)100;
 }

 oldused=used;
 oldcputotal=cputotal;

 if(mem>999.9){
  mem=mem/1024;
  strcpy(memind,"g");
 }
 if(swap>999.9){
  swap=swap/1024;
  strcpy(swapind,"g");
 }
 if(swaptotal==0){
  swap=0;
 }
}

void tick(void* v){
 checkup();
 Fl_Box* box=(Fl_Box*)v;
 char yeah[25]="";
 if(showswap){
	if(mib) sprintf(yeah,"C%.1f%% M%.1f%s  S%.1f%s",cpu,mem,memind,swap,swapind);
	else sprintf(yeah,"%.1f%%C  %.1f%%M  %.1f%%S",cpu,mem,swap);
 }
 else{
	if(mib) sprintf(yeah,"C%.1f%% M%.1f%s",cpu,mem,memind);
	else sprintf(yeah,"%.1f%%C  %.1f%%M",cpu,mem);
 }
 box->copy_label(yeah);
 Fl::repeat_timeout(timeout,tick,box);
}

int parser(int argc, char **argv, int &z){
 if(strcmp(argv[z], "-h")==0){
  printf("Watcher %s\n" \
  "(C) Curaga 2008\n" \
  "Fixes from softwaregurl\n\n" \
  "Switches: \n" \
  "\t-bg <color> background color \n" \
  "\t-fg <color> text color\n" \
  "\t-m show used MiB instead of percent on mem/swap\n" \
  "\t-r show remaining MiB instead of percent on mem/swap\n" \
  "\t-s <float> check every s secs, default %.2f\n" \
  "\t-f <size> use font size f (default %d)\n" \
  "\t-x don't show swap\n" \
  "The color can be either named (green) or rgb ('#00ff00')\n",version,
  timeout,fontsize);
  exit(0);
 }

 if(strcmp(argv[z], "-s")==0){
  timeout=strtof(argv[(z+1)],NULL);
  z+=2;
  return 1;
 }

 if(strcmp(argv[z], "-f")==0){
  fontsize=atoi(argv[(z+1)]);
  z+=2;
  return 1;
 }

 if(strcmp(argv[z], "-m")==0){
  mib=1;
  z++;
  return 1;
 }

 if(strcmp(argv[z], "-x")==0){
  showswap=0;
  z++;
  return 1;
 }

 if(strcmp(argv[z], "-r")==0){
  mib=2;
  z++;
  return 1;
 }

 return 0;
}

int main(int argc, char **argv) {

  // Graphic stuff
  Fl_Window *window = new Fl_Window(124,18);
  Fl::args(argc,argv,arg_i,&parser);
  Fl_Box *box = new Fl_Box(FL_NO_BOX,0,0,124,18,"Starting...");
  box->labelsize(fontsize);
  window->end();
  window->show(argc, argv);

  Fl::add_timeout(timeout,tick,box);
  return Fl::run();
}
