Mercurial > dwindows
comparison mac/dw.m @ 703:329736825f9b
Implemented more of the missing event/signal handlers and other code cleanups.
author | bsmith@81767d24-ef19-dc11-ae90-00e081727c95 |
---|---|
date | Fri, 11 Mar 2011 17:20:49 +0000 |
parents | e9a3d1da3d3e |
children | 336800e9e648 |
comparison
equal
deleted
inserted
replaced
702:e9a3d1da3d3e | 703:329736825f9b |
---|---|
100 tmp = tmp->next; | 100 tmp = tmp->next; |
101 } | 101 } |
102 return NULL; | 102 return NULL; |
103 } | 103 } |
104 | 104 |
105 typedef struct | |
106 { | |
107 ULONG message; | |
108 char name[30]; | |
109 | |
110 } SignalList; | |
111 | |
112 /* List of signals */ | |
113 #define SIGNALMAX 16 | |
114 | |
115 SignalList SignalTranslate[SIGNALMAX] = { | |
116 { 1, DW_SIGNAL_CONFIGURE }, | |
117 { 2, DW_SIGNAL_KEY_PRESS }, | |
118 { 3, DW_SIGNAL_BUTTON_PRESS }, | |
119 { 4, DW_SIGNAL_BUTTON_RELEASE }, | |
120 { 5, DW_SIGNAL_MOTION_NOTIFY }, | |
121 { 6, DW_SIGNAL_DELETE }, | |
122 { 7, DW_SIGNAL_EXPOSE }, | |
123 { 8, DW_SIGNAL_CLICKED }, | |
124 { 9, DW_SIGNAL_ITEM_ENTER }, | |
125 { 10, DW_SIGNAL_ITEM_CONTEXT }, | |
126 { 11, DW_SIGNAL_LIST_SELECT }, | |
127 { 12, DW_SIGNAL_ITEM_SELECT }, | |
128 { 13, DW_SIGNAL_SET_FOCUS }, | |
129 { 14, DW_SIGNAL_VALUE_CHANGED }, | |
130 { 15, DW_SIGNAL_SWITCH_PAGE }, | |
131 { 16, DW_SIGNAL_TREE_EXPAND } | |
132 }; | |
133 | |
105 int _event_handler(id object, NSEvent *event, int message) | 134 int _event_handler(id object, NSEvent *event, int message) |
106 { | 135 { |
107 SignalHandler *handler = _get_handler(object, message); | 136 SignalHandler *handler = _get_handler(object, message); |
108 /*NSLog(@"Event handler - type %d\n", message);*/ | 137 /*NSLog(@"Event handler - type %d\n", message);*/ |
109 | 138 |
110 if(handler) | 139 if(handler) |
111 { | 140 { |
112 switch(message) | 141 switch(message) |
113 { | 142 { |
143 /* Timer event */ | |
114 case 0: | 144 case 0: |
115 { | 145 { |
116 int (* API timerfunc)(void *) = (int (* API)(void *))handler->signalfunction; | 146 int (* API timerfunc)(void *) = (int (* API)(void *))handler->signalfunction; |
117 | 147 |
118 if(!timerfunc(handler->data)) | 148 if(!timerfunc(handler->data)) |
119 dw_timer_disconnect(handler->id); | 149 dw_timer_disconnect(handler->id); |
120 return 0; | 150 return 0; |
121 } | 151 } |
152 /* Configure/Resize event */ | |
122 case 1: | 153 case 1: |
123 { | 154 { |
124 int (*sizefunc)(HWND, int, int, void *) = handler->signalfunction; | 155 int (*sizefunc)(HWND, int, int, void *) = handler->signalfunction; |
125 NSSize size; | 156 NSSize size; |
126 | 157 |
135 size = [view frame].size; | 166 size = [view frame].size; |
136 } | 167 } |
137 | 168 |
138 return sizefunc(object, size.width, size.height, handler->data); | 169 return sizefunc(object, size.width, size.height, handler->data); |
139 } | 170 } |
171 /* Button press and release event */ | |
140 case 3: | 172 case 3: |
141 case 4: | 173 case 4: |
142 { | 174 { |
143 int (* API buttonfunc)(HWND, int, int, int, void *) = (int (* API)(HWND, int, int, int, void *))handler->signalfunction; | 175 int (* API buttonfunc)(HWND, int, int, int, void *) = (int (* API)(HWND, int, int, int, void *))handler->signalfunction; |
144 int button = (int)event; | 176 int button = (int)event; |
146 | 178 |
147 dw_pointer_query_pos(&x, &y); | 179 dw_pointer_query_pos(&x, &y); |
148 | 180 |
149 return buttonfunc(object, (int)x, (int)y, button, handler->data); | 181 return buttonfunc(object, (int)x, (int)y, button, handler->data); |
150 } | 182 } |
183 /* Window close event */ | |
151 case 6: | 184 case 6: |
152 { | 185 { |
153 int (* API closefunc)(HWND, void *) = (int (* API)(HWND, void *))handler->signalfunction; | 186 int (* API closefunc)(HWND, void *) = (int (* API)(HWND, void *))handler->signalfunction; |
154 return closefunc(object, handler->data); | 187 return closefunc(object, handler->data); |
155 } | 188 } |
189 /* Window expose/draw event */ | |
156 case 7: | 190 case 7: |
157 { | 191 { |
158 DWExpose exp; | 192 DWExpose exp; |
159 int (* API exposefunc)(HWND, DWExpose *, void *) = (int (* API)(HWND, DWExpose *, void *))handler->signalfunction; | 193 int (* API exposefunc)(HWND, DWExpose *, void *) = (int (* API)(HWND, DWExpose *, void *))handler->signalfunction; |
160 NSRect rect = [object frame]; | 194 NSRect rect = [object frame]; |
165 exp.height = rect.size.height; | 199 exp.height = rect.size.height; |
166 int result = exposefunc(object, &exp, handler->data); | 200 int result = exposefunc(object, &exp, handler->data); |
167 [[object window] flushWindow]; | 201 [[object window] flushWindow]; |
168 return result; | 202 return result; |
169 } | 203 } |
204 /* Clicked event for buttons and menu items */ | |
170 case 8: | 205 case 8: |
171 { | 206 { |
172 int (* API clickfunc)(HWND, void *) = (int (* API)(HWND, void *))handler->signalfunction; | 207 int (* API clickfunc)(HWND, void *) = (int (* API)(HWND, void *))handler->signalfunction; |
173 | 208 |
174 return clickfunc(object, handler->data); | 209 return clickfunc(object, handler->data); |
175 } | 210 } |
211 /* Container class selection event */ | |
176 case 9: | 212 case 9: |
177 { | 213 { |
178 int (*containerselectfunc)(HWND, char *, void *) = handler->signalfunction; | 214 int (*containerselectfunc)(HWND, char *, void *) = handler->signalfunction; |
179 | 215 |
180 return containerselectfunc(handler->window, (char *)event, handler->data); | 216 return containerselectfunc(handler->window, (char *)event, handler->data); |
181 } | 217 } |
218 /* Container context menu event */ | |
182 case 10: | 219 case 10: |
183 { | 220 { |
184 int (* API containercontextfunc)(HWND, char *, int, int, void *, void *) = (int (* API)(HWND, char *, int, int, void *, void *))handler->signalfunction; | 221 int (* API containercontextfunc)(HWND, char *, int, int, void *, void *) = (int (* API)(HWND, char *, int, int, void *, void *))handler->signalfunction; |
185 char *text = (char *)event; | 222 char *text = (char *)event; |
186 void *user = NULL; | 223 void *user = NULL; |
188 | 225 |
189 dw_pointer_query_pos(&x, &y); | 226 dw_pointer_query_pos(&x, &y); |
190 | 227 |
191 return containercontextfunc(handler->window, text, (int)x, (int)y, handler->data, user); | 228 return containercontextfunc(handler->window, text, (int)x, (int)y, handler->data, user); |
192 } | 229 } |
230 /* Generic selection changed event for several classes */ | |
231 case 11: | |
232 case 14: | |
233 { | |
234 int (* API valuechangedfunc)(HWND, int, void *) = (int (* API)(HWND, int, void *))handler->signalfunction; | |
235 int selected = (int)event; | |
236 | |
237 return valuechangedfunc(handler->window, selected, handler->data);; | |
238 } | |
239 /* Tree class selection event */ | |
193 case 12: | 240 case 12: |
194 { | 241 { |
195 int (* API treeselectfunc)(HWND, HTREEITEM, char *, void *, void *) = (int (* API)(HWND, HTREEITEM, char *, void *, void *))handler->signalfunction; | 242 int (* API treeselectfunc)(HWND, HTREEITEM, char *, void *, void *) = (int (* API)(HWND, HTREEITEM, char *, void *, void *))handler->signalfunction; |
196 char *text = (char *)event; | 243 char *text = (char *)event; |
197 void *user = NULL; | 244 void *user = NULL; |
198 | 245 |
199 return treeselectfunc(handler->window, NULL, text, handler->data, user); | 246 return treeselectfunc(handler->window, NULL, text, handler->data, user); |
200 } | 247 } |
248 /* Set Focus event */ | |
249 case 13: | |
250 { | |
251 int (* API setfocusfunc)(HWND, void *) = (int (* API)(HWND, void *))handler->signalfunction; | |
252 | |
253 return setfocusfunc(handler->window, handler->data); | |
254 } | |
255 /* Notebook page change event */ | |
256 case 15: | |
257 { | |
258 int (* API switchpagefunc)(HWND, unsigned long, void *) = (int (* API)(HWND, unsigned long, void *))handler->signalfunction; | |
259 int pageid = (int)event; | |
260 | |
261 return switchpagefunc(handler->window, pageid, handler->data); | |
262 } | |
201 } | 263 } |
202 } | 264 } |
203 return -1; | 265 return -1; |
204 } | 266 } |
205 | 267 |
249 @implementation DWObject | 311 @implementation DWObject |
250 -(void)uselessThread:(id)sender { /* Thread only to initialize threading */ } | 312 -(void)uselessThread:(id)sender { /* Thread only to initialize threading */ } |
251 -(void)synchronizeThread:(id)param | 313 -(void)synchronizeThread:(id)param |
252 { | 314 { |
253 pthread_mutex_unlock(DWRunMutex); | 315 pthread_mutex_unlock(DWRunMutex); |
254 //NSLog(@"Main thread releasing lock"); | |
255 pthread_mutex_lock(DWThreadMutex2); | 316 pthread_mutex_lock(DWThreadMutex2); |
256 pthread_mutex_unlock(DWThreadMutex2); | 317 pthread_mutex_unlock(DWThreadMutex2); |
257 pthread_mutex_lock(DWRunMutex); | 318 pthread_mutex_lock(DWRunMutex); |
258 //NSLog(@"Main thread reacquiring lock"); | |
259 } | 319 } |
260 -(void)doBitBlt:(id)param | 320 -(void)doBitBlt:(id)param |
261 { | 321 { |
262 NSValue *bi = (NSValue *)param; | 322 NSValue *bi = (NSValue *)param; |
263 DWBitBlt *bltinfo = (DWBitBlt *)[bi pointerValue]; | 323 DWBitBlt *bltinfo = (DWBitBlt *)[bi pointerValue]; |
418 } | 478 } |
419 else | 479 else |
420 { | 480 { |
421 [DWApp setMainMenu:DWMainMenu]; | 481 [DWApp setMainMenu:DWMainMenu]; |
422 } | 482 } |
423 | 483 _event_handler(self, nil, 13); |
424 } | 484 } |
425 -(void)setMenu:(NSMenu *)input { windowmenu = input; } | 485 -(void)setMenu:(NSMenu *)input { windowmenu = input; } |
426 -(void)menuHandler:(id)sender { _event_handler(sender, nil, 8); } | 486 -(void)menuHandler:(id)sender { _event_handler(sender, nil, 8); } |
427 @end | 487 @end |
428 | 488 |
499 -(int)pageid; | 559 -(int)pageid; |
500 -(void)setPageid:(int)input; | 560 -(void)setPageid:(int)input; |
501 -(void)tabView:(NSTabView *)notebook didSelectTabViewItem:(NSTabViewItem *)notepage; | 561 -(void)tabView:(NSTabView *)notebook didSelectTabViewItem:(NSTabViewItem *)notepage; |
502 @end | 562 @end |
503 | 563 |
564 /* Subclass for a Notebook page type */ | |
565 @interface DWNotebookPage : NSTabViewItem | |
566 { | |
567 void *userdata; | |
568 int pageid; | |
569 } | |
570 -(void *)userdata; | |
571 -(void)setUserdata:(void *)input; | |
572 -(int)pageid; | |
573 -(void)setPageid:(int)input; | |
574 @end | |
575 | |
504 @implementation DWNotebook | 576 @implementation DWNotebook |
505 -(void *)userdata { return userdata; } | 577 -(void *)userdata { return userdata; } |
506 -(void)setUserdata:(void *)input { userdata = input; } | 578 -(void)setUserdata:(void *)input { userdata = input; } |
507 -(int)pageid { return pageid; } | 579 -(int)pageid { return pageid; } |
508 -(void)setPageid:(int)input { pageid = input; } | 580 -(void)setPageid:(int)input { pageid = input; } |
509 -(void)tabView:(NSTabView *)notebook didSelectTabViewItem:(NSTabViewItem *)notepage | 581 -(void)tabView:(NSTabView *)notebook didSelectTabViewItem:(NSTabViewItem *)notepage |
510 { | 582 { |
511 id object = [notepage view]; | 583 id object = [notepage view]; |
584 DWNotebookPage *page = (DWNotebookPage *)notepage; | |
512 | 585 |
513 if([object isMemberOfClass:[DWBox class]]) | 586 if([object isMemberOfClass:[DWBox class]]) |
514 { | 587 { |
515 DWBox *view = object; | 588 DWBox *view = object; |
516 Box *box = [view box]; | 589 Box *box = [view box]; |
517 NSSize size = [view frame].size; | 590 NSSize size = [view frame].size; |
518 _do_resize(box, size.width, size.height); | 591 _do_resize(box, size.width, size.height); |
519 } | 592 } |
593 _event_handler(self, (void *)[page pageid], 15); | |
520 } | 594 } |
521 -(void)dealloc { UserData *root = userdata; _remove_userdata(&root, NULL, TRUE); [super dealloc]; } | 595 -(void)dealloc { UserData *root = userdata; _remove_userdata(&root, NULL, TRUE); [super dealloc]; } |
522 @end | |
523 | |
524 /* Subclass for a Notebook page type */ | |
525 @interface DWNotebookPage : NSTabViewItem | |
526 { | |
527 void *userdata; | |
528 int pageid; | |
529 } | |
530 -(void *)userdata; | |
531 -(void)setUserdata:(void *)input; | |
532 -(int)pageid; | |
533 -(void)setPageid:(int)input; | |
534 @end | 596 @end |
535 | 597 |
536 @implementation DWNotebookPage | 598 @implementation DWNotebookPage |
537 -(void *)userdata { return userdata; } | 599 -(void *)userdata { return userdata; } |
538 -(void)setUserdata:(void *)input { userdata = input; } | 600 -(void)setUserdata:(void *)input { userdata = input; } |
600 { | 662 { |
601 void *userdata; | 663 void *userdata; |
602 } | 664 } |
603 -(void *)userdata; | 665 -(void *)userdata; |
604 -(void)setUserdata:(void *)input; | 666 -(void)setUserdata:(void *)input; |
667 -(void)sliderMoved:(id)sender; | |
605 @end | 668 @end |
606 | 669 |
607 @implementation DWSlider | 670 @implementation DWSlider |
608 -(void *)userdata { return userdata; } | 671 -(void *)userdata { return userdata; } |
609 -(void)setUserdata:(void *)input { userdata = input; } | 672 -(void)setUserdata:(void *)input { userdata = input; } |
673 -(void)sliderMoved:(id)sender { NSLog(@"Slider changed"); _event_handler(self, (void *)[self integerValue], 14); } | |
610 -(void)dealloc { UserData *root = userdata; _remove_userdata(&root, NULL, TRUE); [super dealloc]; } | 674 -(void)dealloc { UserData *root = userdata; _remove_userdata(&root, NULL, TRUE); [super dealloc]; } |
611 @end | 675 @end |
612 | 676 |
613 /* Subclass for a slider type */ | 677 /* Subclass for a slider type */ |
614 @interface DWScrollbar : NSScroller | 678 @interface DWScrollbar : NSScroller |
629 -(void *)userdata { return userdata; } | 693 -(void *)userdata { return userdata; } |
630 -(void)setUserdata:(void *)input { userdata = input; } | 694 -(void)setUserdata:(void *)input { userdata = input; } |
631 -(float)range { return range; } | 695 -(float)range { return range; } |
632 -(float)visible { return visible; } | 696 -(float)visible { return visible; } |
633 -(void)setRange:(float)input1 andVisible:(float)input2 { range = input1; visible = input2; } | 697 -(void)setRange:(float)input1 andVisible:(float)input2 { range = input1; visible = input2; } |
634 -(void)changed:(id)sender { /*NSNumber *num = [NSNumber numberWithDouble:[scroller floatValue]]; NSLog([num stringValue]);*/ } | 698 -(void)changed:(id)sender { NSNumber *num = [NSNumber numberWithDouble:[self floatValue]]; _event_handler(self, (void *)[num integerValue], 14); } |
635 -(void)dealloc { UserData *root = userdata; _remove_userdata(&root, NULL, TRUE); [super dealloc]; } | 699 -(void)dealloc { UserData *root = userdata; _remove_userdata(&root, NULL, TRUE); [super dealloc]; } |
636 @end | 700 @end |
637 | 701 |
638 /* Subclass for a render area type */ | 702 /* Subclass for a render area type */ |
639 @interface DWRender : NSView | 703 @interface DWRender : NSView |
802 } | 866 } |
803 -(int)addRow:(NSArray *)input | 867 -(int)addRow:(NSArray *)input |
804 { | 868 { |
805 if(data) | 869 if(data) |
806 { | 870 { |
807 NSLog(@"addRow: titles: %x data %x", (int)titles, (int)data); | |
808 lastAddPoint = (int)[titles count]; | 871 lastAddPoint = (int)[titles count]; |
809 [data addObjectsFromArray:input]; | 872 [data addObjectsFromArray:input]; |
810 [titles addPointer:NULL]; | 873 [titles addPointer:NULL]; |
811 return (int)[titles count]; | 874 return (int)[titles count]; |
812 } | 875 } |
878 titles = [[NSPointerArray pointerArrayWithWeakObjects] retain]; | 941 titles = [[NSPointerArray pointerArrayWithWeakObjects] retain]; |
879 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(selectionChanged:) name:NSTableViewSelectionDidChangeNotification object:[self window]]; | 942 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(selectionChanged:) name:NSTableViewSelectionDidChangeNotification object:[self window]]; |
880 } | 943 } |
881 -(void)selectionChanged:(id)sender | 944 -(void)selectionChanged:(id)sender |
882 { | 945 { |
946 /* Handler for container class */ | |
883 _event_handler(self, (NSEvent *)[self getRowTitle:(int)[self selectedRow]], 9); | 947 _event_handler(self, (NSEvent *)[self getRowTitle:(int)[self selectedRow]], 9); |
948 /* Handler for listbox class */ | |
949 _event_handler(self, (NSEvent *)(int)[self selectedRow], 11); | |
884 } | 950 } |
885 -(NSMenu *)menuForEvent:(NSEvent *)event | 951 -(NSMenu *)menuForEvent:(NSEvent *)event |
886 { | 952 { |
887 int row; | 953 int row; |
888 NSPoint where = [self convertPoint:[event locationInWindow] fromView:nil]; | 954 NSPoint where = [self convertPoint:[event locationInWindow] fromView:nil]; |
1076 -(void)setUserdata:(void *)input { userdata = input; } | 1142 -(void)setUserdata:(void *)input { userdata = input; } |
1077 -(void)dealloc { UserData *root = userdata; _remove_userdata(&root, NULL, TRUE); [super dealloc]; } | 1143 -(void)dealloc { UserData *root = userdata; _remove_userdata(&root, NULL, TRUE); [super dealloc]; } |
1078 @end | 1144 @end |
1079 | 1145 |
1080 /* Subclass for a Combobox type */ | 1146 /* Subclass for a Combobox type */ |
1081 @interface DWComboBox : NSComboBox | 1147 @interface DWComboBox : NSComboBox <NSComboBoxDelegate> |
1082 { | 1148 { |
1083 void *userdata; | 1149 void *userdata; |
1084 } | 1150 } |
1085 -(void *)userdata; | 1151 -(void *)userdata; |
1086 -(void)setUserdata:(void *)input; | 1152 -(void)setUserdata:(void *)input; |
1153 -(void)comboBoxSelectionDidChange:(NSNotification *)not; | |
1087 @end | 1154 @end |
1088 | 1155 |
1089 @implementation DWComboBox | 1156 @implementation DWComboBox |
1090 -(void *)userdata { return userdata; } | 1157 -(void *)userdata { return userdata; } |
1091 -(void)setUserdata:(void *)input { userdata = input; } | 1158 -(void)setUserdata:(void *)input { userdata = input; } |
1159 -(void)comboBoxSelectionDidChange:(NSNotification *)not { _event_handler(self, (void *)[self indexOfSelectedItem], 11); } | |
1092 -(void)dealloc { UserData *root = userdata; _remove_userdata(&root, NULL, TRUE); [super dealloc]; } | 1160 -(void)dealloc { UserData *root = userdata; _remove_userdata(&root, NULL, TRUE); [super dealloc]; } |
1093 @end | 1161 @end |
1094 | 1162 |
1095 /* Subclass for a stepper component of the spinbutton type */ | 1163 /* Subclass for a stepper component of the spinbutton type */ |
1096 /* This is a bad way of doing this... but I can't get the other methods to work */ | 1164 /* This is a bad way of doing this... but I can't get the other methods to work */ |
1171 @interface DWMDI : DWBox {} | 1239 @interface DWMDI : DWBox {} |
1172 @end | 1240 @end |
1173 | 1241 |
1174 @implementation DWMDI | 1242 @implementation DWMDI |
1175 @end | 1243 @end |
1176 | |
1177 typedef struct | |
1178 { | |
1179 ULONG message; | |
1180 char name[30]; | |
1181 | |
1182 } SignalList; | |
1183 | |
1184 /* List of signals */ | |
1185 #define SIGNALMAX 16 | |
1186 | |
1187 SignalList SignalTranslate[SIGNALMAX] = { | |
1188 { 1, DW_SIGNAL_CONFIGURE }, | |
1189 { 2, DW_SIGNAL_KEY_PRESS }, | |
1190 { 3, DW_SIGNAL_BUTTON_PRESS }, | |
1191 { 4, DW_SIGNAL_BUTTON_RELEASE }, | |
1192 { 5, DW_SIGNAL_MOTION_NOTIFY }, | |
1193 { 6, DW_SIGNAL_DELETE }, | |
1194 { 7, DW_SIGNAL_EXPOSE }, | |
1195 { 8, DW_SIGNAL_CLICKED }, | |
1196 { 9, DW_SIGNAL_ITEM_ENTER }, | |
1197 { 10, DW_SIGNAL_ITEM_CONTEXT }, | |
1198 { 11, DW_SIGNAL_LIST_SELECT }, | |
1199 { 12, DW_SIGNAL_ITEM_SELECT }, | |
1200 { 13, DW_SIGNAL_SET_FOCUS }, | |
1201 { 14, DW_SIGNAL_VALUE_CHANGED }, | |
1202 { 15, DW_SIGNAL_SWITCH_PAGE }, | |
1203 { 16, DW_SIGNAL_TREE_EXPAND } | |
1204 }; | |
1205 | 1244 |
1206 /* This function adds a signal handler callback into the linked list. | 1245 /* This function adds a signal handler callback into the linked list. |
1207 */ | 1246 */ |
1208 void _new_signal(ULONG message, HWND window, int msgid, void *signalfunction, void *data) | 1247 void _new_signal(ULONG message, HWND window, int msgid, void *signalfunction, void *data) |
1209 { | 1248 { |
3069 * id: An ID to be used with dw_window_from_id() or 0L. | 3108 * id: An ID to be used with dw_window_from_id() or 0L. |
3070 */ | 3109 */ |
3071 HWND API dw_combobox_new(char *text, ULONG cid) | 3110 HWND API dw_combobox_new(char *text, ULONG cid) |
3072 { | 3111 { |
3073 DWComboBox *combo = [[DWComboBox alloc] init]; | 3112 DWComboBox *combo = [[DWComboBox alloc] init]; |
3113 [combo setDelegate:combo]; | |
3074 [combo setTag:cid]; | 3114 [combo setTag:cid]; |
3075 return combo; | 3115 return combo; |
3076 } | 3116 } |
3077 | 3117 |
3078 /* | 3118 /* |