diff options
-rw-r--r-- | LICENSE | 31 | ||||
-rw-r--r-- | README.md | 54 | ||||
-rw-r--r-- | acme3k.patch | 917 | ||||
-rw-r--r-- | img/acme.png | bin | 0 -> 70127 bytes | |||
-rw-r--r-- | img/suckme.png | bin | 0 -> 160987 bytes |
5 files changed, 1002 insertions, 0 deletions
diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b30ec57 --- /dev/null +++ b/LICENSE @@ -0,0 +1,31 @@ +Copyright © 2021 Plan 9 Foundation +Portions Copyright © 2001-2008 Russ Cox +Portions Copyright © 2008-2009 Google Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +=================================================================== + +This software is derived from Plan 9, originally copyright Lucent Technologies +and distributed under the Lucent Public License, Version 1.02. +Lucent was bought by Alcatel, which was bought by Nokia. +On March 23, 2021, Nokia announced the transfer of the Plan 9 copyrights to the +Plan 9 Foundation, which in turn relicensed Plan 9 under the the MIT license, +reproduced above. diff --git a/README.md b/README.md new file mode 100644 index 0000000..48f7a43 --- /dev/null +++ b/README.md @@ -0,0 +1,54 @@ +# acme3k +a continuation of [acme2k](https://github.com/karahobny/acme2k) + +![acme](img/acme.png) +### [ACME](http://acme.cat-v.org/) INTERNATIONAL COMPILED EDITORS + +#### THEY EDIT LIKE HELL. +``` + No editor made, pretty much anywhere, + +surpasses our Acme in shape, material or finish. +``` + +## installation + +grab the patch, put it in your `$PLAN9` directory, apply, `mk install` + +``` +# cp acme3k.patch $PLAN9/src/cmd/acme/ +# cd $PLAN9/src/cmd/acme +# patch -p1 < acme3k.patch +# mk clean install +``` + +## features + +![suckme](img/suckme.png) + ++ a centralized `config.h` header heavily inspired by the [suckless](https://suckless.org) design philosophy with the following options: + + + autoindent, scroll button behavior, fonts, and colors modifiable by the user + + + `bartflag` removed as a runtime flag and moved to a configurable option allowing for click-to-focus operation + ++ some keybindings that behave like you expect from other editors/paradigms: + + + up/down arrows move between lines instead of scrolling the view + + + `ctrl+c`/`ctrl+x`/`ctrl+v` for snarfing, cutting, and pasting selected text; `ctrl+z`/`ctrl+y` for undo/redo + + + `home`/`end` move the cursor to the start/end of the current line, as do the original keybindings `ctrl+a`/`ctrl+e` + + + `delete` removes one character forward + +### config.h +`config.h` includes all the neccesary color and font modifications; just `mk install` whenever you modify it + +#### fonts +run `fontsrv -p .` to list all the available fonts + +choose two fonts for `config.h`: the first one is treated as a proportional width font and is used everywhere in `acme`, the second one can be activated for a specific window by executing `Font` from its tag + +#### colors +colors need to be in the format of `0x*rgb hex color code*FF` without the prefixed hashtag diff --git a/acme3k.patch b/acme3k.patch new file mode 100644 index 0000000..292f87c --- /dev/null +++ b/acme3k.patch @@ -0,0 +1,917 @@ +diff --git a/src/cmd/acme/acme.c b/src/cmd/acme/acme.c +index 0e6bc0fd..bb3aa502 100644 +--- a/src/cmd/acme/acme.c ++++ b/src/cmd/acme/acme.c +@@ -11,9 +11,11 @@ + #include <libsec.h> + #include "dat.h" + #include "fns.h" +- /* for generating syms in mkfile only: */ +- #include <bio.h> +- #include "edit.h" ++#include "config.h" ++ ++/* for generating syms in mkfile only: */ ++#include <bio.h> ++#include "edit.h" + + void mousethread(void*); + void keyboardthread(void*); +@@ -21,28 +23,21 @@ void waitthread(void*); + void xfidallocthread(void*); + void newwindowthread(void*); + void plumbproc(void*); +-int timefmt(Fmt*); ++int timefmt(Fmt*); + + Reffont **fontcache; + int nfontcache; +-char wdir[512] = "."; ++char wdir[512] = "."; + Reffont *reffonts[2]; + int snarffd = -1; + int mainpid; +-int swapscrollbuttons = FALSE; +-char *mtpt; ++char *mtpt; + + enum{ + NSnarf = 1000 /* less than 1024, I/O buffer size */ + }; + Rune snarfrune[NSnarf+1]; + +-char *fontnames[2] = +-{ +- "/lib/font/bit/lucsans/euro.8.font", +- "/lib/font/bit/lucm/unicode.9.font" +-}; +- + Command *command; + + void shutdownthread(void*); +@@ -65,7 +60,6 @@ threadmain(int argc, char *argv[]) + Column *c; + int ncol; + Display *d; +- + rfork(RFENVG|RFNAMEG); + + ncol = -1; +@@ -78,11 +72,26 @@ threadmain(int argc, char *argv[]) + } + break; + case 'a': +- globalautoindent = TRUE; ++ if(globalautoindent) ++ globalautoindent = FALSE; ++ else ++ globalautoindent = TRUE; + break; +- case 'b': ++ ++/* bartmode/flag is now an option to be turned on config.h, just ++ * because it is way too useful to leave it as an meaningless ++ * flag, especially since considering how almost everyone seems ++ * to even miss its existence. ++ * ++ * to get to the point, it denies window focus following mouse. ++ * how fickle those mice can truly be when decieveth by a soothing ++ * treat, a teat or two. ++ */ ++ ++/* case 'b': + bartflag = TRUE; +- break; ++ break; */ ++ + case 'c': + p = ARGF(); + if(p == nil) +@@ -393,7 +402,6 @@ acmeerrorproc(void *v) + buf[n] = '\0'; + sendp(cerr, estrdup(buf)); + } +- free(buf); + } + + void +@@ -547,7 +555,7 @@ mousethread(void *v) + case MResize: + if(getwindow(display, Refnone) < 0) + error("attach to window"); +- draw(screen, screen->r, display->white, nil, ZP); ++ draw(screen, screen->r, winbgcol, nil, ZP); + iconinit(); + scrlresize(); + rowresize(&row, screen->clipr); +@@ -964,74 +972,6 @@ Cursor boxcursor = { + 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00} + }; + +-Cursor2 boxcursor2 = { +- {-15, -15}, +- {0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xC0, 0x03, 0xFF, +- 0xFF, 0xC0, 0x03, 0xFF, +- 0xFF, 0xC0, 0x03, 0xFF, +- 0xFF, 0xC0, 0x03, 0xFF, +- 0xFF, 0xC0, 0x03, 0xFF, +- 0xFF, 0xC0, 0x03, 0xFF, +- 0xFF, 0xC0, 0x03, 0xFF, +- 0xFF, 0xC0, 0x03, 0xFF, +- 0xFF, 0xC0, 0x03, 0xFF, +- 0xFF, 0xC0, 0x03, 0xFF, +- 0xFF, 0xC0, 0x03, 0xFF, +- 0xFF, 0xC0, 0x03, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF, +- 0xFF, 0xFF, 0xFF, 0xFF}, +- {0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00, +- 0x3F, 0xFF, 0xFF, 0xFC, +- 0x3F, 0xFF, 0xFF, 0xFC, +- 0x3F, 0xFF, 0xFF, 0xFC, +- 0x3F, 0xFF, 0xFF, 0xFC, +- 0x3F, 0xFF, 0xFF, 0xFC, +- 0x3F, 0xFF, 0xFF, 0xFC, +- 0x3F, 0x00, 0x00, 0xFC, +- 0x3F, 0x00, 0x00, 0xFC, +- 0x3F, 0x00, 0x00, 0xFC, +- 0x3F, 0x00, 0x00, 0xFC, +- 0x3F, 0x00, 0x00, 0xFC, +- 0x3F, 0x00, 0x00, 0xFC, +- 0x3F, 0x00, 0x00, 0xFC, +- 0x3F, 0x00, 0x00, 0xFC, +- 0x3F, 0x00, 0x00, 0xFC, +- 0x3F, 0x00, 0x00, 0xFC, +- 0x3F, 0x00, 0x00, 0xFC, +- 0x3F, 0x00, 0x00, 0xFC, +- 0x3F, 0x00, 0x00, 0xFC, +- 0x3F, 0x00, 0x00, 0xFC, +- 0x3F, 0x00, 0x00, 0xFC, +- 0x3F, 0x00, 0x00, 0xFC, +- 0x3F, 0xFF, 0xFF, 0xFC, +- 0x3F, 0xFF, 0xFF, 0xFC, +- 0x3F, 0xFF, 0xFF, 0xFC, +- 0x3F, 0xFF, 0xFF, 0xFC, +- 0x3F, 0xFF, 0xFF, 0xFC, +- 0x3F, 0xFF, 0xFF, 0xFC, +- 0x00, 0x00, 0x00, 0x00, +- 0x00, 0x00, 0x00, 0x00} +-}; +- + void + iconinit(void) + { +@@ -1039,22 +979,32 @@ iconinit(void) + Image *tmp; + + if(tagcols[BACK] == nil) { +- /* Blue */ +- tagcols[BACK] = allocimagemix(display, DPalebluegreen, DWhite); +- tagcols[HIGH] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPalegreygreen); +- tagcols[BORD] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPurpleblue); +- tagcols[TEXT] = display->black; +- tagcols[HTEXT] = display->black; +- +- /* Yellow */ +- textcols[BACK] = allocimagemix(display, DPaleyellow, DWhite); +- textcols[HIGH] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DDarkyellow); +- textcols[BORD] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DYellowgreen); +- textcols[TEXT] = display->black; +- textcols[HTEXT] = display->black; ++#ifndef ENABLE_PASTELS ++ tagcols[BACK] = allocimage(display, Rect(0,0,1,1), RGBA32, 1, C_TAGBG); ++#else ++ tagcols[BACK] = allocimagemix(display, C_TAGBG, DWhite); ++#endif ++ ++ tagcols[HIGH] = allocimage(display, Rect(0,0,1,1), RGBA32, 1, C_TAGHLBG); ++ tagcols[BORD] = allocimage(display, Rect(0,0,1,1), RGBA32, 1, C_COLBUTTON); ++ tagcols[TEXT] = allocimage(display, Rect(0,0,1,1), RGBA32, 1, C_TAGFG); ++ tagcols[HTEXT] = allocimage(display, Rect(0,0,1,1), RGBA32, 1, C_TAGHLFG); ++#ifndef ENABLE_PASTELS ++ textcols[BACK] = allocimage(display, Rect(0,0,1,1), RGBA32, 1, C_TXTBG); ++#else ++ textcols[BACK] = allocimagemix(display, C_TXTBG, DWhite); ++#endif ++ textcols[HIGH] = allocimage(display, Rect(0,0,1,1), RGBA32, 1, C_TXTHLBG); ++ textcols[BORD] = allocimage(display, Rect(0,0,1,1), RGBA32, 1, C_SCROLLBG); ++ textcols[TEXT] = allocimage(display, Rect(0,0,1,1), RGBA32, 1, C_TXTFG); ++ textcols[HTEXT] = allocimage(display, Rect(0,0,1,1), RGBA32, 1, C_TXTHLFG); ++ + } + +- r = Rect(0, 0, Scrollwid, font->height+1); ++ winbgcol = allocimage(display, Rect(0,0,1,1), RGBA32, 1, C_WINBG); ++ winbordercol = allocimage(display, Rect(0,0,1,1), RGBA32, 1, C_WINBORDER); ++ ++ r = Rect(0, 0, Scrollwid+ButtonBorder, font->height+1); + if(button && eqrect(r, button->r)) + return; + +@@ -1066,22 +1016,24 @@ iconinit(void) + + button = allocimage(display, r, screen->chan, 0, DNofill); + draw(button, r, tagcols[BACK], nil, r.min); ++ r.max.x -= ButtonBorder; + border(button, r, ButtonBorder, tagcols[BORD], ZP); + + r = button->r; + modbutton = allocimage(display, r, screen->chan, 0, DNofill); + draw(modbutton, r, tagcols[BACK], nil, r.min); ++ r.max.x -= ButtonBorder; + border(modbutton, r, ButtonBorder, tagcols[BORD], ZP); + r = insetrect(r, ButtonBorder); +- tmp = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DMedblue); ++ tmp = allocimage(display, Rect(0,0,1,1), RGBA32, 1, C_TMPBUTTON); + draw(modbutton, r, tmp, nil, ZP); + freeimage(tmp); + + r = button->r; +- colbutton = allocimage(display, r, screen->chan, 0, DPurpleblue); ++ colbutton = allocimage(display, r, RGBA32, 1, C_WINBUTTON); + +- but2col = allocimage(display, r, screen->chan, 1, 0xAA0000FF); +- but3col = allocimage(display, r, screen->chan, 1, 0x006600FF); ++ but2col = allocimage(display, r, screen->chan, 1, C_BUTTON2HL); ++ but3col = allocimage(display, r, screen->chan, 1, C_BUTTON3HL); + } + + /* +diff --git a/src/cmd/acme/addr.c b/src/cmd/acme/addr.c +index 6aee8993..2ccae960 100644 +--- a/src/cmd/acme/addr.c ++++ b/src/cmd/acme/addr.c +@@ -240,12 +240,12 @@ address(uint showerr, Text *t, Range lim, Range ar, void *a, uint q0, uint q1, i + case '5': case '6': case '7': case '8': case '9': + n = c -'0'; + while(q<q1){ +- nc = (*getc)(a, q++); +- if(nc<'0' || '9'<nc){ ++ c = (*getc)(a, q++); ++ if(c<'0' || '9'<c){ + q--; + break; + } +- n = n*10+(nc-'0'); ++ n = n*10+(c-'0'); + } + if(*evalp) + r = number(showerr, t, r, n, dir, size, evalp); +diff --git a/src/cmd/acme/cols.c b/src/cmd/acme/cols.c +index a53280c4..72572a39 100644 +--- a/src/cmd/acme/cols.c ++++ b/src/cmd/acme/cols.c +@@ -29,7 +29,7 @@ colinit(Column *c, Rectangle r) + Rectangle r1; + Text *t; + +- draw(screen, r, display->white, nil, ZP); ++ draw(screen, r, winbgcol, nil, ZP); + c->r = r; + c->w = nil; + c->nw = 0; +@@ -42,7 +42,7 @@ colinit(Column *c, Rectangle r) + t->what = Columntag; + r1.min.y = r1.max.y; + r1.max.y += Border; +- draw(screen, r1, display->black, nil, ZP); ++ draw(screen, r1, winbordercol, nil, ZP); + textinsert(t, 0, Lheader, 38, TRUE); + textsetselect(t, t->file->b.nc, t->file->b.nc); + draw(screen, t->scrollr, colbutton, nil, colbutton->r.min); +@@ -117,7 +117,7 @@ coladd(Column *c, Window *w, Window *clone, int y) + r1.max.y = min(y, v->body.fr.r.min.y+v->body.fr.nlines*v->body.fr.font->height); + r1.min.y = winresize(v, r1, FALSE, FALSE); + r1.max.y = r1.min.y+Border; +- draw(screen, r1, display->black, nil, ZP); ++ draw(screen, r1, winbordercol, nil, ZP); + + /* + * leave r with w's coordinates +@@ -184,7 +184,7 @@ colclose(Column *c, Window *w, int dofree) + memmove(c->w+i, c->w+i+1, (c->nw-i)*sizeof(Window*)); + c->w = realloc(c->w, c->nw*sizeof(Window*)); + if(c->nw == 0){ +- draw(screen, r, display->white, nil, ZP); ++ draw(screen, r, winbgcol, nil, ZP); + return; + } + up = 0; +@@ -244,27 +244,28 @@ colresize(Column *c, Rectangle r) + r1.max.y = r1.min.y + c->tag.fr.font->height; + textresize(&c->tag, r1, TRUE); + draw(screen, c->tag.scrollr, colbutton, nil, colbutton->r.min); ++ new = Dy(r) - c->nw*(Border + font->height); ++ old = Dy(c->r) - c->nw*(Border + font->height); + r1.min.y = r1.max.y; + r1.max.y += Border; +- draw(screen, r1, display->black, nil, ZP); ++ draw(screen, r1, winbordercol, nil, ZP); + r1.max.y = r.max.y; +- new = Dy(r) - c->nw*(Border + font->height); +- old = Dy(c->r) - c->nw*(Border + font->height); + for(i=0; i<c->nw; i++){ + w = c->w[i]; + w->maxlines = 0; + if(i == c->nw-1) + r1.max.y = r.max.y; +- else{ ++ else { + r1.max.y = r1.min.y; + if(new > 0 && old > 0 && Dy(w->r) > Border+font->height){ + r1.max.y += (Dy(w->r)-Border-font->height)*new/old + Border + font->height; + } ++ r1.max.y = r1.min.y+(Dy(w->r)+Border)*Dy(r)/Dy(c->r); + } + r1.max.y = max(r1.max.y, r1.min.y + Border+font->height); + r2 = r1; + r2.max.y = r2.min.y+Border; +- draw(screen, r2, display->black, nil, ZP); ++ draw(screen, r2, winbordercol, nil, ZP); + r1.min.y = r2.max.y; + r1.min.y = winresize(w, r1, FALSE, i==c->nw-1); + } +@@ -320,7 +321,7 @@ colsort(Column *c) + r.max.y = r.min.y+Dy(w->r)+Border; + r1 = r; + r1.max.y = r1.min.y+Border; +- draw(screen, r1, display->black, nil, ZP); ++ draw(screen, r1, winbordercol, nil, ZP); + r.min.y = r1.max.y; + y = winresize(w, r, FALSE, i==c->nw-1); + } +@@ -417,8 +418,8 @@ colgrow(Column *c, Window *w, int but) + if(nl[j]) + r.max.y += 1 + nl[j]*v->body.fr.font->height; + r.min.y = winresize(v, r, c->safe, FALSE); +- r.max.y = r.min.y + Border; +- draw(screen, r, display->black, nil, ZP); ++ r.max.y += Border; ++ draw(screen, r, winbordercol, nil, ZP); + y1 = r.max.y; + } + /* scan to see new size of everyone below */ +@@ -445,7 +446,7 @@ colgrow(Column *c, Window *w, int but) + if(i < c->nw-1){ + r.min.y = r.max.y; + r.max.y += Border; +- draw(screen, r, display->black, nil, ZP); ++ draw(screen, r, winbordercol, nil, ZP); + for(j=i+1; j<c->nw; j++) + ny[j] -= (y2-r.max.y); + } +@@ -462,7 +463,7 @@ colgrow(Column *c, Window *w, int but) + if(j < c->nw-1){ /* no border on last window */ + r.min.y = y1; + r.max.y += Border; +- draw(screen, r, display->black, nil, ZP); ++ draw(screen, r, winbordercol, nil, ZP); + y1 = r.max.y; + } + } +@@ -482,7 +483,7 @@ coldragwin(Column *c, Window *w, int but) + Column *nc; + + clearmouse(); +- setcursor2(mousectl, &boxcursor, &boxcursor2); ++ setcursor(mousectl, &boxcursor); + b = mouse->buttons; + op = mouse->xy; + while(mouse->buttons == b) +@@ -544,7 +545,7 @@ coldragwin(Column *c, Window *w, int but) + } + r.min.y = winresize(v, r, c->safe, FALSE); + r.max.y = r.min.y+Border; +- draw(screen, r, display->black, nil, ZP); ++ draw(screen, r, winbordercol, nil, ZP); + r.min.y = r.max.y; + if(i == c->nw-1) + r.max.y = c->r.max.y; +diff --git a/src/cmd/acme/config.h b/src/cmd/acme/config.h +new file mode 100644 +index 00000000..104f9c98 +--- /dev/null ++++ b/src/cmd/acme/config.h +@@ -0,0 +1,32 @@ ++char *fontnames[2] = { ++ "/mnt/font/DejaVuSansMono/11a/font", ++ "/mnt/font/DejaVuSansMono/18a/font", ++}; ++ ++int bartflag = FALSE; // click-to-focus (experimental) ++int globalautoindent = TRUE; // default auto-indent ++int swapscrollbuttons = FALSE; // TRUE = 1:down/3:up ++ ++#define C_TAGBG 0x222222FF // tag window bg ++#define C_TAGHLBG 0x444444FF // tag window highlighted bg ++ ++#define C_TAGFG 0xBBBBBBFF // tag window fg ++#define C_TAGHLFG 0xEEEEEEFF // tag window highlighted fg ++ ++#define C_TXTBG 0x000000FF // text window bg ++#define C_TXTHLBG 0x444444FF // text window highlighted bg ++ ++#define C_TXTFG 0xEEEEEEFF // text window fg ++#define C_TXTHLFG 0xEEEEEEFF // text window highlighted fg ++ ++#define C_WINBG 0x111111FF // empty column bg ++#define C_WINBORDER 0x111111FF // separator between tags/windows ++#define C_WINBUTTON 0x005577FF // window frame decorations ++ ++#define C_COLBUTTON 0x005577FF // column button ++#define C_TMPBUTTON 0x55AAAAFF // modified window button (inside WINBUTTON) ++ ++#define C_SCROLLBG 0x222222FF // scrollbar bg ++ ++#define C_BUTTON2HL 0xCC3333FF // button 2 drag highlight bg ++#define C_BUTTON3HL 0x005577FF // button 3 drag highlight bg +diff --git a/src/cmd/acme/dat.h b/src/cmd/acme/dat.h +index e540605a..abab2fdc 100644 +--- a/src/cmd/acme/dat.h ++++ b/src/cmd/acme/dat.h +@@ -524,8 +524,9 @@ Image *colbutton; + Image *button; + Image *but2col; + Image *but3col; ++Image *winbgcol; ++Image *winbordercol; + Cursor boxcursor; +-Cursor2 boxcursor2; + Row row; + int timerpid; + Disk *disk; +diff --git a/src/cmd/acme/ecmd.c b/src/cmd/acme/ecmd.c +index f7613172..be580234 100644 +--- a/src/cmd/acme/ecmd.c ++++ b/src/cmd/acme/ecmd.c +@@ -582,8 +582,6 @@ x_cmd(Text *t, Cmd *cp) + int + X_cmd(Text *t, Cmd *cp) + { +- USED(t); +- + filelooper(t, cp, cp->cmdc=='X'); + return TRUE; + } +@@ -1002,14 +1000,16 @@ filelooper(Text *t, Cmd *cp, int XY) + */ + allwindows(alllocker, (void*)1); + globalincref = 1; +- ++ for(i=0; i<loopstruct.nw; i++) ++ cmdexec(&loopstruct.w[i]->body, cp->u.cmd); ++ + /* + * Unlock the window running the X command. + * We'll need to lock and unlock each target window in turn. + */ + if(t && t->w) + winunlock(t->w); +- ++ + for(i=0; i<loopstruct.nw; i++) { + targ = &loopstruct.w[i]->body; + if(targ && targ->w) +diff --git a/src/cmd/acme/exec.c b/src/cmd/acme/exec.c +index 1dd02288..cd2e36b2 100644 +--- a/src/cmd/acme/exec.c ++++ b/src/cmd/acme/exec.c +@@ -768,7 +768,7 @@ putfile(File *f, int q0, int q1, Rune *namer, int nname) + b = nil; + if(ret < 0 || retc < 0) { + warning(nil, "can't write file %s: %r\n", name); +- goto Rescue2; // flush or close failed ++ goto Rescue2; + } + if(runeeq(namer, nname, f->name, f->nname)){ + if(q0!=0 || q1!=f->b.nc){ +diff --git a/src/cmd/acme/look.c b/src/cmd/acme/look.c +index a7172b50..6fe18974 100644 +--- a/src/cmd/acme/look.c ++++ b/src/cmd/acme/look.c +@@ -491,11 +491,12 @@ dirname(Text *t, Rune *r, int n) + if(n>=1 && r[0]=='/') + goto Rescue; + b = parsetag(t->w, n, &i); ++ bufread(&t->w->tag.file->b, 0, b, nt); + slash = -1; + for(i--; i >= 0; i--){ +- if(b[i] == '/'){ +- slash = i; +- break; ++ if(b[i] == '/'){ ++ slash = i; ++ break; + } + } + if(slash < 0) +diff --git a/src/cmd/acme/mkfile b/src/cmd/acme/mkfile +index 18bea9e0..2bad712c 100644 +--- a/src/cmd/acme/mkfile ++++ b/src/cmd/acme/mkfile +@@ -29,6 +29,7 @@ OFILES=\ + HFILES=dat.h\ + edit.h\ + fns.h\ ++ config.h + + <$PLAN9/src/mkone + <$PLAN9/src/mkdirs +diff --git a/src/cmd/acme/rows.c b/src/cmd/acme/rows.c +index 7a64fabf..93445861 100644 +--- a/src/cmd/acme/rows.c ++++ b/src/cmd/acme/rows.c +@@ -28,7 +28,7 @@ rowinit(Row *row, Rectangle r) + Rectangle r1; + Text *t; + +- draw(screen, r, display->white, nil, ZP); ++ draw(screen, r, winbgcol, nil, ZP); + row->r = r; + row->col = nil; + row->ncol = 0; +@@ -42,7 +42,7 @@ rowinit(Row *row, Rectangle r) + t->col = nil; + r1.min.y = r1.max.y; + r1.max.y += Border; +- draw(screen, r1, display->black, nil, ZP); ++ draw(screen, r1, winbordercol, nil, ZP); + textinsert(t, 0, Lcolhdr, 29, TRUE); + textsetselect(t, t->file->b.nc, t->file->b.nc); + } +@@ -73,7 +73,7 @@ rowadd(Row *row, Column *c, int x) + r = d->r; + if(Dx(r) < 100) + return nil; +- draw(screen, r, display->white, nil, ZP); ++ draw(screen, r, winbgcol, nil, ZP); + r1 = r; + r1.max.x = min(x-Border, r.max.x-50); + if(Dx(r1) < 50) +@@ -81,7 +81,7 @@ rowadd(Row *row, Column *c, int x) + colresize(d, r1); + r1.min.x = r1.max.x; + r1.max.x = r1.min.x+Border; +- draw(screen, r1, display->black, nil, ZP); ++ draw(screen, r1, winbordercol, nil, ZP); + r.min.x = r1.max.x; + } + if(c == nil){ +@@ -115,7 +115,7 @@ rowresize(Row *row, Rectangle r) + textresize(&row->tag, r1, TRUE); + r1.min.y = r1.max.y; + r1.max.y += Border; +- draw(screen, r1, display->black, nil, ZP); ++ draw(screen, r1, winbordercol, nil, ZP); + r.min.y = r1.max.y; + r1 = r; + r1.max.x = r1.min.x; +@@ -130,7 +130,7 @@ rowresize(Row *row, Rectangle r) + if(i > 0){ + r2 = r1; + r2.max.x = r2.min.x+Border; +- draw(screen, r2, display->black, nil, ZP); ++ draw(screen, r2, winbordercol, nil, ZP); + r1.min.x = r2.max.x; + } + colresize(c, r1); +@@ -148,7 +148,7 @@ rowdragcol(Row *row, Column *c, int _0) + USED(_0); + + clearmouse(); +- setcursor2(mousectl, &boxcursor, &boxcursor2); ++ setcursor(mousectl, &boxcursor); + b = mouse->buttons; + op = mouse->xy; + while(mouse->buttons == b) +@@ -191,14 +191,14 @@ rowdragcol(Row *row, Column *c, int _0) + p.x = c->r.max.x-80-Scrollwid; + r = d->r; + r.max.x = c->r.max.x; +- draw(screen, r, display->white, nil, ZP); ++ draw(screen, r, winbgcol, nil, ZP); + r.max.x = p.x; + colresize(d, r); + r = c->r; + r.min.x = p.x; + r.max.x = r.min.x; + r.max.x += Border; +- draw(screen, r, display->black, nil, ZP); ++ draw(screen, r, winbordercol, nil, ZP); + r.min.x = r.max.x; + r.max.x = c->r.max.x; + colresize(c, r); +@@ -223,7 +223,7 @@ rowclose(Row *row, Column *c, int dofree) + memmove(row->col+i, row->col+i+1, (row->ncol-i)*sizeof(Column*)); + row->col = realloc(row->col, row->ncol*sizeof(Column*)); + if(row->ncol == 0){ +- draw(screen, r, display->white, nil, ZP); ++ draw(screen, r, winbgcol, nil, ZP); + return; + } + if(i == row->ncol){ /* extend last column right */ +@@ -234,7 +234,7 @@ rowclose(Row *row, Column *c, int dofree) + c = row->col[i]; + r.max.x = c->r.max.x; + } +- draw(screen, r, display->white, nil, ZP); ++ draw(screen, r, winbgcol, nil, ZP); + colresize(c, r); + } + +@@ -592,12 +592,12 @@ rowload(Row *row, char *file, int initing) + r2.min.x = x; + if(Dx(r1) < 50 || Dx(r2) < 50) + continue; +- draw(screen, Rpt(r1.min, r2.max), display->white, nil, ZP); ++ draw(screen, Rpt(r1.min, r2.max), winbgcol, nil, ZP); + colresize(c1, r1); + colresize(c2, r2); + r2.min.x = x-Border; + r2.max.x = x; +- draw(screen, r2, display->black, nil, ZP); ++ draw(screen, r2, winbordercol, nil, ZP); + } + if(i >= row->ncol) + rowadd(row, nil, x); +diff --git a/src/cmd/acme/text.c b/src/cmd/acme/text.c +index 09422dda..92404ddc 100644 +--- a/src/cmd/acme/text.c ++++ b/src/cmd/acme/text.c +@@ -542,6 +542,8 @@ textbswidth(Text *t, Rune c) + /* there is known to be at least one character to erase */ + if(c == 0x08) /* ^H: erase character */ + return 1; ++ if(c == 0x7F) /* DEL */ ++ return 1; + q = t->q0; + skipping = TRUE; + while(q > 0){ +@@ -691,11 +693,6 @@ texttype(Text *t, Rune r) + if(t->q1 < t->file->b.nc) + textshow(t, t->q1+1, t->q1+1, TRUE); + return; +- case Kdown: +- if(t->what == Tag) +- goto Tagdown; +- n = t->fr.maxlines/3; +- goto case_Down; + case Kscrollonedown: + if(t->what == Tag) + goto Tagdown; +@@ -709,11 +706,6 @@ texttype(Text *t, Rune r) + q0 = t->org+frcharofpt(&t->fr, Pt(t->fr.r.min.x, t->fr.r.min.y+n*t->fr.font->height)); + textsetorigin(t, q0, TRUE); + return; +- case Kup: +- if(t->what == Tag) +- goto Tagup; +- n = t->fr.maxlines/3; +- goto case_Up; + case Kscrolloneup: + if(t->what == Tag) + goto Tagup; +@@ -725,27 +717,61 @@ texttype(Text *t, Rune r) + q0 = textbacknl(t, t->org, n); + textsetorigin(t, q0, TRUE); + return; +- case Khome: ++ ++/* ++ * Keybindings for moving the cursor up and ++ * down the text via up and down arrow keys. ++ */ ++ ++ case Kdown: ++ if(t->what == Tag) ++ goto Tagdown; + typecommit(t); +- if(t->org > t->iq1) { +- q0 = textbacknl(t, t->iq1, 1); +- textsetorigin(t, q0, TRUE); +- } else +- textshow(t, 0, 0, FALSE); ++ /* 1rst check for being in the last line*/ ++ q0 = t->q0; ++ q1 = q0; ++ if (q1) q1--; ++ nnb = 0; ++ while(q0<t->file->b.nc && textreadc(t, q0)!='\n') ++ q0++; ++ if (q0 == (t->file->b.nc)-1) { ++ textshow(t, q0, q0, TRUE); ++ return; ++ } ++ q0++; ++ /* find old pos in ln */ ++ while(q1>1 && textreadc(t, q1)!='\n'){ ++ nnb++; ++ q1--; ++ } ++ /* go right until reachg pos or \n */ ++ while(q0<t->file->b.nc && (nnb>0 && textreadc(t, q0)!='\n')){ ++ q0++; ++ nnb--; ++ } ++ if (q0>1 && q0<t->file->b.nc) ++ textshow(t, q0, q0, TRUE); + return; +- case Kend: ++ case Kup: ++ if(t->what == Tag) ++ goto Tagup; + typecommit(t); +- if(t->iq1 > t->org+t->fr.nchars) { +- if(t->iq1 > t->file->b.nc) { +- // should not happen, but does. and it will crash textbacknl. +- t->iq1 = t->file->b.nc; +- } +- q0 = textbacknl(t, t->iq1, 1); +- textsetorigin(t, q0, TRUE); +- } else +- textshow(t, t->file->b.nc, t->file->b.nc, FALSE); ++ nnb = 0; ++ if(t->q0>0 && textreadc(t, t->q0-1)!='\n') ++ nnb = textbswidth(t, 0x15); ++ /* BOL - 1 if not first line of txt BOL*/ ++ if( t->q0-nnb > 1 && textreadc(t, t->q0-nnb-1)=='\n' ) nnb++; ++ textshow(t, t->q0-nnb, t->q0-nnb, TRUE); + return; +- case 0x01: /* ^A: beginning of line */ ++ ++/* ++ * Home and End now respectively take you to the ++ * beginning and to the end of the line respectively. ++ * Also keep the original ^A and ^E keybindings. ++ */ ++ ++ case 0x01: ++ case Khome: + typecommit(t); + /* go to where ^U would erase, if not already at BOL */ + nnb = 0; +@@ -753,13 +779,17 @@ texttype(Text *t, Rune r) + nnb = textbswidth(t, 0x15); + textshow(t, t->q0-nnb, t->q0-nnb, TRUE); + return; +- case 0x05: /* ^E: end of line */ ++ case 0x05: ++ case Kend: + typecommit(t); + q0 = t->q0; + while(q0<t->file->b.nc && textreadc(t, q0)!='\n') + q0++; + textshow(t, q0, q0, TRUE); + return; ++ ++/* I'll keep the MAC-keybindings 'cuz im such a nice guy */ ++ + case Kcmd+'c': /* %C: copy */ + typecommit(t); + cut(t, t, nil, TRUE, FALSE, nil, 0); +@@ -773,14 +803,32 @@ texttype(Text *t, Rune r) + undo(t, nil, nil, FALSE, 0, nil, 0); + return; + ++/* ++ * Adding Windows and X11 -compatible Ctrl+C, Ctrl+Z and ++ * Ctrl+Y (for redoing). TODO: find out how to check out for ++ * shift press, for Ctrl+Shift+Z in this godforsaken switch() ++ */ ++ ++ case 0x03: /* Ctrl+C: copy */ ++ typecommit(t); ++ cut(t, t, nil, TRUE, FALSE, nil, 0); ++ return; ++ case 0x1A: /* Ctrl+Z: undo */ ++ typecommit(t); ++ undo(t, nil, nil, TRUE, 0, nil, 0); ++ return; ++ case 0x19: /* Ctrl+Y: redo */ ++ typecommit(t); ++ undo(t, nil, nil, FALSE, 0, nil, 0); ++ return; ++ + Tagdown: + /* expand tag to show all text */ + if(!t->w->tagexpand){ +- t->w->tagexpand = TRUE; +- winresize(t->w, t->w->r, FALSE, TRUE); ++ t->w->tagexpand = TRUE; ++ winresize(t->w, t->w->r, FALSE, TRUE); + } + return; +- + Tagup: + /* shrink tag to single line */ + if(t->w->tagexpand){ +@@ -790,11 +838,16 @@ texttype(Text *t, Rune r) + } + return; + } ++ ++ ++ + if(t->what == Body){ + seq++; + filemark(t->file); + } ++ + /* cut/paste must be done after the seq++/filemark */ ++ + switch(r){ + case Kcmd+'x': /* %X: cut */ + typecommit(t); +@@ -816,7 +869,31 @@ texttype(Text *t, Rune r) + textshow(t, t->q0, t->q1, 1); + t->iq1 = t->q1; + return; ++ ++ /* Same for Windows / X11 */ ++ ++ case 0x18: /* Ctrl+X: cut */ ++ typecommit(t); ++ if(t->what == Body){ ++ seq++; ++ filemark(t->file); ++ } ++ cut(t, t, nil, TRUE, TRUE, nil, 0); ++ textshow(t, t->q0, t->q0, 1); ++ t->iq1 = t->q0; ++ return; ++ case 0x16: /* Ctrl+V: paste */ ++ typecommit(t); ++ if(t->what == Body){ ++ seq++; ++ filemark(t->file); ++ } ++ paste(t, t, nil, TRUE, FALSE, nil, 0); ++ textshow(t, t->q0, t->q1, 1); ++ t->iq1 = t->q1; ++ return; + } ++ + if(t->q1 > t->q0){ + if(t->ncache != 0) + error("text.type"); +@@ -824,6 +901,7 @@ texttype(Text *t, Rune r) + t->eq0 = ~0; + } + textshow(t, t->q0, t->q0, 1); ++ + switch(r){ + case 0x06: /* ^F: complete */ + case Kins: +@@ -844,9 +922,21 @@ texttype(Text *t, Rune r) + typecommit(t); + t->iq1 = t->q0; + return; ++ ++ case 0x7F: /* [delete key] */ ++ /* ensure we're not at the end of the buffer */ ++ if(t->q1 >= t->file->b.nc) { ++ return; ++ } ++ /* emulate rightarrow key */ ++ typecommit(t); ++ textshow(t, t->q1+1, t->q1+1, TRUE); ++ /* emulate backspace key */ ++ // r = 0x08; /* needed for textbswidth() to return correct value */ ++ /* now fall through to next case */ + case 0x08: /* ^H: erase character */ + case 0x15: /* ^U: erase line */ +- case 0x17: /* ^W: erase word */ ++ case 0x17: /* ^W: erase word */ + if(t->q0 == 0) /* nothing to erase */ + return; + nnb = textbswidth(t, r); +diff --git a/src/cmd/acme/wind.c b/src/cmd/acme/wind.c +index 9441bbb7..98c97368 100644 +--- a/src/cmd/acme/wind.c ++++ b/src/cmd/acme/wind.c +@@ -235,7 +235,6 @@ winresize(Window *w, Rectangle r, int safe, int keepextra) + r1.min.y = min(y, r.max.y); + r1.max.y = r.max.y; + }else{ +- draw(screen, r1, textcols[BACK], nil, ZP); + r1.min.y = y; + r1.max.y = y; + } diff --git a/img/acme.png b/img/acme.png new file mode 100644 index 0000000..4207e3f --- /dev/null +++ b/img/acme.png Binary files differdiff --git a/img/suckme.png b/img/suckme.png new file mode 100644 index 0000000..7f0394d --- /dev/null +++ b/img/suckme.png Binary files differ |