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