jcs
/amend
/amendments
/56
util: Sync with upstream
jcs made amendment 56 over 2 years ago
--- util.c Wed Jan 19 16:02:32 2022
+++ util.c Thu Feb 3 16:35:25 2022
@@ -86,7 +86,7 @@ xmalloc(size_t size)
panic("xmalloc: zero size");
ptr = malloc(size);
if (ptr == NULL)
- panic("xmalloc: allocating %zu bytes", size);
+ panic("xmalloc(%lu) failed", size);
return ptr;
}
@@ -105,7 +105,7 @@ xcalloc(size_t nmemb, size_t size)
ptr = calloc(nmemb, size);
if (ptr == NULL)
- panic("xcalloc: allocating %zu * %zu bytes", nmemb, size);
+ panic("xcalloc(%lu, %lu) failed", nmemb, size);
return ptr;
}
@@ -116,7 +116,7 @@ xrealloc(void *src, size_t size)
ret = realloc(src, size);
if (ret == NULL)
- panic("Couldn't realloc %lu bytes of memory", size);
+ panic("realloc(%lu) failed", size);
return ret;
}
@@ -127,7 +127,7 @@ xmallocarray(size_t nmemb, size_t size)
{
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size)
- panic("xmallocarray");
+ panic("xmallocarray(%lu, %lu) failed", nmemb, size);
return xmalloc(size * nmemb);
}
@@ -138,7 +138,7 @@ xreallocarray(void *optr, size_t nmemb, size_t size)
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size)
- panic("xreallocarray");
+ panic("xreallocarray(%lu, %lu) failed", nmemb, size);
return xrealloc(optr, size * nmemb);
}
@@ -200,11 +200,39 @@ ordinal(unsigned short n)
}
}
-static char ostype_s[5];
+long
+strpos_quoted(char *str, char c)
+{
+ long pos;
+ unsigned char quot = 0;
+
+ for (pos = 0; str[pos] != '\0'; pos++) {
+ if (quot) {
+ if (str[pos] == '\\') {
+ pos++;
+ continue;
+ }
+ if (str[pos] == quot)
+ quot = 0;
+ continue;
+ } else {
+ if (str[pos] == '"') {
+ quot = str[pos];
+ continue;
+ }
+ if (str[pos] == c)
+ return pos;
+ }
+ }
+
+ return -1;
+}
char *
OSTypeToString(OSType type)
{
+ static char ostype_s[5];
+
ostype_s[0] = (unsigned char)((type >> 24) & 0xff);
ostype_s[1] = (unsigned char)((type >> 16) & 0xff);
ostype_s[2] = (unsigned char)((type >> 8) & 0xff);
@@ -863,45 +891,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);
}
@@ -915,17 +996,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:
@@ -950,6 +1044,60 @@ 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;
+}
+
+/* (*(some_te))->caretHook = NullCaretHook; */
+pascal void
+NullCaretHook(void)
+{
+ asm {
+ move.l (a7)+,d0
+ rts
+ }
+}
--- util.h Mon Jan 10 16:40:54 2022
+++ util.h Thu Feb 3 16:41:00 2022
@@ -17,6 +17,7 @@
#ifndef __UTIL_H__
#define __UTIL_H__
+#include <stddef.h>
#include <stdlib.h>
#include <limits.h>
#include <time.h>
@@ -26,6 +27,7 @@
#endif
#define nitems(what) (sizeof((what)) / sizeof((what)[0]))
+#define member_size(type, member) sizeof(((type *)0)->member)
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
@@ -72,6 +74,7 @@ short getline(char *str, size_t len, char **ret);
size_t strlcpy(char *dst, const char *src, size_t dsize);
size_t strlcat(char *dst, const char *src, size_t dsize);
const char *ordinal(unsigned short n);
+long strpos_quoted(char *str, char c);
char *OSTypeToString(OSType type);
unsigned long xorshift32(void);
@@ -104,8 +107,12 @@ 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);
+pascal void NullCaretHook(void);
#endif