X11workbench Toolkit  1.0
child_frame.c
1 // _ _ _ _ __ //
3 // ___| |__ (_) | __| | / _|_ __ __ _ _ __ ___ ___ ___ //
4 // / __| '_ \| | |/ _` | | |_| '__/ _` | '_ ` _ \ / _ \ / __| //
5 // | (__| | | | | | (_| | | _| | | (_| | | | | | | __/| (__ //
6 // \___|_| |_|_|_|\__,_|___|_| |_| \__,_|_| |_| |_|\___(_)___| //
7 // |_____| //
8 // //
9 // a window that exists as a tab in a frame window //
10 // //
11 // (part of the 'frame window' support API) //
12 // //
14 
15 /*****************************************************************************
16 
17  X11workbench - X11 programmer's 'work bench' application and toolkit
18  Copyright (c) 2010-2019 by Bob Frazier (aka 'Big Bad Bombastic Bob')
19 
20 
21  DISCLAIMER: The X11workbench application and toolkit software are supplied
22  'as-is', with no warranties, either implied or explicit.
23  Any claims to alleged functionality or features should be
24  considered 'preliminary', and might not function as advertised.
25 
26  MIT-like license:
27 
28  There is no restriction as to what you can do with this software, so long
29  as you include the above copyright notice and DISCLAIMER for any distributed
30  work that is equal to or derived from this one, along with this paragraph
31  that explains the terms of the license if the source is also being made
32  available. A "derived work" describes a work that uses a significant portion
33  of the source files or algorithms that are included with this one.
34  Specifically excluded from this are files that were generated by the software,
35  or anything that is included with the software that is part of another package
36  (such as files that were created or added during the 'configure' process).
37  Specifically included is the use of part or all of any of the X11 workbench
38  toolkit source or header files in your distributed application. If you do not
39  ship the source, the above copyright statement is still required to be placed
40  in a reasonably prominent place, such as documentation, splash screens, and/or
41  'about the application' dialog boxes.
42 
43  Use and distribution are in accordance with GPL, LGPL, and/or the above
44  MIT-like license. See COPYING and README files for more information.
45 
46 
47  Additional information at http://sourceforge.net/projects/X11workbench
48 
49 ******************************************************************************/
50 
51 
52 #include <stdlib.h>
53 #include <unistd.h>
54 #include <memory.h>
55 #include <string.h>
56 #include <strings.h>
57 
58 #include "window_helper.h"
59 #include "font_helper.h"
60 #include "child_frame.h"
61 #include "draw_text.h"
62 #include "menu_popup.h"
63 
64 #include "dialog_window.h" // for message boxen, etc.
65 
66 
67 
68 static int ChildFrameEditCutHandler(XClientMessageEvent *);
69 static int ChildFrameEditCopyHandler(XClientMessageEvent *);
70 static int ChildFrameEditPasteHandler(XClientMessageEvent *);
71 static int ChildFrameEditDeleteHandler(XClientMessageEvent *);
72 static int ChildFrameEditSelectAllHandler(XClientMessageEvent *);
73 static int ChildFrameEditSelectNoneHandler(XClientMessageEvent *);
74 static int ChildFrameEditPropertiesHandler(XClientMessageEvent *);
75 static int ChildFrameEditCutUIHandler(WBMenu *pMenu, WBMenuItem *pMenuItem);
76 static int ChildFrameEditCopyUIHandler(WBMenu *pMenu, WBMenuItem *pMenuItem);
77 static int ChildFrameEditPasteUIHandler(WBMenu *pMenu, WBMenuItem *pMenuItem);
78 static int ChildFrameEditDeleteUIHandler(WBMenu *pMenu, WBMenuItem *pMenuItem);
79 static int ChildFrameEditSelectAllUIHandler(WBMenu *pMenu, WBMenuItem *pMenuItem);
80 static int ChildFrameEditSelectNoneUIHandler(WBMenu *pMenu, WBMenuItem *pMenuItem);
81 static int ChildFrameEditPropertiesUIHandler(WBMenu *pMenu, WBMenuItem *pMenuItem);
82 
92 FW_MENU_HANDLER_BEGIN(aChildFrameMenuHandler)
93 
94  FW_MENU_HANDLER_ENTRY(FW_EDIT_CUT_MENU, ChildFrameEditCutHandler, ChildFrameEditCutUIHandler)
95  FW_MENU_HANDLER_ENTRY(FW_EDIT_COPY_MENU, ChildFrameEditCopyHandler, ChildFrameEditCopyUIHandler)
96  FW_MENU_HANDLER_ENTRY(FW_EDIT_PASTE_MENU, ChildFrameEditPasteHandler, ChildFrameEditPasteUIHandler)
97  FW_MENU_HANDLER_ENTRY(FW_EDIT_DELETE_MENU, ChildFrameEditDeleteHandler, ChildFrameEditDeleteUIHandler)
98  FW_MENU_HANDLER_ENTRY(FW_EDIT_SELECT_ALL_MENU, ChildFrameEditSelectAllHandler, ChildFrameEditSelectAllUIHandler)
99  FW_MENU_HANDLER_ENTRY(FW_EDIT_SELECT_NONE_MENU, ChildFrameEditSelectNoneHandler, ChildFrameEditSelectNoneUIHandler)
100  FW_MENU_HANDLER_ENTRY(FW_EDIT_PROPERTIES_MENU, ChildFrameEditPropertiesHandler, ChildFrameEditPropertiesUIHandler)
101 
103 
104 
105 
106 static int ChildFrameDoPointerEvent(XClientMessageEvent *pEvent, Display *pDisplay,
107  Window wID, WBChildFrame *pC, WBChildFrameUI *pUI);
108 
109 static int ChildFrameDoScrollEvent(XClientMessageEvent *pEvent, Display *pDisplay,
110  Window wID, WBChildFrame *pC, WBChildFrameUI *pUI);
111 
112 static int ChildFrameDoCharEvent(XClientMessageEvent *pEvent, Display *pDisplay,
113  Window wID, WBChildFrame *pC, WBChildFrameUI *pUI);
114 
115 static WBChildFrame *pChildFrames = NULL; // pointer to linked list of 'Child Frame' windows
116 
117 
118 int FWInitChildFrame(WBChildFrame *pChildFrame, WBFrameWindow *pOwner, WB_FONTC pFont,
119  const char *szFocusMenu, const WBFWMenuHandler *pHandlerArray,
120  WBWinEvent pUserCallback, int fFlags)
121 {
122 WBChildFrame *pC;
123 XSetWindowAttributes xswa; /* Temporary Set Window Attribute struct */
124 Display *pDisplay = WBGetDefaultDisplay();
125 int iRval = -1;
126 
127 
128  if(!pChildFrame || !pOwner || pOwner->wID == None)
129  {
130  // TODO: validate 'pOwner' as a valid WBFrameWindow ??
131 
132  WB_ERROR_PRINT("%s - invalid pointers or owner window does not exist\n", __FUNCTION__);
133 
134  return -1;
135  }
136 
137  // zero out entire structure beforehand
138  bzero(pChildFrame, sizeof(*pChildFrame));
139 
140 
141  // FIRST, attach the child frame to my list o' child frames, making sure
142  // that it is not already there [if it is assume this was called twice]
143  // while I'm at it, zero out the structure BEFORE I assign 'pNext'
144 
145  if(!pChildFrames)
146  {
147  pChildFrames = pChildFrame;
148  pChildFrame->pNext = NULL; // make sure
149  }
150  else
151  {
152  pC = pChildFrames;
153 
154  while(pC->pNext)
155  {
156  if(pC == pChildFrame) // just in case
157  {
158  WB_ERROR_PRINT("%s - unexpected error condition, did you call this function before?\n", __FUNCTION__);
159 
160  return -2;
161  }
162 
163  pC = pC->pNext;
164  }
165 
166  if(pC)
167  {
168  // zero out entire structure beforehand
169  bzero(pChildFrame, sizeof(*pChildFrame));
170 
171  pC->pNext = pChildFrame;
172  pChildFrame->pNext = NULL;
173  }
174  else
175  {
176  // internal error, flag it for now and return "fail"
177  WB_ERROR_PRINT("%s - unexpected condition, returning error\n", __FUNCTION__);
178 
179  return -3;
180  }
181  }
182 
183  // initialize scroll info
184  WBInitScrollInfo(&(pChildFrame->scroll)); // re-initialize (TODO: must I do this every time?)
185 
186 
187  // if the owner is valid, but NOT tabbed, and it already has
188  // a WBChildFrame, then I fail to create this one.
189 
190  if((WBFrameWindow_NO_TABS & pOwner->iFlags)) // window has NO tabs
191  {
192  if(FWGetNumContWindows(pOwner)) // error *OR* > 0, doesn't matter, can ONLY have one tab in the frame
193  {
194  FWDestroyChildFrame(pChildFrame); // this unhooks everything (alloc'd things are zero'd by bzero)
195 
196  return -4; // can't create, SDI
197  }
198  }
199 
200 
201  // NEXT, set up all of the various 'things' in the structure that are simple assignments
202  pChildFrame->ulTag = CHILD_FRAME_TAG;
203  pChildFrame->destructor = NULL; // make sure
204 
205  if(!pFont)
206  {
207  pFont = FWGetFont(pOwner); // make copy of owning frame's font
208 
209  if(!pFont)
210  pFont = WBGetDefaultFont(); // make copy of default font
211  }
212 
213  pChildFrame->pFont = WBCopyFont(pDisplay, pFont);
214 
215  if(!pChildFrame->pFont)
216  {
217  FWDestroyChildFrame(pChildFrame); // this unhooks everything (alloc'd things are zero'd by bzero)
218 
219  return -5; // same as 'not enough memory' if I can't create a copy of the font
220  }
221 
222  if(szFocusMenu)
223  {
224  pChildFrame->pszMenuResource = WBCopyString(szFocusMenu);
225 
226  if(!pChildFrame->pszMenuResource)
227  {
228  FWDestroyChildFrame(pChildFrame); // this unhooks everything (alloc'd things are zero'd by bzero)
229  return -5; // not enough memory
230  }
231  }
232  else
233  {
234  pChildFrame->pszMenuResource = NULL;
235  }
236 
237  pChildFrame->iContextMenuID = -1; // default; use
238 
239  if(pHandlerArray)
240  {
241  const WBFWMenuHandler *pH;
242  int iN;
243 
244  // count the number of entries in the menu handler
245  for(iN=0, pH = pHandlerArray; pH->lMenuID || pH->callback || pH->UIcallback; iN++, pH++)
246  {
247  // NOTHING inside the loop. just count.
248  }
249 
250  // allocate space and make a copy
251 
252  pChildFrame->pMenuHandler = (WBFWMenuHandler *)WBAlloc(sizeof(WBFWMenuHandler)
253  * (iN + 1
254  + sizeof(aChildFrameMenuHandler)
255  / sizeof(aChildFrameMenuHandler[0])
256  )
257  );
258 
259  if(pChildFrame->pMenuHandler)
260  {
261  if(iN > 0)
262  {
263  memcpy(pChildFrame->pMenuHandler, pHandlerArray,
264  sizeof(WBFWMenuHandler) * iN);
265  }
266 
267  memcpy(pChildFrame->pMenuHandler + iN,
268  aChildFrameMenuHandler,
269  sizeof(aChildFrameMenuHandler)); // this includes the NULL entry at the end
270  }
271  else
272  {
273  FWDestroyChildFrame(pChildFrame); // this unhooks everything (alloc'd things are zero'd by bzero)
274  return -5; // not enough memory
275  }
276  }
277 
278  // Next, I need to create the window via 'WBCreateWindow()'
279 
280  bzero(&xswa, sizeof(xswa));
281 
282  xswa.border_pixel = FWGetDefaultBD().pixel;
283  xswa.background_pixel = FWGetDefaultBG().pixel; // typically a 'grey' color
284  xswa.colormap = DefaultColormap(pDisplay, DefaultScreen(pDisplay));
285  xswa.bit_gravity = CenterGravity;
286 
287  pChildFrame->wID = WBCreateWindow(pDisplay, pOwner->wID, FWChildFrameEvent, "ChildFrame",
288  pOwner->iClientX, pOwner->iClientY,
289  pOwner->iClientWidth - 2, pOwner->iClientHeight - 2, // border is 1 pixel, so subtract 2
290  1, InputOutput,
291  CWBorderPixel | CWBackPixel | CWColormap | CWBitGravity,
292  &xswa);
293 
294  if(pChildFrame->wID == None)
295  {
296  FWDestroyChildFrame(pChildFrame);
297  return -6; // could not create the window
298  }
299 
300  // immediately identify this window's data struct using window data
301  WBSetWindowData(pChildFrame->wID, 0, (void *)pChildFrame); // window data is pointer to this struct
302  pChildFrame->pUserCallback = pUserCallback;
303 
304 
305  // create the default graphics context using the frame's color info
306  WBCreateWindowDefaultGC(pChildFrame->wID, FWGetDefaultFG().pixel, FWGetDefaultBG().pixel);
307 
308  // now allow specific kinds of input messages. I won't need 'structure notify' as they won't work
309  // anyway. those end up going to the frame window, and it passes them (as needed) to me.
310  XSelectInput(pDisplay, pChildFrame->wID,
312 
313 
314  // FINALLY, inform the frame window, which will set up some other stuff for me
315 
316  pChildFrame->pOwner = pOwner;
317  iRval = FWAddContainedWindow(pOwner, pChildFrame); // TODO: make THIS assign the owner pointer?
318 
319  if(iRval < 0) // error? (returns negative on error, otherwise the tab index)
320  {
321  FWDestroyChildFrame(pChildFrame); // this frees up all of the resources (but does not free the mem block)
322  }
323 
324  // TODO: other things
325 
326  return iRval;
327 }
328 
330 {
331 WBChildFrame *pC, *pC2;
332 Window wID;
333 
334 
335  if(!pChildFrame)
336  {
337  WB_ERROR_PRINT("ERROR: %s - pChildFrame not valid\n", __FUNCTION__);
338 
339  return;
340  }
341 
342  wID = pChildFrame->wID; // make a copy of it
343 
344  // FIRST, tell the owner to remove me from the list
345 
346  if(pChildFrame->pOwner)
347  {
348  FWRemoveContainedWindow(pChildFrame->pOwner, pChildFrame);
349 
350  if(pChildFrame->pOwner != NULL)
351  {
352  WB_ERROR_PRINT("ERROR: %s - owner pointer was nut 'NULL'd out\n", __FUNCTION__);
353  }
354 
355  pChildFrame->pOwner = NULL;
356  }
357 
358  // NOW, free up any resources that were WBAlloc'd - they must also be free'd
359 
360  if(pChildFrame->szDisplayName)
361  {
362  WBFree(pChildFrame->szDisplayName);
363  pChildFrame->szDisplayName = NULL;
364  }
365 
366  if(pChildFrame->pFont)
367  {
368  WBFreeFont(WBGetDefaultDisplay(), pChildFrame->pFont);
369  pChildFrame->pFont = NULL;
370  }
371 
372  if(pChildFrame->pMenuHandler)
373  {
374  WBFree(pChildFrame->pMenuHandler);
375  pChildFrame->pMenuHandler = NULL;
376  }
377 
378  if(pChildFrame->szStatusText)
379  {
380  WBFree(pChildFrame->szStatusText);
381  pChildFrame->szStatusText = NULL;
382  }
383 
384  if(pChildFrame->pszMenuResource)
385  {
386  WBFree(pChildFrame->pszMenuResource);
387  pChildFrame->pszMenuResource = NULL;
388  }
389 
390  // And, NOW, destroy the window itself [if it's valid]
391  //
392  // NOTE: to prevent recursion problems, a 'DestroyNotify' would mark the window ID 'None'
393  // before calling this function. this will happen within my OWN proc, if the superclass doesn't do it
394 
395  if(pChildFrame->wID != None) // if there's a chance of recursion, I detect it here
396  {
397  WBDestroyWindow(pChildFrame->wID);
398  pChildFrame->wID = None; // make sure
399  }
400 
401  // FINALLY, unlink this object from the child frame list. Do it by walking the list, looking for
402  // this entry in the list. If I find it, I unlink it [otherwise, the 'pNext' link might be *stale*]
403 
404  if(pChildFrames) // just in case, walk the list - do not rely on possibly stale pointers
405  {
406  pC2 = NULL;
407  pC = pChildFrames;
408 
409  while(pC)
410  {
411  if(pC == pChildFrame) // just in case
412  {
413  if(pC2)
414  {
415  pC2->pNext = pC->pNext; // remove from link list
416  }
417  else
418  {
419  pChildFrames = pC->pNext; // it was the head of the chain
420  }
421 
422  pC->pNext = NULL;
423 
424  break;
425  }
426 
427  pC2 = pC;
428  pC = pC->pNext;
429  }
430  }
431 
432  pChildFrame->pNext = NULL; // make sure it's not a pointer someplace that can cause problems
433 
434  // if the 'superclass' destructor was specified, call it NOW.
435 
436  if(pChildFrame->destructor)
437  {
438  // at this point, we ALWAYS destroy the callback function.
439  // "it is assumed" that I won't be needing 'DestroyNotify' to
440  // trigger any destruction. That happens *AFTER* the window was
441  // destroyed, and happens asynchronously, typically before the
442  // frame window was destroyed.
443 
444  // so, to make sure that I don't get an event callback that references
445  // the window object after it's free'd, I need to remove the callback.
446 
447  if(wID != None)
448  {
449  WBUnregisterWindowCallback(wID); // no more event handling
450  WBSetWindowData(wID, 0, (void *)NULL); // window data is no longer pointing here
451  }
452 
453  // and THEN, it's safe to call the destructor on the original object.
454  pChildFrame->destructor(pChildFrame); // this should auto-delete as well
455  }
456  else
457  {
458  // TODO: should I perform a 'Destroy Notify' callback of my own?
459 
460  // NOTE: NOT calling 'WBunregisterWindowCallback()' so 'Destroy Notify' does its job. hopefully.
461  }
462 
463  // NOTE: I have to leave the tag alone at this point, to validate that it's
464  // a 'Child Frame' structure. But everything else needs to be zero'd out
465  // (I used to use 'bzero' but I'm just commenting it here, for reference)
466  // so... make sure everything that's free'd gets ZERO'd as well. this is
467  // because a 'DestroyNotify' handler that frees up the memory (and destroys
468  // any 'superclass') will probably call this function again, and it might
469  // happen asynchronously. In fact, it probably WILL happen asynchronously.
470 
471  // bzero(pChildFrame, sizeof(*pChildFrame)); // zero it out (as a matter of course)
472 
473  // note that I do *NOT* free the WBChildFrame HERE - this simply releases all resources for it.
474  // If there is NO DESTRUCTOR, the 'Destroy Notify' handler needs to do that, or at least SOMETHING.
475  // *NOT* handling this properly can result in 'use after free' problems.
476 }
477 
478 void FWSetChildFrameMenu(WBChildFrame *pChildFrame, const char *szFocusMenu)
479 {
480  if(!pChildFrame || pChildFrame->ulTag != CHILD_FRAME_TAG)
481  {
482  WB_ERROR_PRINT("ERROR: %s - pChildFrame not valid\n", __FUNCTION__);
483 
484  return;
485  }
486 
487  if(pChildFrame->pszMenuResource)
488  {
489  WBFree(pChildFrame->pszMenuResource);
490  }
491 
492  if(szFocusMenu)
493  {
494  pChildFrame->pszMenuResource = WBCopyString(szFocusMenu);
495  }
496  else
497  {
498  pChildFrame->pszMenuResource = NULL;
499  }
500 
501 }
502 
503 void FWSetChildFrameContextMenuID(WBChildFrame *pChildFrame, int nID)
504 {
505  if(!pChildFrame || pChildFrame->ulTag != CHILD_FRAME_TAG)
506  {
507  WB_ERROR_PRINT("ERROR: %s - pChildFrame not valid\n", __FUNCTION__);
508 
509  return;
510  }
511 
512  pChildFrame->iContextMenuID = nID;
513 }
514 
515 void FWSetChildFrameMenuHandlers(WBChildFrame *pChildFrame, const WBFWMenuHandler *pHandlerArray)
516 {
517  if(!pChildFrame || pChildFrame->ulTag != CHILD_FRAME_TAG)
518  {
519  WB_ERROR_PRINT("ERROR: %s - pChildFrame not valid\n", __FUNCTION__);
520 
521  return;
522  }
523 
524  if(pChildFrame->pMenuHandler)
525  {
526  WBFree(pChildFrame->pMenuHandler);
527  }
528 
529  if(pHandlerArray)
530  {
531  const WBFWMenuHandler *pH;
532  int iN;
533 
534  // count the number of entries in the menu handler
535  for(iN=0, pH = pHandlerArray; pH->lMenuID || pH->callback || pH->UIcallback; iN++, pH++)
536  {
537  // NOTHING inside the loop. just count.
538  }
539 
540  // allocate space and make a copy
541 
542  pChildFrame->pMenuHandler = (WBFWMenuHandler *)WBAlloc(sizeof(WBFWMenuHandler)
543  * (iN + 1
544  + sizeof(aChildFrameMenuHandler)
545  / sizeof(aChildFrameMenuHandler[0])
546  )
547  );
548 
549  if(pChildFrame->pMenuHandler)
550  {
551  if(iN > 0)
552  {
553  memcpy(pChildFrame->pMenuHandler, pHandlerArray,
554  sizeof(WBFWMenuHandler) * iN);
555  }
556 
557  // this adds MY menu default handlers to the end of the list
558  // so it's possible to override them, if the owner wants to
559 
560  memcpy(pChildFrame->pMenuHandler + iN,
561  aChildFrameMenuHandler,
562  sizeof(aChildFrameMenuHandler)); // this includes the NULL entry at the end
563  }
564  }
565  else
566  {
567  pChildFrame->pMenuHandler = NULL;
568  }
569 }
570 
571 void FWSetChildFrameDisplayName(WBChildFrame *pChildFrame, const char *szDisplayName)
572 {
573  if(!pChildFrame || pChildFrame->ulTag != CHILD_FRAME_TAG)
574  {
575  WB_ERROR_PRINT("ERROR: %s - pChildFrame not valid\n", __FUNCTION__);
576 
577  return;
578  }
579 
580  if(pChildFrame->szDisplayName)
581  {
582  WBFree(pChildFrame->szDisplayName);
583  }
584 
585  if(!szDisplayName)
586  {
587  return;
588  }
589 
590  pChildFrame->szDisplayName = WBCopyString(szDisplayName);
591 }
592 
593 void FWSetChildFrameImageAtom(WBChildFrame *pChildFrame, Atom aImage)
594 {
595  if(!pChildFrame || pChildFrame->ulTag != CHILD_FRAME_TAG)
596  {
597  WB_ERROR_PRINT("ERROR: %s - pChildFrame not valid\n", __FUNCTION__);
598 
599  return;
600  }
601 
602  pChildFrame->aImageAtom = aImage;
603 }
604 
605 
606 #if 0 // this function probably won't be used nor implemented; left anyway (reserved)
607 static void InternalSetChildFrameScrollInfo(WBChildFrame *pChildFrame, int iRow, int iMaxRow, int iCol, int iMaxCol,
608  int iRowHeight, int iColWidth)
609 {
610 
611 // NOTE: iTop, iHeight, etc. are "cached" values. use scroll [, iSplit, and scrollSplit] as "official" values
612 
613 // int iTop;
614 // // cached 0-based position of the top of the current viewport (in lines or pixels)
615 // int iHeight;
616 // // cached 0-based height of the current viewport (in lines or pixels)
617 // int iLeft;
618 // // cached 0-based position of the left of the current viewport (in characters or pixels)
619 // int iWidth;
620 // // cached 0-based width of the current viewport (in characters or pixels)
621 //
622 // int iXExtent;
623 // // cached X extent for the display surface (determines scrolling behavior)
624 // int iYExtent;
625 // // cached Y extent for the display surface (determines scrolling behavior)
626 //
627 // WB_SCROLLINFO scroll;
628 // // 'scroll info' (horizontal and vertical min/max/pos and other details)
629 //
630 // int iSplit;
631 // // reserved - position for 'split' (-1 for 'no split')
632 //
633 // WB_SCROLLINFO scrollSplit;
634 // // reserved - 'scroll info' for 'split' area (implementation-defined)
635 //
636 
637 // So, if the window/viewport is too small for the document extents, then I need scrollbars
638 
639 
640 
641 
642 }
643 #endif // 0
644 
645 void FWSetChildFrameExtent(WBChildFrame *pChildFrame, int iXExtent, int iYExtent)
646 {
647  if(!pChildFrame || pChildFrame->ulTag != CHILD_FRAME_TAG)
648  {
649  WB_ERROR_PRINT("ERROR: %s - pChildFrame not valid\n", __FUNCTION__);
650 
651  return;
652  }
653 
654 
655 
656 
657  // NOTE: see (and maybe call something *like* it) FWChildFrameRecalcLayout, below
658 
659  FWChildFrameRecalcLayout(pChildFrame); // for now, do it [later change mind?]
660 }
661 
662 
663 // this function calculates 'pChildFrame->geom' correctly
664 static void InternalChildFrameRecalcGeom(WBChildFrame *pChildFrame, int bResize)
665 {
666 WBFrameWindow *pOwner;
667 Display *pDisplay;
668 int iL, iT, iW, iH;
669 int nL, nL2, nC, nC2;
670 
671 
672  pDisplay = WBGetWindowDisplay(pChildFrame->wID);
673  pOwner = pChildFrame->pOwner;
674 
675  if(!pOwner) // irrelevant if NULL. TODO: properly validate this (anal retentive if DEBUG build)
676  {
677  WB_ERROR_PRINT("ERROR: %s - pOwner is NULL for Child Frame\n", __FUNCTION__);
678 
679  return;
680  }
681 
682  iL = pOwner->iClientX;
683  iT = pOwner->iClientY;
684  iW = pOwner->iClientWidth;
685  iH = pOwner->iClientHeight;
686 
687  if(bResize) // I called this because I resized the owner window
688  {
689  // resize the window accordingly
690  XMoveWindow(pDisplay, pChildFrame->wID, iL, iT);
691  XResizeWindow(pDisplay, pChildFrame->wID, iW - 2, iH - 2); // allow 1 pixel for border
692  }
693 
694  // calculate new client 'geom', backing out 2 additional pixels in all 4 directions
695 
696  pChildFrame->geom.x = 2;
697  pChildFrame->geom.y = 2;
698  pChildFrame->geom.width = iW - 6;
699  pChildFrame->geom.height = iH - 6; // the new width/height of client area
700 
701  // cache this value for later, when I paint
702  memcpy(&(pChildFrame->geomEntire), &(pChildFrame->geom), sizeof(pChildFrame->geomEntire));
703 
704  // NEXT, calculate the total height in rows, and width in cols, and determine whether
705  // the scroll bars need to be made visible.
706 
707  if(pChildFrame->iRowHeight <= 0 || pChildFrame->iColWidth <= 0)
708  {
710  WBFontDescent(pChildFrame->pFont));
711  nC2 = WBFontAvgCharWidth(pChildFrame->pFont);
712 
713  if(nL2 < 0)
714  {
715  nL2 = 16; // for now just use this
716  }
717  if(nC2 < 0)
718  {
719  nC2 = 8; // for now just use this
720  }
721 // pChildFrame->iRowHeight = nL2; // TODO: do this?
722 // pChildFrame->iColWidth = nC2; // TODO: do this?
723  }
724  else
725  {
726  nL2 = pChildFrame->iRowHeight;
727  nC2 = pChildFrame->iColWidth;
728  }
729 
730  nL = pChildFrame->geom.height - nL2 - 4; // the size if there were scroll bars
731  nC = pChildFrame->geom.width - nC2 - 4;
732 
733  nL /= nL2; // total number of lines displayed (if scroll bars present)
734  nC /= nC2; // total number of columns displayed (if scroll bars present)
735 
736  if((nL > 0 && nL <= pChildFrame->extent.height) || // # lines on screen > 0 and less than the extent's height?
737  (nC > 0 && nC <= pChildFrame->extent.width)) // # cols on screen > 0 and less than the extent's width?
738  {
739  // set up the scroll bar ranges correctly
740 
741  if(nC > 0 && nC <= pChildFrame->extent.width)
742  {
743  WBSetHScrollRange(&(pChildFrame->scroll), 0, pChildFrame->extent.width); // use entire width for range
744  }
745  else
746  {
747  WBSetHScrollRange(&(pChildFrame->scroll), 0, 0); // disabled
748  }
749 
750  if((nL - 2) < pChildFrame->extent.height) // brings vert scroll into place if H scroll came into place
751  {
752  if(WBSetVScrollRange(&(pChildFrame->scroll), 0,
753  pChildFrame->extent.height - (nL - 2))) // 2 extra line - scroll is for the top
754  {
755  nC--; // subtract an extra column when VScroll is visible
756 
757 reset_hscroll_range:
758  // if I changed the vscroll info, use this to re-set the hscroll info
759 
760  if(nC > 0 && nC <= pChildFrame->extent.width)
761  {
762  WBSetHScrollRange(&(pChildFrame->scroll), 0, pChildFrame->extent.width); // use entire width for range
763  }
764  else
765  {
766  WBSetHScrollRange(&(pChildFrame->scroll), 0, 0); // disabled
767  }
768  }
769  }
770  else
771  {
772  if(WBSetVScrollRange(&(pChildFrame->scroll), 0, 0)) // disable vertical scrollbar
773  {
774  goto reset_hscroll_range;
775  }
776  }
777 
778  // set the HPos and VPos based on what's currently visible (upper left corner)
779 
780  pChildFrame->scroll.iHPos = pChildFrame->origin.x;
781  pChildFrame->scroll.iVPos = pChildFrame->origin.y;
782  }
783  else
784  {
785  WBSetHScrollRange(&(pChildFrame->scroll), 0, 0); // thus disabling them
786  WBSetVScrollRange(&(pChildFrame->scroll), 0, 0);
787  }
788 
789  // TODO: anything ELSE that I need to do when re-calculating the layout, scrollbars, whatever
790  // just apply that to geom so that it reflects the correct viewpoirt in pixels
791  // minus any border, decorations, scrollbars, whatever, with 0,0 being top,left
792  // for the window [in this case, border is 1 pixel already]
793 
794 
795 
796  // TODO: if I need to show scrollbars, subtract height/width of bar (plus border) from
797  // the geometry width and height, as needed
798 
799 
800  WBUpdateScrollBarGeometry(&(pChildFrame->scroll), pChildFrame->pFont, // for now do this
801  &(pChildFrame->geom), &(pChildFrame->geom));
802 }
803 
804 void FWSetChildFrameScrollInfo(WBChildFrame *pChildFrame, int iRow, int iMaxRow, int iCol, int iMaxCol,
805  int iRowHeight, int iColWidth)
806 {
807  if(!pChildFrame || pChildFrame->ulTag != CHILD_FRAME_TAG)
808  {
809  WB_ERROR_PRINT("ERROR: %s - pChildFrame not valid\n", __FUNCTION__);
810 
811  return;
812  }
813 
814  pChildFrame->origin.y = iRow;
815  pChildFrame->origin.x = iCol;
816 
817  pChildFrame->extent.width = iMaxCol;
818  pChildFrame->extent.height = iMaxRow;
819  pChildFrame->iRowHeight = iRowHeight;
820  pChildFrame->iColWidth = iColWidth;
821 
822  // NOTE: this function must *NOT* call FWChildFrameRecalcLayout, nor FWSetChildFrameExtent, in
823  // order to prevent problems with recursion. Instead, it must 'nuke out' (aka 'derive')
824  // all of those things, independently.
825 
826  InternalChildFrameRecalcGeom(pChildFrame, 0); // re-calculate geom but do NOT re-size window
827 
828  // Need for scroll bars (and window shrinkage) was determined by InternalChildFrameRecalcGeom().
829 
830  // at this point the scroll bars will be correctly drawn, and the display area appropriately "shrunk"
831  // when re-painting the client area, using 'pChildFrame->extent' and 'pChildFrame->geom'.
832 
833 
834 
835  // FINALLY, auto-scroll iRow and iCol into view [as needed]
836 
837 
838  WB_WARN_PRINT("TODO: %s - implement. %p %u (%08xH) %d, %d, %d, %d, %d, %d\n", __FUNCTION__,
839  pChildFrame, (int)pChildFrame->wID, (int)pChildFrame->wID,
840  iRow, iMaxRow, iCol, iMaxCol, iRowHeight, iColWidth);
841 }
842 
843 
844 
846 {
847  if(!pChildFrame || pChildFrame->ulTag != CHILD_FRAME_TAG)
848  {
849  WB_ERROR_PRINT("ERROR: %s - pChildFrame not valid\n", __FUNCTION__);
850 
851  return;
852  }
853 
854  // before I begin, recalculate the geometry and account for scroll bars
855 
856  InternalChildFrameRecalcGeom(pChildFrame, 1); // re-calculate geom and re-size window
857 
858  // TODO:
859  // pChildFrame->iLeft = iL converted to correct units and scrolled;
860  // pChildFrame->iTop = iT converted to correct units and scrolled;
861  // pChildRrame->iWidth = iW converted to correct units;
862  // pChildFrame->iHeight = iH converted to correct units;
863 
864 
865  // NOW, tell the user callback function (if any) what's happening.
866  // I must assume that the owning frame is valid and has already re-calc'd its layout
867 
868  if(pChildFrame->pUserCallback)
869  {
870  Display *pDisplay;
871  XClientMessageEvent evt;
872 
873  pDisplay = WBGetWindowDisplay(pChildFrame->wID);
874 
875  bzero(&evt, sizeof(evt));
876  evt.type = ClientMessage;
877 
878  evt.display = pDisplay;
879  evt.window = pChildFrame->wID;
880  evt.message_type = aRESIZE_NOTIFY;
881  evt.format = 32; // always
882  evt.data.l[0] = pChildFrame->geom.x; // left
883  evt.data.l[1] = pChildFrame->geom.y; // top
884  evt.data.l[2] = pChildFrame->geom.x + pChildFrame->geom.width; // right
885  evt.data.l[3] = pChildFrame->geom.y + pChildFrame->geom.height; // bottom
886 
887  // required implementation. superclass must process this and fix up scroll info
888  pChildFrame->pUserCallback(evt.window, (XEvent *)&evt);
889  }
890 
891  // TODO: fix the scrollbars and invalidate rectangles
892 
893  WBInvalidateRect(pChildFrame->wID, NULL, 1); // for now, do this
894 
895 }
896 
898 {
899  if(!pChildFrame || pChildFrame->ulTag != CHILD_FRAME_TAG)
900  {
901  WB_ERROR_PRINT("ERROR: %s - pChildFrame not valid\n", __FUNCTION__);
902 
903  return;
904  }
905 
906  // for now, don't mess with the tabs, just set the text
907  // later, I may need to store the tab info.
908 
909  FWSetStatusText(pChildFrame->pOwner, pChildFrame->szStatusText);
910 }
911 
912 
914 {
915 Display *pDisplay;
916 XClientMessageEvent evt;
917 
918 
919  if(!pChildFrame || pChildFrame->ulTag != CHILD_FRAME_TAG)
920  {
921  WB_ERROR_PRINT("ERROR: %s - pChildFrame not valid\n", __FUNCTION__);
922 
923  return -1; // an error
924  }
925 
926  if(!pChildFrame->pUserCallback)
927  {
928  return 0; // return 'ok to close' when there's no 'user callback' function to query
929  }
930 
931  pDisplay = WBGetWindowDisplay(pChildFrame->wID);
932 
933  bzero(&evt, sizeof(evt));
934  evt.type = ClientMessage;
935 
936  evt.display = pDisplay;
937  evt.window = pChildFrame->wID;
938  evt.message_type = aQUERY_CLOSE;
939  evt.format = 32; // always
940 
941  return pChildFrame->pUserCallback(evt.window, (XEvent *)&evt);
942 }
943 
944 
945 // DEFAULT WINDOW EVENT HANDLER FOR CHILD FRAME
946 
947 int FWChildFrameEvent(Window wID, XEvent *pEvent)
948 {
949 int iRval = 0;
950 WBChildFrame *pC;
951 WBFrameWindow *pFW;
952 Display *pDisplay;
953 #ifndef NO_DEBUG
954 char tbuf[32]; // for keyboard input
955 int nChar = sizeof(tbuf);
956 #endif // NO_DEBUG
957 
958 
959  pDisplay = WBGetWindowDisplay(wID);
960  pC = FWGetChildFrameStruct(wID);
961 
962  if(!pC)
963  {
964 #ifndef NO_DEBUG
965  WB_ERROR_PRINT("ERROR: %s - no child frame structure, window data is %p\n", __FUNCTION__, WBGetWindowData(wID, 0));
966 
967  WBDebugDumpEvent(pEvent);
968 #endif // NO_DEBUG
969 
970  return 0;
971  }
972 
973  pFW = pC->pOwner; // make sure I know my owning frame window
974 
975  // if I have visible scroll bars, paint them on 'Expose'
976  if(pEvent->type == Expose)
977  {
978  WB_GEOM geomTemp;
979  WBGC gc;
980  XColor clrBG;
981 
982  // first, horizontal bar
983  geomTemp.x = pC->geom.x;
984  geomTemp.y = pC->geom.y + pC->geom.height;
985  geomTemp.width = pC->geom.width;
986  geomTemp.height = pC->geomEntire.height - pC->geom.height;
987 
988  if(geomTemp.width > 0 && geomTemp.height > 0)
989  {
990  gc = WBBeginPaintGeom(pC->wID, &geomTemp);
991 
992  if(gc != None)
993  {
994  WBPaintHScrollBar(&(pC->scroll), pDisplay, wID, gc, &(pC->geomEntire));
995  WBEndPaint(wID, gc);
996  }
997  }
998 
999  // then, vertical bar
1000  geomTemp.x = pC->geom.x + pC->geom.width;
1001  geomTemp.y = pC->geom.y;
1002  geomTemp.width = pC->geomEntire.width - pC->geom.width;
1003  geomTemp.height = pC->geom.height;
1004 
1005  if(geomTemp.width > 0 && geomTemp.height > 0)
1006  {
1007  gc = WBBeginPaintGeom(pC->wID, &geomTemp);
1008 
1009  if(gc != None)
1010  {
1011  WBPaintVScrollBar(&(pC->scroll), pDisplay, wID, gc, &(pC->geomEntire));
1012  WBEndPaint(wID, gc);
1013  }
1014  }
1015 
1016  // finally, if both bars are visible, I need to paint the square in the lower
1017  // right-hand corner. I'll use the frame background default color for that
1018 
1019  geomTemp.x = pC->geom.x + pC->geom.width;
1020  geomTemp.y = pC->geom.y + pC->geom.height;
1021  geomTemp.width = pC->geomEntire.width - pC->geom.width;
1022  geomTemp.height = pC->geomEntire.height - pC->geom.height;
1023 
1024  if(geomTemp.width > 0 && geomTemp.height > 0)
1025  {
1026  clrBG = FWGetDefaultBG();
1027 
1028  gc = WBBeginPaintGeom(pC->wID, &geomTemp);
1029 
1030  if(gc != None)
1031  {
1032  WBSetForeground(gc, clrBG.pixel);
1033  WBSetBackground(gc, clrBG.pixel);
1034 
1035  WBFillRectangle(pDisplay, wID, gc, geomTemp.x, geomTemp.y, geomTemp.width, geomTemp.height);
1036 
1037  WBEndPaint(wID, gc);
1038  }
1039  }
1040  }
1041  else if(pEvent->type == ClientMessage)
1042  {
1043  iRval = WBScrollBarEvent(wID, pEvent, &(pC->scroll));
1044 
1045  if(iRval)
1046  {
1047  return iRval; // return whatever 'WBScrollBarEvent' says to return
1048  }
1049  }
1050 
1051  // TODO: messages I handle myself, before any user callbacks
1052  // (and perhaps messages that I don't pass to the callback at all)
1053 
1054  if(pC->pUserCallback)
1055  {
1056  iRval = pC->pUserCallback(wID, pEvent);
1057  }
1058 
1059 
1060  // TODO: menu and menu UI handler? For now, no. rely on frame window.
1061 
1062  if(pEvent->type == ClientMessage &&
1063  (pEvent->xclient.message_type == aMENU_COMMAND ||
1064  pEvent->xclient.message_type == aMENU_UI_COMMAND))
1065  {
1066  // TODO: special handling?
1067 
1068  return iRval; // default behavior for these
1069  }
1070 
1072  // //
1073  // _____ _ ___ __ __ _____ _ _ _ _ _ ____ _____ ___ __ __ _ _____ ___ ___ _ _ //
1074  // | ___|/ | / _ \ | \/ || ____|| \ | || | | | / \ / ___||_ _||_ _|\ \ / // \ |_ _||_ _|/ _ \ | \ | | //
1075  // | |_ | || | | | | |\/| || _| | \| || | | | / _ \ | | | | | | \ \ / // _ \ | | | || | | || \| | //
1076  // | _| | || |_| | | | | || |___ | |\ || |_| | / ___ \| |___ | | | | \ V // ___ \ | | | || |_| || |\ | //
1077  // |_| |_| \___/ |_| |_||_____||_| \_| \___/ /_/ \_\\____| |_| |___| \_//_/ \_\|_| |___|\___/ |_| \_| //
1078  // //
1079  // //
1081 
1082  // checking for menu activation
1083 
1084  if(!iRval && !pFW &&
1085  pEvent->type == ClientMessage &&
1086  pEvent->xclient.message_type == aWB_CHAR &&
1087  pEvent->xclient.data.l[0] == XK_F10 && // keystroke is F10
1088  (pEvent->xclient.data.l[1] & WB_KEYEVENT_KEYSYM))
1089  {
1090  // activate the menu in the owning frame (if there is one) or display a popup
1091 
1092  Window wIDMenu = WBGetMenuWindow(pFW->wID);
1093 
1094  int iACS = (int)pEvent->xclient.data.l[1] & WB_KEYEVENT_ACSMASK;
1095 
1096  if(iACS == WB_KEYEVENT_SHIFT)
1097  {
1098  // send a command to pop up the context menu
1099 
1100  return 1; // handled
1101  }
1102  else if(!iACS) // no ctrl+alt+shift
1103  {
1104  if(wIDMenu)
1105  {
1106  // send command to pop up the frame's menu
1107 
1108  XClientMessageEvent evt;
1109 
1110  // post a high-priority message to myself to display the menu
1111 
1112  bzero(&evt, sizeof(evt));
1113  evt.type = ClientMessage;
1114  evt.display = WBGetWindowDisplay(wIDMenu);
1115  evt.window = wIDMenu;
1116  evt.message_type = aMENU_ACTIVATE;
1117  evt.format = 32;
1118  evt.data.l[0] = 0;
1119  evt.data.l[1] = 0;
1120 
1121  WBPostPriorityEvent(wIDMenu, (XEvent *)&evt);
1122 
1123  WB_DEBUG_PRINT(DebugLevel_Chatty | DebugSubSystem_Menu | DebugSubSystem_Frame,
1124  "%s - posting client event message to display menu\n", __FUNCTION__);
1125 
1126  return 1; // handled
1127  }
1128  }
1129  }
1130 
1131 
1132  // regardless, for a 'DestroyNotify, assign wID to 'None' in the ChildFrame class
1133 
1134  if(!iRval)
1135  {
1136  // TODO: default handling of messages NOT handled by user callback
1137 
1138  switch(pEvent->type)
1139  {
1140  case KeyPress:
1141  {
1142 #ifndef NO_DEBUG
1143  int iACS = 0;
1144  int iKey = WBKeyEventProcessKey((XKeyEvent *)pEvent, tbuf, &nChar, &iACS);
1145 
1146  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_Frame | DebugSubSystem_Keyboard,
1147  "%s KEY PRESS for KEY %d KEYCODE %d MASK=%d (%xH)\n",
1148  __FUNCTION__, iKey, ((XKeyEvent *)pEvent)->keycode,
1149  ((XKeyEvent *)pEvent)->state, ((XKeyEvent *)pEvent)->state);
1150 #endif // NO_DEBUG
1151 
1152  // check for menu and hotkey activation.
1153 // if(nChar > 0) // only for "real" characters (i.e. not just the ALT key)
1154  if(pFW)
1155  {
1157 
1158  if(pMenuBar) // menu bar exists?
1159  {
1160  WB_DEBUG_PRINT(DebugLevel_Excessive | DebugSubSystem_Menu | DebugSubSystem_Frame | DebugSubSystem_Keyboard,
1161  "%s call to MBMenuProcessHotKey for menu window %d (%08xH)\n",
1162  __FUNCTION__, (int)pMenuBar->wSelf, (int)pMenuBar->wSelf);
1163 
1164  iRval = MBMenuProcessHotKey(pMenuBar->pMenu, (XKeyEvent *)pEvent);
1165  }
1166  }
1167  }
1168  break;
1169 
1170  case KeyRelease:
1171  {
1172  // KeyRelease
1173 #ifndef NO_DEBUG
1174  int iACS = 0, iKey = WBKeyEventProcessKey((XKeyEvent *)pEvent, tbuf, &nChar, &iACS);
1175 
1176  if(nChar > 0)
1177  {
1178  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_Frame | DebugSubSystem_Keyboard,
1179  "%s KEY RELEASE for KEY %d KEYCODE %d MASK=%d (%xH)\n",
1180  __FUNCTION__, iKey, ((XKeyEvent *)pEvent)->keycode,
1181  ((XKeyEvent *)pEvent)->state, ((XKeyEvent *)pEvent)->state);
1182 
1183  }
1184 #endif // NO_DEBUG
1185 
1186  }
1187 
1188  break;
1189 
1190  case ClientMessage:
1191  if(pEvent->xclient.message_type == aWB_CHAR) // generated by WBDefault
1192  {
1193  if(pC->pUI)
1194  {
1195  iRval = ChildFrameDoCharEvent(&pEvent->xclient, WBGetWindowDisplay(wID), wID, pC, pC->pUI);
1196  }
1197  else if(WBCheckDebugLevel(DebugLevel_Heavy | DebugSubSystem_Keyboard))
1198  {
1199  WB_ERROR_PRINT("%s - WB_CHAR, no UI\n", __FUNCTION__);
1200  WBDebugDumpEvent((XEvent *)pEvent);
1201  }
1202  }
1203  else if(pEvent->xclient.message_type == aWB_POINTER) // generated by WBDefault
1204  {
1205  if(pC->pUI)
1206  {
1207  iRval = ChildFrameDoPointerEvent(&pEvent->xclient, WBGetWindowDisplay(wID), wID, pC, pC->pUI);
1208  }
1209  else if(WBCheckDebugLevel(DebugLevel_Heavy | DebugSubSystem_Keyboard))
1210  {
1211  WB_ERROR_PRINT("%s - WB_POINTER, no UI\n", __FUNCTION__);
1212  WBDebugDumpEvent((XEvent *)pEvent);
1213  }
1214  }
1215  else if(pEvent->xclient.message_type == aSCROLL_NOTIFY) // generated by WBScrollBarEvent()
1216  {
1217  if(pC->pUI)
1218  {
1219  iRval = ChildFrameDoScrollEvent(&pEvent->xclient, WBGetWindowDisplay(wID), wID, pC, pC->pUI);
1220  }
1221  else if(WBCheckDebugLevel(DebugLevel_Heavy | DebugSubSystem_ScrollBar))
1222  {
1223  WB_ERROR_PRINT("%s - WB_SCROLL_NOTIFY, no UI\n", __FUNCTION__);
1224  WBDebugDumpEvent((XEvent *)pEvent);
1225  }
1226  }
1227 
1228  break;
1229  }
1230  }
1231 
1232 
1233  if(pEvent->type == DestroyNotify &&
1234  pEvent->xdestroywindow.window == wID)
1235  {
1236  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_Frame,
1237  "%s - DestroyNotify\n", __FUNCTION__);
1238 
1239  if(!iRval)
1240  {
1241  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Frame,
1242  "%s - DestroyNotify *NOT* handled by superclass\n", __FUNCTION__);
1243  }
1244 
1245  pC = FWGetChildFrameStruct(wID); // re-get the structure (it may have been deleted, probably SHOULD have been)
1246 
1247  if(pC && pC->wID != None) // haven't called FWDestroyChildFrame yet?
1248  {
1249  // mark window ID 'None', then call FWDestroyChildFrame from here
1250  // by design it's safe to do that...
1251 
1252  pC->wID = None; // since window already 'destroyed' - I'm getting the notification after all
1253 
1254  // set the window callback to NULL - this disconnects me from the message processor also
1255  // as well as freeing up everything
1256 
1257  FWDestroyChildFrame(pC); // make sure it's destroyed, unlinked, etc. (pointer may not be valid now)
1258 
1259  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Frame,
1260  "%s - DestroyNotify handled by Child Window base class\n", __FUNCTION__);
1261  }
1262 
1263  WBUnregisterWindowCallback(wID); // prevents any more messages from being dispatched to this function
1264 
1265  WB_DEBUG_PRINT(DebugLevel_ERROR/*DebugLevel_Verbose | DebugSubSystem_Event | DebugSubSystem_Frame*/,
1266  "%s - child frame window destroyed\n", __FUNCTION__);
1267  return 1;
1268  }
1269 
1270 
1271  return iRval;
1272 }
1273 
1274 
1275 static int ChildFrameDoPointerEvent(XClientMessageEvent *pEvent, Display *pDisplay,
1276  Window wID, WBChildFrame *pC, WBChildFrameUI *pUI)
1277 {
1278 int iACS;
1279 int iX, iY;
1280 int iButtonMask;
1281 
1282 
1283  if(wID == None || !pC || !pUI ||
1284  pEvent->type != ClientMessage ||
1285  pEvent->message_type != aWB_POINTER)
1286  {
1287  return 0; // sanity check (temporary?)
1288  }
1289 
1290 //#ifndef NO_DEBUG
1291 // WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Mouse,
1292 // "%s - WB_POINTER\n", __FUNCTION__);
1293 // WBDebugDumpEvent((XEvent *)pEvent);
1294 //#endif // NO_DEBUG
1295 
1296 
1297  // left-click - position cursor, cancel selection
1298  // shift-left-click - select from cursor to THIS point
1299  // (other modifiers, ignore the modifier key)
1300  // right-click - drop-down edit menu
1301  // middle click - select word? paste?
1302  // scroll wheel up/down - should be handled by scrollbar thingy
1303  // left-drag - select from starting position
1304  // right-drag - drag/drop?
1305  // middle-drag - ?
1306 
1307  iButtonMask = pEvent->data.l[1]; // WB_POINTER_BUTTON1 through WB_POINTER_BUTTON5 (bitmask)
1308 
1309  iACS = pEvent->data.l[2];
1310 
1311  iX = pEvent->data.l[3];
1312  iY = pEvent->data.l[4];
1313 
1314  WB_DEBUG_PRINT(DebugLevel_Medium | DebugSubSystem_Mouse | DebugSubSystem_Frame | DebugSubSystem_Event,
1315  "INFO: %s EVENT=%lu (%08lxH) iButtonMask=%x iACS=%x iX=%d iY=%d\n",
1316  __FUNCTION__, (unsigned long)pEvent->data.l[0], (unsigned long)pEvent->data.l[0],
1317  iButtonMask, iACS, iX, iY);
1318 
1319  switch(pEvent->data.l[0])
1320  {
1321  case WB_POINTER_CLICK:
1322  if(pUI->mouse_click)
1323  {
1324  pUI->mouse_click(pC, iX, iY, iButtonMask, iACS);
1325  return 1; // handled
1326  }
1327 
1328  break;
1329 
1330  case WB_POINTER_DBLCLICK:
1331  if(pUI->mouse_dblclick)
1332  {
1333  pUI->mouse_dblclick(pC, iX, iY, iButtonMask, iACS);
1334  return 1; // handled
1335  }
1336 
1337  break;
1338 
1339  case WB_POINTER_DRAG:
1340  if(pUI->mouse_drag)
1341  {
1342  pUI->mouse_drag(pC, iX, iY, iButtonMask, iACS);
1343 
1344  return wID; // do this to support pointer drag (it sets up a few things correctly)
1345  // NOTE: if the function isn't NULL it's expected to perform the correct operation
1346  // and if there's an error, it can post a 'DRAG CANCEL' request
1347  }
1348 
1349  break;
1350 
1351  case WB_POINTER_DROP:
1352  if(pUI->mouse_drop)
1353  {
1354  pUI->mouse_drop(pC, iX, iY, iButtonMask, iACS);
1355  return 1; // handled
1356  }
1357 
1358  break;
1359 
1360  case WB_POINTER_MOVE:
1361  if(pUI->mouse_move)
1362  {
1363  pUI->mouse_move(pC, iX, iY); // assumes button/flags haven't changed since last time (useful only for drags)
1364  return 1; // handled
1365  }
1366 
1367  break;
1368 
1369  case WB_POINTER_CANCEL:
1370  if(pUI->mouse_cancel)
1371  {
1372  pUI->mouse_cancel(pC);
1373  return 1; // handled
1374  }
1375 
1376  break;
1377 
1378  case WB_POINTER_SCROLLUP:
1379  if(pUI->scroll_vert)
1380  {
1381  WB_WARN_PRINT("WARNING: %s %d - WB_POINTER_SCROLLUP\n", __FUNCTION__, __LINE__);
1382  pUI->scroll_vert(pC, 1, -1); // scroll up
1383  return 1; // handled
1384  }
1385 
1386  WB_WARN_PRINT("WARNING: %s %d - WB_POINTER_SCROLLUP (not handled)\n", __FUNCTION__, __LINE__);
1387 
1388  break;
1389 
1390  case WB_POINTER_SCROLLDOWN:
1391  if(pUI->scroll_vert)
1392  {
1393  WB_WARN_PRINT("WARNING: %s %d - WB_POINTER_SCROLLDOWN\n", __FUNCTION__, __LINE__);
1394  pUI->scroll_vert(pC, 1, 1); // scroll down
1395  return 1; // handled
1396  }
1397 
1398  WB_WARN_PRINT("WARNING: %s %d - WB_POINTER_SCROLLDOWN (not handled)\n", __FUNCTION__, __LINE__);
1399 
1400  break;
1401 
1402 
1403  default:
1404 
1405  if(WBCheckDebugLevel(DebugLevel_Light | DebugSubSystem_ScrollBar))
1406  {
1407  WB_ERROR_PRINT("%s.%d - unhandled mousie message\n", __FUNCTION__, __LINE__);
1408 
1409  WBDebugDumpEvent((XEvent *)pEvent);
1410  }
1411 
1412  break;
1413  }
1414 
1415  return 0; // must indicate 'did not handle' if I get here
1416 }
1417 
1418 static int ChildFrameDoScrollEvent(XClientMessageEvent *pEvent, Display *pDisplay,
1419  Window wID, WBChildFrame *pC, WBChildFrameUI *pUI)
1420 {
1421  if(pEvent->data.l[0] == WB_SCROLL_VERTICAL)
1422  {
1423  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_ScrollBar,
1424  "%s %d - SCROLL_NOTIFY - SCROLL_VERTICAL, %lx, %lx, %lx, %lx\n",
1425  __FUNCTION__, __LINE__,
1426  pEvent->data.l[1],
1427  pEvent->data.l[2],
1428  pEvent->data.l[3],
1429  pEvent->data.l[4]);
1430 
1431  switch(pEvent->data.l[1])
1432  {
1433  case WB_SCROLL_KNOB: // 'knob track' - knob position will be in data.l[2]
1434  if(pUI->scroll_vert)
1435  {
1436  pUI->scroll_vert(pC, 0, (int)pEvent->data.l[2]);
1437  }
1438 
1439  break;
1440 
1441  case WB_SCROLL_FORWARD: // move down, or move right
1442  if(pUI->scroll_vert)
1443  {
1444  pUI->scroll_vert(pC, 1, 1);
1445  }
1446 
1447  break;
1448 
1449  case WB_SCROLL_BACKWARD: // move up, or move left
1450  if(pUI->scroll_vert)
1451  {
1452  pUI->scroll_vert(pC, 1, -1);
1453  }
1454 
1455  break;
1456 
1457  case WB_SCROLL_PAGEFWD: // page down or page right
1458  if(pUI->pgdown)
1459  {
1460  pUI->pgdown(pC, 0);
1461  }
1462 
1463  break;
1464 
1465  case WB_SCROLL_PAGEBACK: // page up or page left
1466  if(pUI->pgup)
1467  {
1468  pUI->pgup(pC, 0);
1469  }
1470 
1471  break;
1472 
1473  case WB_SCROLL_FIRST: // scroll to first entry, i.e. home or top
1474  if(pUI->scroll_vert)
1475  {
1476  pUI->scroll_vert(pC, 0, 0);
1477  }
1478 
1479  break;
1480 
1481  case WB_SCROLL_LAST: // scroll to last entry, i.e. bottom or end
1482  if(pUI->scroll_vert)
1483  {
1484  pUI->scroll_vert(pC, 0, -1); // indicates 'end'
1485  }
1486 
1487  break;
1488 
1489  case WB_SCROLL_DBLCLICK: // double-click detection (no selection info in data.l[2])
1490  return 0; // not handled
1491 
1492  case WB_SCROLL_ABSOLUTE: // absolute scroll, to the absolute position in data.l[2]
1493  case WB_SCROLL_RELATIVE: // relative scroll, relative +/- position in data.l[2]
1494  if(pUI->scroll_vert)
1495  {
1496  pUI->scroll_vert(pC,
1497  pEvent->data.l[1] == WB_SCROLL_ABSOLUTE ? 0 : 1,
1498  (int)pEvent->data.l[2]);
1499  }
1500 
1501  break;
1502 
1503  case WB_SCROLL_NA: // generic 'NA' or 'UNDEFINED' value
1504  WB_DEBUG_PRINT(DebugLevel_WARN | DebugSubSystem_Event | DebugSubSystem_Frame | DebugSubSystem_ScrollBar,
1505  "WARNING: %s %d - SCROLL_NOTIFY - SCROLL_VERTICAL - WB_SCROLL_NA\n", __FUNCTION__, __LINE__);
1506  }
1507 
1508  return 1;
1509  }
1510  else if(pEvent->data.l[0] == WB_SCROLL_HORIZONTAL)
1511  {
1512  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_ScrollBar,
1513  "%s %d - SCROLL_NOTIFY - SCROLL_HORIZONTAL, %lx, %lx, %lx, %lx\n",
1514  __FUNCTION__, __LINE__,
1515  pEvent->data.l[1],
1516  pEvent->data.l[2],
1517  pEvent->data.l[3],
1518  pEvent->data.l[4]);
1519 
1520  switch(pEvent->data.l[1])
1521  {
1522  case WB_SCROLL_KNOB: // 'knob track' - knob position will be in data.l[2]
1523  if(pUI->scroll_horiz)
1524  {
1525  pUI->scroll_horiz(pC, 0, (int)pEvent->data.l[2]);
1526  }
1527 
1528  break;
1529 
1530  case WB_SCROLL_FORWARD: // move down, or move right
1531  if(pUI->scroll_horiz)
1532  {
1533  pUI->scroll_horiz(pC, 1, 1);
1534  }
1535 
1536  break;
1537 
1538  case WB_SCROLL_BACKWARD: // move up, or move left
1539  if(pUI->scroll_horiz)
1540  {
1541  pUI->scroll_horiz(pC, 1, -1);
1542  }
1543 
1544  break;
1545 
1546  case WB_SCROLL_PAGEFWD: // page down or page right
1547  if(pUI->pgright)
1548  {
1549  pUI->pgright(pC, 0);
1550  }
1551 
1552  break;
1553 
1554  case WB_SCROLL_PAGEBACK: // page up or page left
1555  if(pUI->pgleft)
1556  {
1557  pUI->pgleft(pC, 0);
1558  }
1559 
1560  break;
1561 
1562  case WB_SCROLL_FIRST: // scroll to first entry, i.e. home or top
1563  if(pUI->scroll_horiz)
1564  {
1565  pUI->scroll_horiz(pC, 0, 0);
1566  }
1567 
1568  break;
1569 
1570  case WB_SCROLL_LAST: // scroll to last entry, i.e. bottom or end
1571 // if(pUI->end)
1572 // {
1573 // pUI->end(pC, 0);
1574 // }
1575  if(pUI->scroll_horiz)
1576  {
1577  pUI->scroll_horiz(pC, 0, -1); // indicates 'end'
1578  }
1579 
1580  break;
1581 
1582  case WB_SCROLL_DBLCLICK: // double-click detection (no selection info in data.l[2])
1583  return 0; // not handled
1584 
1585  case WB_SCROLL_ABSOLUTE: // absolute scroll, to the absolute position in data.l[2]
1586  case WB_SCROLL_RELATIVE: // relative scroll, relative +/- position in data.l[2]
1587  if(pUI->scroll_horiz)
1588  {
1589  pUI->scroll_horiz(pC,
1590  pEvent->data.l[1] == WB_SCROLL_ABSOLUTE ? 0 : 1,
1591  (int)pEvent->data.l[2]);
1592  }
1593 
1594  break;
1595 
1596  case WB_SCROLL_NA: // generic 'NA' or 'UNDEFINED' value
1597  WB_DEBUG_PRINT(DebugLevel_WARN | DebugSubSystem_Event | DebugSubSystem_Frame | DebugSubSystem_ScrollBar,
1598  "WARNING: %s %d - SCROLL_NOTIFY - SCROLL_HORIZONTAL - WB_SCROLL_NA\n", __FUNCTION__, __LINE__);
1599  }
1600 
1601  return 1;
1602  }
1603 
1604  WB_ERROR_PRINT("WARNING: %s %d - SCROLL_NOTIFY not handled - %lx, %lx, %lx, %lx, %lx\n",
1605  __FUNCTION__, __LINE__,
1606  pEvent->data.l[0],
1607  pEvent->data.l[1],
1608  pEvent->data.l[2],
1609  pEvent->data.l[3],
1610  pEvent->data.l[4]);
1611 
1612  return 0;
1613 }
1614 
1615 
1616 static int ChildFrameDoCharEvent(XClientMessageEvent *pEvent, Display *pDisplay,
1617  Window wID, WBChildFrame *pC, WBChildFrameUI *pUI)
1618 {
1619 int iKey, iACS, nChar;
1620 char *pBuf;
1621 int iRval = 0;
1622 
1623 
1624  if(wID == None || !pC || !pUI ||
1625  pEvent->type != ClientMessage ||
1626  pEvent->message_type != aWB_CHAR)
1627  {
1628  return 0; // sanity check (temporary?)
1629  }
1630 
1631 //#ifndef NO_DEBUG
1632 // WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Keyboard,
1633 // "%s - WB_CHAR\n", __FUNCTION__);
1634 // WBDebugDumpEvent((XEvent *)pEvent);
1635 //#endif // NO_DEBUG
1636 
1637  iKey = pEvent->data.l[0]; // result from WBKeyEventProcessKey()
1638  iACS = pEvent->data.l[1];
1639  nChar = pEvent->data.l[2];
1640  pBuf = (char *)&(pEvent->data.l[3]);
1641 
1642 
1643  if(nChar > 0) // normal ASCII characters
1644  {
1645  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_Keyboard,
1646  "%s KEY RELEASE for KEY %d KEYCODE %d MASK=%d (%xH)\n",
1647  __FUNCTION__, iKey, ((XKeyEvent *)pEvent)->keycode,
1648  ((XKeyEvent *)pEvent)->state, ((XKeyEvent *)pEvent)->state);
1649 
1650  if(iKey == 8) // backspace
1651  {
1652  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_Keyboard,
1653  "%s - BACKSPACE key pressed, iACS=%d (%xH)\n", __FUNCTION__, iACS, iACS);
1654 
1655  if(pUI->bkspace)
1656  {
1657  pUI->bkspace(pC, iACS);
1658  }
1659  else
1660  {
1661  XBell(pDisplay, -100);
1662  }
1663 
1664  iRval = 1;
1665  }
1666  else if(iKey == 13) // CR
1667  {
1668  // special handling for ALT+ENTER
1669  if(pUI->properties && (iACS & WB_KEYEVENT_ACSMASK) == WB_KEYEVENT_ALT)
1670  {
1671  pUI->properties(pC);
1672  }
1673  else if(pUI->enter)
1674  {
1675  pUI->enter(pC, iACS);
1676  }
1677  else if(pUI->do_char)
1678  {
1679  pUI->do_char(pC, pEvent);
1680  }
1681  else
1682  {
1683  XBell(pDisplay, -100);
1684  }
1685 
1686  iRval = 1;
1687  }
1688  else if(iKey == 10) // LF
1689  {
1690  if(pUI->do_char)
1691  {
1692  pUI->do_char(pC, pEvent);
1693  }
1694  else if(pUI->enter) // just in case, allow 'LF' to be 'ENTER' if no char handler
1695  {
1696  pUI->enter(pC, iACS);
1697  }
1698  else
1699  {
1700  XBell(pDisplay, -100);
1701  }
1702 
1703  iRval = 1;
1704  }
1705  else if(iKey == 9) // tab
1706  {
1707  if(pUI->tab)
1708  {
1709  pUI->tab(pC, iACS);
1710  }
1711  else if(pUI->do_char)
1712  {
1713  pUI->do_char(pC, pEvent); // treat tab like normal char
1714  }
1715  else
1716  {
1717  XBell(pDisplay, -100);
1718  }
1719 
1720  iRval = 1;
1721  }
1722  else if(iKey == 1) // CTRL+A
1723  {
1724  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_Keyboard,
1725  "%s - CTRL+A key pressed, iACS=%d (%xH)\n", __FUNCTION__, iACS, iACS);
1726 
1727  if((iACS & WB_KEYEVENT_ACSMASK) == WB_KEYEVENT_CTRL) // control key will always be pressed, but no shift
1728  {
1729  if(pUI->select_all)
1730  {
1731  pUI->select_all(pC);
1732  }
1733  else
1734  {
1735  XBell(pDisplay, -100);
1736  }
1737 
1738  iRval = 1;
1739  }
1740  else
1741  {
1742  if(pUI->do_char)
1743  {
1744  pUI->do_char(pC, pEvent); // normal 'A' character
1745 
1746  iRval = 1;
1747  }
1748  }
1749  }
1750  else if(iKey == 3) // CTRL+C
1751  {
1752  if((iACS & WB_KEYEVENT_ACSMASK) == WB_KEYEVENT_CTRL) // control key will always be pressed, but no shift
1753  {
1754  if(pUI->has_selection && pUI->copy_to_cb && pUI->has_selection(pC))
1755  {
1756  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_Clipboard | DebugSubSystem_Keyboard,
1757  "%s - CTRL+C key pressed, iACS=%d (%xH)\n", __FUNCTION__, iACS, iACS);
1758 
1759  pUI->copy_to_cb(pC);
1760  }
1761  else
1762  {
1763  XBell(pDisplay, -100);
1764  WB_DEBUG_PRINT(DebugLevel_Light | DebugSubSystem_Event | DebugSubSystem_Clipboard | DebugSubSystem_Keyboard,
1765  "%s.%d - no selection, can't 'COPY'\n", __FUNCTION__, __LINE__);
1766  }
1767 
1768  iRval = 1;
1769  }
1770  else
1771  {
1772  if(pUI->do_char)
1773  {
1774  pUI->do_char(pC, pEvent); // normal 'C' character
1775 
1776  iRval = 1;
1777  }
1778  }
1779  }
1780  else if(iKey == 22) // CTRL+V
1781  {
1782  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_Clipboard | DebugSubSystem_Keyboard,
1783  "%s - CTRL+V key pressed, iACS=%d (%xH)\n", __FUNCTION__, iACS, iACS);
1784 
1785  if((iACS & WB_KEYEVENT_ACSMASK) == WB_KEYEVENT_CTRL) // control key will always be pressed, but no shift
1786  {
1787  // TODO: check for valid clipboard selection - see if there's a clipboard owner maybe?
1788 
1789  if(pUI->paste_from_cb)
1790  {
1791  pUI->paste_from_cb(pC);
1792  }
1793 
1794  iRval = 1;
1795  }
1796  else
1797  {
1798  if(pUI->do_char)
1799  {
1800  pUI->do_char(pC, pEvent); // normal 'V' character
1801 
1802  iRval = 1;
1803  }
1804  }
1805  }
1806  else if(iKey == 24) // CTRL+X
1807  {
1808  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_Keyboard,
1809  "%s - CTRL+X key pressed, iACS=%d (%xH)\n", __FUNCTION__, iACS, iACS);
1810 
1811  if((iACS & WB_KEYEVENT_ACSMASK) == WB_KEYEVENT_CTRL) // control key will always be pressed, but no shift
1812  {
1813  if(pUI->has_selection && pUI->cut_to_cb && pUI->has_selection(pC))
1814  {
1815  pUI->cut_to_cb(pC);
1816  }
1817  else
1818  {
1819  XBell(pDisplay, -100);
1820  }
1821 
1822  iRval = 1;
1823  }
1824  else
1825  {
1826  if(pUI->do_char)
1827  {
1828  pUI->do_char(pC, pEvent); // normal 'X' character
1829 
1830  iRval = 1;
1831  }
1832  }
1833  }
1834  else if(iKey == 26) // ctrl+Z
1835  {
1836  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_Keyboard,
1837  "%s - CTRL+Z key pressed, iACS=%d (%xH)\n", __FUNCTION__, iACS, iACS);
1838 
1839  if((iACS & WB_KEYEVENT_ACSMASK) == WB_KEYEVENT_CTRL) // control key will always be pressed, but no shift
1840  {
1841  if(pUI->can_undo && pUI->undo && pUI->can_undo(pC))
1842  {
1843  pUI->undo(pC);
1844  }
1845  else
1846  {
1847  XBell(pDisplay, -100);
1848  }
1849 
1850  iRval = 1;
1851  }
1852  else if((iACS & WB_KEYEVENT_ACSMASK) == (WB_KEYEVENT_CTRL | WB_KEYEVENT_SHIFT)) // ctrl+shift, no alt
1853  {
1854  if(pUI->can_redo && pUI->redo && pUI->can_redo(pC))
1855  {
1856  pUI->redo(pC);
1857  }
1858  else
1859  {
1860  XBell(pDisplay, -100);
1861  }
1862 
1863  iRval = 1;
1864  }
1865  else
1866  {
1867  if(pUI->do_char)
1868  {
1869  pUI->do_char(pC, pEvent); // normal 'Z' character
1870 
1871  iRval = 1; // "handled"
1872  }
1873 
1874  // ONLY assign 'iRval' if the character was processed
1875  }
1876 
1877  // NOT assigning 'iRval' for all conditions here...
1878  }
1879  else if(iKey == '\x1b') // ESC
1880  {
1881  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_Keyboard,
1882  "%s - ESC key pressed, iACS=%d (%xH)\n", __FUNCTION__, iACS, iACS);
1883 
1884  // cancel mousie things and 'select none'
1885 
1886  if(pUI->mouse_cancel)
1887  {
1888  pUI->mouse_cancel(pC);
1889  }
1890 
1891  if(pUI->select_none)
1892  {
1893  pUI->select_none(pC);
1894  }
1895 
1896  if(!pUI->select_none && !pUI->mouse_cancel)
1897  {
1898  XBell(pDisplay, -100);
1899  }
1900 
1901  iRval = 1;
1902  }
1903  else
1904  {
1905  if(pUI->do_char)
1906  {
1907  pUI->do_char(pC, pEvent);
1908 
1909  iRval = 1; // "handled"
1910  }
1911 
1912  // NOTE: don't call 'XBell' if I don't return "handled", and no 'do_char' means "not handled"
1913  }
1914  }
1915  else // SPECIAL characters.
1916  {
1917  if(iACS & WB_KEYEVENT_KEYSYM)
1918  {
1919  // TODO: international, 'dead' and other KEYSYM key assignments
1920 #define KEYSYM_MATCH_CURSOR_NAME(X) (iKey == XK_##X || iKey == XK_KP_##X)
1921 
1922  if(KEYSYM_MATCH_CURSOR_NAME(Home))
1923  {
1924  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_Keyboard,
1925  "%s - Home key pressed iACS=%d (%08xH)\n", __FUNCTION__, iACS, iACS);
1926 
1927  if(pUI->home)
1928  {
1929  pUI->home(pC, iACS);
1930  }
1931 
1932  iRval = 1;
1933  }
1934  else if(KEYSYM_MATCH_CURSOR_NAME(End))
1935  {
1936  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_Keyboard,
1937  "%s - End key pressed iACS=%d (%08xH)\n", __FUNCTION__, iACS, iACS);
1938 
1939  if(pUI->end)
1940  {
1941  pUI->end(pC, iACS);
1942  }
1943 
1944  iRval = 1;
1945  }
1946  else if(KEYSYM_MATCH_CURSOR_NAME(Left))
1947  {
1948  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_Keyboard,
1949  "%s - Left key pressed iACS=%d (%08xH)\n", __FUNCTION__, iACS, iACS);
1950 
1951  if(pUI->leftarrow)
1952  {
1953  pUI->leftarrow(pC, iACS);
1954  }
1955 
1956  iRval = 1;
1957  }
1958  else if(KEYSYM_MATCH_CURSOR_NAME(Right))
1959  {
1960  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_Keyboard,
1961  "%s - Right key pressed iACS=%d (%08xH)\n", __FUNCTION__, iACS, iACS);
1962 
1963  if(pUI->rightarrow)
1964  {
1965  pUI->rightarrow(pC, iACS);
1966  }
1967 
1968  iRval = 1;
1969  }
1970  else if(KEYSYM_MATCH_CURSOR_NAME(Up))
1971  {
1972  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_Keyboard,
1973  "%s - Up key pressed iACS=%d (%08xH)\n", __FUNCTION__, iACS, iACS);
1974 
1975  if(pUI->uparrow)
1976  {
1977  pUI->uparrow(pC, iACS);
1978  }
1979 
1980  iRval = 1;
1981  }
1982  else if(KEYSYM_MATCH_CURSOR_NAME(Down))
1983  {
1984  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_Keyboard,
1985  "%s - Down key pressed iACS=%d (%08xH)\n", __FUNCTION__, iACS, iACS);
1986 
1987  if(pUI->downarrow)
1988  {
1989  pUI->downarrow(pC, iACS);
1990  }
1991  else
1992  {
1993  XBell(pDisplay, -100);
1994  }
1995 
1996  iRval = 1;
1997  }
1998  else if(KEYSYM_MATCH_CURSOR_NAME(Page_Up))
1999  {
2000  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_Keyboard,
2001  "%s - Page Up key pressed iACS=%d (%08xH)\n", __FUNCTION__, iACS, iACS);
2002 
2003  if(iACS & WB_KEYEVENT_CTRL) // page left
2004  {
2005  if(pUI->pgleft)
2006  {
2007  pUI->pgleft(pC, iACS /* & ~WB_KEYEVENT_CTRL */); // TODO: turn off 'ctrl' bit?
2008  }
2009  else
2010  {
2011  XBell(pDisplay, -100);
2012  }
2013 
2014  iRval = 1;
2015  }
2016  else
2017  {
2018  if(pUI->pgup)
2019  {
2020  pUI->pgup(pC, iACS);
2021  }
2022  else
2023  {
2024  XBell(pDisplay, -100);
2025  }
2026 
2027  iRval = 1;
2028  }
2029  }
2030  else if(KEYSYM_MATCH_CURSOR_NAME(Page_Down))
2031  {
2032  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_Keyboard,
2033  "%s - Page Down key pressed iACS=%d (%08xH)\n", __FUNCTION__, iACS, iACS);
2034 
2035  if(iACS & WB_KEYEVENT_CTRL) // page right
2036  {
2037  if(pUI->pgright)
2038  {
2039  pUI->pgright(pC, iACS /* & ~WB_KEYEVENT_CTRL */); // TODO: turn off 'ctrl' bit?
2040  }
2041  else
2042  {
2043  XBell(pDisplay, -100);
2044  }
2045 
2046  iRval = 1;
2047  }
2048  else
2049  {
2050  if(pUI->pgdown)
2051  {
2052  pUI->pgdown(pC, iACS);
2053  }
2054  else
2055  {
2056  XBell(pDisplay, -100);
2057  }
2058 
2059  iRval = 1;
2060  }
2061  }
2062  else if(KEYSYM_MATCH_CURSOR_NAME(Begin)) // beginning of current line
2063  {
2064  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_Keyboard,
2065  "%s - Beginning Of Line key pressed iACS=%d (%08xH)\n", __FUNCTION__, iACS, iACS);
2066 
2067  // treat this as 'home' key
2068 
2069  if((iACS & WB_KEYEVENT_ACSMASK) == WB_KEYEVENT_SHIFT) // shift
2070  {
2071  if(pUI->home)
2072  {
2073  pUI->home(pC, WB_KEYEVENT_SHIFT);
2074  }
2075  else
2076  {
2077  XBell(pDisplay, -100);
2078  }
2079 
2080  iRval = 1;
2081  }
2082  else if((iACS & WB_KEYEVENT_ACSMASK) == 0) // normal
2083  {
2084  if(pUI->home)
2085  {
2086  pUI->home(pC, iACS);
2087  }
2088  else
2089  {
2090  XBell(pDisplay, -100);
2091  }
2092 
2093  iRval = 1;
2094  }
2095  }
2096  else if(KEYSYM_MATCH_CURSOR_NAME(Insert)) // toggle 'insert' mode, copy, or paste
2097  {
2098  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_Keyboard,
2099  "%s - Insert key pressed iACS=%d (%08xH)\n", __FUNCTION__, iACS, iACS);
2100 
2101  if((iACS & WB_KEYEVENT_ACSMASK) == 0) // normal
2102  {
2103  if(pUI->toggle_ins_mode)
2104  {
2105  pUI->toggle_ins_mode(pC);
2106 
2107  // TODO: update status bar text
2108  }
2109  else
2110  {
2111  XBell(pDisplay, -100);
2112  }
2113 
2114  iRval = 1;
2115  }
2116  else if((iACS & WB_KEYEVENT_ACSMASK) == WB_KEYEVENT_SHIFT) // SHIFT+insert (paste)
2117  {
2118  if(pUI->paste_from_cb)
2119  {
2120  pUI->paste_from_cb(pC);
2121  }
2122  else
2123  {
2124  XBell(pDisplay, -100);
2125  }
2126 
2127  iRval = 1;
2128  }
2129  else if((iACS & WB_KEYEVENT_ACSMASK) == WB_KEYEVENT_CTRL) // CTRL+insert (copy)
2130  {
2131  if(pUI->has_selection && pUI->copy_to_cb && pUI->has_selection(pC))
2132  {
2133  pUI->copy_to_cb(pC);
2134  }
2135  else
2136  {
2137  XBell(pDisplay, -100);
2138  }
2139 
2140  iRval = 1;
2141  }
2142  }
2143  else if(KEYSYM_MATCH_CURSOR_NAME(Delete)) // delete key (keypad may use this)
2144  {
2145  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_Keyboard,
2146  "%s - Delete key pressed iACS=%d (%08xH)\n", __FUNCTION__, iACS, iACS);
2147 
2148  if((iACS & WB_KEYEVENT_ACSMASK) == WB_KEYEVENT_SHIFT) // shift+del (cut)
2149  {
2150  if(pUI->has_selection && pUI->cut_to_cb && pUI->has_selection(pC))
2151  {
2152  pUI->cut_to_cb(pC);
2153  }
2154  else
2155  {
2156  XBell(pDisplay, -100);
2157  }
2158 
2159  iRval = 1;
2160  }
2161  else if(iACS & WB_KEYEVENT_CTRL) // ctrl+del (??) alt+del (??) any other combo?
2162  {
2163  if(pUI->del)
2164  {
2165  pUI->del(pC, iACS);
2166  }
2167  else
2168  {
2169  XBell(pDisplay, -100);
2170  }
2171 
2172  iRval = 1; // for now handle it THIS way
2173  }
2174  else // if((iACS & WB_KEYEVENT_ACSMASK) == 0) // normal or "other flags"
2175  {
2176  if(pUI->del)
2177  {
2178  pUI->del(pC, iACS);
2179  }
2180  else
2181  {
2182  XBell(pDisplay, -100);
2183  }
2184 
2185  iRval = 1;
2186  }
2187  }
2188 #undef KEYSYM_MATCH_CURSOR_NAME
2189  else
2190  {
2191  if(pUI->scancode)
2192  {
2193  pUI->scancode(pC, pEvent);
2194 
2195  iRval = 1; // handled
2196  }
2197  else
2198  {
2199  // is it an unknown cursor key? let's find out (dump it)
2200  WB_DEBUG_PRINT(DebugLevel_WARN | DebugSubSystem_Event | DebugSubSystem_Keyboard,
2201  "%s - CURSOR KEY? %d (%08xH) %d (%08xH)\n",
2202  __FUNCTION__, iKey, iKey, iACS, iACS);
2203 
2204  // 'iRval' left at 0 for "not handled"
2205  }
2206  }
2207  }
2208  }
2209 
2210  return 0; // "not handled"
2211 }
2212 
2213 
2214 
2215 static int ChildFrameEditCutHandler(XClientMessageEvent *pEvent)
2216 {
2217 WBChildFrame *pChildFrame;
2218 WBFrameWindow *pFrame;
2219 
2220 
2221  if(!pEvent || pEvent->window == None)
2222  {
2223  WB_ERROR_PRINT("ERROR: %s bad window or event\n", __FUNCTION__);
2224  return -1; // an error
2225  }
2226 
2227  pFrame = FWGetFrameWindowStruct(pEvent->window);
2228 
2229  if(!pFrame)
2230  {
2231  WB_ERROR_PRINT("ERROR: %s bad window (not frame window)\n", __FUNCTION__);
2232  return -1; // an error
2233  }
2234 
2235  pChildFrame = FWGetContainedWindowByIndex(pFrame, -1); // current focus window
2236 
2237  if(!pChildFrame)
2238  {
2239  WB_ERROR_PRINT("ERROR: %s - no child frame has focus\n", __FUNCTION__);
2240  return -1; // an error
2241  }
2242 
2243  if(pChildFrame->pUI && pChildFrame->pUI->has_selection && pChildFrame->pUI->cut_to_cb)
2244  {
2245  if(pChildFrame->pUI->has_selection(pChildFrame))
2246  {
2247  pChildFrame->pUI->cut_to_cb(pChildFrame);
2248 
2249  return 1; // HANDLED
2250  }
2251  }
2252 
2253  return 0; // NOT handled (but not an error)
2254 }
2255 
2256 static int ChildFrameEditCopyHandler(XClientMessageEvent *pEvent)
2257 {
2258 WBChildFrame *pChildFrame;
2259 WBFrameWindow *pFrame;
2260 
2261 
2262  if(!pEvent || pEvent->window == None)
2263  {
2264  WB_ERROR_PRINT("ERROR: %s bad window or event\n", __FUNCTION__);
2265  return -1; // an error
2266  }
2267 
2268  pFrame = FWGetFrameWindowStruct(pEvent->window);
2269 
2270  if(!pFrame)
2271  {
2272  WB_ERROR_PRINT("ERROR: %s bad window (not frame window)\n", __FUNCTION__);
2273  return -1; // an error
2274  }
2275 
2276  pChildFrame = FWGetContainedWindowByIndex(pFrame, -1); // current focus window
2277 
2278  if(!pChildFrame)
2279  {
2280  WB_ERROR_PRINT("ERROR: %s - no child frame has focus\n", __FUNCTION__);
2281  return -1; // an error
2282  }
2283 
2284  if(pChildFrame->pUI && pChildFrame->pUI->has_selection && pChildFrame->pUI->copy_to_cb)
2285  {
2286  if(pChildFrame->pUI->has_selection(pChildFrame))
2287  {
2288  pChildFrame->pUI->copy_to_cb(pChildFrame);
2289 
2290  return 1; // HANDLED
2291  }
2292  }
2293 
2294  return 0; // NOT handled (but not an error)
2295 }
2296 
2297 static int ChildFrameEditPasteHandler(XClientMessageEvent *pEvent)
2298 {
2299 WBChildFrame *pChildFrame;
2300 WBFrameWindow *pFrame;
2301 
2302 
2303  if(!pEvent || pEvent->window == None)
2304  {
2305  WB_ERROR_PRINT("ERROR: %s bad window or event\n", __FUNCTION__);
2306  return -1; // an error
2307  }
2308 
2309  pFrame = FWGetFrameWindowStruct(pEvent->window);
2310 
2311  if(!pFrame)
2312  {
2313  WB_ERROR_PRINT("ERROR: %s bad window (not frame window)\n", __FUNCTION__);
2314  return -1; // an error
2315  }
2316 
2317  pChildFrame = FWGetContainedWindowByIndex(pFrame, -1); // current focus window
2318 
2319  if(!pChildFrame)
2320  {
2321  WB_ERROR_PRINT("ERROR: %s - no child frame has focus\n", __FUNCTION__);
2322  return -1; // an error
2323  }
2324 
2325  if(pChildFrame->pUI && pChildFrame->pUI->paste_from_cb)
2326  {
2327  // TODO: check for valid clipboard contents first?? or assume 'NULL' is ok?
2328 
2329  pChildFrame->pUI->paste_from_cb(pChildFrame);
2330 
2331  return 1; // HANDLED
2332  }
2333 
2334  return 0; // NOT handled (but not an error)
2335 }
2336 
2337 static int ChildFrameEditDeleteHandler(XClientMessageEvent *pEvent)
2338 {
2339 WBChildFrame *pChildFrame;
2340 WBFrameWindow *pFrame;
2341 
2342 
2343  if(!pEvent || pEvent->window == None)
2344  {
2345  WB_ERROR_PRINT("ERROR: %s bad window or event\n", __FUNCTION__);
2346  return -1; // an error
2347  }
2348 
2349  pFrame = FWGetFrameWindowStruct(pEvent->window);
2350 
2351  if(!pFrame)
2352  {
2353  WB_ERROR_PRINT("ERROR: %s bad window (not frame window)\n", __FUNCTION__);
2354  return -1; // an error
2355  }
2356 
2357  pChildFrame = FWGetContainedWindowByIndex(pFrame, -1); // current focus window
2358 
2359  if(!pChildFrame)
2360  {
2361  WB_ERROR_PRINT("ERROR: %s - no child frame has focus\n", __FUNCTION__);
2362  return -1; // an error
2363  }
2364 
2365  if(pChildFrame->pUI && pChildFrame->pUI->has_selection && pChildFrame->pUI->delete_sel)
2366  {
2367  if(pChildFrame->pUI->has_selection(pChildFrame))
2368  {
2369  pChildFrame->pUI->delete_sel(pChildFrame);
2370 
2371  return 1; // HANDLED
2372  }
2373  }
2374 
2375  return 0; // NOT handled (but not an error)
2376 }
2377 
2378 static int ChildFrameEditSelectAllHandler(XClientMessageEvent *pEvent)
2379 {
2380 WBChildFrame *pChildFrame;
2381 WBFrameWindow *pFrame;
2382 
2383 
2384  if(!pEvent || pEvent->window == None)
2385  {
2386  WB_ERROR_PRINT("ERROR: %s bad window or event\n", __FUNCTION__);
2387  return -1; // an error
2388  }
2389 
2390  pFrame = FWGetFrameWindowStruct(pEvent->window);
2391 
2392  if(!pFrame)
2393  {
2394  WB_ERROR_PRINT("ERROR: %s bad window (not frame window)\n", __FUNCTION__);
2395  return -1; // an error
2396  }
2397 
2398  pChildFrame = FWGetContainedWindowByIndex(pFrame, -1); // current focus window
2399 
2400  if(!pChildFrame)
2401  {
2402  WB_ERROR_PRINT("ERROR: %s - no child frame has focus\n", __FUNCTION__);
2403  return -1; // an error
2404  }
2405 
2406  if(pChildFrame->pUI && pChildFrame->pUI->select_all)
2407  {
2408  pChildFrame->pUI->select_all(pChildFrame);
2409 
2410  return 1; // HANDLED
2411  }
2412 
2413  WB_ERROR_PRINT("NOT HANDLED: %s - pChildFrame->pUI = %p, select_all = %p\n",
2414  __FUNCTION__, pChildFrame->pUI,
2415  (void *)(pChildFrame->pUI ? pChildFrame->pUI->select_all : NULL));
2416 
2417  return 0; // NOT handled (but not an error)
2418 }
2419 
2420 static int ChildFrameEditSelectNoneHandler(XClientMessageEvent *pEvent)
2421 {
2422 WBChildFrame *pChildFrame;
2423 WBFrameWindow *pFrame;
2424 
2425 
2426  if(!pEvent || pEvent->window == None)
2427  {
2428  WB_ERROR_PRINT("ERROR: %s bad window or event\n", __FUNCTION__);
2429  return -1; // an error
2430  }
2431 
2432  pFrame = FWGetFrameWindowStruct(pEvent->window);
2433 
2434  if(!pFrame)
2435  {
2436  WB_ERROR_PRINT("ERROR: %s bad window (not frame window)\n", __FUNCTION__);
2437  return -1; // an error
2438  }
2439 
2440  pChildFrame = FWGetContainedWindowByIndex(pFrame, -1); // current focus window
2441 
2442  if(!pChildFrame)
2443  {
2444  WB_ERROR_PRINT("ERROR: %s - no child frame has focus\n", __FUNCTION__);
2445  return -1; // an error
2446  }
2447 
2448  if(pChildFrame->pUI && pChildFrame->pUI->select_none)
2449  {
2450  pChildFrame->pUI->select_none(pChildFrame);
2451 
2452  return 1; // HANDLED
2453  }
2454 
2455  WB_ERROR_PRINT("NOT HANDLED: %s - pChildFrame->pUI = %p, select_none = %p\n",
2456  __FUNCTION__, pChildFrame->pUI,
2457  (void *)(pChildFrame->pUI ? pChildFrame->pUI->select_none : NULL));
2458 
2459  return 0; // NOT handled (but not an error)
2460 }
2461 
2462 static int ChildFrameEditCutUIHandler(WBMenu *pMenu, WBMenuItem *pMenuItem)
2463 {
2464 Window wID;
2465 WBChildFrame *pChildFrame;
2466 WBFrameWindow *pFrame;
2467 WBMenuPopupWindow *pPopup;
2468 
2469 
2470  // pMenu essentially belongs to the frame window. determine which tab has focus, and whether
2471  // or not there's anything selected. if there is something selected, enable the menu.
2472  //
2473  // NOTE: this is called by the popup menu window itself, and so the pointer will not
2474  // be asynchronously destroyed when I call MBFindMenuPopupWindow(), nor will
2475  // the owning frame window be destroyed, either (unless someone seriously
2476  // violated the way these things are supposed to work).
2477 
2478  pPopup = MBFindMenuPopupWindow(pMenu);
2479 
2480  if(pPopup)
2481  {
2482  wID = pPopup->wOwner;
2483 
2484  if(wID != None)
2485  {
2486  pFrame = FWGetFrameWindowStruct(wID);
2487 
2488  if(pFrame)
2489  {
2490  pChildFrame = FWGetContainedWindowByIndex(pFrame, -1); // current focus window
2491 
2492  if(pChildFrame && pChildFrame->pUI && pChildFrame->pUI->has_selection)
2493  {
2494  if(pChildFrame->pUI->has_selection(pChildFrame))
2495  {
2496  return 1; // select this
2497  }
2498  }
2499  }
2500  }
2501  }
2502 
2503  return -1; // disable this menu
2504 }
2505 
2506 static int ChildFrameEditCopyUIHandler(WBMenu *pMenu, WBMenuItem *pMenuItem)
2507 {
2508 Window wID;
2509 WBChildFrame *pChildFrame;
2510 WBFrameWindow *pFrame;
2511 WBMenuPopupWindow *pPopup;
2512 
2513 
2514  // pMenu essentially belongs to the frame window. determine which tab has focus, and whether
2515  // or not there's anything selected. if there is something selected, enable the menu.
2516  //
2517  // NOTE: this is called by the popup menu window itself, and so the pointer will not
2518  // be asynchronously destroyed when I call MBFindMenuPopupWindow(), nor will
2519  // the owning frame window be destroyed, either (unless someone seriously
2520  // violated the way these things are supposed to work).
2521 
2522  pPopup = MBFindMenuPopupWindow(pMenu);
2523 
2524  if(pPopup)
2525  {
2526  wID = pPopup->wOwner;
2527 
2528  if(wID != None)
2529  {
2530  pFrame = FWGetFrameWindowStruct(wID);
2531 
2532  if(pFrame)
2533  {
2534  pChildFrame = FWGetContainedWindowByIndex(pFrame, -1); // current focus window
2535 
2536  if(pChildFrame && pChildFrame->pUI && pChildFrame->pUI->has_selection)
2537  {
2538  if(pChildFrame->pUI->has_selection(pChildFrame))
2539  {
2540  return 1; // select this
2541  }
2542  }
2543  }
2544  }
2545  }
2546 
2547  return -1; // disable this menu
2548 }
2549 
2550 static int ChildFrameEditPasteUIHandler(WBMenu *pMenu, WBMenuItem *pMenuItem)
2551 {
2552 Window wID;
2553 WBChildFrame *pChildFrame;
2554 WBFrameWindow *pFrame;
2555 WBMenuPopupWindow *pPopup;
2556 Display *pDisplay;
2557 
2558  // pMenu essentially belongs to the frame window. determine which tab has focus
2559  // THEN, determine if there's a clipboard owner, and enable if so. Disable if there
2560  // are no child frames with the focus or clipboard owners
2561  //
2562  // NOTE: this is called by the popup menu window itself, and so the pointer will not
2563  // be asynchronously destroyed when I call MBFindMenuPopupWindow(), nor will
2564  // the owning frame window be destroyed, either (unless someone seriously
2565  // violated the way these things are supposed to work).
2566 
2567  pPopup = MBFindMenuPopupWindow(pMenu);
2568 
2569  if(pPopup)
2570  {
2571  wID = pPopup->wOwner;
2572 
2573  if(wID != None)
2574  {
2575  pDisplay = WBGetWindowDisplay(wID);
2576  pFrame = FWGetFrameWindowStruct(wID);
2577 
2578  if(pFrame)
2579  {
2580  pChildFrame = FWGetContainedWindowByIndex(pFrame, -1); // current focus window
2581 
2582  if(pChildFrame && pChildFrame->pUI)
2583  {
2584  if(XGetSelectionOwner(pDisplay, aCLIPBOARD) != None ||
2585  XGetSelectionOwner(pDisplay, aPRIMARY) != None)
2586  {
2587  return 1; // there's a clipboard selection out there, waiting to be pasted
2588  }
2589  }
2590  }
2591  }
2592  }
2593 
2594  return -1; // disable this menu
2595 
2596 }
2597 
2598 static int ChildFrameEditDeleteUIHandler(WBMenu *pMenu, WBMenuItem *pMenuItem)
2599 {
2600 Window wID;
2601 WBChildFrame *pChildFrame;
2602 WBFrameWindow *pFrame;
2603 WBMenuPopupWindow *pPopup;
2604 
2605 
2606  // pMenu essentially belongs to the frame window. determine which tab has focus, and whether
2607  // or not there's anything selected. if there is something selected, enable the menu.
2608  //
2609  // NOTE: this is called by the popup menu window itself, and so the pointer will not
2610  // be asynchronously destroyed when I call MBFindMenuPopupWindow(), nor will
2611  // the owning frame window be destroyed, either (unless someone seriously
2612  // violated the way these things are supposed to work).
2613 
2614  pPopup = MBFindMenuPopupWindow(pMenu);
2615 
2616  if(pPopup)
2617  {
2618  wID = pPopup->wOwner;
2619 
2620  if(wID != None)
2621  {
2622  pFrame = FWGetFrameWindowStruct(wID);
2623 
2624  if(pFrame)
2625  {
2626  pChildFrame = FWGetContainedWindowByIndex(pFrame, -1); // current focus window
2627 
2628  if(pChildFrame && pChildFrame->pUI && pChildFrame->pUI->has_selection)
2629  {
2630  if(pChildFrame->pUI->has_selection(pChildFrame))
2631  {
2632  return 1; // select this
2633  }
2634  }
2635  }
2636  }
2637  }
2638 
2639  return -1; // disable this menu
2640 }
2641 
2642 static int ChildFrameEditSelectAllUIHandler(WBMenu *pMenu, WBMenuItem *pMenuItem)
2643 {
2644 Window wID;
2645 WBChildFrame *pChildFrame;
2646 WBFrameWindow *pFrame;
2647 WBMenuPopupWindow *pPopup;
2648 
2649 
2650  // pMenu essentially belongs to the frame window. determine which tab has focus, and whether
2651  // or not there's anything there. if there is something that CAN be selected, enable the menu.
2652  //
2653  // NOTE: this is called by the popup menu window itself, and so the pointer will not
2654  // be asynchronously destroyed when I call MBFindMenuPopupWindow(), nor will
2655  // the owning frame window be destroyed, either (unless someone seriously
2656  // violated the way these things are supposed to work).
2657 
2658  pPopup = MBFindMenuPopupWindow(pMenu);
2659 
2660  if(!pPopup)
2661  {
2662  WB_ERROR_PRINT("ERROR: %s no popup for menu %p\n", __FUNCTION__, pMenu);
2663  }
2664  else
2665  {
2666  wID = pPopup->wOwner;
2667 
2668  if(wID == None)
2669  {
2670  WB_ERROR_PRINT("ERROR: %s no owner for popup menu %p\n", __FUNCTION__, pPopup);
2671  }
2672  else
2673  {
2674  pFrame = FWGetFrameWindowStruct(wID);
2675 
2676  if(!pFrame)
2677  {
2678  WB_ERROR_PRINT("ERROR: %s no frame for window %u (%08xH)\n", __FUNCTION__, (unsigned int)wID, (unsigned int)wID);
2679  }
2680  else
2681  {
2682  pChildFrame = FWGetContainedWindowByIndex(pFrame, -1); // current focus window
2683 
2684  if(!pChildFrame || !pChildFrame->pUI)
2685  {
2686  WB_ERROR_PRINT("ERROR: %s no child frame %p or UI %p\n", __FUNCTION__,
2687  pChildFrame, pChildFrame ? pChildFrame->pUI : NULL);
2688  }
2689  else
2690  {
2691  if((pChildFrame->pUI->has_selection && pChildFrame->pUI->has_selection(pChildFrame)) ||
2692  (pChildFrame->pUI->is_empty && !pChildFrame->pUI->is_empty(pChildFrame)))
2693  {
2694  return 1; // select this
2695  }
2696  else
2697  {
2698  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Clipboard,
2699  "%s - no selection or is empty\n", __FUNCTION__);
2700 
2701  return -1;
2702  }
2703  }
2704  }
2705  }
2706  }
2707 
2708  return -1; // disable this menu
2709 }
2710 
2711 static int ChildFrameEditSelectNoneUIHandler(WBMenu *pMenu, WBMenuItem *pMenuItem)
2712 {
2713 Window wID;
2714 WBChildFrame *pChildFrame;
2715 WBFrameWindow *pFrame;
2716 WBMenuPopupWindow *pPopup;
2717 
2718 
2719  // pMenu essentially belongs to the frame window. determine which tab has focus, and whether
2720  // or not there's anything selected. if there is something selected, enable the menu.
2721  //
2722  // NOTE: this is called by the popup menu window itself, and so the pointer will not
2723  // be asynchronously destroyed when I call MBFindMenuPopupWindow(), nor will
2724  // the owning frame window be destroyed, either (unless someone seriously
2725  // violated the way these things are supposed to work).
2726 
2727  pPopup = MBFindMenuPopupWindow(pMenu);
2728 
2729  if(pPopup)
2730  {
2731  wID = pPopup->wOwner;
2732 
2733  if(wID != None)
2734  {
2735  pFrame = FWGetFrameWindowStruct(wID);
2736 
2737  if(pFrame)
2738  {
2739  pChildFrame = FWGetContainedWindowByIndex(pFrame, -1); // current focus window
2740 
2741  if(pChildFrame && pChildFrame->pUI && pChildFrame->pUI->has_selection)
2742  {
2743  if(pChildFrame->pUI->has_selection(pChildFrame))
2744  {
2745  return 1; // select this
2746  }
2747  else
2748  {
2749  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Clipboard,
2750  "%s - no selection\n", __FUNCTION__);
2751 
2752  return -1;
2753  }
2754  }
2755  }
2756  }
2757  }
2758 
2759  return -1; // disable this menu
2760 }
2761 
2762 
2763 
2764 
2765 static int ChildFrameEditPropertiesHandler(XClientMessageEvent *pEvent)
2766 {
2767 WBChildFrame *pChildFrame;
2768 WBFrameWindow *pFrame;
2769 
2770 
2771  if(!pEvent || pEvent->window == None)
2772  {
2773  WB_ERROR_PRINT("ERROR: %s bad window or event\n", __FUNCTION__);
2774  return -1; // an error
2775  }
2776 
2777  pFrame = FWGetFrameWindowStruct(pEvent->window);
2778 
2779  if(!pFrame)
2780  {
2781  WB_ERROR_PRINT("ERROR: %s bad window (not frame window)\n", __FUNCTION__);
2782  return -1; // an error
2783  }
2784 
2785  pChildFrame = FWGetContainedWindowByIndex(pFrame, -1); // current focus window
2786 
2787  if(!pChildFrame)
2788  {
2789  WB_ERROR_PRINT("ERROR: %s - no child frame has focus\n", __FUNCTION__);
2790  return -1; // an error
2791  }
2792 
2793  if(pChildFrame->pUI && pChildFrame->pUI->properties)
2794  {
2795  pChildFrame->pUI->properties(pChildFrame);
2796 
2797  return 1; // HANDLED
2798  }
2799 
2800  WB_ERROR_PRINT("NOT HANDLED: %s - pChildFrame->pUI = %p, properties = %p\n",
2801  __FUNCTION__, pChildFrame->pUI,
2802  (void *)(pChildFrame->pUI ? pChildFrame->pUI->select_all : NULL));
2803 
2804  return 0; // NOT handled (but not an error)
2805 }
2806 
2807 static int ChildFrameEditPropertiesUIHandler(WBMenu *pMenu, WBMenuItem *pMenuItem)
2808 {
2809 Window wID;
2810 WBChildFrame *pChildFrame;
2811 WBFrameWindow *pFrame;
2812 WBMenuPopupWindow *pPopup;
2813 
2814 
2815  // pMenu essentially belongs to the frame window. determine which tab has focus, and whether
2816  // or not there's anything selected. if there is something selected, enable the menu.
2817  //
2818  // NOTE: this is called by the popup menu window itself, and so the pointer will not
2819  // be asynchronously destroyed when I call MBFindMenuPopupWindow(), nor will
2820  // the owning frame window be destroyed, either (unless someone seriously
2821  // violated the way these things are supposed to work).
2822 
2823  pPopup = MBFindMenuPopupWindow(pMenu);
2824 
2825  if(pPopup)
2826  {
2827  wID = pPopup->wOwner;
2828 
2829  if(wID != None)
2830  {
2831  pFrame = FWGetFrameWindowStruct(wID);
2832 
2833  if(pFrame)
2834  {
2835  pChildFrame = FWGetContainedWindowByIndex(pFrame, -1); // current focus window
2836 
2837 // if(pChildFrame && pChildFrame->pUI && pChildFrame->pUI->properties)
2838  {
2839  return 1; // select this
2840  }
2841  }
2842  }
2843  }
2844 
2845  return -1; // disable this menu
2846 }
2847 
void(* pgleft)(WBChildFrame *, int iACS)
'page left' navigation.
Definition: frame_window.h:695
int iFlags
bitmask of attribute flags (see WBFrameWindow_FLAGS enumeration)
Definition: frame_window.h:278
Window wID
Window id for the frame window.
Definition: frame_window.h:277
structure for managing menu items
Definition: menu.h:127
Atom aPRIMARY
PRIMARY Atom for the clipboard - uses XA_PRIMARY.
2nd parameter (direction) - up, left
WBWinEvent pUserCallback
message callback function pointer (can be NULL)
Definition: frame_window.h:458
Atom aMENU_UI_COMMAND
UI notifications sent by menus to owning Frame windows via ClientMessage using 'WBWindowDispatch'.
void(* home)(WBChildFrame *, int iACS)
'home' arrow navigation.
Definition: frame_window.h:691
set this to disable tabs (single child frame only)
Definition: frame_window.h:300
void(* scancode)(WBChildFrame *, XClientMessageEvent *)
handler for 'other scan code' WB_CHAR Client Messages.
Definition: frame_window.h:681
int iClientY
The current Y position of the frame window's client area (relative to the window)
Definition: frame_window.h:281
void(* leftarrow)(WBChildFrame *, int iACS)
'left' arrow navigation.
Definition: frame_window.h:689
#define WB_POINTER_DBLCLICK
WB_POINTER 'double-click' event, send in lieu of WB_POINTER_CLICK for double-click.
'window helper' main header file for the X11workbench Toolkit API
#define WB_POINTER_CLICK
Mouse 'click' event.
void WBFreeFont(Display *pDisplay, WB_FONT pFont)
free a WB_FONT that was created using one of the WBFont APIs
Definition: font_helper.c:250
void FWRemoveContainedWindow(WBFrameWindow *pFW, WBChildFrame *pCont)
Removes a 'contained' window from a frame window. Does not destroy the 'contained' window.
struct tagWBChildFrame * pNext
'Next Object' pointer in an internally stored linked list (do not alter or use this)
Definition: frame_window.h:462
int FWInitChildFrame(WBChildFrame *pChildFrame, WBFrameWindow *pOwner, WB_FONTC pFont, const char *szFocusMenu, const WBFWMenuHandler *pHandlerArray, WBWinEvent pUserCallback, int fFlags)
Initialize a child frame (assumed to be a base 'class' for the window)
Definition: child_frame.c:118
void(* undo)(WBChildFrame *)
perform an undo operation
Definition: frame_window.h:728
#define WB_DEBUG_PRINT(L,...)
Preferred method of implementing conditional debug output.
Definition: debug_helper.h:364
void * WBGetWindowData(Window wID, int iIndex)
Gets the data associated with this window and the specified index.
void(* pgright)(WBChildFrame *, int iACS)
'page right' navigation.
Definition: frame_window.h:696
unsigned int width
the 'width' value of the extent.
#define WB_POINTER_DROP
WB_POINTER 'drop' event, only sent if drag/drop supported AND was not 'canceled'; see WB_POINTER_CANC...
int WBFontAscent(WB_FONTC pFont0)
Get the maximum character ascent from a WB_FONT.
Definition: font_helper.c:495
Utilities for copying and drawing text, determining text extents, and so on.
void FWSetChildFrameContextMenuID(WBChildFrame *pChildFrame, int nID)
Function to assign the context menu ID (from the menu resource) to a Child Frame.
Definition: child_frame.c:503
structure for defining a menu bar window
Definition: menu_bar.h:113
void WBPaintHScrollBar(WB_SCROLLINFO *pScrollInfo, Display *pDisplay, Drawable wID, WBGC gc, WB_GEOM *pgeomClient)
Paint the horizontal scroll bar within a window based on WB_SCROLLINFO.
int x
the 'x' value of the point. can be negative.
static __inline__ int WBCheckDebugLevel(WB_UINT64 dwLevel)
Check specified debug level against the value returned by WBGetDebugLevel() and return non-zero for a...
Definition: debug_helper.h:300
int WBKeyEventProcessKey(const XKeyEvent *pEvent, char *pBuf, int *pcbLen, int *piAltCtrlShift)
Generic keyboard event translation utility.
void(* do_char)(WBChildFrame *, XClientMessageEvent *)
handler for regular WB_CHAR Client Messages (typed-in characters).
Definition: frame_window.h:680
int iHPos
current horozontal scroll position (N/A if outside of min/max range)
int WBFontAvgCharWidth(WB_FONTC pFont0)
Get the average character width for a font.
Definition: font_helper.c:343
generic 'NA' or 'UNDEFINED' value
void WBCreateWindowDefaultGC(Window wID, unsigned long clrFG, unsigned long clrBG)
creates a default WBGC for a window
#define WB_POINTER_SCROLLDOWN
WB_POINTER 'scroll down' event, caused by mouse button 5.
WBFWMenuHandler * pMenuHandler
menu handler for this child frame's menu (NULL = 'use default')
Definition: frame_window.h:455
structure for managing menu callbacks
Definition: frame_window.h:217
int WBScrollBarEvent(Window wID, XEvent *pEvent, WB_SCROLLINFO *pScrollInfo)
Event handler for scroll bars.
#define WB_KEYEVENT_ALT
'AltCtrlShift' bit flag for ALT modifier for WBKeyEventProcessKey()
#define FW_EDIT_DELETE_MENU
Definition: child_frame.h:115
WB_FONT WBCopyFont(Display *pDisplay, WB_FONTC pOldFont)
make a copy of an existing font (best when assigning to a window)
Definition: font_helper.c:168
void(* mouse_cancel)(WBChildFrame *)
'mouse cancel' notification (cancel 'drag', etc.).
Definition: frame_window.h:725
Window wID
window identifier for the 'Child Frame' window. may contain 'None' while being destroyed
Definition: frame_window.h:429
WBMenuPopupWindow * MBFindMenuPopupWindow(WBMenu *pMenu)
Find the first WBMenuPopupWindow that references a WBMenu.
Definition: menu_popup.c:456
unsigned int width
Definition file for font helper functions and structures.
structure for managing menu items
Definition: menu.h:185
static __inline__ WBFrameWindow * FWGetFrameWindowStruct(Window wID)
Obtain the associated WBFrameWindow structure pointer for a frame window's Window ID.
Definition: frame_window.h:835
#define FW_EDIT_SELECT_NONE_MENU
Definition: child_frame.h:117
1st parameter (bar) - The vertical scroll bar for the control or window.
2nd parameter (direction) - 'knob track' - pos in data.l[2]
WB_FONTC FWGetFont(WBFrameWindow *pFW)
Get the frame window WB_FONTC.
Definition: frame_window.c:445
int WBPostPriorityEvent(Window wID, XEvent *pEvent)
Places a copy of the specified event at the end of the priority (internal) event queue.
void(* toggle_ins_mode)(WBChildFrame *)
toggles insert mode on or off
Definition: frame_window.h:701
int WBTextObjectCalculateLineHeight(int iAscent, int iDescent)
Calculate the correct per-line height (in pixels) for a specified font ascent and descent.
Definition: text_object.c:864
Atom aWB_CHAR
keystroke/character notifications generated by API
static __inline__ Display * WBGetDefaultDisplay(void)
Returns the default Display.
internal wrapper struct for X11 'geometry' definition
void FWChildFrameStatusChanged(WBChildFrame *pChildFrame)
Notify Child Frame to update status text in Frame Window.
Definition: child_frame.c:897
void(* tab)(WBChildFrame *, int iACS)
'tab' char, or tab navigation.
Definition: frame_window.h:684
void(* delete_sel)(WBChildFrame *)
delete selection only
Definition: frame_window.h:705
void FWSetChildFrameMenu(WBChildFrame *pChildFrame, const char *szFocusMenu)
Function to assign the menu resource to a Child Frame.
Definition: child_frame.c:478
uintptr_t lMenuID
menu ID (< 0x10000L) or const pointer to string
Definition: frame_window.h:219
void(* bkspace)(WBChildFrame *, int iACS)
'backspace' delete character (backspace equivalent), or perform related 'backspace' operation via ctr...
Definition: frame_window.h:682
WB_GEOM geomEntire
client-area geometry (excludes scroll bars)
Definition: frame_window.h:434
int WBSetForeground(WBGC hGC, unsigned long foreground)
Assign foreground color, a wrapper for XSetForeground()
Atom aWB_POINTER
pointer click/double-click/drag notifications generated by API
XColor FWGetDefaultFG(void)
Get the default foreground color.
Definition: frame_window.c:424
Atom aMENU_COMMAND
commands sent by menus via ClientMessage
void(* pgup)(WBChildFrame *, int iACS)
'page up' navigation.
Definition: frame_window.h:693
Atom aSCROLL_NOTIFY
void FWChildFrameRecalcLayout(WBChildFrame *pChildFrame)
Child frame notification callback (called by frame window)
Definition: child_frame.c:845
void(* properties)(WBChildFrame *)
display the property sheet for the displayed document (optional)
Definition: frame_window.h:686
1st parameter (bar) - The horizontal scroll bar for the control or window
XColor FWGetDefaultBD(void)
Get the default border color.
Definition: frame_window.c:438
WB_SCROLLINFO scroll
'scroll info' (horizontal and vertical min/max/pos and other details)
Definition: frame_window.h:441
Child Frame API functions.
void(* del)(WBChildFrame *, int iACS)
'delete' char under cursor (delete equivalent), or perform related 'delete' operation via ctrl/alt/sh...
Definition: frame_window.h:683
static __inline__ WBChildFrame * FWGetChildFrameStruct(Window wID)
Obtain the associated WBChildFrame structure pointer for a Window ID.
Definition: child_frame.h:376
void(* copy_to_cb)(WBChildFrame *)
copy selection to clipboard
Definition: frame_window.h:702
WB_POINT origin
viewport 'origin' in 'client units' (such as chars and lines) - determines scroll behavior
Definition: frame_window.h:435
WB_EXTENT extent
viewport 'extent' in 'client units' (such as chars and lines) - determines scroll behavior
Definition: frame_window.h:436
2nd parameter (direction) - bottom, end
void(* select_none)(WBChildFrame *)
select none
Definition: frame_window.h:707
void * WBAlloc(int nSize)
High performance memory sub-allocator 'allocate'.
int FWAddContainedWindow(WBFrameWindow *pFW, WBChildFrame *pNew)
Adds a 'contained' window and returns the tab order index.
static __inline__ WBMenuBarWindow * MBGetMenuBarWindowStruct(Window wID)
Obtain a pointer to the WBMenuBarWindow structure from a Window ID of a Menu Bar window.
Definition: menu_bar.h:191
#define WB_POINTER_SCROLLUP
WB_POINTER 'scroll up' event, caused by mouse button 4.
int FWGetNumContWindows(const WBFrameWindow *pFW)
Returns the total number of 'contained' windows.
int iClientX
The current X position of the frame window's client area (relative to the window)
Definition: frame_window.h:280
2nd parameter (direction) - relative scroll - rel pos in data.l[2]
void(* downarrow)(WBChildFrame *, int iACS)
'down' arrow navigation.
Definition: frame_window.h:688
int(* can_undo)(WBChildFrame *)
returns non-zero value if 'can undo'
Definition: frame_window.h:730
char * szStatusText
Status text ('WBAlloc'd) to display when this child frame window has the input focus....
Definition: frame_window.h:452
Window WBGetMenuWindow(Window wID)
Returns the Window ID of the (first) menu window assigned to a (frame) window.
struct tagWBMenuPopupWindow WBMenuPopupWindow
structure for managing a popup menu window
int iVPos
current vertical scroll position (N/A if outside of min/max range)
#define FW_EDIT_CUT_MENU
Definition: child_frame.h:112
#define FW_MENU_HANDLER_BEGIN(X)
Use this macro to begin definition of a WBFWMenuHandler array.
Definition: frame_window.h:893
#define WB_ERROR_PRINT(...)
Preferred method of implementing an 'error level' debug message for all subsystems.
Definition: debug_helper.h:474
void FWSetChildFrameMenuHandlers(WBChildFrame *pChildFrame, const WBFWMenuHandler *pHandlerArray)
Function to assign menu handlers to a Child Frame.
Definition: child_frame.c:515
int iRowHeight
cached 'row height' (height of line including interline spacing)
Definition: frame_window.h:438
void(* scroll_vert)(WBChildFrame *, int iMode, int iValue)
'scroll vertical' notification.
Definition: frame_window.h:722
void(* mouse_drop)(WBChildFrame *, int iX, int iY, int iButtonMask, int iACS)
'mouse drop' (drag end) notification.
Definition: frame_window.h:718
void WBFree(void *pBuf)
High performance memory sub-allocator 'free'.
static __inline__ void WBInvalidateRect(Window wID, const WB_RECT *pRCT, int bPaintFlag)
'Paint' helper, invalidates a WB_RECT for asynchronous Expose event generation
void WBDestroyWindow(Window wID)
Destroy a window.
2nd parameter (direction) - pgup, pgleft
#define WB_POINTER_CANCEL
WB_POINTER 'cancel' event, cancels an ongoing operation, such as drag/drop (useful for resource clean...
#define WB_KEYEVENT_SHIFT
'AltCtrlShift' bit flag for Shift modifier for WBKeyEventProcessKey()
int(* UIcallback)(WBMenu *, WBMenuItem *)
menu 'UI' callback to handle displaying menu states.
Definition: frame_window.h:228
int y
the 'y' value of the point. can be negative.
void FWSetChildFrameDisplayName(WBChildFrame *pChildFrame, const char *szDisplayName)
Assign the display name.
Definition: child_frame.c:571
WB_GEOM geom
total client-area geometry (excludes scroll bars) in 'pixels'
Definition: frame_window.h:433
#define FW_MENU_HANDLER_END
Use this macro to complete the definition of a WBFWMenuHandler array.
Definition: frame_window.h:907
#define CHILD_FRAME_TAG
TAG for the WBChildFrame structure.
Definition: child_frame.h:94
#define FW_EDIT_PROPERTIES_MENU
Definition: child_frame.h:120
#define WB_MOUSE_INPUT_MASK
'Mouse' input mask, bit flag for window creation
void FWSetChildFrameScrollInfo(WBChildFrame *pChildFrame, int iRow, int iMaxRow, int iCol, int iMaxCol, int iRowHeight, int iColWidth)
Set the X,Y extent for the child frame (notifies everything)
Definition: child_frame.c:804
#define WB_POINTER_MOVE
WB_POINTER 'move' event, for motion notification during drag/drop.
#define WB_POINTER_DRAG
WB_POINTER 'drag' event, window proc MUST return the window ID to auto-support drag/drop.
void FWDestroyChildFrame(WBChildFrame *pChildFrame)
Destroy an Child Frame.
Definition: child_frame.c:329
Atom aMENU_ACTIVATE
Internal Client Message Atom for 'ACTIVATE' notification.
Definition: menu_bar.c:150
2nd parameter (direction) - absolute scroll - pos in data.l[2]
Window WBCreateWindow(Display *pDisplay, Window wIDParent, WBWinEvent pProc, const char *szClass, int iX, int iY, int iWidth, int iHeight, int iBorder, int iIO, WB_UINT64 iFlags, XSetWindowAttributes *pXSWA)
Create a window.
Atom aCLIPBOARD
CLIPBOARD Atom for the clipboard.
Window wSelf
The window ID of the menu bar window.
Definition: menu_bar.h:116
int iClientHeight
The current height of the frame window's client area.
Definition: frame_window.h:283
void(* destructor)(struct tagWBChildFrame *)
pointer to a 'superclass' destructor. If not NULL, will be called by FWDestroyChildFrame()
Definition: frame_window.h:459
void(* select_all)(WBChildFrame *)
select all
Definition: frame_window.h:706
int WBSetHScrollRange(WB_SCROLLINFO *pSI, int iMin, int iMax)
Set the scroll range for a horizontal scrollbar in the WB_SCROLLINFO structure.
2nd parameter (direction) - double-clicked item (no selection change info) (sent to list control's ow...
#define WB_STANDARD_INPUT_MASK
'Standard' input mask, bit flag for window creation
void WBDebugDumpEvent(XEvent *pEvent)
dumps the contents of an XEvent
void WBUnregisterWindowCallback(Window wID)
un-register the window's callback function (implies resource destruction)
#define WB_KEYEVENT_ACSMASK
'AltCtrlShift' bit mask for Alt+Ctrl+Shift bits for WBKeyEventProcessKey()
unsigned int ulTag
tag indicating I'm a 'Child Frame' window
Definition: frame_window.h:428
int(* has_selection)(WBChildFrame *)
returns non-zero value if there is a selection
Definition: frame_window.h:727
int iClientWidth
The current width of the frame window's client area.
Definition: frame_window.h:282
int(* WBWinEvent)(Window wID, XEvent *pEvent)
event callback function type for window events
2nd parameter (direction) - home, top
int iContextMenuID
menu ID (from pszMenuResource or owning frame's menu) for context popup, -1 if none
Definition: frame_window.h:456
XColor FWGetDefaultBG(void)
Get the default background color.
Definition: frame_window.c:431
void(* redo)(WBChildFrame *)
perform a re-do
Definition: frame_window.h:729
main controlling structure for frame windows
Definition: frame_window.h:274
void(* paste_from_cb)(WBChildFrame *)
paste from clipboard
Definition: frame_window.h:703
unsigned int height
int WBFontDescent(WB_FONTC pFont0)
Get the maximum character descent from a WB_FONT.
Definition: font_helper.c:443
void(* mouse_dblclick)(WBChildFrame *, int iX, int iY, int iButtonMask, int iACS)
'mouse double click' notification.
Definition: frame_window.h:714
int(* is_empty)(WBChildFrame *)
returns non-zero value if contents are 'empty'
Definition: frame_window.h:732
int MBMenuProcessHotKey(WBMenu *pMenu, XKeyEvent *pEvent)
Event handler for menu hotkeys.
Definition: menu.c:1228
Atom aQUERY_CLOSE
query if it's ok to close (and optionally destroy yourself if ok) a window
int(* callback)(XClientMessageEvent *)
menu callback (gets pointer to the 'XClientMessageEvent').
Definition: frame_window.h:221
WBFrameWindow * pOwner
a pointer to the WBFrameWindow owner
Definition: frame_window.h:430
WBChildFrame * FWGetContainedWindowByIndex(const WBFrameWindow *pFW, int iIndex)
Returns the Window ID for the specified 'contained' window. The index follows the tab order.
Display * WBGetWindowDisplay(Window wID)
returns the Display associated with a window
void WBSetWindowData(Window wID, int iIndex, void *pData)
assign 'data pointer' for a window and specified index value
void(* scroll_horiz)(WBChildFrame *, int iMode, int iValue)
'scroll vertical' notification.
Definition: frame_window.h:723
2nd parameter (direction) - pgdn, pgright
int iColWidth
cached 'column width' (width of 1 character)
Definition: frame_window.h:439
int FWChildFrameEvent(Window wID, XEvent *pEvent)
Default event handler for Child Frame window.
Definition: child_frame.c:947
void(* pgdown)(WBChildFrame *, int iACS)
'page down' navigation.
Definition: frame_window.h:694
void(* enter)(WBChildFrame *, int iACS)
'enter' char, or 'enter' for navigation.
Definition: frame_window.h:685
#define FW_EDIT_SELECT_ALL_MENU
Definition: child_frame.h:116
int FWChildFrameQueryClose(WBChildFrame *pChildFrame)
Returns if it's safe to close the child frame; prompts user as needed.
Definition: child_frame.c:913
int WBFillRectangle(Display *display, Drawable d, WBGC gc, int x, int y, unsigned int width, unsigned int height)
Wrapper for XFillRectangle()
WBMenu * pMenu
a pointer to the associated WBMenu structure
Definition: menu_bar.h:119
int WBSetBackground(WBGC hGC, unsigned long background)
Assign background color, a wrapper for XSetBackground()
void(* rightarrow)(WBChildFrame *, int iACS)
'right' arrow navigation.
Definition: frame_window.h:690
void(* mouse_drag)(WBChildFrame *, int iX, int iY, int iButtonMask, int iACS)
'mouse drag' (begin) notification.
Definition: frame_window.h:716
#define WB_KEYEVENT_CTRL
'AltCtrlShift' bit flag for Control modifier for WBKeyEventProcessKey()
An allocated structure containing XFontStruct, XFontInfo, and XftFont [as applicable] for a specified...
Definition: font_helper.h:152
int WBSetVScrollRange(WB_SCROLLINFO *pSI, int iMin, int iMax)
Set the scroll range for a vertical scrollbar in the WB_SCROLLINFO structure.
static __inline__ void WBInitScrollInfo(WB_SCROLLINFO *pSI)
Initialization function for a 'WB_SCROLLINFO' structure.
char * WBCopyString(const char *pSrc)
A simple utility that returns a WBAlloc() copy of a 0-byte terminated string.
void(* end)(WBChildFrame *, int iACS)
'end' arrow navigation.
Definition: frame_window.h:692
#define WB_KEYBOARD_INPUT_MASK
'Keyboard' input mask, bit flag for window creation
int(* can_redo)(WBChildFrame *)
returns non-zero value if 'can redo'
Definition: frame_window.h:731
void FWSetChildFrameExtent(WBChildFrame *pChildFrame, int iXExtent, int iYExtent)
Set the X,Y extent for the child frame (notifies everything)
Definition: child_frame.c:645
unsigned int height
the 'height' value of the extent.
void WBEndPaint(Window wID, WBGC gc)
'Paint' helper, frees resources and marks the update region 'valid'
internal wrapper struct for GC with local cache
Structure that defines a Child Frame within a Frame Window.
Definition: frame_window.h:426
Atom aRESIZE_NOTIFY
notification of window re-size via ClientMessage
Structure that defines a Child Frame's UI, mainly for a 'superclass'.
Definition: frame_window.h:677
void FWSetStatusText(WBFrameWindow *pFW, const char *szText)
Sets the 'status' text for a Frame Window with a status bar, forcing a re-paint.
2nd parameter (direction) - down, right
#define FW_EDIT_PASTE_MENU
Definition: child_frame.h:114
void WBPaintVScrollBar(WB_SCROLLINFO *pScrollInfo, Display *pDisplay, Drawable wID, WBGC gc, WB_GEOM *pgeomClient)
Paint the vertical scroll bar within a window based on WB_SCROLLINFO.
void(* uparrow)(WBChildFrame *, int iACS)
'up' arrow navigation.
Definition: frame_window.h:687
Atom aImageAtom
'image' atom for display in tabs. default is 'None'. You should not alter this member directly.
Definition: frame_window.h:450
#define FW_MENU_HANDLER_ENTRY(X, Y, Z)
Use this macro to define an entry for a WBFWMenuHandler array.
Definition: frame_window.h:902
char * szDisplayName
display name shown in tab and title bar. You should not alter this member directly.
Definition: frame_window.h:449
#define WB_WARN_PRINT(...)
Preferred method of implementing a 'warning level' debug message for all subsystems.
Definition: debug_helper.h:467
struct tagWBChildFrameUI * pUI
pointer to 'WBChildFrameUI' function pointer table (assigned by 'superclass')
Definition: frame_window.h:460
void(* cut_to_cb)(WBChildFrame *)
delete selection, copying to clipboard first
Definition: frame_window.h:704
char * pszMenuResource
resource string for this child frame's menu (NULL = 'use default')
Definition: frame_window.h:454
void WBUpdateScrollBarGeometry(WB_SCROLLINFO *pSI, WB_FONTC pFont, WB_GEOM *pgeomClient, WB_GEOM *pgeomUsable)
Update the scroll bar geometry within the WB_SCROLLINFO structure.
void(* mouse_click)(WBChildFrame *, int iX, int iY, int iButtonMask, int iACS)
'mouse click' notification.
Definition: frame_window.h:712
WB_FONT pFont
default font for the window
Definition: frame_window.h:431
void(* mouse_move)(WBChildFrame *, int iX, int iY)
'mouse motion' notification.
Definition: frame_window.h:720
#define FW_EDIT_COPY_MENU
Definition: child_frame.h:113
WBGC WBBeginPaintGeom(Window wID, WB_GEOM *pgBounds)
'Paint' helper, creates a WBGC for use in updating the window for a specified rectangular area
#define WB_KEYEVENT_KEYSYM
'AltCtrlShift' bit flag for 'VK_' keys for WBKeyEventProcessKey()
void FWSetChildFrameImageAtom(WBChildFrame *pChildFrame, Atom aImage)
Assign the image atom for the child frame. the image appears in the tab associated with the child fra...
Definition: child_frame.c:593
WB_FONTC WBGetDefaultFont(void)
Returns a pointer to the default font WB_FONT for the default display. This is a shared resource; do ...