jcs
/amend
/amendments
/88
editor: Add amendment metadata editor
This allows changing an amendment's author, date/time, and log.
Also continue on changing commit to amendment.
jcs made amendment 88 over 2 years ago
--- amend.h Tue Aug 16 10:54:26 2022
+++ amend.h Tue Aug 16 16:38:21 2022
@@ -38,11 +38,11 @@
#define REPO_MENU_DISCARD_CHANGES_ID 2
#define REPO_MENU_APPLY_PATCH_ID 3
-#define COMMIT_MENU_ID 132
-#define COMMIT_MENU_EDIT_ID 1
-#define COMMIT_MENU_EXPORT_ID 2
+#define AMENDMENT_MENU_ID 132
+#define AMENDMENT_MENU_EDIT_ID 1
+#define AMENDMENT_MENU_EXPORT_ID 2
-#define COMMIT_LDEF_ID 128
+#define AMENDMENT_LDEF_ID 128
#define SETTINGS_DLOG_ID 130
#define SETTINGS_SAVE_ID 1
@@ -53,6 +53,6 @@
#define STR_AUTHOR_ID 128
#define STR_TABWIDTH_ID 129
-extern MenuHandle file_menu, edit_menu, repo_menu, commit_menu;
+extern MenuHandle file_menu, edit_menu, repo_menu, amendment_menu;
void menu_defaults(void);
--- browser.c Tue Aug 16 14:34:48 2022
+++ browser.c Wed Aug 17 14:24:15 2022
@@ -22,6 +22,7 @@
#include "browser.h"
#include "committer.h"
#include "diff.h"
+#include "editor.h"
#include "focusable.h"
#include "patch.h"
#include "repo.h"
@@ -33,16 +34,17 @@ bool browser_close(struct focusable *focusable);
void browser_idle(struct focusable *focusable, EventRecord *event);
void browser_update_menu(struct browser *browser);
void browser_update(struct focusable *focusable, EventRecord *event);
-void browser_show_commit(struct browser *browser,
- struct repo_commit *commit);
+void browser_show_amendment(struct browser *browser,
+ struct repo_amendment *amendment);
void browser_key_down(struct focusable *focusable, EventRecord *event);
void browser_mouse_down(struct focusable *focusable, EventRecord *event);
bool browser_handle_menu(struct focusable *focusable, short menu,
short item);
void browser_add_files(struct browser *browser);
-void browser_filter_commits(struct browser *browser);
+void browser_filter_amendments(struct browser *browser);
void browser_discard_changes(struct browser *browser);
+void browser_edit_amendment(struct browser *browser);
Pattern fill_pattern;
@@ -53,6 +55,10 @@ browser_idle(struct focusable *focusable, EventRecord
switch (browser->state) {
case BROWSER_STATE_IDLE:
+ if (browser->need_refresh) {
+ browser->need_refresh = false;
+ browser->state = BROWSER_STATE_UPDATE_AMENDMENT_LIST;
+ }
break;
case BROWSER_STATE_ADD_FILE:
if (repo_add_file(browser->repo) == NULL)
@@ -64,8 +70,8 @@ browser_idle(struct focusable *focusable, EventRecord
browser_add_files(browser);
browser->state = BROWSER_STATE_IDLE;
break;
- case BROWSER_STATE_UPDATE_COMMIT_LIST:
- browser_filter_commits(browser);
+ case BROWSER_STATE_UPDATE_AMENDMENT_LIST:
+ browser_filter_amendments(browser);
browser->state = BROWSER_STATE_IDLE;
break;
case BROWSER_STATE_OPEN_COMMITTER:
@@ -86,6 +92,10 @@ browser_idle(struct focusable *focusable, EventRecord
browser_apply_patch(browser);
browser->state = BROWSER_STATE_IDLE;
break;
+ case BROWSER_STATE_EDIT_AMENDMENT:
+ browser_edit_amendment(browser);
+ browser->state = BROWSER_STATE_IDLE;
+ break;
}
}
@@ -153,21 +163,21 @@ browser_init(struct repo *repo)
browser->diff_button = NewControl(browser->win, &bounds,
"\pGenerate Diff", true, 1, 1, 1, pushButProc | useWFont, 0L);
- /* commit list */
+ /* amendment list */
bounds.top = bounds.left = padding;
bounds.left = bounds.right + padding;
bounds.right = browser->win->portRect.right - SCROLLBAR_WIDTH - padding;
cell_size.v = (FontHeight(applFont, 9) * 2) + 2;
- browser->commit_list = LNew(&bounds, &data_bounds, cell_size,
- COMMIT_LDEF_ID, browser->win, true, true, false, true);
- if (!browser->commit_list)
- err(1, "Can't create commit list");
- LAddColumn(1, 0, browser->commit_list);
- (*(browser->commit_list))->selFlags = lOnlyOne;
+ browser->amendment_list = LNew(&bounds, &data_bounds, cell_size,
+ AMENDMENT_LDEF_ID, browser->win, true, true, false, true);
+ if (!browser->amendment_list)
+ err(1, "Can't create amendment list");
+ LAddColumn(1, 0, browser->amendment_list);
+ (*(browser->amendment_list))->selFlags = lOnlyOne;
/* diff text */
- bounds.top = (*browser->commit_list)->rView.bottom + padding;
+ bounds.top = (*browser->amendment_list)->rView.bottom + padding;
bounds.left = padding;
bounds.right = browser->win->portRect.right - SCROLLBAR_WIDTH - padding;
bounds.bottom = browser->win->portRect.bottom - padding;
@@ -248,7 +258,7 @@ browser_add_files(struct browser *browser)
LDoDraw(false, browser->file_list);
LDelRow(0, 0, browser->file_list);
- browser_show_commit(browser, NULL);
+ browser_show_amendment(browser, NULL);
TextFont(applFont);
TextSize(10);
@@ -272,7 +282,7 @@ browser_add_files(struct browser *browser)
LDoDraw(true, browser->file_list);
- browser_filter_commits(browser);
+ browser_filter_amendments(browser);
InvalRect(&browser->win->portRect);
}
@@ -326,28 +336,28 @@ browser_selected_file_ids(struct browser *browser, sho
}
void
-browser_filter_commits(struct browser *browser)
+browser_filter_amendments(struct browser *browser)
{
Cell cell = { 0 };
- struct repo_commit *commit;
+ struct repo_amendment *amendment;
short i, j, k, add = 0, file_id;
short *selected_files = NULL;
short nselected_files = 0;
- LDoDraw(false, browser->commit_list);
- LDelRow(0, 0, browser->commit_list);
- browser_show_commit(browser, NULL);
+ LDoDraw(false, browser->amendment_list);
+ LDelRow(0, 0, browser->amendment_list);
+ browser_show_amendment(browser, NULL);
- /* fill in commits for selected files */
+ /* fill in amendments for selected files */
nselected_files = browser_selected_file_ids(browser, &selected_files);
cell.v = 0;
- for (i = 0; i < browser->repo->ncommits; i++) {
+ for (i = 0; i < browser->repo->namendments; i++) {
add = 0;
- commit = browser->repo->commits[i];
- for (j = 0; j < commit->nfiles; j++) {
- file_id = commit->file_ids[j];
+ amendment = browser->repo->amendments[i];
+ for (j = 0; j < amendment->nfiles; j++) {
+ file_id = amendment->file_ids[j];
for (k = 0; k < nselected_files; k++) {
- if (selected_files[k] == commit->file_ids[j]) {
+ if (selected_files[k] == amendment->file_ids[j]) {
add = 1;
break;
}
@@ -359,32 +369,33 @@ browser_filter_commits(struct browser *browser)
if (!add)
continue;
- LAddRow(1, cell.v, browser->commit_list);
- LSetCell(&(browser->repo->commits[i]), sizeof(Ptr), cell,
- browser->commit_list);
+ LAddRow(1, cell.v, browser->amendment_list);
+ LSetCell(&(browser->repo->amendments[i]), sizeof(Ptr), cell,
+ browser->amendment_list);
cell.v++;
}
- LDoDraw(true, browser->commit_list);
- InvalRect(&(*(browser->commit_list))->rView);
+ LDoDraw(true, browser->amendment_list);
+ InvalRect(&(*(browser->amendment_list))->rView);
if (selected_files)
free(selected_files);
}
void
-browser_show_commit(struct browser *browser, struct repo_commit *commit)
+browser_show_amendment(struct browser *browser,
+ struct repo_amendment *amendment)
{
struct repo_diff *diff;
- if (commit == NULL) {
+ if (amendment == NULL) {
TESetText("", 0, browser->diff_te);
HLock(browser->diff_te);
InvalRect(&(*(browser->diff_te))->viewRect);
HUnlock(browser->diff_te);
} else {
SetCursor(*(GetCursor(watchCursor)));
- repo_show_diff_text(browser->repo, commit, browser->diff_te);
+ repo_show_diff_text(browser->repo, amendment, browser->diff_te);
SetCursor(&arrow);
}
@@ -428,21 +439,21 @@ browser_export_patch(struct browser *browser)
{
Point pt = { 75, 100 };
Cell selected = { 0 };
- struct repo_commit *commit;
+ struct repo_amendment *amendment;
short error, len;
SFReply reply;
- if (LGetSelect(true, &selected, browser->commit_list) == false)
+ if (LGetSelect(true, &selected, browser->amendment_list) == false)
return;
len = sizeof(Ptr);
- LGetCell(&commit, &len, selected, browser->commit_list);
+ LGetCell(&amendment, &len, selected, browser->amendment_list);
SFPutFile(pt, "\pSave patch as:", NULL, NULL, &reply);
if (!reply.good)
return;
- repo_export_patch(browser->repo, commit, reply.vRefNum, reply.fName);
+ repo_export_patch(browser->repo, amendment, reply.vRefNum, reply.fName);
}
void
@@ -459,6 +470,24 @@ browser_apply_patch(struct browser *browser)
}
void
+browser_edit_amendment(struct browser *browser)
+{
+ Point pt = { 75, 100 };
+ Cell selected = { 0 };
+ struct repo_amendment *amendment;
+ short error, len;
+ SFReply reply;
+
+ if (LGetSelect(true, &selected, browser->amendment_list) == false)
+ return;
+
+ len = sizeof(Ptr);
+ LGetCell(&amendment, &len, selected, browser->amendment_list);
+
+ editor_init(browser, amendment);
+}
+
+void
browser_update_menu(struct browser *browser)
{
size_t vlines;
@@ -498,10 +527,12 @@ browser_update_menu(struct browser *browser)
EnableItem(repo_menu, REPO_MENU_APPLY_PATCH_ID);
}
- if (LGetSelect(true, &cell, browser->commit_list)) {
- EnableItem(commit_menu, COMMIT_MENU_EXPORT_ID);
+ if (LGetSelect(true, &cell, browser->amendment_list)) {
+ EnableItem(amendment_menu, AMENDMENT_MENU_EDIT_ID);
+ EnableItem(amendment_menu, AMENDMENT_MENU_EXPORT_ID);
} else {
- DisableItem(commit_menu, COMMIT_MENU_EXPORT_ID);
+ DisableItem(amendment_menu, AMENDMENT_MENU_EDIT_ID);
+ DisableItem(amendment_menu, AMENDMENT_MENU_EXPORT_ID);
}
}
@@ -535,11 +566,11 @@ browser_update(struct focusable *focusable, EventRecor
TextSize(10);
LUpdate(browser->win->visRgn, browser->file_list);
- r = (*(browser->commit_list))->rView;
+ r = (*(browser->amendment_list))->rView;
InsetRect(&r, -1, -1);
FillRect(&r, white);
FrameRect(&r);
- LUpdate(browser->win->visRgn, browser->commit_list);
+ LUpdate(browser->win->visRgn, browser->amendment_list);
TextFont(applFont);
TextSize(11);
@@ -559,7 +590,7 @@ browser_mouse_down(struct focusable *focusable, EventR
ControlHandle control;
Rect r;
struct browser *browser = (struct browser *)focusable->cookie;
- struct repo_commit *commit = NULL;
+ struct repo_amendment *amendment = NULL;
short *selected_files = NULL, *now_selected_files = NULL;
short nselected = 0, nnow_selected = 0;
short val, adj, page, was_selected, part, i, data_len;
@@ -598,13 +629,13 @@ browser_mouse_down(struct focusable *focusable, EventR
selected.v = 0;
LSetSelect(true, selected, browser->file_list);
if (nselected != browser->repo->nfiles)
- browser_filter_commits(browser);
+ browser_filter_amendments(browser);
} else if (nselected != nnow_selected) {
- browser_filter_commits(browser);
+ browser_filter_amendments(browser);
} else {
for (i = 0; i < nselected; i++) {
if (selected_files[i] != now_selected_files[i]) {
- browser_filter_commits(browser);
+ browser_filter_amendments(browser);
break;
}
}
@@ -618,31 +649,31 @@ browser_mouse_down(struct focusable *focusable, EventR
return;
}
- /* is it in commit list? */
- r = (*(browser->commit_list))->rView;
+ /* is it in amendment list? */
+ r = (*(browser->amendment_list))->rView;
r.right += SCROLLBAR_WIDTH;
if (PtInRect(p, &r)) {
if (browser->repo == NULL)
return;
/* store what is selected now */
- was_selected = LGetSelect(true, &selected, browser->commit_list);
+ was_selected = LGetSelect(true, &selected, browser->amendment_list);
/* possibly highlight a new cell */
- LClick(p, event->modifiers, browser->commit_list);
+ LClick(p, event->modifiers, browser->amendment_list);
- if (LGetSelect(true, &now, browser->commit_list) == false) {
+ if (LGetSelect(true, &now, browser->amendment_list) == false) {
if (was_selected)
- browser_show_commit(browser, NULL);
+ browser_show_amendment(browser, NULL);
} else if (!was_selected || selected.v != now.v) {
if (was_selected)
- LSetSelect(false, selected, browser->commit_list);
- LSetSelect(true, now, browser->commit_list);
+ LSetSelect(false, selected, browser->amendment_list);
+ LSetSelect(true, now, browser->amendment_list);
- /* in a filtered list, commits[now.v] won't be accurate */
+ /* in a filtered list, amendments[now.v] won't be accurate */
data_len = sizeof(Ptr);
- LGetCell(&commit, &data_len, now, browser->commit_list);
- browser_show_commit(browser, commit);
+ LGetCell(&amendment, &data_len, now, browser->amendment_list);
+ browser_show_amendment(browser, amendment);
}
return;
@@ -711,9 +742,12 @@ browser_handle_menu(struct focusable *focusable, short
return true;
}
break;
- case COMMIT_MENU_ID:
+ case AMENDMENT_MENU_ID:
switch (item) {
- case COMMIT_MENU_EXPORT_ID:
+ case AMENDMENT_MENU_EDIT_ID:
+ browser->state = BROWSER_STATE_EDIT_AMENDMENT;
+ return true;
+ case AMENDMENT_MENU_EXPORT_ID:
browser->state = BROWSER_STATE_EXPORT_PATCH;
return true;
}
--- browser.h Tue Aug 16 13:20:59 2022
+++ browser.h Wed Aug 17 14:23:45 2022
@@ -26,13 +26,14 @@ enum {
BROWSER_STATE_IDLE,
BROWSER_STATE_ADD_FILE,
BROWSER_STATE_UPDATE_FILE_LIST,
- BROWSER_STATE_UPDATE_COMMIT_LIST,
+ BROWSER_STATE_UPDATE_AMENDMENT_LIST,
BROWSER_STATE_OPEN_COMMITTER,
BROWSER_STATE_WAITING_FOR_COMMITTER,
BROWSER_STATE_REMOVE_FILE,
BROWSER_STATE_DISCARD_CHANGES,
BROWSER_STATE_EXPORT_PATCH,
- BROWSER_STATE_APPLY_PATCH
+ BROWSER_STATE_APPLY_PATCH,
+ BROWSER_STATE_EDIT_AMENDMENT
};
struct browser {
@@ -40,17 +41,18 @@ struct browser {
WindowPtr win;
struct repo *repo;
ListHandle file_list;
- ListHandle commit_list;
+ ListHandle amendment_list;
TEHandle diff_te;
ControlHandle diff_scroller;
ControlHandle diff_button;
struct committer *committer;
+ bool need_refresh;
};
struct browser *browser_init(struct repo *repo);
void browser_update_titlebar(struct browser *browser);
-void browser_show_commit(struct browser *browser,
- struct repo_commit *commit);
+void browser_show_amendment(struct browser *browser,
+ struct repo_amendment *amendment);
void browser_close_committer(struct browser *browser);
void browser_export_patch(struct browser *browser);
short browser_is_all_files_selected(struct browser *browser);
@@ -58,7 +60,7 @@ short browser_selected_file_ids(struct browser *browse
short **selected_files);
void browser_apply_patch(struct browser *browser);
-pascal void commit_list_ldef(short message, Boolean selected,
+pascal void amendment_list_ldef(short message, Boolean selected,
Rect *cellRect, Cell theCell, short dataOffset, short dataLen,
ListHandle theList);
--- committer.c Tue Aug 16 13:40:20 2022
+++ committer.c Tue Aug 16 16:56:14 2022
@@ -67,12 +67,12 @@ committer_init(struct browser *browser)
committer->browser = browser;
browser->committer = committer;
- /* main window */
- bounds.left = (padding / 2);
- bounds.top = screenBits.bounds.top + (GetMBarHeight() * 2) - 1 +
- (padding / 2);
- bounds.right = screenBits.bounds.right - 1 - (padding / 2);
- bounds.bottom = screenBits.bounds.bottom - 1 - (padding / 2);
+ /* main window, centered in its browser */
+ bounds = (*(((WindowPeek)browser->win)->strucRgn))->rgnBBox;
+ bounds.left += (padding / 2);
+ bounds.top += ((padding / 2) + MBarHeight);
+ bounds.right -= (padding / 2);
+ bounds.bottom -= (padding / 2);
memcpy(filename, browser->repo->bile->filename, sizeof(filename));
PtoCstr(filename);
@@ -401,8 +401,8 @@ committer_update_menu(struct committer *committer)
DisableItem(repo_menu, REPO_MENU_DISCARD_CHANGES_ID);
DisableItem(repo_menu, REPO_MENU_APPLY_PATCH_ID);
- DisableItem(commit_menu, COMMIT_MENU_EDIT_ID);
- DisableItem(commit_menu, COMMIT_MENU_EXPORT_ID);
+ DisableItem(amendment_menu, AMENDMENT_MENU_EDIT_ID);
+ DisableItem(amendment_menu, AMENDMENT_MENU_EXPORT_ID);
HUnlock(committer->log_te);
HUnlock(committer->diff_te);
@@ -510,7 +510,7 @@ committer_commit(struct committer *committer)
progress("Committing changes...");
- repo_commit(committer->browser->repo, committer->diffed_files,
+ repo_amend(committer->browser->repo, committer->diffed_files,
committer->ndiffed_files, committer->diff_adds, committer->diff_subs,
settings.author, (*(committer->log_te))->hText, loglen,
(*(committer->diff_te))->hText, committer->diff_te_len);
@@ -523,7 +523,7 @@ committer_commit(struct committer *committer)
browser = committer->browser;
browser_close_committer(committer->browser);
- browser->state = BROWSER_STATE_UPDATE_COMMIT_LIST;
+ browser->state = BROWSER_STATE_UPDATE_AMENDMENT_LIST;
}
bool
--- editor.c Wed Aug 17 14:25:10 2022
+++ editor.c Wed Aug 17 14:25:10 2022
@@ -0,0 +1,495 @@
+/*
+ * Copyright (c) 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
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <time.h>
+#include "amend.h"
+#include "browser.h"
+#include "editor.h"
+#include "focusable.h"
+#include "repo.h"
+#include "tetab.h"
+#include "util.h"
+
+static short padding = 10;
+
+bool editor_close(struct focusable *focusable);
+void editor_idle(struct focusable *focusable, EventRecord *event);
+void editor_update(struct focusable *focusable, EventRecord *event);
+void editor_suspend(struct focusable *focusable);
+void editor_resume(struct focusable *focusable);
+void editor_key_down(struct focusable *focusable, EventRecord *event);
+void editor_mouse_down(struct focusable *focusable, EventRecord *event);
+bool editor_handle_menu(struct focusable *focusable, short menu,
+ short item);
+
+void editor_update_menu(struct editor *editor);
+void editor_save(struct editor *editor);
+
+void
+editor_init(struct browser *browser, struct repo_amendment *amendment)
+{
+ Str255 title, filename;
+ struct editor *editor;
+ struct focusable *focusable;
+ char date[32];
+ Rect bounds = { 0 }, te_bounds = { 0 };
+ TextStyle style;
+ short fh, off;
+ struct tm *ttm = NULL;
+
+ editor = xmalloczero(sizeof(struct editor));
+ editor->browser = browser;
+ editor->amendment = amendment;
+
+ /* main window, centered in its browser */
+ window_rect(browser->win, &bounds);
+ bounds.top += MBarHeight;
+ InsetRect(&bounds, 2, 2);
+ off = (bounds.bottom - bounds.top) / 5;
+ bounds.top += off;
+ bounds.bottom -= off;
+
+ memcpy(filename, browser->repo->bile->filename, sizeof(filename));
+ PtoCstr(filename);
+ snprintf((char *)&title, sizeof(title), "%s: %s: Edit Amendment",
+ PROGRAM_NAME, (browser->repo ? (char *)filename : "No repo open"));
+
+ editor->win = NewWindow(0L, &bounds, CtoPstr(title), false,
+ noGrowDocProc, (WindowPtr)-1L, true, 0);
+ if (!editor)
+ err(1, "Can't create editor window");
+ SetPort(editor->win);
+
+ /* author */
+ bounds.top = padding;
+ bounds.left = 60;
+ fh = FontHeight(applFont, 10);
+ bounds.bottom = bounds.top + fh + 4;
+ bounds.right = 140;
+ te_bounds = bounds;
+ InsetRect(&te_bounds, 2, 2);
+ TextFont(applFont);
+ TextSize(10);
+ editor->author_te = TENew(&te_bounds, &bounds);
+ TEAutoView(true, editor->author_te);
+ TEActivate(editor->author_te);
+ TEInsert(amendment->author, strlen(amendment->author),
+ editor->author_te);
+
+ /* date */
+ bounds.top = bounds.bottom + padding;
+ bounds.bottom = bounds.top + fh + 2;
+ bounds.right = 200;
+ te_bounds = bounds;
+ InsetRect(&te_bounds, 2, 2);
+ TextFont(applFont);
+ TextSize(10);
+ editor->date_te = TENew(&te_bounds, &bounds);
+ TEAutoView(true, editor->date_te);
+
+ ttm = localtime(&amendment->date);
+ snprintf(date, sizeof(date), "%04d-%02d-%02d %02d:%02d:%02d",
+ ttm->tm_year + 1900, ttm->tm_mon + 1, ttm->tm_mday,
+ ttm->tm_hour, ttm->tm_min, ttm->tm_sec);
+ TEInsert(date, strlen(date), editor->date_te);
+
+ /* log message */
+ bounds.top = bounds.bottom + padding;
+ fh = FontHeight(monaco, 9);
+ bounds.bottom = editor->win->portRect.bottom - 20 - (padding * 2);
+ bounds.right = editor->win->portRect.right - SCROLLBAR_WIDTH -
+ padding;
+ te_bounds = bounds;
+ InsetRect(&te_bounds, 2, 2);
+ TextFont(monaco);
+ TextSize(9);
+ editor->log_te = TEStylNew(&te_bounds, &bounds);
+ style.tsFont = monaco;
+ style.tsSize = 9;
+ TESetStyle(doFont | doSize, &style, false, editor->log_te);
+ TEAutoView(true, editor->log_te);
+ TETabEnable(editor->log_te);
+ HLock(amendment->log);
+ TEInsert(*(amendment->log), amendment->log_len, editor->log_te);
+ HUnlock(amendment->log);
+
+ /* scrollbar for log message */
+ bounds.left = bounds.right;
+ bounds.right += SCROLLBAR_WIDTH;
+ bounds.bottom++;
+ bounds.top--;
+ editor->log_scroller = NewControl(editor->win, &bounds, "\p",
+ true, 1, 1, 1, scrollBarProc, 0L);
+
+ /* save button */
+ TextFont(applFont);
+ TextSize(11);
+ bounds.left = editor->win->portRect.right - padding - 100;
+ bounds.right = bounds.left + 100;
+ bounds.bottom = editor->win->portRect.bottom - padding;
+ bounds.top = bounds.bottom - 20;
+ editor->save_button = NewControl(editor->win, &bounds, "\pSave",
+ true, 1, 1, 1, pushButProc, 0L);
+
+ editor->last_te = editor->author_te;
+
+ focusable = xmalloczero(sizeof(struct focusable));
+ focusable->cookie = editor;
+ focusable->win = editor->win;
+ focusable->modal = true;
+ focusable->idle = editor_idle;
+ focusable->update = editor_update;
+ focusable->mouse_down = editor_mouse_down;
+ focusable->key_down = editor_key_down;
+ focusable->menu = editor_handle_menu;
+ focusable->close = editor_close;
+ focusable_add(focusable);
+}
+
+bool
+editor_close(struct focusable *focusable)
+{
+ struct editor *editor = (struct editor *)focusable->cookie;
+
+ TEDispose(editor->author_te);
+ TEDispose(editor->date_te);
+ TEDispose(editor->log_te);
+ DisposeWindow(editor->win);
+
+ free(editor);
+
+ return true;
+}
+
+void
+editor_idle(struct focusable *focusable, EventRecord *event)
+{
+ struct editor *editor = (struct editor *)focusable->cookie;
+
+ TEIdle(editor->last_te);
+}
+
+void
+editor_update(struct focusable *focusable, EventRecord *event)
+{
+ Str255 buf;
+ Rect r;
+ short what = -1, len;
+ struct editor *editor = (struct editor *)focusable->cookie;
+
+ if (event != NULL)
+ what = event->what;
+
+ switch (what) {
+ case -1:
+ case updateEvt:
+ r = (*(editor->author_te))->viewRect;
+ MoveTo(padding, r.top + FontHeight(applFont, 11) - 2);
+ TextFont(applFont);
+ TextSize(11);
+ DrawText("Author:", 0, 7);
+ InsetRect(&r, -1, -1);
+ FrameRect(&r);
+ TEUpdate(&r, editor->author_te);
+
+ r = (*(editor->date_te))->viewRect;
+ MoveTo(padding, r.top + FontHeight(applFont, 11) - 2);
+ TextFont(applFont);
+ TextSize(11);
+ DrawText("Date:", 0, 5);
+ InsetRect(&r, -1, -1);
+ FrameRect(&r);
+ TEUpdate(&r, editor->date_te);
+
+ r = (*(editor->log_te))->viewRect;
+ MoveTo(padding, r.top + FontHeight(applFont, 11) - 2);
+ TextFont(applFont);
+ TextSize(11);
+ DrawText("Log:", 0, 4);
+ InsetRect(&r, -1, -1);
+ FrameRect(&r);
+ TEUpdate(&r, editor->log_te);
+
+ editor_update_menu(editor);
+ UpdtControl(editor->win, editor->win->visRgn);
+
+ break;
+ }
+}
+
+void
+editor_suspend(struct focusable *focusable)
+{
+ struct editor *editor = (struct editor *)focusable->cookie;
+
+ TEDeactivate(editor->author_te);
+ TEDeactivate(editor->date_te);
+ TEDeactivate(editor->log_te);
+}
+
+void
+editor_resume(struct focusable *focusable)
+{
+ struct editor *editor = (struct editor *)focusable->cookie;
+
+ TEActivate(editor->author_te);
+ TEActivate(editor->date_te);
+ TEActivate(editor->log_te);
+}
+
+void
+editor_key_down(struct focusable *focusable, EventRecord *event)
+{
+ struct editor *editor = (struct editor *)focusable->cookie;
+ char k;
+
+ k = (event->message & charCodeMask);
+
+ if (k == '\r' && (editor->last_te == editor->author_te ||
+ editor->last_te == editor->date_te))
+ return;
+
+ TEKey(k, editor->last_te);
+ if (editor->last_te == editor->log_te)
+ UpdateScrollbarForTE(editor->log_scroller, editor->last_te, false);
+ editor_update_menu(editor);
+}
+
+void
+editor_mouse_down(struct focusable *focusable, EventRecord *event)
+{
+ struct editor *editor = (struct editor *)focusable->cookie;
+ Point p;
+ ControlHandle control;
+ Rect r;
+ short val, adj, page, was_selected, part, i;
+
+ p = event->where;
+ GlobalToLocal(&p);
+
+ r = (*(editor->author_te))->viewRect;
+ if (PtInRect(p, &r)) {
+ if (editor->last_te != editor->author_te) {
+ editor->last_te = editor->author_te;
+ TEDeactivate(editor->date_te);
+ TEDeactivate(editor->log_te);
+ TEActivate(editor->author_te);
+ }
+ TEClick(p, ((event->modifiers & shiftKey) != 0), editor->author_te);
+ editor_update_menu(editor);
+ return;
+ }
+
+
+ r = (*(editor->date_te))->viewRect;
+ if (PtInRect(p, &r)) {
+ if (editor->last_te != editor->date_te) {
+ editor->last_te = editor->date_te;
+ TEDeactivate(editor->author_te);
+ TEDeactivate(editor->log_te);
+ TEActivate(editor->date_te);
+ }
+ TEClick(p, ((event->modifiers & shiftKey) != 0), editor->date_te);
+ editor_update_menu(editor);
+ return;
+ }
+
+ r = (*(editor->log_te))->viewRect;
+ if (PtInRect(p, &r)) {
+ if (editor->last_te != editor->log_te) {
+ editor->last_te = editor->log_te;
+ TEDeactivate(editor->author_te);
+ TEDeactivate(editor->date_te);
+ TEActivate(editor->log_te);
+ }
+ TEClick(p, ((event->modifiers & shiftKey) != 0), editor->log_te);
+ editor_update_menu(editor);
+ return;
+ }
+
+ switch (part = FindControl(p, editor->win, &control)) {
+ case inButton:
+ TextFont(applFont);
+ TextSize(11);
+ if (TrackControl(control, p, 0L) &&
+ control == editor->save_button)
+ editor_save(editor);
+ break;
+ case inUpButton:
+ case inDownButton:
+ case inPageUp:
+ case inPageDown:
+ if (control == editor->log_scroller)
+ SetTrackControlTE(editor->log_te);
+ else
+ break;
+ TrackControl(control, p, TrackMouseDownInControl);
+ break;
+ case inThumb:
+ val = GetCtlValue(control);
+ if (TrackControl(control, p, 0L) == 0)
+ break;
+ adj = val - GetCtlValue(control);
+ if (adj != 0) {
+ val -= adj;
+ if (control == editor->log_scroller)
+ TEScroll(0, adj * TEGetHeight(0, 0, editor->log_te),
+ editor->log_te);
+ SetCtlValue(control, val);
+ }
+ break;
+ }
+}
+
+void
+editor_update_menu(struct editor *editor)
+{
+ if ((*(editor->last_te))->selStart == (*(editor->last_te))->selEnd) {
+ DisableItem(edit_menu, EDIT_MENU_CUT_ID);
+ DisableItem(edit_menu, EDIT_MENU_COPY_ID);
+ } else {
+ EnableItem(edit_menu, EDIT_MENU_CUT_ID);
+ EnableItem(edit_menu, EDIT_MENU_COPY_ID);
+ }
+ if ((*(editor->last_te))->nLines > 0)
+ EnableItem(edit_menu, EDIT_MENU_SELECT_ALL_ID);
+ else
+ DisableItem(edit_menu, EDIT_MENU_SELECT_ALL_ID);
+ EnableItem(edit_menu, EDIT_MENU_PASTE_ID);
+
+ DisableItem(repo_menu, REPO_MENU_ADD_FILE_ID);
+ DisableItem(repo_menu, REPO_MENU_DISCARD_CHANGES_ID);
+ DisableItem(repo_menu, REPO_MENU_APPLY_PATCH_ID);
+
+ DisableItem(amendment_menu, AMENDMENT_MENU_EDIT_ID);
+ DisableItem(amendment_menu, AMENDMENT_MENU_EXPORT_ID);
+
+ EnableItem(repo_menu, 0);
+}
+
+bool
+editor_handle_menu(struct focusable *focusable, short menu, short item)
+{
+ struct editor *editor = (struct editor *)focusable->cookie;
+
+ switch (menu) {
+ case EDIT_MENU_ID:
+ switch (item) {
+ case EDIT_MENU_CUT_ID:
+ TECut(editor->last_te);
+ editor_update_menu(editor);
+ return true;
+ case EDIT_MENU_COPY_ID:
+ TECopy(editor->last_te);
+ editor_update_menu(editor);
+ return true;
+ case EDIT_MENU_PASTE_ID:
+ TEPaste(editor->last_te);
+ editor_update_menu(editor);
+ return true;
+ case EDIT_MENU_SELECT_ALL_ID:
+ TESetSelect(0, 1024 * 32, editor->last_te);
+ editor_update_menu(editor);
+ return true;
+ }
+ break;
+ }
+
+ return false;
+}
+
+void
+editor_save(struct editor *editor)
+{
+ struct tm ttm;
+ size_t len, size;
+ time_t ts;
+ short ret, yy, mm, dd, hh, min, ss, count = 0;
+ char *date, *author, *log, *data;
+
+ if ((*(editor->author_te))->teLength == 0) {
+ warn("Author field cannot be blank");
+ return;
+ }
+
+ len = (*(editor->date_te))->teLength;
+ if (len == 0) {
+ warn("Date field cannot be blank");
+ return;
+ }
+
+ date = xmalloc(len + 1);
+ memcpy(date, *(*(editor->date_te))->hText, len);
+ date[len] = '\0';
+
+ ret = sscanf(date, "%d-%d-%d %d:%d:%d%n", &yy, &mm, &dd, &hh, &min,
+ &ss, &count);
+ free(date);
+ if (ret != 6 || count < 11) {
+ warn("Date must be in YYYY-MM-DD HH:MM:SS format");
+ return;
+ }
+
+ ttm.tm_year = yy - 1900;
+ ttm.tm_mon = mm - 1;
+ ttm.tm_mday = dd;
+ ttm.tm_hour = hh;
+ ttm.tm_min = min;
+ ttm.tm_sec = ss;
+ ts = mktime(&ttm);
+
+ len = (*(editor->log_te))->teLength;
+ if (len == 0) {
+ warn("Log cannot be blank");
+ return;
+ }
+
+ editor->amendment->date = ts;
+
+ len = sizeof(editor->amendment->author) - 1;
+ if ((*(editor->author_te))->teLength < len)
+ len = (*(editor->author_te))->teLength;
+ memcpy(editor->amendment->author, *(*(editor->author_te))->hText,
+ len);
+ editor->amendment->author[len] = '\0';
+
+ editor->amendment->log_len = (*(editor->log_te))->teLength;
+ if (editor->amendment->log)
+ DisposHandle(editor->amendment->log);
+
+ editor->amendment->log = xNewHandle(editor->amendment->log_len);
+ memcpy(*(editor->amendment->log), *(*(editor->log_te))->hText,
+ editor->amendment->log_len);
+
+ progress("Storing updated amendment metadata...");
+
+ repo_marshall_amendment(editor->amendment, &data, &len);
+
+ size = bile_write(editor->browser->repo->bile, REPO_AMENDMENT_RTYPE,
+ editor->amendment->id, data, len);
+ if (size != len)
+ panic("Failed storing amendment in repo file: %d",
+ bile_error(editor->browser->repo->bile));
+ free(data);
+
+ editor->browser->need_refresh = true;
+ focusable_close(focusable_find(editor->win));
+ progress(NULL);
+}
--- editor.h Tue Aug 16 22:12:41 2022
+++ editor.h Tue Aug 16 22:12:41 2022
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 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
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __EDITOR_H__
+#define __EDITOR_H__
+
+#include "browser.h"
+#include "repo.h"
+#include "util.h"
+
+struct editor {
+ struct browser *browser;
+ WindowPtr win;
+ short state;
+ TEHandle log_te;
+ ControlHandle log_scroller;
+ TEHandle date_te;
+ TEHandle author_te;
+ ControlHandle save_button;
+ TEHandle last_te;
+ struct repo_amendment *amendment;
+};
+
+void editor_init(struct browser *browser, struct repo_amendment *amendment);
+
+#endif
--- main.c Tue Aug 16 13:32:45 2022
+++ main.c Tue Aug 16 16:44:27 2022
@@ -25,8 +25,8 @@
#include "settings.h"
#include "util.h"
-MenuHandle file_menu, edit_menu, repo_menu, commit_menu;
-Handle commit_list_ldef_h;
+MenuHandle file_menu, edit_menu, repo_menu, amendment_menu;
+Handle amendment_list_ldef_h;
bool quitting = false;
void handle_menu(long menu_id);
@@ -65,16 +65,16 @@ main(void)
file_menu = GetMHandle(FILE_MENU_ID);
edit_menu = GetMHandle(EDIT_MENU_ID);
repo_menu = GetMHandle(REPO_MENU_ID);
- commit_menu = GetMHandle(COMMIT_MENU_ID);
+ amendment_menu = GetMHandle(AMENDMENT_MENU_ID);
menu_defaults();
DrawMenuBar();
/* dynamically patch list LDEF to point to our *_list_ldef funcs */
- commit_list_ldef_h = GetResource('LDEF', COMMIT_LDEF_ID);
- if (!commit_list_ldef_h)
- err(1, "Can't find commit list LDEF %d", COMMIT_LDEF_ID);
- HLock(commit_list_ldef_h);
- ((tCodeStub *)*commit_list_ldef_h)->addr = &commit_list_ldef;
+ amendment_list_ldef_h = GetResource('LDEF', AMENDMENT_LDEF_ID);
+ if (!amendment_list_ldef_h)
+ err(1, "Can't find amendment list LDEF %d", AMENDMENT_LDEF_ID);
+ HLock(amendment_list_ldef_h);
+ ((tCodeStub *)*amendment_list_ldef_h)->addr = &amendment_list_ldef;
/* see if we were started by double-clicking a .repo file */
CountAppFiles(&finder_action, &finder_count);
@@ -272,6 +272,6 @@ menu_defaults(void)
DisableItem(repo_menu, REPO_MENU_DISCARD_CHANGES_ID);
DisableItem(repo_menu, REPO_MENU_APPLY_PATCH_ID);
- DisableItem(commit_menu, COMMIT_MENU_EDIT_ID);
- DisableItem(commit_menu, COMMIT_MENU_EXPORT_ID);
+ DisableItem(amendment_menu, AMENDMENT_MENU_EDIT_ID);
+ DisableItem(amendment_menu, AMENDMENT_MENU_EXPORT_ID);
}