ref: 2eacf6036e4260756aa9923029719d9f32c5fdc0
parent: 1c1edbf0ca89d54abd729b6592892c00d8aec6d0
author: sirjofri <sirjofri@sirjofri.de>
date: Thu Nov 20 14:13:31 EST 2025
adds new watch program
--- a/mkfile
+++ b/mkfile
@@ -4,8 +4,16 @@
files=hours.awk report clock watch
install:V: ${files:%=$home/bin/rc/hours/%}+ @{cd watch && mk install && cd ..}$home/bin/rc/hours/%: %
if(! test -d $home/bin/rc/hours)
mkdir $home/bin/rc/hours
cp $prereq $target
+
+$home/bin/rc/hours/watch:V:
+ cat <<! >$target
+ #!/bin/rc
+ exec $home/bin/$objtype/hours/watch
+ !
+ chmod +x $target
--- a/watch
+++ /dev/null
@@ -1,31 +1,0 @@
-#!/bin/rc
-
-rfork e
-clockfile=$home/lib/clocked_hour
-nl='
-'
-
-echo 'hours/watch' | tr -d $nl >/dev/label
-echo 'bottom' >/dev/wctl
-echo 'hide' >/dev/wctl
-
-fn loop{- if (! test -r $clockfile){- echo 'no clock is running'
- }
- if not{- data=`{cat $clockfile}- end=`{date -un}- start=$data(1)
- td=`{echo $end - $start | hoc}- msg=$data(2-)
-
- hours=`{echo 'int(' $td / 3600 ')' | hoc}- min=`{echo 'int(int(' $td / 60 ')' % 60 ')' | hoc}- sec=`{echo $td % 60 | hoc}-
- echo $hours^'h' $min^'m' $sec^'s' : $msg
- }
-}
-
-@{while (sleep 1) loop} | aux/statusmsg--- /dev/null
+++ b/watch/mkfile
@@ -1,0 +1,11 @@
+</$objtype/mkfile
+
+BIN=$home/bin/$objtype/hours
+TARG=watch
+OFILES=watch.$O
+
+</sys/src/cmd/mkone
+
+$BIN/$TARG: $O.out
+ mkdir -p `{basename -d $target}+ cp $prereq $BIN/$TARG
--- /dev/null
+++ b/watch/watch.c
@@ -1,0 +1,269 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <draw.h>
+#include <event.h>
+#include <keyboard.h>
+
+void
+usage(void)
+{+ fprint(2, "usage: %s\n", argv0);
+ exits("usage");+}
+
+char *libhours = nil;
+char *watchfile = nil;
+
+char *message = nil;
+char *runtime = nil;
+
+int lineheight = 0;
+
+Image *playimg = nil;
+Image *stopimg = nil;
+
+Rectangle buttonbox;
+int timerrunning = 0;
+
+Point playps[] = {+ { 20, 20 },+ { 20, 80 },+ { 80, 50 },+};
+
+Point stopps[] = {+ { 20, 20 },+ { 20, 80 },+ { 80, 80 },+ { 80, 20 },+};
+
+void
+initimages(void)
+{+ playimg = allocimage(display, Rect(0, 0, 100, 100), screen->chan, 0, DWhite);
+ stopimg = allocimage(display, Rect(0, 0, 100, 100), screen->chan, 0, DWhite);
+
+ border(playimg, playimg->r, 1, display->black, ZP);
+ border(stopimg, stopimg->r, 1, display->black, ZP);
+
+ fillpoly(playimg, playps, 3, 0, display->black, ZP);
+ fillpoly(stopimg, stopps, 4, 0, display->black, ZP);
+}
+
+void
+setmessage(char *s)
+{+ if (message)
+ free(message);
+ message = s;
+}
+
+void
+setruntime(long tm)
+{+ int hours, minutes, seconds;
+
+ if (runtime)
+ free(runtime);
+
+ hours = (int)(tm/3600);
+ minutes = (int)((tm/60)%60);
+ seconds = (int)(tm % 60);
+
+ runtime = smprint("%dh %dm %ds", hours, minutes, seconds);+}
+
+void
+redraw(void)
+{+ Point p;
+ int x;
+ Image *todraw;
+ draw(screen, screen->r, display->white, nil, ZP);
+
+ x = screen->r.min.x + 5;
+ p.y = screen->r.min.y + 5;
+ p.x = x;
+
+ p = string(screen, p, display->black, ZP, font, runtime);
+ p.x = x;
+ p.y += lineheight;
+ p = string(screen, p, display->black, ZP, font, message);
+
+ todraw = timerrunning ? stopimg : playimg;
+
+ p.x = x;
+ p.y += lineheight;
+ buttonbox = rectaddpt(todraw->r, p);
+ draw(screen, buttonbox, todraw, nil, ZP);
+}
+
+long
+getstarttime(char **msg)
+{+ Biobuf *bin;
+ char *s;
+ long t;
+
+ bin = Bopen(watchfile, OREAD);
+ if (!bin)
+ return -1;
+
+ s = Brdstr(bin, '\n', 1);
+
+ *msg = strchr(s, '\t');
+ (*msg)++;
+ *msg = strdup(*msg);
+ t = atol(s);
+ free(s);
+ return t;
+}
+
+void
+update(void)
+{+ char *msg;
+ long current, start;
+
+ msg = nil;
+ start = getstarttime(&msg);
+
+ if (start < 0) {+ timerrunning = 0;
+ setmessage(strdup("no timer"));+ setruntime(0);
+ redraw();
+ return;
+ }
+
+ current = time(nil);
+ current -= start;
+
+ timerrunning = 1;
+ setmessage(msg);
+ setruntime(current);
+
+ redraw();
+}
+
+void
+stoptimer(void)
+{+ int fd;
+ char *msg;
+ long start, current;
+
+ fd = open(".hours", OWRITE);+ if (fd < 0)
+ fd = open(libhours, OWRITE);
+
+ if (fd < 0)
+ fd = create(libhours, OWRITE, 0666);
+
+ if (fd < 0)
+ sysfatal("error accessing hours file: %r");+
+ msg = nil;
+ start = getstarttime(&msg);
+ if (start < 0)
+ return;
+
+ current = time(nil);
+
+ seek(fd, 0, 2);
+ fprint(fd, "%ld\t%ld\t%s\n", start, current, msg);
+ close(fd);
+
+ remove(watchfile);
+}
+
+void
+starttimer(Mouse m)
+{+ int fd;
+ long t;
+ char buf[1024];
+
+ if (!access(watchfile, AEXIST))
+ return;
+
+ fd = create(watchfile, OWRITE, 0666);
+ if (fd < 0)
+ sysfatal("create: %r");+
+ buf[0] = 0;
+ if (eenter("desc", buf, sizeof buf, &m) < 0)+ return;
+
+ t = time(nil);
+
+ fprint(fd, "%ld\t%s\n", t, buf);
+ close(fd);
+}
+
+void
+mouseinput(Mouse m)
+{+ if (m.buttons != 1)
+ return;
+
+ if (ptinrect(m.xy, buttonbox)) {+ if (timerrunning)
+ stoptimer();
+ else
+ starttimer(m);
+ update();
+ return;
+ }
+}
+
+void
+eresized(int new)
+{+ if (new && getwindow(display, Refnone) < 0)
+ sysfatal("%r");+
+ redraw();
+}
+
+void
+main(int argc, char **argv)
+{+ int e, timer;
+ Event ev;
+
+ ARGBEGIN{+ case 'h':
+ usage();
+ }ARGEND;
+
+ if (initdraw(nil, nil, "hours/watch") < 0)
+ sysfatal("initdraw: %r");+ initimages();
+
+ einit(Emouse|Ekeyboard);
+ timer = etimer(0, 1000);
+
+ watchfile = smprint("/usr/%s/lib/clocked_hour", getenv("user"));+ libhours = smprint("/usr/%s/lib/hours", getenv("user"));+ assert(watchfile && libhours);
+
+ lineheight = stringsize(font, "M").y;
+
+ for (;;) {+ e = event(&ev);
+ switch (e) {+ case Emouse:
+ mouseinput(ev.mouse);
+ break;
+ case Ekeyboard:
+ if (ev.kbdc == 'q' || ev.kbdc == Kdel)
+ exits(nil);
+ break;
+ }
+ if (e == timer)
+ update();
+ }
+}
--
⑨