2020-01-04 22:21:39 -05:00
|
|
|
package zenity
|
|
|
|
|
|
|
|
import (
|
2022-05-09 10:49:32 -04:00
|
|
|
"bytes"
|
2020-01-30 09:14:42 -05:00
|
|
|
"context"
|
2022-05-09 10:49:32 -04:00
|
|
|
"os"
|
2020-01-04 22:21:39 -05:00
|
|
|
"syscall"
|
|
|
|
"unsafe"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2022-05-09 10:49:32 -04:00
|
|
|
messageBox = user32.NewProc("MessageBoxW")
|
|
|
|
getDlgCtrlID = user32.NewProc("GetDlgCtrlID")
|
|
|
|
loadImage = user32.NewProc("LoadImageW")
|
|
|
|
destroyIcon = user32.NewProc("DestroyIcon")
|
|
|
|
createIconFromResource = user32.NewProc("CreateIconFromResource")
|
2020-01-04 22:21:39 -05:00
|
|
|
)
|
|
|
|
|
2021-04-29 11:05:28 -04:00
|
|
|
func message(kind messageKind, text string, opts options) error {
|
2020-01-27 13:11:38 -05:00
|
|
|
var flags uintptr
|
2020-01-04 22:21:39 -05:00
|
|
|
|
|
|
|
switch {
|
2021-03-03 22:25:45 -05:00
|
|
|
case kind == questionKind && opts.extraButton != nil:
|
2022-03-28 22:05:46 -04:00
|
|
|
flags |= _MB_YESNOCANCEL
|
2021-03-03 22:32:55 -05:00
|
|
|
case kind == questionKind:
|
2022-03-28 22:05:46 -04:00
|
|
|
flags |= _MB_OKCANCEL
|
2021-03-03 22:32:55 -05:00
|
|
|
case opts.extraButton != nil:
|
2022-03-28 22:05:46 -04:00
|
|
|
flags |= _MB_YESNO
|
2020-01-04 22:21:39 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
switch opts.icon {
|
|
|
|
case ErrorIcon:
|
2022-03-28 22:05:46 -04:00
|
|
|
flags |= _MB_ICONERROR
|
2020-01-04 22:21:39 -05:00
|
|
|
case QuestionIcon:
|
2022-03-28 22:05:46 -04:00
|
|
|
flags |= _MB_ICONQUESTION
|
2020-01-04 22:21:39 -05:00
|
|
|
case WarningIcon:
|
2022-03-28 22:05:46 -04:00
|
|
|
flags |= _MB_ICONWARNING
|
2020-01-04 22:21:39 -05:00
|
|
|
case InfoIcon:
|
2022-03-28 22:05:46 -04:00
|
|
|
flags |= _MB_ICONINFORMATION
|
2022-05-17 11:18:12 -04:00
|
|
|
case nil:
|
2022-03-25 22:56:06 -04:00
|
|
|
switch kind {
|
|
|
|
case errorKind:
|
2022-03-28 22:05:46 -04:00
|
|
|
flags |= _MB_ICONERROR
|
2022-03-25 22:56:06 -04:00
|
|
|
case questionKind:
|
2022-03-28 22:05:46 -04:00
|
|
|
flags |= _MB_ICONQUESTION
|
2022-03-25 22:56:06 -04:00
|
|
|
case warningKind:
|
2022-03-28 22:05:46 -04:00
|
|
|
flags |= _MB_ICONWARNING
|
2022-03-25 22:56:06 -04:00
|
|
|
case infoKind:
|
2022-03-28 22:05:46 -04:00
|
|
|
flags |= _MB_ICONINFORMATION
|
2022-03-25 22:56:06 -04:00
|
|
|
}
|
2020-01-04 22:21:39 -05:00
|
|
|
}
|
|
|
|
|
2020-01-24 07:52:45 -05:00
|
|
|
if kind == questionKind && opts.defaultCancel {
|
2021-03-03 22:25:45 -05:00
|
|
|
if opts.extraButton == nil {
|
2022-03-28 22:05:46 -04:00
|
|
|
flags |= _MB_DEFBUTTON2
|
2020-01-07 19:44:26 -05:00
|
|
|
} else {
|
2022-03-28 22:05:46 -04:00
|
|
|
flags |= _MB_DEFBUTTON3
|
2020-01-07 19:44:26 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-26 08:40:24 -04:00
|
|
|
defer setup()()
|
2020-01-07 19:44:26 -05:00
|
|
|
|
2022-05-17 11:18:12 -04:00
|
|
|
if opts.ctx != nil || opts.okLabel != nil || opts.cancelLabel != nil || opts.extraButton != nil || opts.icon != nil {
|
2022-05-09 10:49:32 -04:00
|
|
|
unhook, err := hookMessageDialog(kind, opts)
|
2020-01-30 09:14:42 -05:00
|
|
|
if err != nil {
|
2021-04-29 11:05:28 -04:00
|
|
|
return err
|
2020-01-07 19:44:26 -05:00
|
|
|
}
|
2020-01-30 09:14:42 -05:00
|
|
|
defer unhook()
|
2020-01-07 19:44:26 -05:00
|
|
|
}
|
|
|
|
|
2021-09-15 08:54:35 -04:00
|
|
|
var title *uint16
|
2021-03-03 22:25:45 -05:00
|
|
|
if opts.title != nil {
|
2021-09-15 08:54:35 -04:00
|
|
|
title = syscall.StringToUTF16Ptr(*opts.title)
|
2021-03-03 22:25:45 -05:00
|
|
|
}
|
|
|
|
|
2021-09-15 08:54:35 -04:00
|
|
|
s, _, err := messageBox.Call(0, strptr(text), uintptr(unsafe.Pointer(title)), flags)
|
2020-01-04 22:21:39 -05:00
|
|
|
|
2020-01-30 09:14:42 -05:00
|
|
|
if opts.ctx != nil && opts.ctx.Err() != nil {
|
2021-04-29 11:05:28 -04:00
|
|
|
return opts.ctx.Err()
|
2020-01-30 09:14:42 -05:00
|
|
|
}
|
2021-03-03 22:32:55 -05:00
|
|
|
switch s {
|
2022-03-28 22:05:46 -04:00
|
|
|
case _IDOK, _IDYES:
|
2021-04-29 11:05:28 -04:00
|
|
|
return nil
|
2022-03-28 22:05:46 -04:00
|
|
|
case _IDCANCEL:
|
2021-04-29 11:05:28 -04:00
|
|
|
return ErrCanceled
|
2022-03-28 22:05:46 -04:00
|
|
|
case _IDNO:
|
2021-04-29 11:05:28 -04:00
|
|
|
return ErrExtraButton
|
2021-03-03 22:32:55 -05:00
|
|
|
default:
|
2021-04-29 11:05:28 -04:00
|
|
|
return err
|
2020-01-07 19:44:26 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-09 10:49:32 -04:00
|
|
|
func hookMessageDialog(kind messageKind, opts options) (unhook context.CancelFunc, err error) {
|
2020-01-30 09:14:42 -05:00
|
|
|
return hookDialog(opts.ctx, func(wnd uintptr) {
|
|
|
|
enumChildWindows.Call(wnd,
|
2022-05-09 10:49:32 -04:00
|
|
|
syscall.NewCallback(hookMessageDialogCallback),
|
2021-09-13 08:17:15 -04:00
|
|
|
uintptr(unsafe.Pointer(&opts)))
|
2020-01-30 09:14:42 -05:00
|
|
|
})
|
2020-01-04 22:21:39 -05:00
|
|
|
}
|
2021-09-13 08:17:15 -04:00
|
|
|
|
2022-05-09 10:49:32 -04:00
|
|
|
func hookMessageDialogCallback(wnd uintptr, lparam *options) uintptr {
|
|
|
|
ctl, _, _ := getDlgCtrlID.Call(wnd)
|
|
|
|
|
|
|
|
var text *string
|
|
|
|
switch ctl {
|
|
|
|
case _IDOK, _IDYES:
|
|
|
|
text = lparam.okLabel
|
|
|
|
case _IDCANCEL:
|
|
|
|
text = lparam.cancelLabel
|
|
|
|
case _IDNO:
|
|
|
|
text = lparam.extraButton
|
|
|
|
}
|
|
|
|
if text != nil {
|
|
|
|
setWindowText.Call(wnd, strptr(*text))
|
|
|
|
}
|
|
|
|
|
2022-05-17 11:18:12 -04:00
|
|
|
if i, ok := lparam.icon.(string); ok && ctl == 20 /*IDC_STATIC_OK*/ {
|
2022-05-09 10:49:32 -04:00
|
|
|
var icon uintptr
|
2022-05-17 11:18:12 -04:00
|
|
|
data, _ := os.ReadFile(i)
|
2022-05-09 10:49:32 -04:00
|
|
|
switch {
|
|
|
|
case bytes.HasPrefix(data, []byte("\x00\x00\x01\x00")):
|
|
|
|
icon, _, _ = loadImage.Call(0,
|
2022-05-17 11:18:12 -04:00
|
|
|
strptr(i),
|
2022-05-09 10:49:32 -04:00
|
|
|
1, /*IMAGE_ICON*/
|
|
|
|
0, 0,
|
|
|
|
0x00008050 /*LR_LOADFROMFILE|LR_DEFAULTSIZE|LR_SHARED*/)
|
|
|
|
case bytes.HasPrefix(data, []byte("\x89PNG\r\n\x1a\n")):
|
|
|
|
icon, _, _ = createIconFromResource.Call(
|
|
|
|
uintptr(unsafe.Pointer(&data[0])),
|
|
|
|
uintptr(len(data)),
|
|
|
|
1, 0x00030000)
|
|
|
|
defer destroyIcon.Call(icon)
|
2021-09-13 08:17:15 -04:00
|
|
|
}
|
2022-05-09 10:49:32 -04:00
|
|
|
|
|
|
|
if icon != 0 {
|
|
|
|
sendMessage.Call(wnd, 0x0170 /*STM_SETICON*/, icon, 0)
|
2021-09-13 08:17:15 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1
|
|
|
|
}
|