AmendHub

Download:

jcs

/

amend

/

amendments

/

15

browser+committer: Enable TETab on all TextEdits

Fix some logic errors in UpdateScrollbarForTE

jcs made amendment 15 over 3 years ago
--- browser.c Mon Oct 18 13:09:06 2021 +++ browser.c Thu Oct 21 17:37:32 2021 @@ -23,6 +23,7 @@ #include "committer.h" #include "diff.h" #include "repo.h" +#include "tetab.h" #include "util.h" void browser_add_files(struct browser *browser); @@ -144,12 +145,11 @@ browser_init(struct repo *repo) bounds.left = padding; bounds.right = browser->win->portRect.right - SCROLLBAR_WIDTH - padding; bounds.bottom = browser->win->portRect.bottom - padding; - TextFont(monaco); - TextSize(9); te_bounds = bounds; InsetRect(&te_bounds, 2, 2); - browser->diff_te = TENew(&te_bounds, &bounds); + browser->diff_te = TEStylNew(&te_bounds, &bounds); TEAutoView(true, browser->diff_te); + TETabEnable(browser->diff_te); /* scrollbar for diff text */ bounds.right = browser->win->portRect.right - padding; @@ -325,7 +325,6 @@ browser_show_commit(struct browser *browser, struct re SetCursor(&arrow); } - InvalRect(&(*(browser->diff_te))->viewRect); UpdateScrollbarForTE(browser->diff_scroller, browser->diff_te, true); } @@ -404,7 +403,6 @@ browser_update(struct browser *browser, EventRecord *e case updateEvt: FillRect(&browser->win->portRect, fill_pattern); - TextFont(monaco); r = (*(browser->diff_te))->viewRect; FillRect(&r, white); TEUpdate(&r, browser->diff_te); @@ -563,7 +561,7 @@ browser_mouse_down(struct browser *browser, EventRecor if (adj != 0) { val -= adj; if (control == browser->diff_scroller) - TEScroll(0, adj * (*(browser->diff_te))->lineHeight, + TEScroll(0, adj * TEGetHeight(0, 0, browser->diff_te), browser->diff_te); SetCtlValue(control, val); } --- committer.c Mon Oct 18 16:47:01 2021 +++ committer.c Fri Oct 22 10:23:36 2021 @@ -23,6 +23,7 @@ #include "committer.h" #include "diff.h" #include "repo.h" +#include "tetab.h" #include "util.h" /* needed by diffreg */ @@ -30,10 +31,14 @@ struct stat stb1, stb2; long diff_format, diff_context, status = 0; char *ifdefname, *diffargs, *label[2], *ignore_pats; -#define DIFF_LINE_SIZE 1024 +#define DIFF_LINE_SIZE 512 Handle diff_line = NULL; size_t diff_line_pos = 0; +#define DIFF_CHUNK_SIZE (1024 * 4) +Handle diff_chunk = NULL; +size_t diff_chunk_pos = 0; + static short padding = 10; static short diff_too_big = 0; @@ -46,7 +51,8 @@ void committer_generate_diff(struct committer *committ void committer_update_menu(struct committer *committer); void committer_status(char *format, ...); void committer_commit(struct committer *committer); -void diff_append_line(char *str, size_t len); +void diff_append_line(char *str, size_t len, bool flush); +void diff_chunk_write(void); void diff_finish(void); void @@ -55,6 +61,7 @@ committer_init(struct browser *browser) char title[256] = { 0 }; struct committer *committer; Rect bounds = { 0 }, te_bounds = { 0 }; + TextStyle style; short fh; committer = xmalloczero(sizeof(struct committer)); @@ -82,15 +89,19 @@ committer_init(struct browser *browser) bounds.top = padding; bounds.left = 50; fh = FontHeight(monaco, 9); - bounds.bottom = bounds.top + 2 + (fh * 5) + 2; + bounds.bottom = bounds.top + (fh * 5) + 2; bounds.right = committer->win->portRect.right - SCROLLBAR_WIDTH - padding; - TextFont(monaco); - TextSize(9); te_bounds = bounds; InsetRect(&te_bounds, 2, 2); - committer->log_te = TENew(&te_bounds, &bounds); + TextFont(monaco); + TextSize(9); + committer->log_te = TEStylNew(&te_bounds, &bounds); + style.tsFont = monaco; + style.tsSize = 9; + TESetStyle(doFont | doSize, &style, false, committer->log_te); TEAutoView(true, committer->log_te); + TETabEnable(committer->log_te); /* scrollbar for log message */ bounds.left = bounds.right; @@ -107,12 +118,11 @@ committer_init(struct browser *browser) padding; bounds.right = committer->win->portRect.right - SCROLLBAR_WIDTH - padding; - TextFont(monaco); - TextSize(9); te_bounds = bounds; InsetRect(&te_bounds, 2, 2); - committer->diff_te = TENew(&te_bounds, &bounds); + committer->diff_te = TEStylNew(&te_bounds, &bounds); TEAutoView(true, committer->diff_te); + TETabEnable(committer->diff_te); /* scrollbar for diff */ bounds.left = bounds.right; @@ -153,10 +163,13 @@ committer_close(struct committer *committer) DisposeWindow(committer->win); TEDispose(committer->log_te); DisposHandle(committer->log_scroller); - TEDispose(committer->diff_te); DisposHandle(committer->diff_scroller); DisposHandle(committer->commit_button); + /* in case the hText got committed as a resource */ + ReleaseResource((*(committer->log_te))->hText); + TEDispose(committer->diff_te); + free(committer); } @@ -179,14 +192,12 @@ committer_update(struct committer *committer, EventRec switch (what) { case -1: case updateEvt: + r = (*(committer->log_te))->viewRect; + MoveTo(r.top, r.top + FontHeight(applFont, 11) - 2); TextFont(applFont); TextSize(11); - - r = (*(committer->log_te))->viewRect; - MoveTo(r.top, r.top + FontHeight(applFont, 10) - 2); DrawText("Log:", 0, 4); - TextFont(monaco); r = (*(committer->log_te))->viewRect; TEUpdate(&r, committer->log_te); InsetRect(&r, -1, -1); @@ -228,7 +239,8 @@ committer_key_down(struct committer *committer, EventR k = (event->message & charCodeMask); TEKey(k, committer->log_te); - UpdateScrollbarForTE(committer->log_scroller, committer->log_te, false); + UpdateScrollbarForTE(committer->log_scroller, committer->log_te, + false); committer_update_menu(committer); } @@ -287,10 +299,10 @@ committer_mouse_down(struct committer *committer, Even if (adj != 0) { val -= adj; if (control == committer->diff_scroller) - TEScroll(0, adj * (*(committer->diff_te))->lineHeight, + TEScroll(0, adj * TEGetHeight(0, 0, committer->diff_te), committer->diff_te); else if (control == committer->log_scroller) - TEScroll(0, adj * (*(committer->log_te))->lineHeight, + TEScroll(0, adj * TEGetHeight(0, 0, committer->log_te), committer->log_te); SetCtlValue(control, val); } @@ -335,6 +347,7 @@ committer_generate_diff(struct committer *committer) short i; short *selected_files = NULL; short nselected_files = 0; + TextStyle style; SetCursor(*(GetCursor(watchCursor))); @@ -355,6 +368,10 @@ committer_generate_diff(struct committer *committer) HLock(committer->diff_te); + style.tsFont = monaco; + style.tsSize = 9; + TESetStyle(doFont | doSize, &style, false, cur_committer->diff_te); + for (i = 0; i < nselected_files; i++) { file = repo_file_with_id(committer->browser->repo, selected_files[i]); @@ -369,7 +386,8 @@ committer_generate_diff(struct committer *committer) HUnlock(committer->diff_te); InvalRect(&committer->win->portRect); - UpdateScrollbarForTE(committer->diff_scroller, committer->diff_te, true); + UpdateScrollbarForTE(committer->diff_scroller, committer->diff_te, + true); cur_committer = NULL; committer_status(NULL); @@ -476,7 +494,8 @@ diff_output(const char *format, ...) for (i = last_pos; i < diff_line_pos; i++) { if (((char *)*diff_line)[i] == '\n') { ((char *)*diff_line)[i] = '\r'; - diff_append_line(*diff_line + last_line, i - last_line + 1); + diff_append_line(*diff_line + last_line, i - last_line + 1, + false); last_line = i + 1; } } @@ -493,37 +512,56 @@ diff_output(const char *format, ...) } void -diff_append_line(char *str, size_t len) +diff_append_line(char *str, size_t len, bool flush) { - unsigned long cur_htext_size; short tabsize; - cur_htext_size = GetHandleSize((*(cur_committer->diff_te))->hText); - if (cur_committer->diff_te_len + len >= cur_htext_size) { - SetHandleSize((*(cur_committer->diff_te))->hText, - cur_htext_size + (1024 * 4)); - if (MemError()) - err(1, "Out of memory! Can't expand diff TE beyond %lu bytes.", - cur_htext_size); + if (diff_chunk == NULL) { + diff_chunk = xNewHandle(DIFF_CHUNK_SIZE); + diff_chunk_pos = 0; } + if (str[0] == '-' && str[1] != '-') + cur_committer->diff_subs++; + else if (str[0] == '+' && str[1] != '+') + cur_committer->diff_adds++; + + if (diff_chunk_pos + len >= DIFF_CHUNK_SIZE) + diff_chunk_write(); + + HLock(diff_chunk); + memcpy(*diff_chunk + diff_chunk_pos, str, len); + HUnlock(diff_chunk); + diff_chunk_pos += len; + + if (flush) + diff_chunk_write(); +} + +void +diff_chunk_write(void) +{ + HLock(diff_chunk); + + if (cur_committer->diff_te_len + diff_chunk_pos > MAX_TEXTEDIT_SIZE) { + HUnlock((*(cur_committer->diff_te))->hText); + SetHandleSize((*(cur_committer->diff_te))->hText, + cur_committer->diff_te_len + diff_chunk_pos); + if (MemError()) + err(1, "Out of memory! Can't expand diff TE by %lu bytes.", + diff_chunk_pos); HLock((*(cur_committer->diff_te))->hText); memcpy(*(*(cur_committer->diff_te))->hText + - cur_committer->diff_te_len, str, len); + cur_committer->diff_te_len, *diff_chunk, diff_chunk_pos); HUnlock((*(cur_committer->diff_te))->hText); - - cur_committer->diff_te_len += len; - - if (!diff_too_big && TECanAddLine(cur_committer->diff_te, len)) { - (*(cur_committer->diff_te))->teLength = cur_committer->diff_te_len; } else { - diff_too_big = 1; + TEStylInsert(*diff_chunk, diff_chunk_pos, 0, + cur_committer->diff_te); } + HUnlock(diff_chunk); - if (str[0] == '-' && str[1] != '-') - cur_committer->diff_subs++; - else if (str[0] == '+' && str[1] != '+') - cur_committer->diff_adds++; + cur_committer->diff_te_len += diff_chunk_pos; + diff_chunk_pos = 0; } void @@ -531,26 +569,20 @@ diff_finish(void) { if (diff_line != NULL) { if (diff_line_pos) - diff_append_line(*diff_line, diff_line_pos); + diff_append_line(*diff_line, diff_line_pos, true); DisposHandle(diff_line); diff_line = NULL; } -#if 0 if (diff_chunk != NULL) { - if (diff_chunk_pos) { - TESetSelect(1024 * 32, 1024 * 32, cur_committer->diff_te); - TEInsert((*diff_chunk), diff_chunk_pos, - cur_committer->diff_te); - } - - diff_chunk_pos = 0; + if (diff_chunk_pos) + diff_chunk_write(); DisposHandle(diff_chunk); diff_chunk = NULL; } -#endif + HUnlock((*(cur_committer->diff_te))->hText); SetHandleSize((*(cur_committer->diff_te))->hText, cur_committer->diff_te_len); TECalText(cur_committer->diff_te); --- repo.c Mon Oct 18 17:12:17 2021 +++ repo.c Fri Oct 22 13:10:20 2021 @@ -331,23 +331,33 @@ repo_file_with_id(struct repo *repo, short id) void repo_show_diff_text(struct repo_commit *commit, TEHandle te) { - char buf[512]; - Handle diffh; + Handle diffh, allh; + TextStyle style; struct tm *ttm = NULL; - unsigned long diff_len; - short header_len, i, blen; + char *buf; + char truncbuf[64]; + unsigned long diff_len, all_len; + short header_len, i, blen, height, trunc = 0; + unsigned short warn_off; diffh = Get1Resource(REPO_DIFF_RTYPE, commit->id); if (diffh == NULL) err(1, "failed finding DIFF %d", commit->id); - HLock(diffh); - HLock(commit->log); - diff_len = GetHandleSize(diffh); + if (diff_len == 0) { + /* + * Not sure why this happens when viewing the diff that was just + * committed. + */ + ReleaseResource(diffh); + diffh = Get1Resource(REPO_DIFF_RTYPE, commit->id); + diff_len = GetHandleSize(diffh); if (diff_len == 0) - LoadResource(diffh); + err(1, "diff still zero bytes"); + } + buf = xmalloc(512); ttm = localtime(&commit->date); header_len = sprintf(buf, "Author: %s\r" @@ -357,32 +367,63 @@ repo_show_diff_text(struct repo_commit *commit, TEHand ttm->tm_year + 1900, ttm->tm_mon + 1, ttm->tm_mday, ttm->tm_hour, ttm->tm_min, ttm->tm_sec); + /* copy log, indenting each line */ + HLock(commit->log); for (i = 0; i < commit->log_len; i++) { - buf[header_len++] = (*(commit->log))[i]; + *(buf + header_len++) = (*(commit->log))[i]; if ((*(commit->log))[i] == '\r' && i < commit->log_len - 1) { - buf[header_len++] = ' '; - buf[header_len++] = ' '; + *(buf + header_len++) = ' '; + *(buf + header_len++) = ' '; } } - buf[header_len++] = '\r'; - buf[header_len++] = '\r'; + HUnlock(commit->log); + *(buf + header_len++) = '\r'; + *(buf + header_len++) = '\r'; - TESetText("", 0, te); - TEAppendFast(buf, header_len, te); + all_len = header_len + diff_len; + if (all_len >= MAX_TEXTEDIT_SIZE) { + all_len = MAX_TEXTEDIT_SIZE; + trunc = 1; + } + allh = xNewHandle(all_len); - if (diff_len + header_len > 32767L) { - diff_len = 32767L - header_len - strlen(REPO_DIFF_TOO_BIG) - 20; - blen = sprintf(buf, REPO_DIFF_TOO_BIG, - GetHandleSize(diffh) - diff_len); - TEAppendFast(*diffh, diff_len, te); - TEAppendFast(buf, blen, te); - } else - TEAppendFast(*diffh, diff_len, te); + /* + * A more memory-efficient method would be: + * + * DetachResource(diffh); + * SetHandleSize(diffh, all_len); + * memmove(*diffh, *diffh + header_len, all_len - header_len); + * memcpy(*diffh, buf, header_len); + * + * But memmove doesn't support overlapping buffers :/ + */ + HLock(allh); + memcpy(*allh, buf, header_len); + free(buf); + + HLock(diffh); + memcpy(*allh + header_len, *diffh, all_len - header_len); ReleaseResource(diffh); - TECalText(te); + if (trunc) { + warn_off = MAX_TEXTEDIT_SIZE - header_len - + strlen(REPO_DIFF_TOO_BIG); + blen = sprintf(truncbuf, REPO_DIFF_TOO_BIG, + diff_len - warn_off); + memcpy(*allh + MAX_TEXTEDIT_SIZE - blen, truncbuf, blen); + } + + TESetText("", 0, te); + /* manually reset scroll without TESetSelect(0, 0, te) which redraws */ + height = (*te)->destRect.bottom - (*te)->destRect.top; + (*te)->destRect.top = (*te)->viewRect.top; + (*te)->destRect.bottom = (*te)->viewRect.top + height; + style.tsFont = monaco; + style.tsSize = 9; + TESetStyle(doFont | doSize, &style, false, te); + TEStylInsert(*allh, all_len, 0, te); } struct repo_file * --- util.c Mon Oct 18 13:14:58 2021 +++ util.c Fri Oct 22 13:02:18 2021 @@ -460,32 +460,42 @@ DrawGrowIconOnly(WindowPtr win) void UpdateScrollbarForTE(ControlHandle scroller, TEHandle te, bool reset) { - size_t vlines; + size_t vlines, telines; TERec *ter; - short vtop; + short vtop, lheight; + short max, val; HLock(te); ter = *te; - vlines = (ter->viewRect.bottom - ter->viewRect.top) / ter->lineHeight; - if (vlines >= ter->nLines) - vlines = ter->nLines; - SetCtlMax(scroller, ter->nLines - vlines + 1); +#define ceildiv(a,b) ((a / b) + (!!(a % b))) - if (reset) { - SetCtlValue(scroller, 1); + lheight = TEGetHeight(0, 0, te); + vlines = (ter->viewRect.bottom - ter->viewRect.top) / lheight; + telines = ter->nLines; + /* telines is inaccurate if the last line doesn't have any chars */ + if (telines >= vlines) + telines++; + max = telines - vlines; + if (max < 1) + max = 1; - /* - * TESetSelect will redraw if TEAutoView is enabled, but only if - * the control was scrolled already - */ + if (reset) { + val = 1; vtop = (*te)->viewRect.top; TESetSelect(0, 0, te); - if (vtop == (*te)->viewRect.top) - TEUpdate(&ter->viewRect, te); - ValidRect(&ter->viewRect); - } else if (GetCtlValue(scroller) > GetCtlMax(scroller)) - SetCtlValue(scroller, GetCtlMax(scroller)); + } else { + val = (ter->viewRect.top - ter->destRect.top); + if (val < 0) + val = 1; + else { + val = ceildiv(val, lheight) + 1; + if (val > max) + max = val; + } + } + SetCtlMax(scroller, max); + SetCtlValue(scroller, val); HUnlock(te); } @@ -499,15 +509,16 @@ SetTrackControlTE(TEHandle te) pascal void TrackMouseDownInControl(ControlHandle control, short part) { - short page, val, adj; + short page, val, adj, lheight; if (track_control_te == NULL) err(1, "TrackMouseDownInControl without SetTrackControlTE"); + lheight = TEGetHeight(0, 0, track_control_te); + /* keep 1 line of context between pages */ page = (((*track_control_te)->viewRect.bottom - - (*track_control_te)->viewRect.top) / - (*track_control_te)->lineHeight) - 1; + (*track_control_te)->viewRect.top) / lheight) - 1; adj = 0; switch (part) { @@ -533,7 +544,7 @@ TrackMouseDownInControl(ControlHandle control, short p if (adj == 0) return; - TEScroll(0, -adj * (*track_control_te)->lineHeight, track_control_te); + TEScroll(0, -adj * lheight, track_control_te); SetCtlValue(control, val + adj); } --- util.h Mon Oct 18 13:09:59 2021 +++ util.h Thu Oct 21 21:20:25 2021 @@ -27,6 +27,8 @@ #define SCROLLBAR_WIDTH 16 +#define MAX_TEXTEDIT_SIZE 32767L + #define nitems(what) (sizeof((what)) / sizeof((what)[0])) #ifndef bool