comparison ios/dw.m @ 2407:6336244aa895

iOS: Fix timers and implement dw_beep().
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Sun, 28 Mar 2021 20:51:44 +0000
parents 38c17a19e00d
children 795056df9efd
comparison
equal deleted inserted replaced
2406:716f38f69073 2407:6336244aa895
9 * clang -g -o dwtest -D__IOS__ -I. dwtest.c ios/dw.m -framework UIKit -framework WebKit -framework Foundation -framework UserNotifications 9 * clang -g -o dwtest -D__IOS__ -I. dwtest.c ios/dw.m -framework UIKit -framework WebKit -framework Foundation -framework UserNotifications
10 */ 10 */
11 #import <Foundation/Foundation.h> 11 #import <Foundation/Foundation.h>
12 #import <UIKit/UIKit.h> 12 #import <UIKit/UIKit.h>
13 #import <WebKit/WebKit.h> 13 #import <WebKit/WebKit.h>
14 #import <AudioToolbox/AudioToolbox.h>
14 #import <UserNotifications/UserNotifications.h> 15 #import <UserNotifications/UserNotifications.h>
15 #include "dw.h" 16 #include "dw.h"
16 #include <sys/utsname.h> 17 #include <sys/utsname.h>
17 #include <sys/socket.h> 18 #include <sys/socket.h>
18 #include <sys/un.h> 19 #include <sys/un.h>
3515 * id: An ID to be used with dw_window_from_id() or 0L. 3516 * id: An ID to be used with dw_window_from_id() or 0L.
3516 * filename: Name of the file, omit extention to have 3517 * filename: Name of the file, omit extention to have
3517 * DW pick the appropriate file extension. 3518 * DW pick the appropriate file extension.
3518 * (BMP on OS/2 or Windows, XPM on Unix) 3519 * (BMP on OS/2 or Windows, XPM on Unix)
3519 */ 3520 */
3520 DW_FUNCTION_DEFINITION(dw_bitmapbutton_new_from_file, HWND, const char *text, ULONG cid, const char *filename) 3521 DW_FUNCTION_DEFINITION(dw_bitmapbutton_new_from_file, HWND, DW_UNUSED(const char *text), ULONG cid, const char *filename)
3521 DW_FUNCTION_ADD_PARAM3(text, cid, filename) 3522 DW_FUNCTION_ADD_PARAM3(text, cid, filename)
3522 DW_FUNCTION_RETURN(dw_bitmapbutton_new_from_file, HWND) 3523 DW_FUNCTION_RETURN(dw_bitmapbutton_new_from_file, HWND)
3523 DW_FUNCTION_RESTORE_PARAM3(text, const char *, cid, ULONG, filename, const char *) 3524 DW_FUNCTION_RESTORE_PARAM3(DW_UNUSED(text), const char *, cid, ULONG, filename, const char *)
3524 { 3525 {
3525 char *ext = _dw_get_image_extension(filename); 3526 char *ext = _dw_get_image_extension(filename);
3526 3527
3527 NSString *nstr = [ NSString stringWithUTF8String:filename ]; 3528 NSString *nstr = [ NSString stringWithUTF8String:filename ];
3528 UIImage *image = [[UIImage alloc] initWithContentsOfFile:nstr]; 3529 UIImage *image = [[UIImage alloc] initWithContentsOfFile:nstr];
3667 * Parameters: 3668 * Parameters:
3668 * vertical: TRUE or FALSE if slider is vertical. 3669 * vertical: TRUE or FALSE if slider is vertical.
3669 * increments: Number of increments available. 3670 * increments: Number of increments available.
3670 * id: An ID to be used with dw_window_from_id() or 0L. 3671 * id: An ID to be used with dw_window_from_id() or 0L.
3671 */ 3672 */
3672 DW_FUNCTION_DEFINITION(dw_slider_new, HWND, int vertical, int increments, ULONG cid) 3673 DW_FUNCTION_DEFINITION(dw_slider_new, HWND, int DW_UNUSED(vertical), int increments, ULONG cid)
3673 DW_FUNCTION_ADD_PARAM3(vertical, increments, cid) 3674 DW_FUNCTION_ADD_PARAM3(vertical, increments, cid)
3674 DW_FUNCTION_RETURN(dw_slider_new, HWND) 3675 DW_FUNCTION_RETURN(dw_slider_new, HWND)
3675 DW_FUNCTION_RESTORE_PARAM3(vertical, int, increments, int, cid, ULONG) 3676 DW_FUNCTION_RESTORE_PARAM3(DW_UNUSED(vertical), int, increments, int, cid, ULONG)
3676 { 3677 {
3677 DWSlider *slider = [[[DWSlider alloc] init] retain]; 3678 DWSlider *slider = [[[DWSlider alloc] init] retain];
3678 [slider setMaximumValue:(double)increments]; 3679 [slider setMaximumValue:(double)increments];
3679 [slider setMinimumValue:0]; 3680 [slider setMinimumValue:0];
3680 [slider setContinuous:YES]; 3681 [slider setContinuous:YES];
5860 * handle: Handle to the window (widget) to be scrolled. 5861 * handle: Handle to the window (widget) to be scrolled.
5861 * direction: DW_SCROLL_UP, DW_SCROLL_DOWN, DW_SCROLL_TOP or 5862 * direction: DW_SCROLL_UP, DW_SCROLL_DOWN, DW_SCROLL_TOP or
5862 * DW_SCROLL_BOTTOM. (rows is ignored for last two) 5863 * DW_SCROLL_BOTTOM. (rows is ignored for last two)
5863 * rows: The number of rows to be scrolled. 5864 * rows: The number of rows to be scrolled.
5864 */ 5865 */
5865 DW_FUNCTION_DEFINITION(dw_container_scroll, void, HWND handle, int direction, long rows) 5866 DW_FUNCTION_DEFINITION(dw_container_scroll, void, HWND handle, int direction, DW_UNUSED(long rows))
5866 DW_FUNCTION_ADD_PARAM3(handle, direction, rows) 5867 DW_FUNCTION_ADD_PARAM3(handle, direction, rows)
5867 DW_FUNCTION_NO_RETURN(dw_container_scroll) 5868 DW_FUNCTION_NO_RETURN(dw_container_scroll)
5868 DW_FUNCTION_RESTORE_PARAM3(handle, HWND, direction, int, rows, long) 5869 DW_FUNCTION_RESTORE_PARAM3(handle, HWND, direction, int, DW_UNUSED(rows), long)
5869 { 5870 {
5870 DW_FUNCTION_INIT; 5871 DW_FUNCTION_INIT;
5871 DWContainer *cont = handle; 5872 DWContainer *cont = handle;
5872 UIScrollView *sv = [cont scrollview]; 5873 UIScrollView *sv = [cont scrollview];
5873 int rowcount = (int)[cont numberOfRowsInSection:0]; 5874 int rowcount = (int)[cont numberOfRowsInSection:0];
5889 case DW_SCROLL_BOTTOM: 5890 case DW_SCROLL_BOTTOM:
5890 { 5891 {
5891 offset.y = [sv contentSize].height - [sv visibleSize].height; 5892 offset.y = [sv contentSize].height - [sv visibleSize].height;
5892 break; 5893 break;
5893 } 5894 }
5895 /* TODO: Currently scrolling a full page, need to use row parameter instead */
5894 case DW_SCROLL_UP: 5896 case DW_SCROLL_UP:
5895 { 5897 {
5896 offset.y = offset.y - [sv visibleSize].height; 5898 offset.y -= [sv visibleSize].height;
5897 break; 5899 break;
5898 } 5900 }
5899 case DW_SCROLL_DOWN: 5901 case DW_SCROLL_DOWN:
5900 { 5902 {
5901 offset.y = offset.y + [sv visibleSize].height; 5903 offset.y += [sv visibleSize].height;
5902 break; 5904 break;
5903 } 5905 }
5904 } 5906 }
5905 if(offset.y < 0) 5907 if(offset.y < 0)
5906 offset.y = 0; 5908 offset.y = 0;
7190 * Create a notebook object to be packed. 7192 * Create a notebook object to be packed.
7191 * Parameters: 7193 * Parameters:
7192 * id: An ID to be used for getting the resource from the 7194 * id: An ID to be used for getting the resource from the
7193 * resource file. 7195 * resource file.
7194 */ 7196 */
7195 DW_FUNCTION_DEFINITION(dw_notebook_new, HWND, ULONG cid, int top) 7197 DW_FUNCTION_DEFINITION(dw_notebook_new, HWND, ULONG cid, DW_UNUSED(int top))
7196 DW_FUNCTION_ADD_PARAM2(cid, top) 7198 DW_FUNCTION_ADD_PARAM2(cid, top)
7197 DW_FUNCTION_RETURN(dw_notebook_new, HWND) 7199 DW_FUNCTION_RETURN(dw_notebook_new, HWND)
7198 DW_FUNCTION_RESTORE_PARAM2(cid, ULONG, top, int) 7200 DW_FUNCTION_RESTORE_PARAM2(cid, ULONG, DW_UNUSED(top), int)
7199 { 7201 {
7200 DWNotebook *notebook = [[[DWNotebook alloc] init] retain]; 7202 DWNotebook *notebook = [[[DWNotebook alloc] init] retain];
7201 [notebook addTarget:notebook 7203 [notebook addTarget:notebook
7202 action:@selector(pageChanged:) 7204 action:@selector(pageChanged:)
7203 forControlEvents:UIControlEventValueChanged]; 7205 forControlEvents:UIControlEventValueChanged];
8521 * freq: Frequency. 8523 * freq: Frequency.
8522 * dur: Duration. 8524 * dur: Duration.
8523 */ 8525 */
8524 void API dw_beep(int freq, int dur) 8526 void API dw_beep(int freq, int dur)
8525 { 8527 {
8526 /* TODO: Don't see a simple way to do this without bundling sounds */ 8528 AudioServicesPlayAlertSound((SystemSoundID)1104);
8527 } 8529 }
8528 8530
8529 /* Call this after drawing to the screen to make sure 8531 /* Call this after drawing to the screen to make sure
8530 * anything you have drawn is visible. 8532 * anything you have drawn is visible.
8531 */ 8533 */
8632 * Parameters: 8634 * Parameters:
8633 * window: Window handle of signal to be called back. 8635 * window: Window handle of signal to be called back.
8634 * dataname: A string pointer identifying which signal to be hooked. 8636 * dataname: A string pointer identifying which signal to be hooked.
8635 * data: User data to be passed to the handler function. 8637 * data: User data to be passed to the handler function.
8636 */ 8638 */
8637 void dw_window_set_data(HWND window, const char *dataname, void *data) 8639 DW_FUNCTION_DEFINITION(dw_window_set_data, void, HWND window, const char *dataname, void *data)
8640 DW_FUNCTION_ADD_PARAM3(window, dataname, data)
8641 DW_FUNCTION_NO_RETURN(dw_window_set_data)
8642 DW_FUNCTION_RESTORE_PARAM3(window, HWND, dataname, const char *, data, void *)
8638 { 8643 {
8639 id object = window; 8644 id object = window;
8640 if([object isMemberOfClass:[DWWindow class]]) 8645 if([object isMemberOfClass:[DWWindow class]])
8641 { 8646 {
8642 UIWindow *win = window; 8647 UIWindow *win = window;
8667 if(dataname) 8672 if(dataname)
8668 _dw_remove_userdata(&(blah->root), dataname, FALSE); 8673 _dw_remove_userdata(&(blah->root), dataname, FALSE);
8669 else 8674 else
8670 _dw_remove_userdata(&(blah->root), NULL, TRUE); 8675 _dw_remove_userdata(&(blah->root), NULL, TRUE);
8671 } 8676 }
8677 DW_FUNCTION_RETURN_NOTHING;
8672 } 8678 }
8673 8679
8674 /* 8680 /*
8675 * Gets a named user data item to a window handle. 8681 * Gets a named user data item to a window handle.
8676 * Parameters: 8682 * Parameters:
8677 * window: Window handle of signal to be called back. 8683 * window: Window handle of signal to be called back.
8678 * dataname: A string pointer identifying which signal to be hooked. 8684 * dataname: A string pointer identifying which signal to be hooked.
8679 * data: User data to be passed to the handler function. 8685 * data: User data to be passed to the handler function.
8680 */ 8686 */
8681 void *dw_window_get_data(HWND window, const char *dataname) 8687 DW_FUNCTION_DEFINITION(dw_window_get_data, void *, HWND window, const char *dataname)
8688 DW_FUNCTION_ADD_PARAM2(window, dataname)
8689 DW_FUNCTION_RETURN(dw_window_get_data, void *)
8690 DW_FUNCTION_RESTORE_PARAM2(window, HWND, dataname, const char *)
8682 { 8691 {
8683 id object = window; 8692 id object = window;
8693 void *retval = NULL;
8694
8684 if([object isMemberOfClass:[DWWindow class]]) 8695 if([object isMemberOfClass:[DWWindow class]])
8685 { 8696 {
8686 UIWindow *win = window; 8697 UIWindow *win = window;
8687 NSArray *subviews = [win subviews]; 8698 NSArray *subviews = [win subviews];
8688 object = [subviews firstObject]; 8699 object = [subviews firstObject];
8697 8708
8698 if(blah && blah->root && dataname) 8709 if(blah && blah->root && dataname)
8699 { 8710 {
8700 UserData *ud = _dw_find_userdata(&(blah->root), dataname); 8711 UserData *ud = _dw_find_userdata(&(blah->root), dataname);
8701 if(ud) 8712 if(ud)
8702 return ud->data; 8713 retval = ud->data;
8703 } 8714 }
8704 return NULL; 8715 DW_FUNCTION_RETURN_THIS(retval);
8705 } 8716 }
8706 8717
8707 #define DW_TIMER_MAX 64 8718 #define DW_TIMER_MAX 64
8708 static NSTimer *DWTimers[DW_TIMER_MAX]; 8719 static NSTimer *DWTimers[DW_TIMER_MAX];
8709 8720
8714 * sigfunc: The pointer to the function to be used as the callback. 8725 * sigfunc: The pointer to the function to be used as the callback.
8715 * data: User data to be passed to the handler function. 8726 * data: User data to be passed to the handler function.
8716 * Returns: 8727 * Returns:
8717 * Timer ID for use with dw_timer_disconnect(), 0 on error. 8728 * Timer ID for use with dw_timer_disconnect(), 0 on error.
8718 */ 8729 */
8719 int API dw_timer_connect(int interval, void *sigfunc, void *data) 8730 DW_FUNCTION_DEFINITION(dw_timer_connect, int, int interval, void *sigfunc, void *data)
8720 { 8731 DW_FUNCTION_ADD_PARAM3(interval, sigfunc, data)
8721 int z; 8732 DW_FUNCTION_RETURN(dw_timer_connect, int)
8733 DW_FUNCTION_RESTORE_PARAM3(interval, int, sigfunc, void *, data, void *)
8734 {
8735 int z, retval = 0;
8722 8736
8723 for(z=0;z<DW_TIMER_MAX;z++) 8737 for(z=0;z<DW_TIMER_MAX;z++)
8724 { 8738 {
8725 if(!DWTimers[z]) 8739 if(!DWTimers[z])
8726 { 8740 {
8731 if(sigfunc && !DWTimers[z]) 8745 if(sigfunc && !DWTimers[z])
8732 { 8746 {
8733 NSTimeInterval seconds = (double)interval / 1000.0; 8747 NSTimeInterval seconds = (double)interval / 1000.0;
8734 NSTimer *thistimer = DWTimers[z] = [NSTimer scheduledTimerWithTimeInterval:seconds target:DWHandler selector:@selector(runTimer:) userInfo:nil repeats:YES]; 8748 NSTimer *thistimer = DWTimers[z] = [NSTimer scheduledTimerWithTimeInterval:seconds target:DWHandler selector:@selector(runTimer:) userInfo:nil repeats:YES];
8735 _dw_new_signal(0, thistimer, z+1, sigfunc, NULL, data); 8749 _dw_new_signal(0, thistimer, z+1, sigfunc, NULL, data);
8736 return z+1; 8750 retval = z+1;
8737 } 8751 }
8738 return 0; 8752 DW_FUNCTION_RETURN_THIS(retval);
8739 } 8753 }
8740 8754
8741 /* 8755 /*
8742 * Removes timer callback. 8756 * Removes timer callback.
8743 * Parameters: 8757 * Parameters:
8744 * id: Timer ID returned by dw_timer_connect(). 8758 * id: Timer ID returned by dw_timer_connect().
8745 */ 8759 */
8746 void API dw_timer_disconnect(int timerid) 8760 DW_FUNCTION_DEFINITION(dw_timer_disconnect, void, int timerid)
8761 DW_FUNCTION_ADD_PARAM1(timerid)
8762 DW_FUNCTION_NO_RETURN(dw_timer_disconnect)
8763 DW_FUNCTION_RESTORE_PARAM1(timerid, int)
8747 { 8764 {
8748 SignalHandler *prev = NULL, *tmp = DWRoot; 8765 SignalHandler *prev = NULL, *tmp = DWRoot;
8749 NSTimer *thistimer; 8766 NSTimer *thistimer;
8750 8767
8751 /* 0 is an invalid timer ID */ 8768 /* 0 is an invalid timer ID */
8752 if(timerid < 1 || !DWTimers[timerid-1]) 8769 if(timerid > 0 && timerid < DW_TIMER_MAX && DWTimers[timerid-1])
8753 return; 8770 {
8754 8771 thistimer = DWTimers[timerid-1];
8755 thistimer = DWTimers[timerid-1]; 8772 DWTimers[timerid-1] = nil;
8756 DWTimers[timerid-1] = nil; 8773
8757 8774 [thistimer invalidate];
8758 [thistimer invalidate]; 8775
8759 8776 while(tmp)
8760 while(tmp) 8777 {
8761 { 8778 if(tmp->id == timerid && tmp->window == thistimer)
8762 if(tmp->id == timerid && tmp->window == thistimer)
8763 {
8764 if(prev)
8765 { 8779 {
8766 prev->next = tmp->next; 8780 if(prev)
8767 free(tmp); 8781 {
8768 tmp = prev->next; 8782 prev->next = tmp->next;
8783 free(tmp);
8784 tmp = prev->next;
8785 }
8786 else
8787 {
8788 DWRoot = tmp->next;
8789 free(tmp);
8790 tmp = DWRoot;
8791 }
8769 } 8792 }
8770 else 8793 else
8771 { 8794 {
8772 DWRoot = tmp->next; 8795 prev = tmp;
8773 free(tmp); 8796 tmp = tmp->next;
8774 tmp = DWRoot;
8775 } 8797 }
8776 } 8798 }
8777 else 8799 }
8778 { 8800 DW_FUNCTION_RETURN_NOTHING;
8779 prev = tmp;
8780 tmp = tmp->next;
8781 }
8782 }
8783 } 8801 }
8784 8802
8785 /* 8803 /*
8786 * Add a callback to a window event. 8804 * Add a callback to a window event.
8787 * Parameters: 8805 * Parameters:
9691 dw_event_reset(DWMainEvent); 9709 dw_event_reset(DWMainEvent);
9692 /* We wait for the dw_init() in the user's main function */ 9710 /* We wait for the dw_init() in the user's main function */
9693 dw_event_wait(DWMainEvent, DW_TIMEOUT_INFINITE); 9711 dw_event_wait(DWMainEvent, DW_TIMEOUT_INFINITE);
9694 DWThread = dw_thread_id(); 9712 DWThread = dw_thread_id();
9695 DWObj = [[DWObject alloc] init]; 9713 DWObj = [[DWObject alloc] init];
9714 /* Create object for handling timers */
9715 DWHandler = [[DWTimerHandler alloc] init];
9696 UIApplicationMain(argc, argv, nil, NSStringFromClass([DWAppDel class])); 9716 UIApplicationMain(argc, argv, nil, NSStringFromClass([DWAppDel class]));
9697 /* Shouldn't get here, but ... just in case */ 9717 /* Shouldn't get here, but ... just in case */
9698 DWThread = (DWTID)-1; 9718 DWThread = (DWTID)-1;
9699 } 9719 }
9700 9720
9790 * directly, otherwise specify UTF-8 explicitly. 9810 * directly, otherwise specify UTF-8 explicitly.
9791 */ 9811 */
9792 setlocale(LC_ALL, lang && strstr(lang, ".UTF-8") ? lang : "UTF-8"); 9812 setlocale(LC_ALL, lang && strstr(lang, ".UTF-8") ? lang : "UTF-8");
9793 /* Create the application object */ 9813 /* Create the application object */
9794 _dw_app_init(); 9814 _dw_app_init();
9795 /* Create object for handling timers */
9796 DWHandler = [[DWTimerHandler alloc] init];
9797 pthread_key_create(&_dw_pool_key, NULL); 9815 pthread_key_create(&_dw_pool_key, NULL);
9798 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 9816 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
9799 pthread_setspecific(_dw_pool_key, pool); 9817 pthread_setspecific(_dw_pool_key, pool);
9800 pthread_key_create(&_dw_fg_color_key, NULL); 9818 pthread_key_create(&_dw_fg_color_key, NULL);
9801 pthread_key_create(&_dw_bg_color_key, NULL); 9819 pthread_key_create(&_dw_bg_color_key, NULL);