Skip to content

Commit eecd71d

Browse files
committed
Sync
- Rename Checkout to Switch - Add encoding found in libssh2 history - Use window style that doesn't set a dtor on the SIL - Clean up UTF-8 handling, add macros for common MB2WC/WC2MB patterns - Implement wide variants of many internal APIs - Convert more of git config, convert explorer, convert history, convert staging drag, convert properties, convert some of commit properties, convert open in system (the git config approach is more UTF-16y, but it interfaces with win32 as supposed to libgit2 more)
1 parent c0d6686 commit eecd71d

15 files changed

Lines changed: 258 additions & 154 deletions

LGit.aps

4 Bytes
Binary file not shown.

LGit.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@
1717
#define CheckMenuItemIf(menu, command, cond) \
1818
CheckMenuItem(menu, command, MF_BYCOMMAND | ((cond) ? MF_CHECKED : MF_UNCHECKED))
1919

20+
/* Useful macros for simple conversions. Note -1 will copy the NUL too. */
21+
#define LGitWideToUtf8(wide, utf8, utf8size) WideCharToMultiByte(CP_UTF8, 0, wide, -1, utf8, utf8size, NULL, NULL)
22+
/* this is in wide codepoints */
23+
#define LGitUtf8ToWide(utf8, wide, widesize) MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wide, widesize)
24+
2025
/* XXX: Use a case-insensitive comparator */
2126
typedef std::set<std::string> CheckoutQueue;
2227

@@ -68,7 +73,9 @@ void LGitLibraryError(HWND hWnd, LPCSTR title);
6873
/* path.cpp */
6974
void LGitFreePathList(char **paths, int path_count);
7075
LGIT_API void LGitTranslateStringChars(char *buf, int char1, int char2);
76+
LGIT_API void LGitTranslateStringCharsW(wchar_t *buf, int char1, int char2);
7177
const char *LGitStripBasePath(LGitContext *ctx, const char *abs);
78+
const wchar_t *LGitStripBasePathW(LGitContext *ctx, const wchar_t *abs);
7279
LGIT_API BOOL LGitGetProjectNameFromPath(char *project, const char *path, size_t bufsz);
7380
void LGitOpenFiles(LGitContext *ctx, git_strarray *paths);
7481

@@ -205,6 +212,7 @@ BOOL LGitCertificatePrompt(LGitContext *ctx, HWND parent, git_cert *cert, const
205212

206213
/* string.cpp */
207214
char *strcasestr(const char *s, const char *find);
215+
wchar_t *wcscasestr(const wchar_t *s, const wchar_t *find);
208216
size_t strlcat(char *dst, const char *src, size_t siz);
209217
size_t strlcpy(char *dst, const char *src, size_t siz);
210218
size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t dsize);

LGit.rc

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,8 @@ BEGIN
163163
LTEXT "The files below are known by Git and can be added into your project.",
164164
IDC_STATIC,7,7,388,10
165165
CONTROL "List1",IDC_ADDSCC_LIST,"SysListView32",LVS_SMALLICON |
166-
LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER |
167-
WS_TABSTOP,7,22,388,197
166+
LVS_SHAREIMAGELISTS | LVS_NOCOLUMNHEADER |
167+
LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,22,388,197
168168
END
169169

170170
IDD_CLONE DIALOG DISCARDABLE 0, 0, 254, 191
@@ -365,8 +365,8 @@ CAPTION "Repository Explorer"
365365
FONT 8, "MS Sans Serif"
366366
BEGIN
367367
CONTROL "List1",IDC_EXPLORER_FILES,"SysListView32",LVS_REPORT |
368-
LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,7,386,186,
369-
WS_EX_ACCEPTFILES
368+
LVS_SHAREIMAGELISTS | LVS_NOSORTHEADER | WS_BORDER |
369+
WS_TABSTOP,7,7,386,186,WS_EX_ACCEPTFILES
370370
END
371371

372372
IDD_ABOUT DIALOG DISCARDABLE 0, 0, 186, 90
@@ -987,11 +987,11 @@ BEGIN
987987
ID_EXPLORER_REPOSITORY_OPENINWINDOWS
988988

989989
MENUITEM SEPARATOR
990-
MENUITEM "Re&ferences...", ID_EXPLORER_REPOSITORY_BRANCHES
990+
MENUITEM "&References...", ID_EXPLORER_REPOSITORY_BRANCHES
991991

992992
MENUITEM "&History...", ID_EXPLORER_REPOSITORY_HISTORY
993993

994-
MENUITEM "Ch&eckout Revision...", ID_EXPLORER_REPOSITORY_CHECKOUT
994+
MENUITEM "&Switch to Revision...", ID_EXPLORER_REPOSITORY_CHECKOUT
995995

996996
MENUITEM SEPARATOR
997997
MENUITEM "&Close", ID_EXPLORER_REPOSITORY_CLOSE
@@ -1033,7 +1033,7 @@ BEGIN
10331033

10341034
MENUITEM "Diff from &Revision...", ID_EXPLORER_DIFF_DIFFFROMREVISION
10351035

1036-
MENUITEM "", 1
1036+
MENUITEM SEPARATOR
10371037
MENUITEM "&Apply Patch...", ID_EXPLORER_REPOSITORY_APPLYPATCH
10381038

10391039
END

addscc.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,13 +167,6 @@ static BOOL CALLBACK AddFromDialogProc(HWND hwnd,
167167
return TRUE;
168168
}
169169
return FALSE;
170-
case WM_DESTROY:
171-
{
172-
/* annoying dtor we have to do, or the SIL gets blown away */
173-
HWND lv = GetDlgItem(hwnd, IDC_ADDSCC_LIST);
174-
ListView_SetImageList(lv, NULL, LVSIL_SMALL);
175-
}
176-
return TRUE;
177170
default:
178171
return FALSE;
179172
}

commitvw.cpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -207,43 +207,43 @@ void LGitViewCommitInfo(LGitContext *ctx, HWND hWnd, git_commit *commit, git_tag
207207
params.tag = tag;
208208

209209
int page_count = 0;
210-
PROPSHEETPAGE psp[3];
211-
ZeroMemory(&psp[page_count], sizeof(PROPSHEETPAGE));
212-
psp[page_count].dwSize = sizeof(PROPSHEETPAGE);
210+
PROPSHEETPAGEW psp[3];
211+
ZeroMemory(&psp[page_count], sizeof(PROPSHEETPAGEW));
212+
psp[page_count].dwSize = sizeof(PROPSHEETPAGEW);
213213
psp[page_count].hInstance = ctx->dllInst;
214-
psp[page_count].pszTemplate = MAKEINTRESOURCE(IDD_COMMITINFO);
214+
psp[page_count].pszTemplate = MAKEINTRESOURCEW(IDD_COMMITINFO);
215215
psp[page_count].pfnDlgProc = CommitInfoDialogProc;
216216
psp[page_count].lParam = (LPARAM)&params;
217217
page_count++;
218-
ZeroMemory(&psp[page_count], sizeof(PROPSHEETPAGE));
219-
psp[page_count].dwSize = sizeof(PROPSHEETPAGE);
218+
ZeroMemory(&psp[page_count], sizeof(PROPSHEETPAGEW));
219+
psp[page_count].dwSize = sizeof(PROPSHEETPAGEW);
220220
psp[page_count].hInstance = ctx->dllInst;
221-
psp[page_count].pszTemplate = MAKEINTRESOURCE(IDD_COMMITINFO_REFERENCES);
221+
psp[page_count].pszTemplate = MAKEINTRESOURCEW(IDD_COMMITINFO_REFERENCES);
222222
psp[page_count].pfnDlgProc = RefsDialogProc;
223223
psp[page_count].lParam = (LPARAM)&params;
224224
if (tag != NULL) {
225225
page_count++;
226-
ZeroMemory(&psp[page_count], sizeof(PROPSHEETPAGE));
227-
psp[page_count].dwSize = sizeof(PROPSHEETPAGE);
226+
ZeroMemory(&psp[page_count], sizeof(PROPSHEETPAGEW));
227+
psp[page_count].dwSize = sizeof(PROPSHEETPAGEW);
228228
psp[page_count].hInstance = ctx->dllInst;
229-
psp[page_count].pszTemplate = MAKEINTRESOURCE(IDD_TAGINFO);
229+
psp[page_count].pszTemplate = MAKEINTRESOURCEW(IDD_TAGINFO);
230230
psp[page_count].pfnDlgProc = TagInfoDialogProc;
231231
psp[page_count].lParam = (LPARAM)&params;
232232
}
233233
page_count++; /* for nPages */
234-
PROPSHEETHEADER psh;
235-
ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
236-
psh.dwSize = sizeof(PROPSHEETHEADER);
234+
PROPSHEETHEADERW psh;
235+
ZeroMemory(&psh, sizeof(PROPSHEETHEADERW));
236+
psh.dwSize = sizeof(PROPSHEETHEADERW);
237237
psh.dwFlags = PSH_PROPSHEETPAGE
238238
| PSH_NOAPPLYNOW
239239
| PSH_NOCONTEXTHELP
240240
| PSH_USECALLBACK;
241241
psh.pfnCallback = LGitImmutablePropSheetProc;
242242
psh.hwndParent = hWnd;
243243
psh.hInstance = ctx->dllInst;
244-
psh.pszCaption = "Commit Details";
244+
psh.pszCaption = L"Commit Details";
245245
psh.nPages = page_count;
246246
psh.ppsp = psp;
247247

248-
PropertySheet(&psh);
248+
PropertySheetW(&psh);
249249
}

format.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,16 @@ int LGitFormatSignatureW(const git_signature *sig, wchar_t *buf, size_t bufsz)
6464
{
6565
/* I assume these are UTF-8; it's never clear */
6666
wchar_t name[128], email[128];
67-
MultiByteToWideChar(CP_UTF8, 0, sig->name, -1, name, 128);
68-
MultiByteToWideChar(CP_UTF8, 0, sig->email, -1, email, 128);
67+
LGitUtf8ToWide(sig->name, name, 128);
68+
LGitUtf8ToWide(sig->email, email, 128);
6969
return _snwprintf(buf, bufsz, L"%s <%s>", name, email);
7070
}
7171

7272
int LGitFormatSignatureWithTimeW(const git_signature *sig, wchar_t *buf, size_t bufsz)
7373
{
7474
wchar_t name[128], email[128], time[128];
75-
MultiByteToWideChar(CP_UTF8, 0, sig->name, -1, name, 128);
76-
MultiByteToWideChar(CP_UTF8, 0, sig->email, -1, email, 128);
75+
LGitUtf8ToWide(sig->name, name, 128);
76+
LGitUtf8ToWide(sig->email, email, 128);
7777
LGitTimeToStringW(&sig->when, time, 128);
7878
return _snwprintf(buf, bufsz, L"%s %s <%s>", time, name, email);
7979
}
@@ -83,6 +83,9 @@ UINT LGitGitToWindowsCodepage(const char *encoding)
8383
/* Likely */
8484
if (encoding == NULL || strcmp(encoding, "UTF-8") == 0) {
8585
goto utf8;
86+
} else if (strcmp(encoding, "iso-8859-4") == 0) {
87+
/* found in libssh2 */
88+
return 28594;
8689
}
8790
LGitLog(" ! Unknown encoding '%s'\n", encoding);
8891
utf8:

gitconf.cpp

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ int ConfigForeach(const git_config_entry *e, void *payload)
130130
*/
131131

132132
wchar_t buf[1024];
133-
MultiByteToWideChar(CP_UTF8, 0, e->name, -1, buf, 1024);
133+
LGitUtf8ToWide(e->name, buf, 1024);
134134
/*
135135
* We should check if the item is already existant. If so, replace if the
136136
* level is higher. Otherwise, it can be confusing because operations will
@@ -174,7 +174,7 @@ int ConfigForeach(const git_config_entry *e, void *payload)
174174
}
175175
}
176176
/* now for the subitems... */
177-
MultiByteToWideChar(CP_UTF8, 0, e->value, -1, buf, 1024);
177+
LGitUtf8ToWide(e->value, buf, 1024);
178178
lvi.mask = LVIF_TEXT;
179179
lvi.iSubItem = 1;
180180
lvi.pszText = (wchar_t*)buf;
@@ -214,7 +214,7 @@ static void FillConfigView(HWND hwnd, LGitConfigDialogParams *params)
214214
}
215215
}
216216

217-
static BOOL GetSelectedConfig(HWND hwnd, char *buf, size_t bufsz)
217+
static BOOL GetSelectedConfig(HWND hwnd, wchar_t *buf, size_t bufsz)
218218
{
219219
HWND lv = GetDlgItem(hwnd, IDC_CONFIG_LIST);
220220
if (lv == NULL) {
@@ -224,21 +224,26 @@ static BOOL GetSelectedConfig(HWND hwnd, char *buf, size_t bufsz)
224224
if (selected == -1) {
225225
return FALSE;
226226
}
227-
ListView_GetItemText(lv, selected, 0, buf, bufsz);
228-
return TRUE;
227+
LVITEMW lvi;
228+
ZeroMemory(&lvi, sizeof(lvi));
229+
lvi.mask = LVIF_TEXT;
230+
lvi.iItem = selected; /* in case */
231+
lvi.pszText = buf;
232+
lvi.cchTextMax = bufsz;
233+
return SendMessage(lv, LVM_GETITEMTEXTW, selected, (LPARAM)&lvi) > 0;
229234
}
230235

231236
/**
232237
* Name and value are used to pre-fill the dialog; they aren't written to.
233238
*/
234-
static void ConfigEditDialog(HWND hwnd, LGitConfigDialogParams *params, const char *name, const char *value, BOOL isNew)
239+
static void ConfigEditDialog(HWND hwnd, LGitConfigDialogParams *params, const wchar_t *name, const wchar_t *value, BOOL isNew)
235240
{
236241
LGitEditConfigDialogParams ec_params;
237242
ZeroMemory(&ec_params, sizeof(LGitEditConfigDialogParams));
238243
ec_params.ctx = params->ctx;
239244
ec_params.is_new = isNew;
240-
MultiByteToWideChar(CP_UTF8, 0, name == NULL ? "" : name, -1, ec_params.new_name, 128);
241-
MultiByteToWideChar(CP_UTF8, 0, value == NULL ? "" : value, -1, ec_params.new_value, 128);
245+
wcslcpy(ec_params.new_name, name, 128);
246+
wcslcpy(ec_params.new_value, value, 128);
242247
switch (DialogBoxParam(params->ctx->dllInst,
243248
MAKEINTRESOURCE(IDD_CONFIG_EDIT),
244249
hwnd,
@@ -257,8 +262,8 @@ static void ConfigEditDialog(HWND hwnd, LGitConfigDialogParams *params, const ch
257262
/* convert */
258263
char new_name[256];
259264
char new_value[256];
260-
WideCharToMultiByte(CP_UTF8, 0, ec_params.new_name, -1, new_name, 256, NULL, NULL);
261-
WideCharToMultiByte(CP_UTF8, 0, ec_params.new_value, -1, new_value, 256, NULL, NULL);
265+
LGitWideToUtf8(ec_params.new_name, new_name, 256);
266+
LGitWideToUtf8(ec_params.new_value, new_value, 256);
262267
if (git_config_set_string(params->config, new_name, new_value) != 0) {
263268
LGitLibraryError(hwnd, "git_config_set_string");
264269
return;
@@ -269,42 +274,47 @@ static void ConfigEditDialog(HWND hwnd, LGitConfigDialogParams *params, const ch
269274

270275
static void ConfigEdit(HWND hwnd, LGitConfigDialogParams *params)
271276
{
272-
char name[128];
277+
wchar_t name[128];
278+
char name_utf8[128];
273279
if (!GetSelectedConfig(hwnd, name, 128)) {
274280
LGitLog(" ! No config?\n");
275281
return;
276282
}
283+
LGitWideToUtf8(name, name_utf8, 128);
277284
/*
278285
* XXX: Check if we're editing in the same level. If not, a new value is
279286
* inserted at the higher level which supersedes the lower one.
280287
*/
281288
git_buf old_val_buf = {0};
282-
if (git_config_get_string_buf(&old_val_buf, params->config, name) != 0) {
289+
wchar_t old_val_utf16[128];
290+
if (git_config_get_string_buf(&old_val_buf, params->config, name_utf8) != 0) {
283291
LGitLibraryError(hwnd, "git_config_get_string_buf");
284292
return;
285293
}
286-
LGitLog(" ! Editing %s?\n", name);
287-
ConfigEditDialog(hwnd, params, name, old_val_buf.ptr, FALSE);
294+
LGitUtf8ToWide(old_val_buf.ptr, old_val_utf16, 128);
295+
LGitLog(" ! Editing %s?\n", name_utf8);
296+
ConfigEditDialog(hwnd, params, name, old_val_utf16, FALSE);
288297
git_buf_dispose(&old_val_buf);
289298
}
290299

291300
static void ConfigRemove(HWND hwnd, LGitConfigDialogParams *params)
292301
{
293302
/* XXX: Multiple selection could be handy here */
294-
char name[128];
303+
wchar_t name[128];
304+
char name_utf8[128];
295305
if (!GetSelectedConfig(hwnd, name, 128)) {
296306
LGitLog(" ! No config?\n");
297307
return;
298308
}
299-
LGitLog(" ! Removing %s?\n", name);
309+
LGitWideToUtf8(name, name_utf8, 128);
300310
if (MessageBox(hwnd,
301311
"This configuration entry will be deleted from its source. "
302312
"It may be replaced with an inherited configuration. Are you sure?",
303313
"Remove Config Entry?",
304314
MB_ICONWARNING | MB_YESNO) != IDYES) {
305315
return;
306316
}
307-
if (git_config_delete_entry(params->config, name) != 0) {
317+
if (git_config_delete_entry(params->config, name_utf8) != 0) {
308318
LGitLibraryError(hwnd, "git_config_delete_entry");
309319
return;
310320
}

history.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,20 @@ typedef struct _LGitHistoryDialogParams {
4141
static void InitializeHistoryWindow(HWND hwnd, LGitHistoryDialogParams *params)
4242
{
4343
SetMenu(hwnd, params->menu);
44-
char title[256];
44+
wchar_t title[256], thing[256];
4545
/* XXX: Load string resources */
4646
if (params->path_count == 0 && params->ref == NULL) {
47-
_snprintf(title, 256, "Commit History for Repository");
47+
wcslcpy(title, L"Commit History for Repository", 256);
4848
} else if (params->path_count == 0) {
49-
_snprintf(title, 256, "Commit History for %s", params->ref);
49+
LGitUtf8ToWide(params->ref, thing, 256);
50+
_snwprintf(title, 256, L"Commit History for %s", thing);
5051
} else if (params->path_count == 1) {
51-
_snprintf(title, 256, "Commit History for %s", params->paths[0]);
52+
LGitUtf8ToWide(params->paths[0], thing, 256);
53+
_snwprintf(title, 256, L"Commit History for %s", thing);
5254
} else {
53-
_snprintf(title, 256, "Commit History for %d files", params->path_count);
55+
_snwprintf(title, 256, L"Commit History for %d files", params->path_count);
5456
}
55-
SetWindowText(hwnd, title);
57+
SetWindowTextW(hwnd, title);
5658
}
5759

5860
static void InitializeHistoryListView(HWND hwnd)
@@ -217,7 +219,7 @@ static BOOL FillHistoryListView(HWND hwnd,
217219

218220
ZeroMemory(&lvi, sizeof(LVITEM));
219221
lvi.mask = LVIF_TEXT;
220-
MultiByteToWideChar(CP_UTF8, 0, oid_str, -1, formatted, 256);
222+
LGitUtf8ToWide(oid_str, formatted, 256);
221223
lvi.pszText = formatted;
222224
lvi.iItem = index++;
223225
lvi.iSubItem = 0;
@@ -516,8 +518,8 @@ static SCCRTN LGitHistoryInternal(LGitContext *ctx,
516518
params.diffopts = &diffopts;
517519
params.ref = ref;
518520
params.menu = LoadMenu(ctx->dllInst, MAKEINTRESOURCE(IDR_HISTORY_MENU));
519-
switch (DialogBoxParam(ctx->dllInst,
520-
MAKEINTRESOURCE(IDD_COMMITHISTORY),
521+
switch (DialogBoxParamW(ctx->dllInst,
522+
MAKEINTRESOURCEW(IDD_COMMITHISTORY),
521523
hWnd,
522524
HistoryDialogProc,
523525
(LPARAM)&params)) {

0 commit comments

Comments
 (0)