summaryrefslogtreecommitdiffstats
path: root/zbar/processor/win.c
diff options
context:
space:
mode:
Diffstat (limited to 'zbar/processor/win.c')
-rw-r--r--zbar/processor/win.c332
1 files changed, 332 insertions, 0 deletions
diff --git a/zbar/processor/win.c b/zbar/processor/win.c
new file mode 100644
index 0000000..48fa9ac
--- /dev/null
+++ b/zbar/processor/win.c
@@ -0,0 +1,332 @@
+/*------------------------------------------------------------------------
+ * Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+
+#include <assert.h>
+#if defined(_MSC_VER)
+#include <WinSock2.h>
+#endif
+#include <windows.h>
+#include "processor.h"
+
+#define WIN_STYLE \
+ (WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)
+#define EXT_STYLE (WS_EX_APPWINDOW | WS_EX_OVERLAPPEDWINDOW)
+
+struct processor_state_s {
+ ATOM registeredClass;
+};
+
+int _zbar_event_init(zbar_event_t *event)
+{
+ *event = CreateEvent(NULL, 0, 0, NULL);
+ return ((*event) ? 0 : -1);
+}
+
+void _zbar_event_destroy(zbar_event_t *event)
+{
+ if (*event) {
+ CloseHandle(*event);
+ *event = NULL;
+ }
+}
+
+void _zbar_event_trigger(zbar_event_t *event)
+{
+ SetEvent(*event);
+}
+
+/* lock must be held */
+int _zbar_event_wait(zbar_event_t *event, zbar_mutex_t *lock,
+ zbar_timer_t *timeout)
+{
+ int rc;
+ if (lock)
+ _zbar_mutex_unlock(lock);
+ rc = WaitForSingleObject(*event, _zbar_timer_check(timeout));
+ if (lock)
+ _zbar_mutex_lock(lock);
+
+ if (!rc)
+ return (1); /* got event */
+ if (rc == WAIT_TIMEOUT)
+ return (0); /* timed out */
+ return (-1); /* error (FIXME save info) */
+}
+
+int _zbar_thread_start(zbar_thread_t *thr, zbar_thread_proc_t *proc, void *arg,
+ zbar_mutex_t *lock)
+{
+ HANDLE hthr;
+ int rc;
+ if (thr->started || thr->running)
+ return (-1 /*FIXME*/);
+ thr->started = 1;
+ _zbar_event_init(&thr->notify);
+ _zbar_event_init(&thr->activity);
+
+ hthr = CreateThread(NULL, 0, proc, arg, 0, NULL);
+ rc = (!hthr || _zbar_event_wait(&thr->activity, NULL, NULL) < 0 ||
+ !thr->running);
+ CloseHandle(hthr);
+ if (rc) {
+ thr->started = 0;
+ _zbar_event_destroy(&thr->notify);
+ _zbar_event_destroy(&thr->activity);
+ return (-1 /*FIXME*/);
+ }
+ return (0);
+}
+
+int _zbar_thread_stop(zbar_thread_t *thr, zbar_mutex_t *lock)
+{
+ if (thr->started) {
+ thr->started = 0;
+ _zbar_event_trigger(&thr->notify);
+ while (thr->running)
+ /* FIXME time out and abandon? */
+ _zbar_event_wait(&thr->activity, lock, NULL);
+ _zbar_event_destroy(&thr->notify);
+ _zbar_event_destroy(&thr->activity);
+ }
+ return (0);
+}
+
+static LRESULT CALLBACK win_handle_event(HWND hwnd, UINT message, WPARAM wparam,
+ LPARAM lparam)
+{
+ zbar_processor_t *proc =
+ (zbar_processor_t *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ /* initialized during window creation */
+ if (message == WM_NCCREATE) {
+ proc = ((LPCREATESTRUCT)lparam)->lpCreateParams;
+ assert(proc);
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)proc);
+ proc->display = hwnd;
+
+ zbar_window_attach(proc->window, proc->display, proc->xwin);
+ } else if (!proc)
+ return (DefWindowProc(hwnd, message, wparam, lparam));
+
+ switch (message) {
+ case WM_SIZE: {
+ RECT r;
+ GetClientRect(hwnd, &r);
+ zprintf(3, "WM_SIZE %ldx%ld\n", r.right, r.bottom);
+ assert(proc);
+ zbar_window_resize(proc->window, r.right, r.bottom);
+ InvalidateRect(hwnd, NULL, 0);
+ return (0);
+ }
+
+ case WM_PAINT: {
+ PAINTSTRUCT ps;
+ BeginPaint(hwnd, &ps);
+ if (zbar_window_redraw(proc->window)) {
+ HDC hdc = GetDC(hwnd);
+ RECT r;
+ GetClientRect(hwnd, &r);
+ FillRect(hdc, &r, GetStockObject(BLACK_BRUSH));
+ ReleaseDC(hwnd, hdc);
+ }
+ EndPaint(hwnd, &ps);
+ return (0);
+ }
+
+ case WM_CHAR: {
+ _zbar_processor_handle_input(proc, wparam);
+ return (0);
+ }
+
+ case WM_LBUTTONDOWN: {
+ _zbar_processor_handle_input(proc, 1);
+ return (0);
+ }
+
+ case WM_MBUTTONDOWN: {
+ _zbar_processor_handle_input(proc, 2);
+ return (0);
+ }
+
+ case WM_RBUTTONDOWN: {
+ _zbar_processor_handle_input(proc, 3);
+ return (0);
+ }
+
+ case WM_CLOSE: {
+ zprintf(3, "WM_CLOSE\n");
+ _zbar_processor_handle_input(proc, -1);
+ return (1);
+ }
+
+ case WM_DESTROY: {
+ zprintf(3, "WM_DESTROY\n");
+ proc->display = NULL;
+ zbar_window_attach(proc->window, NULL, 0);
+ return (0);
+ }
+ }
+ return (DefWindowProc(hwnd, message, wparam, lparam));
+}
+
+static inline int win_handle_events(zbar_processor_t *proc)
+{
+ int rc = 0;
+ while (1) {
+ MSG msg;
+ rc = PeekMessage(&msg, proc->display, 0, 0, PM_NOYIELD | PM_REMOVE);
+ if (!rc)
+ return (0);
+ if (rc < 0)
+ return (err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__,
+ "failed to obtain event"));
+
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+}
+
+int _zbar_processor_init(zbar_processor_t *proc)
+{
+ proc->state = calloc(1, sizeof(processor_state_t));
+ return (0);
+}
+
+int _zbar_processor_cleanup(zbar_processor_t *proc)
+{
+ free(proc->state);
+ proc->state = 0;
+ return (0);
+}
+
+int _zbar_processor_input_wait(zbar_processor_t *proc, zbar_event_t *event,
+ int timeout)
+{
+ int n = (event) ? 1 : 0;
+ int rc = MsgWaitForMultipleObjects(n, event, 0, timeout, QS_ALLINPUT);
+
+ if (rc == n) {
+ if (win_handle_events(proc) < 0)
+ return (-1);
+ return (1);
+ }
+ if (!rc)
+ return (1);
+ if (rc == WAIT_TIMEOUT)
+ return (0);
+ return (-1);
+}
+
+int _zbar_processor_enable(zbar_processor_t *proc)
+{
+ return (0);
+}
+
+static inline ATOM win_register_class(HINSTANCE hmod)
+{
+ BYTE and_mask[1] = { 0xff };
+ BYTE xor_mask[1] = { 0x00 };
+
+ WNDCLASSEX wc = {
+ sizeof(WNDCLASSEX),
+ 0,
+ };
+ wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ wc.hInstance = hmod;
+ wc.lpfnWndProc = win_handle_event;
+ wc.lpszClassName = "_ZBar Class";
+ wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+ wc.hCursor = CreateCursor(hmod, 0, 0, 1, 1, and_mask, xor_mask);
+
+ return (RegisterClassEx(&wc));
+}
+
+int _zbar_processor_open(zbar_processor_t *proc, char *title, unsigned width,
+ unsigned height)
+{
+ ATOM wca;
+ RECT r = { 0, 0, width, height };
+ HMODULE hmod = NULL;
+ if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
+ GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+ (void *)_zbar_processor_open, (HINSTANCE *)&hmod))
+ return (err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__,
+ "failed to obtain module handle"));
+
+ wca = win_register_class(hmod);
+ if (!wca)
+ return (err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__,
+ "failed to register window class"));
+
+ proc->state->registeredClass = wca;
+ AdjustWindowRectEx(&r, WIN_STYLE, 0, EXT_STYLE);
+ proc->display = CreateWindowEx(EXT_STYLE, (LPCTSTR)(long)wca, "ZBar",
+ WIN_STYLE, CW_USEDEFAULT, CW_USEDEFAULT,
+ r.right - r.left, r.bottom - r.top, NULL,
+ NULL, hmod, proc);
+
+ if (!proc->display)
+ return (err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__,
+ "failed to open window"));
+ return (0);
+}
+
+int _zbar_processor_close(zbar_processor_t *proc)
+{
+ if (proc->display) {
+ DestroyWindow(proc->display);
+ UnregisterClass((LPCTSTR)(long)proc->state->registeredClass, 0);
+ proc->display = NULL;
+ }
+ return (0);
+}
+
+int _zbar_processor_set_visible(zbar_processor_t *proc, int visible)
+{
+ ShowWindow(proc->display, (visible) ? SW_SHOWNORMAL : SW_HIDE);
+ if (visible)
+ InvalidateRect(proc->display, NULL, 0);
+ /* no error conditions */
+ return (0);
+}
+
+int _zbar_processor_set_size(zbar_processor_t *proc, unsigned width,
+ unsigned height)
+{
+ RECT r = { 0, 0, width, height };
+ AdjustWindowRectEx(&r, GetWindowLong(proc->display, GWL_STYLE), 0,
+ GetWindowLong(proc->display, GWL_EXSTYLE));
+ if (!SetWindowPos(
+ proc->display, NULL, 0, 0, r.right - r.left, r.bottom - r.top,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOREPOSITION))
+ return (-1 /*FIXME*/);
+
+ return (0);
+}
+
+int _zbar_processor_invalidate(zbar_processor_t *proc)
+{
+ if (!InvalidateRect(proc->display, NULL, 0))
+ return (-1 /*FIXME*/);
+
+ return (0);
+}