AmendHub

Download:

jcs

/

subtext

/

amendments

/

57

util: Add ask() DIT, make TE* functions work with horizontal scrolling


jcs made amendment 57 over 2 years ago
--- util.c Mon Jan 17 15:29:55 2022 +++ util.c Fri Jan 21 14:31:05 2022 @@ -40,6 +40,21 @@ static char alert_ditl[] = { }; static Handle alert_ditl_h = NULL; +/* DITL with a Yes button (1), No button (2), text (3), and icon (4) */ +static char ask_ditl[] = { + 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, + 0x00, 0xE6, 0x00, 0x5A, 0x01, 0x20, 0x04, 0x03, + 0x59, 0x65, 0x73, 0x21, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x46, 0x00, 0xA0, 0x00, 0x5A, 0x00, 0xDA, + 0x04, 0x02, 0x4E, 0x6F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0A, 0x00, 0x32, 0x00, 0x41, 0x01, 0x22, + 0x08, 0x02, 0x5E, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x2A, 0x00, 0x2A, + 0xA0, 0x02, 0x00, 0x01 +}; +static Handle ask_ditl_h = NULL; + +/* DITL with just a text view */ static char progress_ditl[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x1E, 0x00, 0x32, 0x01, 0x3B, 0x08, 0x02, @@ -323,22 +338,49 @@ note(const char *format, ...) short ask(const char *format, ...) { - size_t len; - short ret; - WindowPtr win; + Rect bounds, irect; + short height, width, hit; + WindowPtr win, dialog; + OSType itype; + Handle ihandle; va_list ap; GetPort(&win); va_start(ap, format); - len = vsnprintf(err_str, ERROR_STRING_SIZE, format, ap); + vsnprintf(err_str, ERROR_STRING_SIZE, format, ap); va_end(ap); - ParamText(CtoPstr(err_str), "\p", "\p", "\p"); - ret = StopAlert(ASK_ALERT_ID, nil); + width = 300; + height = 100; + bounds.left = (screenBits.bounds.right - width) / 2; + bounds.right = bounds.left + width; + bounds.top = GetMBarHeight() + + ((screenBits.bounds.bottom - height) / 2.5); + bounds.bottom = bounds.top + height; + ParamText(CtoPstr(err_str), "\p", "\p", "\p"); + + ask_ditl_h = xNewHandle(sizeof(ask_ditl)); + HLock(ask_ditl_h); + memcpy(*ask_ditl_h, ask_ditl, sizeof(ask_ditl)); + HUnlock(ask_ditl_h); + + dialog = NewDialog(nil, &bounds, "\p", false, dBoxProc, + (WindowPtr)-1L, false, 0, ask_ditl_h); + + ShowWindow(dialog); + for (;;) { + ModalDialog(0, &hit); + if (hit == 1 || hit == 2) + break; + } + DisposDialog(dialog); + DisposHandle(alert_ditl_h); + SetPort(win); - return ret; + + return (hit == 1); } void @@ -821,45 +863,98 @@ DrawGrowIconOnly(WindowPtr win) DisposeRgn(tmp); } +/* assumes a fixed-width style */ +short +TEGetWidth(short off, TEHandle te) +{ + TextStyle style; + short fheight, fwidth, ascent, old_font, old_size; + + TEGetStyle(off, &style, &fheight, &ascent, te); + + old_font = thePort->txFace; + old_size = thePort->txSize; + thePort->txFace = style.tsFont; + thePort->txSize = style.tsSize; + fwidth = CharWidth('m'); + thePort->txFace = old_font; + thePort->txSize = old_size; + + return fwidth; +} + +#define ceildiv(a,b) ((a / b) + (!!(a % b))) + void -UpdateScrollbarForTE(ControlHandle scroller, TEHandle te, bool reset) +UpdateScrollbarForTE(ControlHandle control, TEHandle te, bool reset) { size_t vlines, telines; TERec *ter; - short vtop, lheight; - short max, val; + short fheight, fwidth, max, val, per_page, per_line, horiz, max_chars, + n; HLock(te); ter = *te; -#define ceildiv(a,b) ((a / b) + (!!(a % b))) + horiz = (((*control)->contrlRect.bottom - (*control)->contrlRect.top) < + ((*control)->contrlRect.right - (*control)->contrlRect.left)); - 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; - - if (reset) { - val = 1; - vtop = (*te)->viewRect.top; - TESetSelect(0, 0, te); + if (horiz) { + fwidth = TEGetWidth(0, te); + per_line = ((ter->viewRect.right - ter->viewRect.left) / + fwidth) - 1; + for (max_chars = 0, n = 1; n < ter->nLines; n++) { + if (ter->lineStarts[n] - ter->lineStarts[n - 1] > max_chars) + max_chars = ter->lineStarts[n] - ter->lineStarts[n - 1]; + } + + if (max_chars <= per_line) + /* don't enable the scrollbar */ + max = 1; + else + max = max_chars - per_line + 1; + + if (reset) { + val = 1; + TESetSelect(0, 0, te); + } else { + val = (ter->viewRect.left - ter->destRect.left); + + if (val < 0) + val = 1; + else { + val = ceildiv(val, fwidth) + 1; + if (val > max) + max = val; + } + } } else { - val = (ter->viewRect.top - ter->destRect.top); - if (val < 0) + fheight = TEGetHeight(0, 0, te); + vlines = (ter->viewRect.bottom - ter->viewRect.top) / fheight; + telines = ter->nLines; + /* telines is inaccurate if the last line doesn't have any chars */ + if (telines >= vlines) + telines++; + max = telines - vlines + 1; + if (max < 1) + max = 1; + + if (reset) { val = 1; - else { - val = ceildiv(val, lheight) + 1; - if (val > max) - max = val; + TESetSelect(0, 0, te); + } else { + val = (ter->viewRect.top - ter->destRect.top); + if (val < 0) + val = 1; + else { + val = ceildiv(val, fheight) + 1; + if (val > max) + max = val; + } } } - SetCtlMax(scroller, max); - SetCtlValue(scroller, val); + SetCtlMax(control, max); + SetCtlValue(control, val); HUnlock(te); } @@ -873,17 +968,30 @@ SetTrackControlTE(TEHandle te) pascal void TrackMouseDownInControl(ControlHandle control, short part) { - short page, val, adj, lheight; - + TERec *ter; + short page, val, adj, fheight, fwidth, horiz, per_line; + if (track_control_te == NULL) panic("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) / lheight) - 1; - + HLock(track_control_te); + ter = *track_control_te; + + horiz = (((*control)->contrlRect.bottom - (*control)->contrlRect.top) < + ((*control)->contrlRect.right - (*control)->contrlRect.left)); + + if (horiz) { + fwidth = TEGetWidth(0, track_control_te); + per_line = ((ter->viewRect.right - ter->viewRect.left) / + fwidth) - 1; + page = ceildiv(GetCtlMax(control) + per_line, + ((per_line * 75) / 100)) + 1; + } else { + /* keep 1 line of context between pages */ + fheight = TEGetHeight(0, 0, track_control_te); + page = ((ter->viewRect.bottom - ter->viewRect.top) / fheight) - 1; + } + adj = 0; switch (part) { case inUpButton: @@ -908,6 +1016,50 @@ TrackMouseDownInControl(ControlHandle control, short p if (adj == 0) return; - TEScroll(0, -adj * lheight, track_control_te); + if (horiz) + TEScroll(-adj * fwidth, 0, track_control_te); + else + TEScroll(0, -adj * fheight, track_control_te); + SetCtlValue(control, val + adj); -} + + HUnlock(track_control_te); +} + +pascal bool +ModalDialogFilter(DialogPtr dlg, EventRecord *event, short *hit) +{ + char key; + + switch (event->what) { + case keyDown: + key = event->message & charCodeMask; + + if (event->modifiers & cmdKey) { + switch (key) { + case 'x': + ZeroScrap(); + DlgCut(dlg); + break; + case 'c': + ZeroScrap(); + DlgCopy(dlg); + break; + case 'v': + if (TEFromScrap() == noErr) + DlgPaste(dlg); + break; + } + event->what = nullEvent; + return false; + } else if (key == 13 || key == 3) { + /* OK button */ + *hit = 1; + return true; + } + + break; + } + + return false; +} --- util.h Mon Jan 10 16:40:54 2022 +++ util.h Fri Jan 21 14:28:14 2022 @@ -104,8 +104,11 @@ OSErr FSReadLine(short frefnum, char *buf, size_t bufl short FontHeight(short font_id, short size); void DrawGrowIconOnly(WindowPtr win); +short TEGetWidth(short off, TEHandle te); void UpdateScrollbarForTE(ControlHandle scroller, TEHandle te, bool reset); void SetTrackControlTE(TEHandle te); pascal void TrackMouseDownInControl(ControlHandle control, short part); +pascal bool ModalDialogFilter(DialogPtr dlg, EventRecord *event, + short *hit); #endif