AmendHub

Download:

jcs

/

subtext

/

amendments

/

51

util: Sync with files from Amend


jcs made amendment 51 over 2 years ago
--- util.c Tue Jan 4 13:56:08 2022 +++ util.c Mon Jan 10 22:12:47 2022 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021 joshua stein <jcs@jcs.org> + * Copyright (c) 2020-2022 joshua stein <jcs@jcs.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -25,6 +25,7 @@ #define ASK_ALERT_ID 130 #define ERROR_STRING_SIZE 1024 +static char err_str[ERROR_STRING_SIZE]; /* basic DITL with an ok button (1), text area (2), and icon (3) */ #define ALERT_DITL_ICON 3 @@ -37,15 +38,22 @@ static char alert_ditl[] = { 0x00, 0x0A, 0x00, 0x2A, 0x00, 0x2A, 0xA0, 0x02, 0x00, 0x02 }; -static Handle alert_ditl_h; +static Handle alert_ditl_h = NULL; +static char progress_ditl[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x1E, 0x00, 0x32, 0x01, 0x3B, 0x08, 0x02, + 0x5E, 0x30 +}; +static Handle progress_ditl_h = NULL; +static DialogPtr progress_dialog = NULL; + enum { STOP_ALERT, CAUTION_ALERT, NOTE_ALERT }; -Handle err_str = NULL; static TEHandle track_control_te = NULL; void vwarn(short alert_func, const char *format, va_list ap); @@ -60,10 +68,10 @@ xmalloc(size_t size) void *ptr; if (size == 0) - err(2, "xmalloc: zero size"); + panic("xmalloc: zero size"); ptr = malloc(size); if (ptr == NULL) - err(2, "xmalloc: allocating %zu bytes", size); + panic("xmalloc: allocating %zu bytes", size); return ptr; } @@ -82,7 +90,7 @@ xcalloc(size_t nmemb, size_t size) ptr = calloc(nmemb, size); if (ptr == NULL) - err(2, "xcalloc: allocating %zu * %zu bytes", nmemb, size); + panic("xcalloc: allocating %zu * %zu bytes", nmemb, size); return ptr; } @@ -93,7 +101,7 @@ xrealloc(void *src, size_t size) ret = realloc(src, size); if (ret == NULL) - err(2, "Couldn't realloc %lu bytes of memory", size); + panic("Couldn't realloc %lu bytes of memory", size); return ret; } @@ -104,7 +112,7 @@ xmallocarray(size_t nmemb, size_t size) { if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && nmemb > 0 && SIZE_MAX / nmemb < size) - err(2, "xmallocarray"); + panic("xmallocarray"); return xmalloc(size * nmemb); } @@ -115,7 +123,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) - err(2, "xreallocarray"); + panic("xreallocarray"); return xrealloc(optr, size * nmemb); } @@ -128,8 +136,7 @@ xstrdup(const char *str) len = strlen(str); cp = xmalloc(len + 1); - strncpy(cp, str, len); - cp[len] = '\0'; + strlcpy(cp, str, len + 1); return cp; } @@ -178,24 +185,24 @@ ordinal(unsigned short n) } } -/* - * BSD err(3) and warn(3) functions, must call err_init() before using - */ - -void -err_init(void) +static char ostype_s[5]; + +char * +OSTypeToString(OSType type) { - if (!(err_str = NewHandle(ERROR_STRING_SIZE))) { - SysBeep(20); - ExitToShell(); - } + ostype_s[0] = (unsigned char)((type >> 24) & 0xff); + ostype_s[1] = (unsigned char)((type >> 16) & 0xff); + ostype_s[2] = (unsigned char)((type >> 8) & 0xff); + ostype_s[3] = (unsigned char)(type & 0xff); + ostype_s[4] = 0; - alert_ditl_h = xNewHandle(sizeof(alert_ditl)); - HLock(alert_ditl_h); - memcpy(*alert_ditl_h, alert_ditl, sizeof(alert_ditl)); - HUnlock(alert_ditl_h); + return ostype_s; } +/* + * BSD err(3) and warn(3) functions + */ + void vwarn(short alert_func, const char *format, va_list ap) { @@ -207,10 +214,7 @@ vwarn(short alert_func, const char *format, va_list ap GetPort(&win); - if (err_str == NULL) - err_init(); - HLock(err_str); - vsnprintf(*err_str, ERROR_STRING_SIZE, format, ap); + vsnprintf(err_str, ERROR_STRING_SIZE, format, ap); width = 300; height = 100; @@ -220,8 +224,13 @@ vwarn(short alert_func, const char *format, va_list ap ((screenBits.bounds.bottom - height) / 2.5); bounds.bottom = bounds.top + height; - ParamText(CtoPstr(*err_str), "\p", "\p", "\p"); - + ParamText(CtoPstr(err_str), "\p", "\p", "\p"); + + alert_ditl_h = xNewHandle(sizeof(alert_ditl)); + HLock(alert_ditl_h); + memcpy(*alert_ditl_h, alert_ditl, sizeof(alert_ditl)); + HUnlock(alert_ditl_h); + dialog = NewDialog(nil, &bounds, "\p", false, dBoxProc, (WindowPtr)-1L, false, 0, alert_ditl_h); @@ -249,9 +258,8 @@ vwarn(short alert_func, const char *format, va_list ap break; } DisposDialog(dialog); - - HUnlock(err_str); - + DisposHandle(alert_ditl_h); + SetPort(win); if (quit) @@ -322,22 +330,62 @@ ask(const char *format, ...) GetPort(&win); - HLock(err_str); va_start(ap, format); - len = vsprintf(*err_str, format, ap); + len = vsnprintf(err_str, ERROR_STRING_SIZE, format, ap); va_end(ap); - if (len >= ERROR_STRING_SIZE) - err(1, "ask string overflow!"); - ParamText(CtoPstr(*err_str), "\p", "\p", "\p"); + ParamText(CtoPstr(err_str), "\p", "\p", "\p"); ret = StopAlert(ASK_ALERT_ID, nil); - HUnlock(err_str); SetPort(win); return ret; } +void +progress(char *format, ...) +{ + static Str255 progress_s; + Handle thandle; + va_list argptr; + Rect bounds = { 100, 90, 160, 420 }; /* tlbr */ + Rect trect; + static WindowPtr progress_win; + short ttype; + if (format == NULL) { + if (progress_dialog != NULL) { + DisposDialog(progress_dialog); + DisposHandle(progress_ditl_h); + progress_dialog = NULL; + } + SetPort(progress_win); + return; + } + + va_start(argptr, format); + vsnprintf((char *)progress_s, 256, format, argptr); + va_end(argptr); + CtoPstr(progress_s); + + if (progress_dialog == NULL) { + GetPort(&progress_win); + + progress_ditl_h = xNewHandle(sizeof(progress_ditl)); + HLock(progress_ditl_h); + memcpy(*progress_ditl_h, progress_ditl, sizeof(progress_ditl)); + HUnlock(progress_ditl_h); + + progress_dialog = NewDialog(nil, &bounds, "\p", false, dBoxProc, + (WindowPtr)-1L, false, 0, progress_ditl_h); + } + + GetDItem(progress_dialog, 1, &ttype, &thandle, &trect); + SetIText(thandle, progress_s); + + ShowWindow(progress_dialog); + DrawDialog(progress_dialog); +} + /* * General Mac-specific non-GUI functions */ @@ -360,16 +408,16 @@ xorshift32(void) */ Handle -xNewHandle(unsigned long size) +xNewHandle(size_t size) { Handle h; - if (size < 1) - err(1, "Bogus xNewHandle size %lu", size); + if (size == 0) + panic("Zero xNewHandle size"); h = NewHandle(size); if (h == NULL) - err(1, "Failed to NewHandle(%lu)", size); + panic("Failed to NewHandle(%lu)", size); return h; } @@ -381,7 +429,7 @@ xGetResource(ResType type, short id) h = GetResource(type, id); if (h == NULL) - err(1, "Failed to find resource %d", id); + panic("Failed to find resource %d", id); return h; } @@ -393,97 +441,62 @@ xGetString(short id) h = GetString(id); if (h == NULL) - err(1, "Failed to find STR resource %d", id); + panic("Failed to find STR resource %d", id); return h; } -void -xSetHandleSize(Handle h, Size s) -{ - SetHandleSize(h, s); - if (MemError()) - err(1, "Failed to SetHandleSize to %ld", s); -} - -/* - * Filesystem utilities - */ - -/* - * With SFGetFile, when the user has a folder selected and clicks Open, - * File Manager will change to the folder and expect the user to select a - * file in it. This triggers sfHookOpenFolder, but when the user double- - * clicks on a folder to browse into it, the same result code is returned. - * - * To be able to return the folder itself, we need to know whether the user - * double-clicked a folder, or clicked Open. When we get our hook callback, - * we check where the mouse is in relation to the Open button rect. If - * the user clicked Open, we return the folder itself, otherwise we assume - * the user double-clicked a folder and we should browse into it. - * - * Finally, we return the full path of the file/folder as a char *, rather - * than just a ref id. - */ char * -askfileordirpath(void) +xGetStringAsChar(short id) { - Point pt = { 75, 75 }; - SFReply reply; - HParamBlockRec hpbr; - Str63 fName = { 0 }; - char *ret = NULL; + StringHandle h = xGetString(id); + char *out; + size_t l; - SFGetFile(pt, "\p", NULL, -1, 0, open_dialog_hook, &reply); - if (!reply.good) - return NULL; - - if (reply.fName[0] == 0) { - /* selected a folder, look it up */ - hpbr.fileParam.ioCompletion = 0; - hpbr.fileParam.ioNamePtr = (StringPtr)&fName; - hpbr.fileParam.ioVRefNum = reply.vRefNum; - hpbr.fileParam.ioDirID = reply.fType; - hpbr.fileParam.ioFDirIndex = -1; - PBGetCatInfo(&hpbr, false); - memcpy(reply.fName, fName, sizeof(fName)); - } + HLock(h); - getpath(reply.vRefNum, reply.fName, &ret, true); + l = (*h)[0]; + out = xmalloc(l + 1); + memcpy((void *)out, (void *)(*h + 1), l); + out[l] = '\0'; - return ret; + DisposHandle(h); + return out; } -pascal short -open_dialog_hook(short theItem, DialogPtr theDialog) +long +xGetStringAsLong(short id) { - short item_type; - Handle item; - Rect item_rect; - Point mouse; + char *c; + long r; - if (theItem == sfHookOpenFolder) { - GetDItem(theDialog, getOpen, &item_type, &item, &item_rect); - GetMouse(&mouse); - - if (PtInRect(mouse, &item_rect)) { - /* clicked open */ - return getOpen; - } - } - - return theItem; + c = xGetStringAsChar(id); + r = atol(c); + free(c); + return r; } +void +xSetHandleSize(Handle h, Size s) +{ + SetHandleSize(h, s); + if (MemError()) + panic("Failed to SetHandleSize to %ld", s); +} + +/* + * Filesystem utilities + */ + short -getpath(short vRefNum, Str255 fileName, char **ret, bool include_file) +getpath(short vRefNum, Str255 fileName, Str255 *ret, bool include_file) { WDPBRec wdir; HVolumeParam wvol; DirInfo wcinfo; Str255 name; - size_t retlen = 0; - char *tmp; + size_t retlen = 0, len; + char tmpret[256], tmp[256]; wdir.ioVRefNum = wdir.ioWDVRefNum = vRefNum; wdir.ioWDIndex = 0; @@ -521,17 +534,14 @@ getpath(short vRefNum, Str255 fileName, char **ret, bo if (PBGetCatInfo((CInfoPBPtr)&wcinfo, 0) != noErr) break; + len = name[0]; + PtoCstr(name); if (retlen == 0) { - retlen = name[0]; - *ret = xmalloc(retlen + 1); - sprintf(*ret, "%s", PtoCstr(name)); + retlen = len; + strlcpy(tmpret, (char *)name, sizeof(tmpret)); } else { - tmp = xstrdup(*ret); - free(*ret); - *ret = xmalloc(retlen + 1 + name[0] + 1); - retlen += 1 + name[0]; - sprintf(*ret, "%s:%s", PtoCstr(name), tmp); - free(tmp); + strlcpy(tmp, tmpret, sizeof(tmp)); + snprintf(tmpret, sizeof(tmpret), "%s:%s", name, tmp); } } @@ -540,31 +550,44 @@ getpath(short vRefNum, Str255 fileName, char **ret, bo memcpy(name, fileName, sizeof(name)); PtoCstr(name); if (retlen == 0) - *ret = xstrdup((char *)name); + strlcpy(tmpret, (char *)name, sizeof(tmpret)); else { - *ret = xrealloc(*ret, retlen + 1 + fileName[0] + 1); - sprintf(*ret + retlen, ":%s", (char *)name); + strlcat(tmpret, ":", sizeof(tmpret)); + strlcat(tmpret, (char *)name, sizeof(tmpret)); } } else if (retlen == 0) { - *ret = NULL; + (*ret)[0] = 0; + return 0; } + CtoPstr(tmpret); + memcpy(*ret, tmpret, sizeof(tmpret)); + return 0; } short -stat(const char *path, struct stat *sb) +stat(char *path, struct stat *sb) { - CInfoPBRec catblock = { 0 }; + char *ppath; short ret; - char *tpath; - tpath = xstrdup(path); - CtoPstr(tpath); + ppath = xstrdup(path); + CtoPstr(ppath); + ret = FStat((unsigned char *)ppath, sb); + free(ppath); + + return ret; +} - catblock.hFileInfo.ioNamePtr = (StringPtr)tpath; +short +FStat(Str255 path, struct stat *sb) +{ + CInfoPBRec catblock = { 0 }; + short ret; + + catblock.hFileInfo.ioNamePtr = path; ret = PBGetCatInfo(&catblock, 0); - free(tpath); if (ret != noErr) return -1; @@ -579,12 +602,12 @@ stat(const char *path, struct stat *sb) } bool -is_dir(char *path) +FIsDir(Str255 path) { struct stat st; short ret; - if ((ret = stat(path, &st)) != 0) + if ((ret = FStat(path, &st)) != 0) return ret; /* bit 4 is set in ioFlAttrib if the item is a directory */ @@ -594,6 +617,122 @@ is_dir(char *path) return false; } +OSErr +copy_file(Str255 source, Str255 dest, bool overwrite) +{ + FInfo fi; + IOParam pb; + short error, source_ref, dest_ref; + + /* copy data fork */ + + error = GetFInfo(source, 0, &fi); + if (error) + return error; + + error = Create(dest, 0, fi.fdCreator, fi.fdType); + if (error == dupFNErr && overwrite) { + error = FSDelete(dest, 0); + if (error) + return error; + error = Create(dest, 0, fi.fdCreator, fi.fdType); + } + if (error) + return error; + + memset(&pb, 0, sizeof(pb)); + pb.ioNamePtr = source; + pb.ioPermssn = fsRdPerm; + error = PBOpen(&pb, false); + if (error) + return error; + source_ref = pb.ioRefNum; + + error = FSOpen(dest, 0, &dest_ref); + if (error) { + FSClose(source_ref); + return error; + } + + error = copy_file_contents(source_ref, dest_ref); + + FSClose(source_ref); + FSClose(dest_ref); + + if (error) + return error; + + /* + * Copy resource fork, open source as shared read/write in case it's + * an open resource file. + */ + source_ref = OpenRFPerm(source, 0, fsRdWrShPerm); + + if (source_ref == -1 && ResError() == eofErr) { + /* no resource fork */ + FSClose(source_ref); + FSClose(dest_ref); + return 0; + } + + if (source_ref == -1) + return ResError(); + + CreateResFile(dest); + if (ResError()) { + FSClose(source_ref); + return ResError(); + } + error = OpenRF(dest, 0, &dest_ref); + if (error) { + FSClose(source_ref); + return error; + } + + error = copy_file_contents(source_ref, dest_ref); + + FSClose(source_ref); + FSClose(dest_ref); + + return error; +} + +OSErr +copy_file_contents(short source_ref, short dest_ref) +{ + char buf[1024]; + short error; + long source_size, count; + + GetEOF(source_ref, &source_size); + error = SetFPos(source_ref, fsFromStart, 0); + if (error) + return error; + error = SetEOF(dest_ref, source_size); + if (error) + return error; + error = SetFPos(dest_ref, fsFromStart, 0); + if (error) + return error; + while (source_size > 0) { + count = sizeof(buf); + if (count > source_size) + count = source_size; + error = FSRead(source_ref, &count, &buf); + if (error && error != eofErr) + break; + source_size -= count; + error = FSWrite(dest_ref, &count, &buf); + if (error && error != eofErr) + break; + } + + if (error && error != eofErr) + return error; + + return 0; +} + /* read a \r-terminated line or the final non-line bytes of an open file */ OSErr FSReadLine(short frefnum, char *buf, size_t buflen) @@ -724,7 +863,7 @@ TrackMouseDownInControl(ControlHandle control, short p short page, val, adj, lheight; if (track_control_te == NULL) - err(1, "TrackMouseDownInControl without SetTrackControlTE"); + panic("TrackMouseDownInControl without SetTrackControlTE"); lheight = TEGetHeight(0, 0, track_control_te); --- util.h Sat Dec 25 21:21:12 2021 +++ util.h Mon Jan 10 16:40:54 2022 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021 joshua stein <jcs@jcs.org> + * Copyright (c) 2020-2022 joshua stein <jcs@jcs.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -72,15 +72,10 @@ 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); -#if 0 -/* from strnatcmp.c */ -int strnatcmp(char const *a, char const *b); -int strnatcasecmp(char const *a, char const *b); -#endif +char *OSTypeToString(OSType type); unsigned long xorshift32(void); -void err_init(void); void panic(const char *format, ...); void err(short ret, const char *format, ...); void warnx(const char *format, ...); @@ -89,22 +84,22 @@ void note(const char *format, ...); short ask(const char *format, ...); #define ASK_YES 1 #define ASK_NO 2 +void progress(char *format, ...); -Handle xNewHandle(unsigned long size); +Handle xNewHandle(size_t size); Handle xGetResource(ResType type, short id); StringHandle xGetString(short id); char *xGetStringAsChar(short id); long xGetStringAsLong(short id); void xSetHandleSize(Handle h, Size s); -char *askfileordirpath(void); -short getpath(short vRefNum, Str255 fileName, char **ret, +short getpath(short vRefNum, Str255 fileName, Str255 *ret, bool include_file); -pascal short open_dialog_hook(short theItem, DialogPtr theDialog); -pascal Boolean open_dialog_filter(DialogPtr theDialog, - EventRecord *theEvent, short *itemHit); -bool is_dir(char *path); -short stat(const char *path, struct stat *sb); +bool FIsDir(Str255 path); +short stat(char *path, struct stat *sb); +short FStat(Str255 path, struct stat *sb); +OSErr copy_file(Str255 source, Str255 dest, bool overwrite); +OSErr copy_file_contents(short source_ref, short dest_ref); OSErr FSReadLine(short frefnum, char *buf, size_t buflen); short FontHeight(short font_id, short size);