From 70acc3bd6b37c8435106468175f6c24f71527770 Mon Sep 17 00:00:00 2001 From: ElectricAlchemist Date: Wed, 30 Oct 2019 21:42:12 +0100 Subject: [PATCH] backed up and did some minor optimizations --- Makefile | 3 +- ste | Bin 22232 -> 22504 bytes ste.bak | 644 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ ste.c | 29 +-- 4 files changed, 661 insertions(+), 15 deletions(-) create mode 100644 ste.bak diff --git a/Makefile b/Makefile index 9672dff..2341577 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,8 @@ CC=gcc CFLAGS=-Wall -Wextra -pedantic -Werror OFLAGS=-O3 -LFLAGS=-lncursesw -ltcmalloc +LFLAGS=-lncursesw +#-ltcmalloc ste: ste.c $(CC) $(CFLAGS) $(OFLAGS) $(LFLAGS) -o ste $^ diff --git a/ste b/ste index ed0cf4d18166351c01062d527625de68b66ed7fe..6f21cd0abefdc8b9f387cb46fdd63be242697945 100755 GIT binary patch literal 22504 zcmeHP4|G)3nSYbXgW*qRf)E-}$`peQQeuJz6JazDCh$fFi5O6^I)=#vQu5Da!XHHl zPC|M6c$l_ot!`V^wpQD1#cgX{*Ode`5l*`Tu8QkFv})f#ML-SskJ;aM-@TJJL#Eq3 zXV0EJdved2_ucPzzwh4fe)sRYGjlgp1{Y*G9Fho5=?aOsol`8Nf+wu1;t`MvsZ1J! z=U1i4(g^U`471WJEP_-ktjbEIE{;1vN$(M!o=zumIYEVmL`g4GxM8f7BB+#W@uVkH zl=JD-$g|`G73s5J2!h)6$Tx?4ELl3VD3z9Ry+TnLZWpzh zb4Lg&{7Ko+=UML0bm~VM1wl!cLe+cGT8ek@dZp7^CM8LN3cYKgM|S?Lfmcsj!pqC# zmqKp8puD=$#SQf*?kWCZtA(t+^W~sE6-lIO)SIu$&nTlL!PkUAuZFbaoeY&-uzW8q-`yY z@7Yo)P`xNr8)=QKtZ$1(TB{e$Z)k3cRM)I%h)AK(%EsoVP+PR7H5v+8qC*O{MQhu_ zt(T^WgjprT=`hLLskQK^mT)k$^DEs-XvCDPi8VxZLkt})UWZdotYg&Ue-ePc~S zLvt8)4@cLxL_#Y<#34^ijpUK=x|&d3eN#;X*>{G2B6oHK=QAgsIoGw$>oW)<{HJ z7!1stADUHkNitS)X)-!%_F%NAl-fwlnAYqmIMIg0XLFe>MhUTEmJF@JS(s&|*uE)&P6m4%={HGfA2@e4M4qp2uzYWE+0khF@UA#rPoaOtss=Awr=I7i%@8729yO58?`CHr&3RSJ-eWTLjgH3!hS2l?_M3B*P6hd~_0( zq+4zH7#lA3nN%j<%CXcIn>;#7GOV-V?j$Nn9X8x!!?)US`@Gj}!^hj?@3-N!#}HwM z4d+`&mh^}XpD2VuciQl;*zhN9c)ktqvEk?1@aJu~*c(&wej9$CP5zJ#Ki`HQw&7p3 z;ie7euK+CdxDEH()M`xKfhTuAXRCV!s-D*0m>T zc%t+jBqgT3i>GHw1!BanqV)LT1j4lcAfA?{_50d?({~6HiN1 zdC(h~1s{8hx$k`mv^_<6+BQWD?6_{)i>B_!U>_*ul$(h=`q{6)mmk`ZrV z{8Zv;sfgdo_({am5)rRr{5iza(h#p;{Al87Nr)FSK8tu-3gTYIpTw&{T{n0Zl2>HCH`J6sA|ulqj@@~!sTkezo3jV3mOdt6+xr6pp2jjf;>|?hy=A` zLG90~cEmhL%K8R~XnktzbRv2o^4XMgG~YADkE~+H9MK%l6aLE*b4N!{%*}~@V0NQb zjy_`szNAt=G`|CCzD|tpn|1}v*-5}_7BB(8GtBN^5V{nF?V?U=iCEU+wY&=<9Ob<%|QwNKEy~&9h|%KEN*fR{fBXeC zOFg0}YL0vlBAUD$PmggFxxtrj%#oyW`7wgFzXixCUynF?25r_g`64jptDjLWQxHWr zE*a2$`G^{-qol{Y1_dCO?;{tkW3K+38fFnh^wJN3BY7Q&Ii5tr@*#r4r5_Nn{6`)u zZ^`v+E5U%%bBBQ__8!T7w4(zB`F975Wm!Rw|D@I{^`ekMqy}Pd zI#q3V$v|Lw9~?HBnK=>(mD(px`9egL^1e-r>O50A;eN947|Mqk^FjQWHeN%`F# zKSPTEp8@-Na}IM64AkYffH~#INu%7n^J%#G9}rjdIm(l_Kob5oh{u>SvODnU zSGAL>Ug7dQkzG7@RPy3K+o@aVGd!D4zD8I+wgOTsV)Qpk;aXEE5b0(~z z=>VLnozTarvEH*h6W4aze4-lHW~mtMP z>HEy1s1ePM`H;F2&{JqVDzXi6bK_~&L|;c-G|}gP^wJ*yfr1-E&)biuGw-{2nmlG zgF8>xVic-|eGfpgWI$b=C{&$u%pUAAV0kaVcs0CA^KtC-I8W!#u)WzBF*?p5tJrC$ z=i9kf9luWnZ9bFDT(Adw956CtZnPLDW8R0fE*Fuou{2S>-(w6=MzRx#1H&=?0R(tG zVy8z(N5xL(c)I=(g`%fk0wKTdJAN6s)jhD&>DM+Cp!L_e^kUP%Mo5=Ekiq<|l)vIJ z?uEC5VKZiC&G17kye}~QId%2k!bPh;C=43w4+V_Mt+d)>5o7DB?!3lmC@Z|ixU?(~ z`>-&e-uA zw55`HFW?~7av?o-3n1?LB`9nks%&b6)}WD8ZTy1*OIo-=2W2|5_X*ywktg+ zYss8|))&-vld9KDpgNT14d|Ql=l5lgzK zWWcW-Kly9*)B#m{!7L$bxVUzV>iK^XC$a zl`H-g%qpHK=%il-(sj^t_d}-=30kHf0PUB*xYQ~lW;#j^YVxOG;~hw;>^itHUx^)Y zRF>@Rmk)9&Kh}Ljt#UQ_HN-XF0X$0%#^cb!R5k;g`9670_f4VrFFwL_F%3XT!u%0P zzq}PN1=RB;MEm7U9EjgSOI+9&1J9-;F*7_2Cqeq>z~h%gretrt1w`3J?dAdHvLJ(J%b1|Fz3{hoHrL^g*e7=Exa0I%Wl>s!B@=EE> zIQ8HYC#WZXXqMANWXMY>7k%bWKw^?3ehDg|M`?I|XpThBjQ^f?oU)2!YTXHxoHv!Y zgPzV2;Lw(6WG&APOq0EMqPti#nvOlz7yzE_Z_w)IJ2ne$jgIb@-=PSCYUI3#sOE@2 zO$%07ejA*skHIoQS?F^e<-UD@HiQ(TJyCwrW86a-?RLcE9|3m6d=G+1THd1|l(9xE zg6?+|BJ(w1k$H$RH*!{i(;e8Gdtos68?01?rOH=P6+)D-vQ`J?H4aqW4`+!g$e1s z=vWN42Y{Of`i!{>CicmXf_L03^aPFHfyBY(xEp1yCqrOtgJ)M&wr5wx2)|L`(B;cf zA1zP9vtMqdG7-=w%l^jqrTI`X7G!BJE7Nq1BOI7VlRPH6z)a*Wv2Gf0eDPH{{D*6H*^yYaA)Ot2*3wu%t%K%tX4U+B_|((+DhlbBxAWpk4$^G8 zj&nyR)pb{FEyEn4>JZ0pDIdRaDVd_3@I0|05BrE-ydVZ0Jrx~^QSJZUCv9MY;eo#F zVy~fOsd`(!dOy}tuW?&8CB=H3YItv7w#%E6>84+*;g_|Xu_#x?`(f$l*gyB7b=z|3 zFzTk8_Y69m*CBF@Jj?13J-1{4!u@hD?Ya>L)zF!}cqKQlM`MclY#C;UU68~fhxQ51 zInaLB1@)C!oA)Rk8?qBpy9<8ldYUqN(?9B%r}J?{m5#aD*cLv4C~Zo+eu#(~zEcWl zUz)FefS!Vln~GT&GjQy4$HsC@n-dDQ=IWEHQB>^ntc?Xvq7|{frTG}HVAH8Sc{WmM zIySCLU`GBEW_UHcr~JiDQ_#4bkVnBu`Ct}SZ_M17eviav{%Iyg4^BqR)qhDOZbB!! zS^1`NvvN!PmzZYJUvJ{P7+03DXUuOfW0x^w@j?T8sXmU7WV&h6#`V^ffamV9mh`PSq zMEUBz5C~pL)$oA%>`^o@27L<_ttx`=z@A^e0ds~*j_y$Gi?$@T6o3T}i$tM9gtZqgg+=D*j#A%^< z0o%w(%Jn$ucnl^h%L14ymIkQPDB2fGalEnv@O8oIUs4^+-yDI#y`?=rimE((W18wNz$}7@8w=Rrqz1s2Z4o1nqb`kvIg}4SE=_O~rU&?Evq^%ky#29#A?{mvERszjJQE znFpP*9mjFlPeFI!RE_<990#5)^vaGf!6K65_9c>IU9RK2u_ImGj*+>9pO4QYc%huZ zWrz$dFG&SRBYE>p%QnfKyTF})m1oRaSBG@vq&XK|QZQBM;}}8OaX68{SDDF>i`X~u zDMX#_;V6~Wg3oV(;gk#S8t&XJu=`R(x8n0U@Or8*!xeXa%(>9*bxv}OcIN|9+^(y~ zd@C7O#sneSgU#Sp&Pum;TejjZ+#>tk#jz1ty`$ZQez$j?J0CLh z+%9#D0z^qc@NW0=d=|PZzU3}MzNjn8N!E}3w)A!6vlaPJ zzQbYI1H&E|_Q0?QhCMLsfng5}dtlfD{~tWi?X_xA#i`iqrc?S47KO1EN&X>=w(1l* zr&;t|izNSNbsp!%yUirdi~n2EI}!zv{>hm{Gvo1N0SfrGnuTusG=KspQZY{#{}uW% zH<;cJDdby3%HvcJu7*D%SqOjalh{|bfW-S8`{@pN@gJNW{Le}Pf1VpG?56in3S2B% zK7PHy>VqUEif1<9HaJr1sI!@Pcx`osG zIDMGYCphin^kq)p=X8Kmt8_HtwN`B5{P~xA3-J%}>E809Sw+Pn{jX6ce(d{*=x{bc zC(c&H|L|=v{&((_%pv8o2k#NEDL64&#JI4*$Yq2i#!o6fQWE_v6?aLZf2QK2B+>6v z@zIhPAE`J-BX7S{e5~Xh631+Ej$P7U zIi&pf_d+>f{Pj%YIt3Dlc(^ z;Tc59&O%$ye zxVVDlbN0Ac$mPZVu|@XF8GiOSZDjeJJzieH{Fp_j!Wi=Q5QF?V@IwdRm#}OhK>q_D zVk(h-2Hb1UfX6$Lzjui7*qb4reHrir8SvMTKizwFB-;3XOG%QN6g20V}fUz7pAF#{gXfZqk2 z{3fOO?QY;+;Y1t#5%6(Y`N{QOB>gf&{`4d4akh0w%#(j)@@~n?`yo4%MrLm?`Lpl4 zcsE1-nS^HM^>X4o|-ptxf$@U zWWX=VfM1aTugrii&w$ru!0*U_8^Ea@)BW%R;NG*VEBz)zKK~4S>JaiTWsrX}1O8qH zoZS>s6vj;+5j?H$*8)v-%~C_rrI*brm2jg;qrX1FQ}{P;^++o(mgwRU#LCL0X8dLp zP>F;u;{1_@NHj8kRSmwO8~j?1R4$!`OGTO@6f2e*nuwN2jUc6EQn)qR7Hvm1VQKI# zl~A-XggZs>EgdcjscjCeY-nCl(-5kSHn+BgYTDOH;pWB`Dy_EYvP;T}hZdsCM(RWC zK9NwQDcVZ6iqtelLbdIUjq9Oe<3e=NN{VPGv|x#{s4`S}ji2ssNfoG-LjD`CQ5FT} zr>3xrSO8&{9;#G%4yu2N6j~TuJWmOR7B5(EU1fEsTA3HDq+Hn@DB-qtW-7b%q@qIH zdNK>Qn*6mZW|B9%@Y`GL_ovu$nLT*TODKXbQERAi+W3_%HaV1LUFwpGF~?Z<$%wmY z_(e37BJQTK-$29d!u>L5-SLu|HCh(tSXaP6Hub`sP;FatXjM&9Exx(6ZkZWW#w{?R zz+x!Y);ERP+ahR=K~Iuds0q7O$NK(wP?5Pbw4$wz7s~FP;aBbO%Wv2%H>n!dl{cvv zzlDciZj+jpay5^2c}}VTU8|FdghIGINc1(jR%pn(f~*^TQZLd;&1dkEAL~A$l&g3K zMX|*yYFpokVGJ5=wdg7l!!1FP))uJMqmx?fbG-65^VtV~= zLv-GRr4oBWD~R`PLDS!qNY)-M07GXyLSMX>3(8+Fk}6`I7Xbd4m7*`+-v#vwK~B^4 z{lM|hvu07gxGzvp@!lcM#awCmT?3xZz=Xay4-oWLtUna!9F6KO^u>AEGGHVk^u@V> zpyHejA}pl)kNyWsXIesEoG%Efay?y$@ZuaoQ1QB)Za>dfx*ZYnsn8ea z6@rR$I#GUl{X4n-Jf5LA*AP^k6Ouli4W{dF2Sz>-=ajT1WPww0p2$&VtB4cT@UiQA zxt^eh(;S|by+rTrcKzgLo^R@fy;K$j!3#=%Sg`AheWIYZjc01fhbUhFKS|RU=fZ-D z^HCw6-v1xv`l9`k=Qzcd#+^cu({%mE)AYr8kD#^xh5oKIeQ_=%s5fbtm67n9$aXIx zbe6)0S@Qfy++&$8FL*&;g09D=FV4vi`v4*cIg1$J*2VHe*&*=b};|| literal 22232 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 +#include +#include +#include + +/* defines */ +#define CTRL(k) ((k) & 0x1f) // Control mask modifier +#define TABSIZE 4 // Tab size as used in render + +/* main data structure containing: + * -cursor position + * +real (matching memory) + * +offset (memory and screen offset) + * +render (drawn on the screen) + * -window size + * -statusbar message */ +struct term { + struct { + int x; + int y; + int off_x; + int off_y; + int r_x; + int r_y; + int xx; + int yy; + } cur; + + struct { + int x; + int y; + } dim; + + char statusbar[30]; + int pad; +} t; + +/* Row structure, defines actual and + * render chars, actual and render size + * and difference between render and + * real size of the row */ +typedef struct row { + int size; + char *chars; + int r_size; + char *render; + int delta; +} row; + +/* Rows structure (or file buffer) + * defines rows and teh number of rows */ +struct { + row *rw; + long rownum; +} rows; + +/* Prototypes */ +/* draw operations */ +static void drawBar (char *s); +static void drawScreen (); +static void drawLines (void); +static void updateRender (row *rw); +static void updateScroll (void); +static void cursorMove(int a); +static int decimalSize (int n); +static inline void lnMove (int y, int x); +static int curRealToRender (row *rw, int c_x); + +/* Row operations */ +static inline void rowInit (void); +static void rowAddChar (row *rw, char c); +static void rowDeleteChar (row *rw, int m); +static void rowCpy (row *to, row *from); + +/* Terminal operations */ +static void termInit (void); +static void termExit (void); +static void termDie (char *s); + +/* file operations */ +static void fileOpen (char *filename); +void fileSave (char *filename); + +/* buffer operations */ +static void rowAddLast (char *s, int len); + +/* garbage */ + +/* testing */ +static void updateInfo (void); +static void rowAddRow (int pos); +static int whatsThat (void); +static void rowFree (row *rw); + + +/* --------------------------------- main ------------------------------------ */ +int main (int argc, char *argv[]) +{ + /* Initialize the first row */ + rowInit(); + + /* Try to open the file */ + if (argc != 2) { + perror("File not found"); + exit(1); + } else fileOpen(argv[1]); + + /* Initialize the terminal in raw mode, + * start curses and initialize the term struct */ + termInit(); + + /* Set the statusbar left (static) message */ + sprintf(t.statusbar, "%s : %s %ld lines %dx%d", argv[0], argv[1], rows.rownum, t.dim.y, t.dim.y); + + /* remember the initial row number */ + int irow = decimalSize(rows.rownum); + + /* Main event loop */ + int c; + while (1) { + /* Redraw the screen */ + drawScreen(); + + /* Wait for an event (keypress) */ + switch (c = getch()) { + case (CTRL('q')): + termExit(); + break; + case (KEY_LEFT): + case (KEY_RIGHT): + case (KEY_UP): + case (KEY_DOWN): + cursorMove(c); + break; + case (KEY_BACKSPACE): + rowDeleteChar(&rows.rw[t.cur.yy], 0); + break; + case (KEY_DC): + rowDeleteChar(&rows.rw[t.cur.yy], 1); + break; + case (KEY_ENTER): + case (10): + case ('\r'): + rowAddRow(t.cur.yy); + break; + case (KEY_END): + t.cur.y = rows.rownum; + t.cur.off_y = 0; + break; + case (KEY_HOME): + t.cur.y = 0; + t.cur.off_y = 0; + break; + default: + if (c == KEY_STAB) c = '\t'; + rowAddChar(&rows.rw[t.cur.yy], c); + } + if (decimalSize(rows.rownum) - irow) updateInfo(); + } + + /* If by chance i find myself here be sure + * end curses mode and clenaup */ + termExit(); + return 0; +} + +/* ----------------------------- end of main ---------------------------------- */ + +void termInit (void) +{ + /* Init the screen and refresh */ + initscr(); + refresh(); + + /* Enable raw mode, this makes the termianl ignore + * interrupt signals like CTRL+C and CTRL+Z + * allowing us to make our own bindings */ + raw(); + + /* Allow use of function keys */ + keypad(stdscr, TRUE); + + /* Turn off echoing */ + noecho(); + + /* Set the tab size */ + set_tabsize(TABSIZE); + + /* Start color mode */ + start_color(); + init_pair(2, COLOR_BLACK, COLOR_CYAN); + init_pair(1, COLOR_RED, COLOR_BLACK); + + /* Set default color */ + //bkgd(COLOR_PAIR(1)); + + /* Populate the main data structure */ + updateInfo(); + + /* Initialize the data staructure */ + t.cur.x = t.cur.off_x = 0; + t.cur.y = t.cur.off_y = 0; +} + +/* Calculate the correct spacing for the line numbers + * based on the size of the file */ +int decimalSize (int n) +{ + static int l; + for (l = 0; n > 0; l++) n /= 10; + return l + 1; +} + +void termExit (void) +{ + erase(); + refresh(); + endwin(); + exit(0); +} + +void termDie (char *s) +{ + erase(); + refresh(); + endwin(); + perror(s); + exit(1); +} + +/* ----------------------------- term operations -------------------------------- */ + +void drawScreen () +{ + /* Clear the screen */ + erase(); + /* Update Scroll */ + updateScroll(); + /* draw the lines */ + drawLines(); + /* draw the bar */ + drawBar(t.statusbar); + /* move back to the cursor position */ + lnMove(t.cur.y, t.cur.r_x); + /* refresh the screen */ + refresh(); +} + +/* Draw all the appropriate lines (following cursor) to the screen */ +void drawLines (void) +{ + static unsigned int line = 0, ln = 0; + static int i = 0; + /* move to the beginning of the screen */ + //lnMove(0, 0); + + for (i = 0; i < t.dim.y; i++) { + if (i >= rows.rownum) break; + ln = i + t.cur.off_y; + + /* Draw the line number */ + attron(COLOR_PAIR(1)); + move(i, 0); + printw("%d", ln + 1); + attroff(COLOR_PAIR(1)); + lnMove(i, 0); + + /* Draw the line matcing render memory */ + addnstr(&rows.rw[ln].render[t.cur.off_x], t.dim.x + 1 - rows.rw[ln].delta); + + lnMove(++line, 0); + } + lnMove(t.cur.y, t.cur.x); +} + +/* Move avoiding the space allocated for line numbers */ +void lnMove (int y, int x) +{ + move(y, x + t.pad); +} + +/* Draw the status bar at the bottom of the screen */ +void drawBar (char *s) +{ + /* Set maximum contrast for bar */ + attron(COLOR_PAIR(2)); + /* get the length of the statusbar text */ + int len = strlen(s); + /* Print the message */ + mvprintw(t.dim.y, 0, s); + /* Fill everything else with spaces */ + for (int i = len; i <= t.dim.x + t.pad; i++) + mvaddch(t.dim.y, i, ' '); + + static char m[40]; + sprintf(m, "x: %d y: %d Zoom: %c", t.cur.xx, t.cur.yy, whatsThat()); + mvaddstr(t.dim.y, t.dim.x + t.pad - strlen(m), m); + + /* Return to normal contrast mode */ + attroff(COLOR_PAIR(2)); +} + +/* convert the cursor matchoing the memory to the drawn one */ +int curRealToRender (row *rw, int c_x) +{ + static int r_x = 0, i = 0; + for (i = 0, r_x = 0; i < c_x; i++) { + if (rw->chars[i] == '\t') r_x += (TABSIZE - 1) - (r_x % TABSIZE); + r_x++; + } + return r_x; +} + +/* -------------------------------- draw operations -------------------------------- */ + +/* Open a file and put it into a buffer line by line */ +void fileOpen (char *filename) +{ + FILE *fp = fopen(filename, "r"); + if (!fp) termDie("Cannot open file"); + + /* Init the linebuffer */ + char *line = NULL; + /* Set linecap to 0 so getline will atumatically allocate + * memory for the line buffer*/ + size_t linecap = 0; + ssize_t linelen; + + /* getline returns -1 if no new line is present */ + while ((linelen = getline(&line, &linecap, fp)) != -1) { + while (linelen > 0 && (line[linelen - 1] == '\n' || line[linelen - 1] == '\r')) + linelen--; + rowAddLast(line, linelen); + } + /* free the line buffer */ + free(line); + /* close the file */ + fclose(fp); +} + +/* Add a row to the file buffer */ +void rowAddLast (char *s, int len) +{ + /* Extend the block of memory containing the lines */ + // reallocarray fails safely + row *newr = NULL; + newr = (row*) reallocarray(rows.rw, (rows.rownum + 1), sizeof(*newr)); + if (newr == NULL) termDie("realloc rowAddLast"); + else rows.rw = newr; + //rows.rw = (row*) realloc(rows.rw, sizeof(row) * (rows.rownum + 1)); + + /* Allocate memory for the line and copy it + * at the current row number */ + rows.rw[rows.rownum].chars = (char*) malloc(len + 1); + memcpy(rows.rw[rows.rownum].chars, s, len); + rows.rw[rows.rownum].chars[len] = '\0'; + rows.rw[rows.rownum].size = len; + updateRender(&rows.rw[rows.rownum]); + rows.rownum++; +} + +void updateRender (row *rw) +{ + /* count the special characters (only tabs for now) */ + int tabs = 0, i; + for (i = 0; i <= rw->size; i++) { + if (rw->chars[i] == '\t') tabs++; + } + rw->render = NULL; + free(rw->render); + + /* Render is long as size with the added tab spaces - 1 + * (we already count for the \t as a char) */ + rw->render = malloc(rw->size + tabs * (TABSIZE - 1) + 1); + + if (rw->render == NULL) termDie ("malloc in updateRender"); + + /* put all the characters (substituing all special chars) + * into the render buffer */ + static int off, j = 0; + off = 0; + for (i = 0; i <= rw->size; i++) { + if (rw->chars[i] == '\t') { + for (j = 0; j < TABSIZE; j++){ + if (!j) rw->render[off++] = '|'; + else rw->render[off++] = ' '; + } + } else { + rw->render[off++] = rw->chars[i]; + } + } + off -= 1; + rw->render[off] = '\0'; + rw->r_size = off; +} + +void rowInit (void) +{ + rows.rw = NULL; + rows.rownum = 0; +} + +void rowAddChar (row *rw, char c) // WIP +{ + // Error checking (allow tab) + if (!c || (iscntrl(c) && c != '\t')) return; + + int i = 0; + char *s = rw->chars; + + // reallocate mem and inc size + rw->chars = (char*) malloc(rw->size + 2); + rw->size++; + + // copy bf cursor + for (i = 0; i < t.cur.xx; i++) { + rw->chars[i] = s[i]; + } + + // add at cursor + rw->chars[t.cur.xx++] = c; + + //copy after cursor + for (i = t.cur.xx; i < rw->size + 1; i++) { + rw->chars[i] = s[i - 1]; + } + + free(s); + + updateRender(rw); + t.cur.x++; +} + +void rowDeleteChar (row *rw, int m) // WIP +{ + char *s = rw->chars; + //Do not delete NULL char + if (s[t.cur.xx - 1] == '\0' && t.cur.xx) return; + if (!t.cur.xx && !m) return; + if (s[t.cur.xx] == '\0' && m) return; + + rw->chars = malloc(rw->size); + rw->size--; + + // Backspace + if (!m) { + for (int i = 0; i < t.cur.xx - 1; i++) + rw->chars[i] = s[i]; + + for (int i = t.cur.xx; i < rw->size + 1; i++) + rw->chars[i - 1] = s[i]; + + t.cur.x--; + // Delete + } else { + if(t.cur.xx) { + for (int i = 0; i < t.cur.xx; i++) + rw->chars[i] = s[i]; + } + + for (int i = t.cur.xx; i < rw->size + 1; i++) + rw->chars[i] = s[i + 1]; + } + + free(s); + updateRender(rw); +} + +/* ----------------------------- file operations --------------------------- */ + +/* take care of the cursor movement */ +void cursorMove (int a) +{ + switch (a) { + case (KEY_LEFT): + if (t.cur.x <= 0 && !t.cur.off_x) { + if (t.cur.y) { + t.cur.y--; + t.cur.yy--; + t.cur.x = rows.rw[t.cur.yy].size; + } + } else t.cur.x--; + break; + + case (KEY_RIGHT): + if (t.cur.xx >= rows.rw[t.cur.yy].size) { + if (t.cur.yy < rows.rownum - 1) { + t.cur.y++; + t.cur.yy++; + if (t.cur.off_x) t.cur.off_x = 0; + t.cur.x = rows.rw[t.cur.yy].size; + } + } else t.cur.x++; + break; + + case (KEY_UP): + if (t.cur.yy > 0) { + if (t.cur.y) { + t.cur.y--; + t.cur.yy--; + if (t.cur.xx > rows.rw[t.cur.yy].size) { + if (t.cur.off_x) t.cur.off_x = 0; + t.cur.x = rows.rw[t.cur.yy].size; + } + } + break; + + case (KEY_DOWN): + if (t.cur.yy < rows.rownum - 1) { + t.cur.y++; + t.cur.yy++; + if (t.cur.xx > rows.rw[t.cur.yy].size) { + if (t.cur.off_x) t.cur.off_x = 0; + t.cur.x = rows.rw[t.cur.yy].size; + } + } + break; + } + } +} + +void updateScroll (void) +{ + /* Set y offset */ + if (t.cur.y >= t.dim.y) { + if (t.cur.y == t.dim.y) t.cur.off_y++; + else t.cur.off_y += t.cur.y - t.dim.y; + + t.cur.y = t.dim.y - 1; + + } else if (t.cur.y <= 0 && t.cur.off_y > 0) { + t.cur.off_y--; + t.cur.y = 0; + } + + /* Set x offeset */ + if (t.cur.x >= t.dim.x) { + if (t.cur.x == t.dim.x - 1) t.cur.off_x++; + else t.cur.off_x += t.cur.x - t.dim.x; + + t.cur.x = t.dim.x; + + } else if (t.cur.x <= 0 && t.cur.off_x > 0) { + t.cur.off_x--; + t.cur.x = 0; + } + /* convert the cursor from real to render */ + t.cur.yy = t.cur.y + t.cur.off_y; + t.cur.xx = t.cur.x + t.cur.off_x; + t.cur.r_x = curRealToRender(&rows.rw[t.cur.yy], t.cur.x); +} + +/*---------------------------------- scroll ------------------------------------*/ + +/* See whats under the cursor (memory) */ +int whatsThat (void) { + int c = rows.rw[t.cur.yy].chars[t.cur.xx]; + switch (c) { + case ('\t'): + return '^'; + break; + case (' '): + return '~'; + break; + case ('\0'): + return '.'; + break; + default: + return c; + break; + } + return 0; +} + +void rowAddRow (int pos) // WIP; TO DOCUMENT +{ + char *s = NULL; + // Move away other lines + //copy old last line to new space + rowAddLast(rows.rw[rows.rownum].chars, rows.rw[rows.rownum].size); + + for (int last = rows.rownum - 1; last > pos; last--) { + rowCpy(&rows.rw[last], &rows.rw[last - 1]); + } + + //copy previous row + int l = rows.rw[pos].size - t.cur.xx; + s = malloc(l + 1); + memcpy(s, &rows.rw[pos].chars[t.cur.xx], l); + s[l] = '\0'; + // Delete prev row until cursor + char *p = malloc(t.cur.xx + 1); + memcpy(p, rows.rw[pos].chars, t.cur.xx); + p[t.cur.xx] = '\0'; + rowFree(&rows.rw[pos]); + rows.rw[pos].chars = malloc(t.cur.xx + 1); + memcpy(rows.rw[pos].chars, p, t.cur.xx + 1); + free(p); + rows.rw[pos].size = t.cur.xx; + updateRender(&rows.rw[pos]); + + if (pos != rows.rownum - 1) { + rowFree(&rows.rw[pos + 1]); + rows.rw[pos + 1].chars = malloc(strlen(s) + 1); + memcpy(rows.rw[pos + 1].chars, s, strlen(s) + 1); + rows.rw[pos + 1].size = strlen(s); + updateRender(&rows.rw[pos + 1]); + } else rowAddLast(s, l); + + free(s); + t.cur.y++; + t.cur.x = 0; + t.cur.off_x = 0; +} + +void rowFree (row *rw) // WIP +{ + free(rw->render); + free(rw->chars); + rw->size = 0; + rw->r_size = 0; +} + +void rowCpy (row *to, row *from) // WIP +{ + rowFree(to); + to->chars = malloc(strlen(from->chars) + 1); + if (to->chars == NULL) termDie("malloc in rowCpy"); + to->size = from->size; + memcpy(to->chars, from->chars, to->size); + updateRender(to); +} + +/*--------------------------------- garbage ------------------------------------*/ + +void updateInfo (void) +{ + getmaxyx(stdscr, t.dim.y, t.dim.x); + t.dim.y -= 1; + t.pad = decimalSize(rows.rownum); + t.dim.x -= t.pad + 1; +} + +/*--------------------------------- testing ------------------------------------*/ diff --git a/ste.c b/ste.c index b6ddaaa..b053481 100644 --- a/ste.c +++ b/ste.c @@ -63,7 +63,7 @@ static void updateRender (row *rw); static void updateScroll (void); static void cursorMove(int a); static int decimalSize (int n); -static void lnMove (int y, int x); +static inline void lnMove (int y, int x); static int curRealToRender (row *rw, int c_x); /* Row operations */ @@ -249,11 +249,11 @@ void drawScreen () /* Draw all the appropriate lines (following cursor) to the screen */ void drawLines (void) { - int line = 0, ln; + static int line = 0, ln, i; /* move to the beginning of the screen */ - lnMove(0, 0); + //lnMove(0, 0); - for (int i = 0; i < t.dim.y; i++) { + for (i = 0; i < t.dim.y; i++) { if (i >= rows.rownum) break; ln = i + t.cur.off_y; @@ -278,10 +278,9 @@ void drawLines (void) } /* Move avoiding the space allocated for line numbers */ -void lnMove (int y, int x) +inline void lnMove (int y, int x) { - x += t.pad; - move(y, x); + move(y, x + t.pad); } /* Draw the status bar at the bottom of the screen */ @@ -297,7 +296,7 @@ void drawBar (char *s) for (int i = len; i <= t.dim.x + t.pad; i++) mvaddch(t.dim.y, i, ' '); - char m[40]; + static char m[40]; sprintf(m, "x: %d y: %d Zoom: %c", t.cur.xx, t.cur.yy, whatsThat()); mvaddstr(t.dim.y, t.dim.x + t.pad - strlen(m), m); @@ -347,7 +346,10 @@ void fileOpen (char *filename) void rowAddLast (char *s, int len) { /* Extend the block of memory containing the lines */ - rows.rw = realloc(rows.rw, sizeof(row) * (rows.rownum + 1)); + row *newr = reallocarray(rows.rw, rows.rownum + 1, sizeof(row)); + if (newr == NULL) termDie("realloc in rowAddLast"); + else rows.rw = newr; + //rows.rw = realloc(rows.rw, sizeof(row) * (rows.rownum + 1)); /* Allocate memory for the line and copy it * at the current row number */ @@ -362,8 +364,8 @@ void rowAddLast (char *s, int len) void updateRender (row *rw) { /* count the special characters (only tabs for now) */ - int tabs = 0, i; - for (i = 0; i < rw->size; i++) { + static int tabs = 0, i, off; + for (i = 0, tabs = 0; i < rw->size; i++) { if (rw->chars[i] == '\t') tabs++; } rw->render = NULL; @@ -377,8 +379,7 @@ void updateRender (row *rw) /* put all the characters (substituing all special chars) * into the render buffer */ - int off = 0; - for (i = 0; i < rw->size; i++) { + for (i = 0, off = 0; i < rw->size; i++) { if (rw->chars[i] == '\t') { for (int j = 0; j < TABSIZE; j++){ if (!j) rw->render[off++] = '|'; @@ -622,7 +623,7 @@ void rowFree (row *rw) // WIP void rowCpy (row *to, row *from) // WIP { rowFree(to); - to->chars = malloc(strlen(from->chars) + 1); + to->chars = (char*) malloc(strlen(from->chars) + 1); to->size = from->size; memcpy(to->chars, from->chars, to->size); updateRender(to);