cat_engine_basement 0.0.0-alpha7

The CatEnigne's basement
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
use super::{
    InstanceHandle,
    window::{
        WindowHandle,
        default_window_procedure,
    },
    icon::IconHandle,
    cursor::CursorHandle,
    brush::BrushHandle,
};

use core::{
    mem::{
        size_of,
        transmute,
        transmute_copy,
    },
    ptr::null_mut,
    num::{
        NonZeroU16,
        NonZeroIsize,
    },
};

use winapi::{
    um::{
        winuser::{
            RegisterClassExW,
            UnregisterClassW,
            GetClassInfoExW,
            // window class styles
            CS_HREDRAW,
            CS_VREDRAW,
            CS_DBLCLKS,
            CS_OWNDC,
            CS_CLASSDC,
            CS_PARENTDC,
            CS_NOCLOSE,
            CS_SAVEBITS,
            CS_BYTEALIGNCLIENT,
            CS_BYTEALIGNWINDOW,
            CS_GLOBALCLASS,
            CS_DROPSHADOW,

            // window background colours
            COLOR_ACTIVEBORDER,
            COLOR_ACTIVECAPTION,
            COLOR_APPWORKSPACE,
            COLOR_BACKGROUND,
            COLOR_BTNFACE,
            COLOR_BTNSHADOW,
            COLOR_BTNTEXT,
            COLOR_CAPTIONTEXT,
            COLOR_GRAYTEXT,
            COLOR_HIGHLIGHT,
            COLOR_HIGHLIGHTTEXT,
            COLOR_INACTIVEBORDER,
            COLOR_INACTIVECAPTION,
            COLOR_MENU,
            COLOR_MENUTEXT,
            COLOR_SCROLLBAR,
            COLOR_WINDOW,
            COLOR_WINDOWFRAME,
            COLOR_WINDOWTEXT,
        },
    }
};

#[repr(u32)]
#[derive(Copy,Clone,Debug)]
pub enum WindowClassStyle{
    /// Redraws the entire window
    /// if a movement or size adjustment changes the height of the client area.
    /// 
    /// 0x0001
    VerticalRedraw=CS_VREDRAW,

    /// Redraws the entire window
    /// if a movement or size adjustment changes the width of the client area.
    /// 
    /// 0x0002
    HorizontalRedraw=CS_HREDRAW,

    /// Sends a double-click message to the window procedure
    /// when the user double-clicks the mouse while the cursor is within a window belonging to the class.
    /// 
    /// 0x0008
    DoubleClicks=CS_DBLCLKS,

    /// Allocates a unique device context for each window in the class.
    /// 
    /// 0x0020
    OwnDeviceContext=CS_OWNDC,

    /// Allocates one device context to be shared by all windows in the class.
    /// Because window classes are process specific,
    /// it is possible for multiple threads of an application to create a window of the same class.
    /// It is also possible for the threads to attempt to use the device context simultaneously.
    /// When this happens, the system allows only one thread to successfully finish its drawing operation.
    /// 
    /// 0x0040
    ClassDeviceContext=CS_CLASSDC,

    /// Sets the clipping rectangle of the child window to that of the parent window so that the child can draw on the parent.
    /// A window with the CS_PARENTDC style bit receives a regular device context from the system's cache of device contexts.
    /// It does not give the child the parent's device context or device context settings.
    /// Specifying CS_PARENTDC enhances an application's performance.
    /// 
    /// 0x0080
    ParentDeviceContext=CS_PARENTDC,

    /// Disables Close on the window menu.
    /// 
    /// 0x0200
    NoClose=CS_NOCLOSE,

    /// Saves, as a bitmap, the portion of the screen image obscured by a window of this class.
    /// When the window is removed, the system uses the saved bitmap to restore the screen image,
    /// including other windows that were obscured.
    /// Therefore, the system does not send WM_PAINT messages to windows that were obscured
    /// if the memory used by the bitmap has not been discarded and if other screen actions have not invalidated the stored image.
    /// This style is useful for small windows (for example, menus or dialog boxes)
    /// that are displayed briefly and then removed before other screen activity takes place.
    /// This style increases the time required to display the window, because the system must first allocate memory to store the bitmap.
    /// 
    /// 0x0800
    SaveBits=CS_SAVEBITS,

    /// Aligns the window's client area on a byte boundary (in the x direction).
    /// This style affects the width of the window and its horizontal placement on the display.
    /// 
    /// 0x1000
    ByteAlignClient=CS_BYTEALIGNCLIENT,

    /// Aligns the window on a byte boundary (in the x direction).
    /// This style affects the width of the window and its horizontal placement on the display.
    /// 
    /// 0x2000
    ByteAlignWindow=CS_BYTEALIGNWINDOW,

    /// Indicates that the window class is an application global class.
    /// For more information, see the "Application Global Classes" section of About Window Classes.
    /// 
    /// 0x4000
    GlobalClass=CS_GLOBALCLASS,

    /// Enables the drop shadow effect on a window.
    /// The effect is turned on and off through SPI_SETDROPSHADOW.
    /// Typically, this is enabled for small,
    /// short-lived windows such as menus to emphasize their Z-order relationship to other windows.
    /// Windows created from a class with this style must be top-level windows;
    /// they may not be child windows.
    /// 
    /// 0x00020000
    DropShadow=CS_DROPSHADOW,
}

/// Represents class styles.
#[derive(Clone,Copy,Debug)]
pub struct WindowClassStyles{
    flag:u32
}

impl WindowClassStyles{
    /// Creates a flag with no styles set.
    pub const fn new()->WindowClassStyles{
        Self{
            flag:0u32,
        }
    }

    /// Sets a style.
    pub const fn set(mut self,style:WindowClassStyle)->WindowClassStyles{
        self.flag|=style as u32;
        self
    }

    /// Removes a style.
    pub const fn remove(mut self,style:WindowClassStyle)->WindowClassStyles{
        self.flag&=!(style as u32);
        self
    }
}

/// A class identifier.
/// Contains a null-terminated string (it specifies the window class name)
/// or a class atom..
pub struct ClassIdentifier{
    identifier:isize,
}

impl ClassIdentifier{
    /// `name` specifies the window class name.
    #[inline(always)]
    pub fn name(name:*const u16)->ClassIdentifier{
        Self{
            identifier:name as isize,
        }
    }

    #[inline(always)]
    pub fn atom(atom:ClassAtom)->ClassIdentifier{
        Self{
            identifier:atom.as_raw() as isize,
        }
    }

    pub const fn as_ptr(&self)->*const u16{
        self.identifier as *const u16
    }
}

#[derive(Clone,Copy)]
#[repr(transparent)]
pub struct ClassAtom{
    inner:NonZeroU16
}

impl ClassAtom{
    #[inline(always)]
    pub fn from_raw(raw:u16)->Option<ClassAtom>{
        unsafe{
            transmute(raw)
        }
    }

    #[inline(always)]
    pub unsafe fn from_raw_unchecked(raw:u16)->ClassAtom{
        transmute(raw)
    }

    #[inline(always)]
    pub fn to_raw(handle:Option<ClassAtom>)->u16{
        unsafe{
            transmute(handle)
        }
    }

    #[inline(always)]
    pub fn as_raw(&self)->u16{
        unsafe{
            transmute_copy(self)
        }
    }
}

#[derive(Copy,Clone,Debug)]
#[repr(i32)]
pub enum WindowBackgroundSystemColour{
    ActiveBorder=COLOR_ACTIVEBORDER,
    ActioveCaption=COLOR_ACTIVECAPTION,
    AppWorkspace=COLOR_APPWORKSPACE,
    Background=COLOR_BACKGROUND,
    ButtonFace=COLOR_BTNFACE,
    ButtonShadow=COLOR_BTNSHADOW,
    ButtonText=COLOR_BTNTEXT,
    CaptionText=COLOR_CAPTIONTEXT,
    GrayText=COLOR_GRAYTEXT,
    Highlight=COLOR_HIGHLIGHT,
    HighlightText=COLOR_HIGHLIGHTTEXT,
    InactiveBorder=COLOR_INACTIVEBORDER,
    InactioveCaption=COLOR_INACTIVECAPTION,
    Menu=COLOR_MENU,
    MenuText=COLOR_MENUTEXT,
    Scrollbar=COLOR_SCROLLBAR,
    Window=COLOR_WINDOW,
    WindowFrame=COLOR_WINDOWFRAME,
    WindowText=COLOR_WINDOWTEXT,
}

/// A handle to the class background brush.
/// This member can be a handle to the brush to be used for painting the background,
/// or it can be a colour value.
#[derive(Clone,Copy,Debug)]
#[repr(transparent)]
pub struct WindowBackgroundColour{
    inner:NonZeroIsize,
}

impl WindowBackgroundColour{
    #[inline(always)]
    pub fn system_colour(colour:WindowBackgroundSystemColour)->WindowBackgroundColour{
        Self{
            inner:unsafe{transmute(colour as isize+1)}
        }
    }

    #[inline(always)]
    pub fn brush(brush:BrushHandle)->WindowBackgroundColour{
        Self{
            inner:unsafe{transmute(brush.as_raw())}
        }
    }
}

/// Contains window class information.
/// It is used with the RegisterClassEx and GetClassInfoEx functions.
#[derive(Clone)]
#[repr(C)]
pub struct WindowClassInfo{
    size:u32,
    /// The class styles.
    /// This member can be any combination of `WindowClassStyle`.
    /// 
    /// The default is no styles.
    pub styles:WindowClassStyles,

    /// A pointer to the window procedure.
    /// You must use the `CallWindowProc` function to call the window procedure.
    /// 
    /// The default is `default_window_procedure` (`DefWindowProcW`).
    pub window_procedure:unsafe extern "system" fn(WindowHandle,u32,usize,isize)->isize,

    /// The number of extra bytes to allocate following the window-class structure.
    /// The system initializes the bytes to zero.
    /// 
    /// The default is `0`.
    pub extra_class_data:i32,

    /// The number of extra bytes to allocate following the window instance.
    /// The system initializes the bytes to zero.
    /// If an application uses `WindowClassInfo` to register a dialog box created
    /// by using the CLASS directive in the resource file,
    /// it must set this member to `8`.
    /// 
    /// The default is `0`.
    pub extra_window_data:i32,

    /// A handle to the instance that contains the window procedure for the class.
    /// 
    /// The default is `None`.
    pub instance:Option<InstanceHandle>,

    /// A handle to the class icon.
    /// This member must be a handle to an icon resource.
    /// If this member is `None`, the system provides a default icon.
    /// 
    /// The default is `None`.
    pub icon:Option<IconHandle>,

    /// A handle to the class cursor.
    /// This member must be a handle to a cursor resource.
    /// If this member is `None`, an application must explicitly set the cursor shape
    /// whenever the mouse moves into the application's window.
    /// 
    /// The default is `None`.
    pub cursor:Option<CursorHandle>,

    /// A handle to the class background brush.
    /// This member can be a handle to the brush to be used for painting the background,
    /// or it can be a colour value.
    /// 
    /// The system automatically deletes class background brushes
    /// when the class is unregistered by using `Class::unregister`.
    /// An application should not delete these brushes.
    /// 
    /// When this member is `None`, an application must paint its own background
    /// whenever it is requested to paint in it's client area.
    /// To determine whether the background must be painted,
    /// an application can either process the `WM_ERASEBKGND` message
    /// or test the `fErase` member of the `PAINTSTRUCT` structure filled by the `BeginPaint` function.
    /// 
    /// The default is `None`.
    pub background:Option<WindowBackgroundColour>,

    /// Pointer to a null-terminated character string
    /// that specifies the resource name of the class menu,
    /// as the name appears in the resource file.
    /// If you use an integer to identify the menu, use the `MAKEINTRESOURCE` macro.
    /// If this member is `None`, windows belonging to this class have no default menu.
    /// 
    /// The default is `null`.
    pub menu_name:*const u16,

    /// A pointer to a null-terminated string or is an atom.
    /// If this parameter is an atom,
    /// it must be a class atom created by a previous call to the `Class::register` function.
    /// The atom must be in the low-order word of `class_name`; the high-order word must be zero.
    /// 
    /// If `class_name` is a string, it specifies the window class name.
    /// The class name can be any name registered with `Class::register`,
    /// or any of the predefined control-class names.
    /// 
    /// The maximum length for `class_name` is 256.
    /// If `class_name` is greater than the maximum length, the `Class::register` function will fail.
    /// 
    /// The default is `null`.
    pub class_name:*const u16,

    /// A handle to a small icon that is associated with the window class.
    /// If this member is `None`, the system searches the icon resource specified
    /// by the `icon` member for an icon of the appropriate size to use as the small icon.
    /// 
    /// The default is `None`.
    pub small_icon:Option<IconHandle>,
}

impl WindowClassInfo{
    pub fn new()->WindowClassInfo{
        Self{
            size:size_of::<WindowClassInfo>() as u32,
            styles:WindowClassStyles::new(),
            window_procedure:default_window_procedure,
            extra_class_data:0i32,
            extra_window_data:0i32,
            instance:None,
            icon:None,
            cursor:None,
            background:None,
            menu_name:null_mut(),
            class_name:null_mut(),
            small_icon:None,
        }
    }
}

/// All window classes that an application registers are unregistered when it terminates.
/// 
/// No window classes registered by a DLL are unregistered when the DLL is unloaded.
/// A DLL must explicitly unregister its classes when it is unloaded.
/// 
/// Before calling `WindowClass::unregister`,
/// an application must destroy all windows created with the specified class.
pub struct WindowClass;

impl WindowClass{
    pub const fn new()->WindowClass{
        Self
    }

    /// Registers a window class for subsequent use in calls to the `Window::create` function.
    /// 
    /// If the function succeeds,
    /// the return value is a class atom that uniquely identifies the class being registered.
    /// If the function fails, the return value is zero.
    /// To get extended error information, call `WindowsCore::get_last_error`.
    pub fn register(
        &self,
        class_name:*const u16,
        styles:WindowClassStyles,
        window_procedure:unsafe extern "system" fn(WindowHandle,u32,usize,isize)->isize,
        extra_class_data:i32,
        extra_window_data:i32,
        instance:Option<InstanceHandle>,
        icon:Option<IconHandle>,
        small_icon:Option<IconHandle>,
        cursor:Option<CursorHandle>,
        background:Option<WindowBackgroundColour>,
        menu_name:*const u16,
    )->Option<ClassAtom>{
        let mut attributes=WindowClassInfo::new();
        attributes.styles=styles;
        attributes.window_procedure=window_procedure;
        attributes.extra_class_data=extra_class_data;
        attributes.extra_window_data=extra_window_data;
        attributes.instance=instance;
        attributes.icon=icon;
        attributes.cursor=cursor;
        attributes.background=background;
        attributes.menu_name=menu_name;
        attributes.class_name=class_name;
        attributes.small_icon=small_icon;
        unsafe{
            ClassAtom::from_raw(RegisterClassExW(transmute(&attributes)))
        }
    }

    #[inline(always)]
    pub fn register_indirect(&self,info:&WindowClassInfo)->Option<ClassAtom>{
        unsafe{
            ClassAtom::from_raw(RegisterClassExW(transmute(&info)))
        }
    }

    /// Unregisters a window class, freeing the memory required for the class.
    /// 
    /// System classes, such as dialog box controls, cannot be unregistered.
    /// 
    /// If the function succeeds, the return value is `true`.
    /// If the class could not be found or if a window still exists that was created with the class,
    /// the return value is `false`.
    /// To get extended error information, call `WindowsCore::get_last_error`.
    #[inline(always)]
    pub fn unregister(&self,class:ClassIdentifier,instance:Option<InstanceHandle>)->bool{
        unsafe{
            UnregisterClassW(class.identifier as *const _,InstanceHandle::to_raw(instance))!=0
        }
    }

    /// Retrieves information about a window class,
    /// including a handle to the small icon associated with the window class.
    /// The function does not retrieve a handle to the small icon.
    /// 
    /// If the function finds a matching class and successfully copies the data,
    /// the return value is `true`.
    /// If the function does not find a matching class and successfully copy the data,
    /// the return value is `false`.
    /// To get extended error information, call `WindowsCore::get_last_error`.
    #[inline(always)]
    pub fn get_info(
        &self,
        class:ClassIdentifier,
        instance:Option<InstanceHandle>,
        info:&mut WindowClassInfo
    )->bool{
        unsafe{
            GetClassInfoExW(
                InstanceHandle::to_raw(instance),
                class.identifier as *const _,
                transmute(info)
            )!=0
        }
    }
}