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