| /* |
| * GraphApp - Cross-Platform Graphics Programming Library. |
| * |
| * File: cursors.c -- change the mouse cursor's shape. |
| * Platform: Windows Version: 2.35 Date: 1998/04/04 |
| * |
| * Version: 1.00 Changes: Original version by Lachlan Patrick. |
| * Version: 1.05 Changes: Moved setcursor() into context.c |
| * Version: 2.00 Changes: New object class mechanism. |
| * Version: 2.30 Changes: Now uses cursor_base. |
| * Version: 2.35 Changes: New reference count technique. |
| */ |
| |
| /* Copyright (C) 1993-1998 Lachlan Patrick |
| |
| This file is part of GraphApp, a cross-platform C graphics library. |
| |
| GraphApp is free software; you can redistribute it and/or modify it |
| under the terms of the GNU Library General Public License. |
| GraphApp is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY. |
| |
| See the file COPYLIB.TXT for details. |
| */ |
| |
| /* Changes for Windows: |
| |
| add cross cursor |
| |
| */ |
| |
| #include "internal.h" |
| |
| __declspec(dllexport) cursor ArrowCursor = NULL; |
| __declspec(dllexport) cursor BlankCursor = NULL; |
| __declspec(dllexport) cursor WatchCursor = NULL; |
| __declspec(dllexport) cursor CaretCursor = NULL; |
| __declspec(dllexport) cursor TextCursor = NULL; |
| __declspec(dllexport) cursor HandCursor = NULL; |
| __declspec(dllexport) cursor CrossCursor = NULL; |
| |
| /* |
| * Define the 'Hand' image shape: |
| */ |
| |
| static rgb cursor_cmap [] = { |
| 0x00000000L, |
| 0x00FFFFFFL, |
| 0xFFFFFFFFL, |
| }; |
| |
| static GAbyte hand_pixels [] = { |
| 2,2,2,2,2,2,0,0,0,2,2,2,2,2,2,2, |
| 2,2,2,2,2,0,1,1,0,0,2,2,2,2,2,2, |
| 2,2,2,2,2,0,1,1,0,0,2,2,2,2,2,2, |
| 2,2,2,2,2,0,1,1,0,0,2,2,2,2,2,2, |
| 2,2,2,2,2,0,1,1,0,0,2,2,2,2,2,2, |
| 2,2,2,2,2,0,1,1,0,0,2,2,2,2,2,2, |
| 2,0,0,0,2,0,1,1,0,0,0,0,0,2,2,2, |
| 0,1,1,0,0,0,1,1,0,1,0,1,0,0,0,2, |
| 2,0,1,1,0,0,1,1,0,1,0,1,0,1,0,0, |
| 2,2,0,1,1,0,1,1,1,1,1,1,0,1,0,0, |
| 2,2,0,1,1,0,1,1,1,1,1,1,1,1,0,0, |
| 2,2,2,0,1,1,1,1,1,1,1,1,1,1,0,0, |
| 2,2,2,2,0,1,1,1,1,1,1,1,1,1,0,0, |
| 2,2,2,2,0,1,1,1,1,1,1,1,1,0,0,2, |
| 2,2,2,2,2,0,1,1,1,1,1,1,1,0,0,2, |
| 2,2,2,2,2,0,1,1,1,1,1,1,1,0,0,2, |
| }; |
| |
| static imagedata hand_imagedata = { |
| 8, /* depth */ |
| 16, /* width */ |
| 16, /* height */ |
| 3, /* cmapsize */ |
| cursor_cmap, |
| hand_pixels |
| }; |
| |
| static image hand_image = & hand_imagedata; |
| static point hand_hotspot = {7,0}; |
| |
| /* |
| * Private cursor destructor. |
| */ |
| static void private_delcursor(cursor c) |
| { |
| DestroyCursor(c->handle); |
| } |
| |
| /* |
| * Private constructor. |
| */ |
| static object get_cursor_base(void) |
| { |
| static object cursor_base = NULL; |
| |
| if (! cursor_base) |
| cursor_base = new_object(BaseObject, 0, NULL); |
| return cursor_base; |
| } |
| |
| static cursor new_cursor_object(HCURSOR hc) |
| { |
| cursor c = new_object(CursorObject, hc, get_cursor_base()); |
| if (c) { |
| c->rect = rect(0,0,16,16); |
| c->depth = 1; |
| c->die = private_delcursor; |
| } |
| return c; |
| } |
| |
| /* |
| * Public constructors. |
| */ |
| cursor createcursor(point offset, GAbyte *white, GAbyte *black) |
| { |
| cursor c; |
| HCURSOR hc; |
| GAbyte *andmask; /* andmask = ~blackmask & ~whitemask */ |
| GAbyte *xormask; /* xormask = ~blackmask & whitemask */ |
| int w, y; |
| int max_width, max_height, row_bytes; |
| |
| /* Library cursors: D = (D | whitemask) & ~blackmask */ |
| /* MS-Windows does: D = (D & andmask) ^ xormask */ |
| |
| /* Determine the best cursor size: */ |
| max_width = GetSystemMetrics(SM_CXCURSOR); |
| max_height = GetSystemMetrics(SM_CYCURSOR); |
| row_bytes = (max_width + 7) / 8; |
| |
| /* Create the data arrays: */ |
| andmask = array(max_height * row_bytes, GAbyte); |
| xormask = array(max_height * row_bytes, GAbyte); |
| |
| /* Assign the data into the arrays: */ |
| for (y=0; y < max_height; y++) { |
| for (w=0; w < row_bytes; w++) { |
| if ((w<2) && (y<16)) { |
| andmask[w+y*row_bytes] = ~(black[w+y*2]) & ~(white[w+y*2]); |
| xormask[w+y*row_bytes] = ~(black[w+y*2]) & (white[w+y*2]); |
| } |
| else { |
| andmask[w+y*row_bytes] = 0xFF; |
| xormask[w+y*row_bytes] = 0x00; |
| } |
| } |
| } |
| |
| /* Create the cursor: */ |
| hc = CreateCursor (this_instance, -offset.x, -offset.y, |
| max_width, max_height, |
| (void FAR *) andmask, (void FAR *) xormask); |
| |
| c = new_cursor_object(hc); |
| |
| /* Clean up: */ |
| discard(andmask); |
| discard(xormask); |
| |
| return c; |
| } |
| |
| static GAbyte form_and_byte(image img, int x, int y) |
| { |
| int i; |
| rgb pixel; |
| GAbyte result = 0x00; |
| |
| for (i=0; i<8; i++) { |
| result <<= 1; |
| pixel = get_monochrome_pixel(img, x+i, y); |
| if (pixel == Transparent) |
| result |= 0x01; |
| } |
| return result; |
| } |
| |
| static GAbyte form_xor_byte(image img, int x, int y) |
| { |
| int i; |
| rgb pixel; |
| GAbyte result = 0x00; |
| |
| for (i=0; i<8; i++) { |
| result <<= 1; |
| pixel = get_monochrome_pixel(img, x+i, y); |
| if (pixel == White) |
| result |= 0x01; |
| } |
| return result; |
| } |
| |
| cursor newcursor(point p, image img) |
| { |
| cursor c; |
| HCURSOR hc; |
| GAbyte *andmask; |
| GAbyte *xormask; |
| int w, y; |
| int max_width, max_height, row_bytes; |
| |
| if (! img) return NULL; |
| |
| /* Determine the best cursor size: */ |
| max_width = GetSystemMetrics(SM_CXCURSOR); |
| max_height = GetSystemMetrics(SM_CYCURSOR); |
| row_bytes = (max_width + 7) / 8; |
| |
| /* Create the data arrays: */ |
| andmask = array(max_height * row_bytes, GAbyte); |
| xormask = array(max_height * row_bytes, GAbyte); |
| |
| /* Assign the data into the arrays: */ |
| for (y=0; y < max_height; y++) { |
| for (w=0; w < row_bytes; w++) { |
| andmask[w+y*row_bytes] = form_and_byte(img, w*8, y); |
| xormask[w+y*row_bytes] = form_xor_byte(img, w*8, y); |
| } |
| } |
| |
| /* Create the cursor: */ |
| hc = CreateCursor (this_instance, p.x, p.y, |
| max_width, max_height, |
| (void FAR *) andmask, (void FAR *) xormask); |
| |
| c = new_cursor_object(hc); |
| |
| /* Clean up: */ |
| discard(andmask); |
| discard(xormask); |
| |
| return c; |
| } |
| |
| #ifdef UNUSED |
| /* |
| * Load a cursor from resources. |
| */ |
| static point load_hotspot(const char *filename) |
| { |
| FILE *file; |
| char line[100]; |
| int i, x, y; |
| point p = pt(0,0); |
| |
| file = fopen(filename, "rt"); |
| while (fgets(line, sizeof(line)-2, file)) { |
| if ( (! strncmp(line, "point", 5)) |
| || (! strncmp(line, "/* point", 8)) ) |
| { |
| i = 5; |
| x = y = 0; |
| while (line[i] && (! isdigit(line[i])) ) |
| i++; /* skip "hotspot = {" */ |
| x = atoi(line+i); |
| while (line[i] && isdigit(line[i])) |
| i++; /* skip x-location */ |
| while (line[i] && (! isdigit(line[i])) ) |
| i++; /* skip comma */ |
| y = atoi(line+i); |
| p = pt(x,y); |
| break; |
| } |
| } |
| fclose(file); |
| return p; |
| } |
| |
| static cursor load_image_cursor(const char *filename) |
| { |
| cursor c = NULL; |
| image img; |
| point p; |
| |
| img = loadimage(filename); |
| if (img) { |
| p = load_hotspot(filename); |
| c = newcursor(p, img); |
| delimage(img); |
| } |
| return c; |
| } |
| |
| cursor loadcursor(const char *name) |
| { |
| HCURSOR hc; |
| cursor c; |
| |
| if (this_instance == 0) |
| return ArrowCursor; |
| |
| hc = LoadCursor(this_instance, name); |
| |
| if (hc) c = new_cursor_object(hc); |
| else c = load_image_cursor(name); |
| |
| if (c) c->text = new_string(name); |
| |
| return c; |
| } |
| #endif |
| |
| /* |
| * Private cursor initialisation routines. |
| */ |
| static cursor make_special_cursor(const char *name, LPCSTR idc) |
| { |
| cursor c; |
| |
| if (idc) c = new_cursor_object(LoadCursor(0, idc)); |
| else c = new_cursor_object(NULL); |
| |
| if (c) { |
| c->text = new_string(name); |
| protect_object(c); |
| } |
| return c; |
| } |
| |
| PROTECTED |
| void init_cursors(void) |
| { |
| ArrowCursor = make_special_cursor("ArrowCursor", IDC_ARROW); |
| BlankCursor = make_special_cursor("BlankCursor", NULL); |
| WatchCursor = make_special_cursor("WatchCursor", IDC_WAIT); |
| CaretCursor = make_special_cursor("CaretCursor", IDC_IBEAM); |
| TextCursor = make_special_cursor("TextCursor", IDC_IBEAM); |
| CrossCursor = make_special_cursor("CrossCursor", IDC_CROSS); |
| |
| HandCursor = newcursor(hand_hotspot, hand_image); |
| if (HandCursor) { |
| settext(HandCursor, "HandCursor"); |
| protect_object(HandCursor); |
| } |
| |
| setcursor(ArrowCursor); |
| } |