X11workbench Toolkit  1.0
dialog_support.c
1 // _ _ _ _ //
3 // __| |(_) __ _ | | ___ __ _ ___ _ _ _ __ _ __ ___ _ __ | |_ ___ //
4 // / _` || | / _` || | / _ \ / _` | / __|| | | || '_ \ | '_ \ / _ \ | '__|| __| / __| //
5 // | (_| || || (_| || || (_) || (_| | \__ \| |_| || |_) || |_) || (_) || | | |_ _| (__ //
6 // \__,_||_| \__,_||_| \___/ \__, |_____|___/ \__,_|| .__/ | .__/ \___/ |_| \__|(_)\___| //
7 // |___/|_____| |_| |_| //
8 // //
9 // //
10 // additional dialog control support //
11 // This file contains various support and functionality that is common to dialog controls //
12 // //
14 
15 
16 /*****************************************************************************
17 
18  X11workbench - X11 programmer's 'work bench' application and toolkit
19  Copyright (c) 2010-2019 by Bob Frazier (aka 'Big Bad Bombastic Bob')
20 
21 
22  DISCLAIMER: The X11workbench application and toolkit software are supplied
23  'as-is', with no warranties, either implied or explicit.
24  Any claims to alleged functionality or features should be
25  considered 'preliminary', and might not function as advertised.
26 
27  MIT-like license:
28 
29  There is no restriction as to what you can do with this software, so long
30  as you include the above copyright notice and DISCLAIMER for any distributed
31  work that is equal to or derived from this one, along with this paragraph
32  that explains the terms of the license if the source is also being made
33  available. A "derived work" describes a work that uses a significant portion
34  of the source files or algorithms that are included with this one.
35  Specifically excluded from this are files that were generated by the software,
36  or anything that is included with the software that is part of another package
37  (such as files that were created or added during the 'configure' process).
38  Specifically included is the use of part or all of any of the X11 workbench
39  toolkit source or header files in your distributed application. If you do not
40  ship the source, the above copyright statement is still required to be placed
41  in a reasonably prominent place, such as documentation, splash screens, and/or
42  'about the application' dialog boxes.
43 
44  Use and distribution are in accordance with GPL, LGPL, and/or the above
45  MIT-like license. See COPYING and README files for more information.
46 
47 
48  Additional information at http://sourceforge.net/projects/X11workbench
49 
50 ******************************************************************************/
51 
52 
53 #ifdef linux /* needed for debian, possibly others */
54 #define _GNU_SOURCE /* in case features.h is involved on linux */
55 #define __USE_GNU /* this enables a few more things in the headers like 'qsort_r' */
56 // TODO: consider making this a 'configure' thing
57 #endif // linux
58 
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <unistd.h>
62 #include <memory.h>
63 #include <string.h>
64 #include <strings.h>
65 #include <signal.h>
66 #include <time.h>
67 #include <sys/stat.h>
68 
69 #ifndef XK_Delete /* moslty for interix */
70 #define XK_MISCELLANY /* mostly for interix */
71 #include <X11/keysymdef.h> // some platforms don't automatically include this with X headers
72 #endif // XK_Delete
73 
74 #define DIALOG_SUPPORT_C /* prevents me from including the various Atom definitions */
75 
76 #include "window_helper.h"
77 #include "pixmap_helper.h" // pixmap helpers, including pre-defined icons
78 #include "dialog_window.h"
79 #include "dialog_controls.h"
80 #include "dialog_support.h" // internal-only definitions
81 #include "conf_help.h"
82 #include "file_help.h"
83 #include "draw_text.h"
84 #include "text_object.h"
85 #include "window_dressing.h"
86 
89 #define THIS_SUBSYSTEM DebugSubSystem_DialogCtrl
90 
91 
92 
93 
94 #define INIT_ATOM(X) if(a##X == None){ a##X = WBGetAtom(WBGetDefaultDisplay(),X##_STR); }
95 #define INIT_ATOM2(X,Y) if(X == None){ X = WBGetAtom(WBGetDefaultDisplay(),Y); }
96 
97 #define DEFAULT_LISTINFO_MAX 16384 /* default initial max # of items in LISTINFO */
98 
99 
100 
101 // atoms first
102 // TODO: make this documentation a bit better. for now the format is OK in doxygen, a little flakey here
103 
106 Atom aFRAME_CONTROL = None;
107 
109 Atom aTEXT_CONTROL = None;
110 
112 Atom aICON_CONTROL = None;
113 
115 Atom aIMAGE_CONTROL = None;
116 
118 Atom aEDIT_CONTROL = None;
119 
121 Atom aPUSHBUTTON_CONTROL = None;
122 
125 
128 
130 Atom aRADIOBUTTON_CONTROL = None;
131 
134 
136 Atom aCHECKBUTTON_CONTROL = None;
137 
140 
142 Atom aHSCROLL_CONTROL = None;
143 
145 Atom aVSCROLL_CONTROL = None;
146 
148 Atom aSLIDER_CONTROL = None;
149 
151 Atom aKNOB_CONTROL = None;
152 
154 Atom aLIST_CONTROL = None;
155 
157 Atom aCOMBO_CONTROL = None;
158 
160 Atom aTREE_CONTROL = None;
161 
163 Atom aCOMBOTREE_CONTROL = None;
164 
166 Atom aFILE_LIST_CONTROL = None;
167 
169 Atom aFILE_COMBO_CONTROL = None;
170 
172 Atom aPATH_TREE_CONTROL = None;
173 
175 Atom aTAB_CONTROL = None;
176 
177 
178 // NOTE: 'xatoms' is in the CORE group - consider moving this into CORE
179 
180 
181 
183 
195 Atom aBUTTON_PRESS = None;
209 Atom aLIST_NOTIFY = None;
222 Atom aTEXT_CHANGED = None;
237 Atom aTEXTSELECT_CHANGE = None;
250 Atom aGOTFOCUS = None;
263 Atom aLOSTFOCUS = None;
278 Atom aMOUSE_CLICK = None;
293 Atom aMOUSE_DBLCLICK = None;
308 Atom aMOUSE_DRAG = None;
321 Atom aKEY_DOWN = None;
334 Atom aKEY_UP = None;
347 Atom aKEYSTROKE = None;
348 
358 Atom aDIALOG_INIT = None;
359 
370 Atom aDLGC_PROP_NOTIFY = None;
371 
383 Atom aLIST_SELCHANGE = None; // list selection has changed (send to self)
384 
385 // control command messages sent to controls to set/get info
399 Atom aDLGC_CONTROL_SET = None;
400 
417 Atom aDLGC_CONTROL_GET = None;
418 
419 // internal-only properties (still have global scope for inline functions, etc.)
426 Atom aDLGC_TEXT = None; // dialog control 'text' property, i.e. 'GetText'
431 Atom aDLGC_CAPTION = None; // dialog control 'caption' property, i.e. 'GetCaption' (not an actual property, notification only)
438 Atom aDLGC_FONT = None;
447 Atom aDLGC_SCROLLINFO = None; // scrollbar info structure (horizontal AND vertical)
448  // (scrollbars, listboxes, combo boxes, multi-line edit)
457 Atom aDLGC_LISTINFO = None; // listbox info structure
458 
468 Atom aDLGC_PATH = None;
469 
470 
472 {
473  INIT_ATOM(FRAME_CONTROL);
474  INIT_ATOM(TEXT_CONTROL);
475  INIT_ATOM(ICON_CONTROL);
476  INIT_ATOM(IMAGE_CONTROL);
477  INIT_ATOM(EDIT_CONTROL);
478  INIT_ATOM(PUSHBUTTON_CONTROL);
479  INIT_ATOM(DEFPUSHBUTTON_CONTROL);
480  INIT_ATOM(CANCELBUTTON_CONTROL);
481  INIT_ATOM(RADIOBUTTON_CONTROL);
482  INIT_ATOM(FIRSTRADIOBUTTON_CONTROL);
483  INIT_ATOM(CHECKBUTTON_CONTROL);
484  INIT_ATOM(TRISTATEBUTTON_CONTROL);
485  INIT_ATOM(HSCROLL_CONTROL);
486  INIT_ATOM(VSCROLL_CONTROL);
487  INIT_ATOM(SLIDER_CONTROL);
488  INIT_ATOM(KNOB_CONTROL);
489  INIT_ATOM(LIST_CONTROL);
490  INIT_ATOM(COMBO_CONTROL);
491  INIT_ATOM(TREE_CONTROL);
492  INIT_ATOM(COMBOTREE_CONTROL);
493  INIT_ATOM(FILE_LIST_CONTROL);
494  INIT_ATOM(FILE_COMBO_CONTROL);
495  INIT_ATOM(PATH_TREE_CONTROL);
496  INIT_ATOM(TAB_CONTROL);
497 
498 // INIT_ATOM2(aCONTROL_NOTIFY,"ControlNotify");
499  INIT_ATOM2(aBUTTON_PRESS,"ButtonPress");
500  INIT_ATOM2(aLIST_NOTIFY,"ListNotify");
501  INIT_ATOM2(aTEXT_CHANGED,"TextChanged");
502  INIT_ATOM2(aTEXTSELECT_CHANGE,"TextSelectChange");
503  INIT_ATOM2(aGOTFOCUS,"GotFocus");
504  INIT_ATOM2(aLOSTFOCUS,"LostFocus");
505  INIT_ATOM2(aMOUSE_CLICK,"MouseDown");
506  INIT_ATOM2(aMOUSE_DBLCLICK,"MouseUp");
507  INIT_ATOM2(aMOUSE_DRAG,"MouseDrag");
508  INIT_ATOM2(aKEY_DOWN,"KeyDown");
509  INIT_ATOM2(aKEY_UP,"KeyUp");
510  INIT_ATOM2(aKEYSTROKE,"Keystroke");
511 
512  INIT_ATOM2(aDLGC_CONTROL_SET,"DLGC_CONTROL_SET");
513  INIT_ATOM2(aDLGC_CONTROL_GET,"DLGC_CONTROL_GET");
514 
515  INIT_ATOM2(aDLGC_TEXT, "DLGC_TEXT");
516  INIT_ATOM2(aDLGC_CAPTION, "DLGC_CAPTION");
517  INIT_ATOM2(aDLGC_FONT, "DLGC_FONT");
518  INIT_ATOM2(aDLGC_SCROLLINFO, "DLGC_SCROLLINFO");
519  INIT_ATOM2(aDLGC_LISTINFO, "DLGC_LISTINFO");
520  INIT_ATOM2(aDLGC_PATH, "DLGC_PATH");
521 
522 
523  // other dialog-related messages
524  INIT_ATOM2(aDIALOG_INIT,"DialogInit");
525 // INIT_ATOM2(aDIALOG_SETFOCUS,"DialogSetFocus");
526  INIT_ATOM2(aDLGC_PROP_NOTIFY, "DLGCPropNotify");
527  INIT_ATOM2(aLIST_SELCHANGE, "LIST_SELCHANGE");
528 
529 }
530 
531 
533 // D I A L O G C O N T R O L P R O P E R T I E S
535 
536 
537 void WBDialogControlSetCaption(WBDialogControl *pCtrl, const char *szCaption)
538 {
539 char *szOldCaption = pCtrl->pCaption;
540 
541  pCtrl->pCaption = WBCopyString(szCaption);
542 
543  if(szOldCaption)
544  {
545  WBFree(szOldCaption);
546  }
547 
548  WBInvalidateGeom(pCtrl->wID, NULL, 0);
549  WBUpdateWindow(pCtrl->wID); // schedule update (not immediate)
550 
551  DLGNotifySelf(pCtrl, aDLGC_PROP_NOTIFY, aDLGC_CAPTION, 0, 0, 0, 0);
552 }
553 
555 {
556  if(!pCtrl->pCaption)
557  {
558  return "";
559  }
560 
561  return pCtrl->pCaption;
562 }
563 
564 void WBDialogControlSetPixmap(WBDialogControl *pCtrl, Pixmap pixmap)
565 {
566 Display *pDisplay = NULL;
567 
568  if(!pCtrl ||
569  (pCtrl->aClass != aICON_CONTROL && pCtrl->aClass != aIMAGE_CONTROL
570  && pCtrl->aClass != aPUSHBUTTON_CONTROL && pCtrl->aClass != aDEFPUSHBUTTON_CONTROL
571  && pCtrl->aClass != aCANCELBUTTON_CONTROL))
572  {
573  return;
574  }
575 
576  pDisplay = WBGetWindowDisplay(pCtrl->wID);
577 
578  if(!pDisplay)
579  {
580  pDisplay = WBGetDefaultDisplay();
581  }
582 
583  if(pCtrl->aClass == aICON_CONTROL ||
584  pCtrl->aClass == aIMAGE_CONTROL)
585  {
586  Pixmap pxOld = ((WBImageControl *)pCtrl)->pixmap;
587  Pixmap pxOld2 = ((WBImageControl *)pCtrl)->pixmap2;
588 
589  ((WBImageControl *)pCtrl)->pixmap = pixmap;
590  ((WBImageControl *)pCtrl)->pixmap2 = None;
591 
593  if(pxOld != None)
594  {
595  XFreePixmap(pDisplay, pxOld);
596  }
597  if(pxOld2 != None)
598  {
599  XFreePixmap(pDisplay, pxOld2);
600  }
602  }
603 
604  if(pCtrl->aClass == aPUSHBUTTON_CONTROL || pCtrl->aClass == aDEFPUSHBUTTON_CONTROL
605  || pCtrl->aClass == aCANCELBUTTON_CONTROL)
606  {
607  Pixmap pxOld = ((WBPushButtonControl *)pCtrl)->pixmap;
608  Pixmap pxOld2 = ((WBPushButtonControl *)pCtrl)->pixmap2;
609 
610  ((WBPushButtonControl *)pCtrl)->pixmap = pixmap;
611  ((WBPushButtonControl *)pCtrl)->pixmap2 = None;
612 
614  if(pxOld != None)
615  {
616  XFreePixmap(pDisplay, pxOld);
617  }
618  if(pxOld2 != None)
619  {
620  XFreePixmap(pDisplay, pxOld2);
621  }
623  }
624 }
625 
627 {
628  if(!pCtrl)
629  {
630  return None;
631  }
632 
633  if(pCtrl->aClass == aICON_CONTROL ||
634  pCtrl->aClass == aIMAGE_CONTROL)
635  {
636  return ((WBImageControl *)pCtrl)->pixmap;
637  }
638 
639  if(pCtrl->aClass == aPUSHBUTTON_CONTROL || pCtrl->aClass == aDEFPUSHBUTTON_CONTROL
640  || pCtrl->aClass == aCANCELBUTTON_CONTROL)
641  {
642  return ((WBPushButtonControl *)pCtrl)->pixmap;
643  }
644 
645  return None;
646 }
647 
648 void WBDialogControlSetIconPixmap(WBDialogControl *pCtrl, Pixmap pixmap, Pixmap pixmap2)
649 {
650 Display *pDisplay = NULL;
651 
652  if(!pCtrl ||
653  (pCtrl->aClass != aICON_CONTROL && pCtrl->aClass != aIMAGE_CONTROL
654  && pCtrl->aClass != aPUSHBUTTON_CONTROL && pCtrl->aClass != aDEFPUSHBUTTON_CONTROL
655  && pCtrl->aClass != aCANCELBUTTON_CONTROL))
656  {
657  return;
658  }
659 
660  pDisplay = WBGetWindowDisplay(pCtrl->wID);
661 
662  if(!pDisplay)
663  {
664  pDisplay = WBGetDefaultDisplay();
665  }
666 
667  if(pCtrl->aClass == aICON_CONTROL ||
668  pCtrl->aClass == aIMAGE_CONTROL)
669  {
670  Pixmap pxOld = ((WBImageControl *)pCtrl)->pixmap;
671  Pixmap pxOld2 = ((WBImageControl *)pCtrl)->pixmap2;
672 
673  ((WBImageControl *)pCtrl)->pixmap = pixmap;
674  ((WBImageControl *)pCtrl)->pixmap2 = pixmap2;
675 
677  if(pxOld != None)
678  {
679  XFreePixmap(pDisplay, pxOld);
680  }
681  if(pxOld2 != None)
682  {
683  XFreePixmap(pDisplay, pxOld2);
684  }
686  }
687 
688  if(pCtrl->aClass == aPUSHBUTTON_CONTROL || pCtrl->aClass == aDEFPUSHBUTTON_CONTROL
689  || pCtrl->aClass == aCANCELBUTTON_CONTROL)
690  {
691  Pixmap pxOld = ((WBPushButtonControl *)pCtrl)->pixmap;
692  Pixmap pxOld2 = ((WBPushButtonControl *)pCtrl)->pixmap2;
693 
694  ((WBPushButtonControl *)pCtrl)->pixmap = pixmap;
695  ((WBPushButtonControl *)pCtrl)->pixmap2 = pixmap2;
696 
698  if(pxOld != None)
699  {
700  XFreePixmap(pDisplay, pxOld);
701  }
702  if(pxOld2 != None)
703  {
704  XFreePixmap(pDisplay, pxOld2);
705  }
707  }
708 }
709 
710 Pixmap WBDialogControlGetIconPixmap(WBDialogControl *pCtrl, Pixmap *pPixmap2)
711 {
712  if(!pCtrl)
713  {
714  return None;
715  }
716 
717  if(pCtrl->aClass == aICON_CONTROL ||
718  pCtrl->aClass == aIMAGE_CONTROL)
719  {
720  if(pPixmap2)
721  {
722  *pPixmap2 = ((WBPushButtonControl *)pCtrl)->pixmap2;
723  }
724 
725  return ((WBImageControl *)pCtrl)->pixmap;
726  }
727 
728  if(pCtrl->aClass == aPUSHBUTTON_CONTROL || pCtrl->aClass == aDEFPUSHBUTTON_CONTROL
729  || pCtrl->aClass == aCANCELBUTTON_CONTROL)
730  {
731  if(pPixmap2)
732  {
733  *pPixmap2 = ((WBPushButtonControl *)pCtrl)->pixmap2;
734  }
735 
736  return ((WBPushButtonControl *)pCtrl)->pixmap;
737  }
738 
739  return None;
740 }
741 
742 void WBDialogControlSetCheck(WBDialogControl *pCtrl, int iCheck)
743 {
744  if(!pCtrl || pCtrl->wID == None)
745  {
746  return;
747  }
748 
749  XClientMessageEvent evt = {
750  .type=ClientMessage,
751  .serial=0,
752  .send_event=0,
753  .display=WBGetWindowDisplay(pCtrl->wID),
754  .window=pCtrl->wID,
755  .message_type=aDLGC_CONTROL_SET,
756  .format=32
757  };
758 
759  evt.data.l[0] = ControlGetSet_CHECK;
760  evt.data.l[1] = iCheck;
761 
762  WBWindowDispatch(pCtrl->wID, (XEvent *)&evt); // call the window proc immediately to process it
763 }
764 
766 {
767  if(!pCtrl || pCtrl->wID == None)
768  {
769  return 0;
770  }
771 
772  XClientMessageEvent evt = {
773  .type=ClientMessage,
774  .serial=0,
775  .send_event=0,
776  .display=WBGetWindowDisplay(pCtrl->wID),
777  .window=pCtrl->wID,
778  .message_type=aDLGC_CONTROL_GET,
779  .format=32
780  };
781 
782  evt.data.l[0] = ControlGetSet_CHECK;
783 
784  return WBWindowDispatch(pCtrl->wID, (XEvent *)&evt); // call the window proc immediately to process it
785 }
786 
787 
788 int WBDialogControlSetPropList(WBDialogControl *pCtrl, const char *szPropList)
789 {
790 // property<tab>value<newline>
791 
792  return 0; // for now (not being used yet)
793 }
794 
795 int WBDialogControlSetProperty(WBDialogControl *pCtrl, Atom aPropName, const char *szPropVal)
796 {
797  WB_DIALOG_PROP p;
798 
799  p.aProp = aPropName;
800  p.lVal = 0;
801  p.pVal = WBCopyString(szPropVal);
802 
803  if(!p.pVal)
804  {
805  return -1;
806  }
807 
808  WBDialogControlSetDialogProp(pCtrl, &p);
809  return 0;
810 }
811 
812 void WBDialogControlSetProperty2(WBDialogControl *pCtrl, Atom aPropName, void *pPropVal)
813 {
814  WB_DIALOG_PROP p;
815 
816  p.aProp = aPropName;
817  p.lVal = 0;
818  p.pVal = pPropVal;
819 
820  WBDialogControlSetDialogProp(pCtrl, &p);
821 }
822 
823 const char *WBDialogControlGetProperty(WBDialogControl *pCtrl, Atom aPropName)
824 {
825 const WB_DIALOG_PROP *pP = WBDialogControlGetDialogProp(pCtrl, aPropName);
826 
827  if(pP)
828  {
829  return pP->pVal; // TODO: if NULL, lVal as a string?
830  }
831 
832  return ""; // so it's not NULL
833 }
834 
835 void *WBDialogControlGetProperty2(WBDialogControl *pCtrl, Atom aPropName)
836 {
837 const WB_DIALOG_PROP *pP = WBDialogControlGetDialogProp(pCtrl, aPropName);
838 
839  if(pP)
840  {
841  return (void *)(pP->pVal); // TODO: if NULL, lVal as a string?
842  }
843 
844  return NULL;
845 }
846 
847 
848 
849 #define INITIAL_PROPERTY_MAX 64
850 
851 static WBDialogPropList * __ConstructPropList(void)
852 {
853  int iInitialSize = sizeof(WBDialogPropList) + INITIAL_PROPERTY_MAX * sizeof(WB_DIALOG_PROP);
854  WBDialogPropList *pRval = (WBDialogPropList *)WBAlloc(iInitialSize);
855 
856  if(pRval)
857  {
858  pRval->nProps = 0;
859  pRval->nMaxProps = INITIAL_PROPERTY_MAX;
860  WB_WARN_PRINT("TEMPORARY: WBDialogPropList constructor %p %d, %d\n", pRval, pRval->nProps, pRval->nMaxProps);
861  }
862  else
863  {
864  WB_ERROR_PRINT("%s - not enough memory\n", __FUNCTION__);
865  }
866 
867  return pRval;
868 }
869 
871 {
872 int i1;
873 WBDialogPropList *pPropList;
874 WB_DIALOG_PROP *pProp = NULL;
875 Atom aProp;
876 
877  if(!pCtrl || !pPropVal)
878  {
879  WB_ERROR_PRINT("%s - pCtrl %p or pPropVal %p\n", __FUNCTION__,
880  pCtrl, pPropVal);
881 
882  return -1;
883  }
884 
885  if(!pCtrl->pPropList)
886  {
887  if(!(pCtrl->pPropList = __ConstructPropList()))
888  {
889  WB_ERROR_PRINT("%s - unable to allocate property list for window %d (%08xH)\n",
890  __FUNCTION__, (int)pCtrl->wID, (int)pCtrl->wID);
891 
892  return -2;
893  }
894  }
895 
896  pPropList = pCtrl->pPropList;
897  aProp = pPropVal->aProp;
898 
899  for(i1=0; i1 < pPropList->nProps; i1++)
900  {
901  register WB_DIALOG_PROP *pProp0 = &(pPropList->aDlgProp[i1]);
902 
903  if(pProp0 && pProp0->aProp == aProp)
904  {
905  pProp = pProp0;
906  break;
907  }
908  }
909 
910  if(!pProp)
911  {
912  if((pPropList->nProps + 1) >= pPropList->nMaxProps)
913  {
914  int iNewSize = (pPropList->nMaxProps + INITIAL_PROPERTY_MAX / 2)
915  * sizeof(pPropList->aDlgProp[0])
916  + sizeof(*pPropList);
917 
918  pPropList = (WBDialogPropList *)WBReAlloc(pPropList, iNewSize);
919  if(!pPropList)
920  {
921  WB_ERROR_PRINT("%s - unable to RE-allocate property list for window %d (%08xH)\n",
922  __FUNCTION__, (int)pCtrl->wID, (int)pCtrl->wID);
923 
924  return -3;
925  }
926 
927  pCtrl->pPropList = pPropList;
928  pPropList->nMaxProps += INITIAL_PROPERTY_MAX / 2;
929 
930  if(pPropList->nProps >= pPropList->nMaxProps)
931  {
932  WB_ERROR_PRINT("%s - internal inconsistency, nProps=%d, nMaxProps=%d\n",
933  __FUNCTION__, pPropList->nProps, pPropList->nMaxProps);
934  return -4;
935  }
936  }
937 
938  pProp = &(pPropList->aDlgProp[pPropList->nProps]);
939  pPropList->nProps++;
940 
941  pProp->aProp = aProp;
942  pProp->lVal = 0;
943  pProp->pVal = NULL;
944  }
945 
946  pProp->lVal = pPropVal->lVal; // just copy the lVal
947 
948  if(pProp->pVal != pPropVal->pVal) // if it changes... and ONLY if it changes
949  {
950  if(pProp->pVal)
951  {
952  if(pProp->aProp == aDLGC_LISTINFO)
953  {
954  DLGCListInfoDestructor((LISTINFO *)(pProp->pVal));
955  }
956  else
957  {
958  WBFree(pProp->pVal);
959  }
960  }
961 
962  pProp->pVal = pPropVal->pVal;
963  }
964 
965  // last but not least, tell the dialog control its properties were altered
966  // by directly calling its callback function with the 'property change' event
967 
968  WB_DEBUG_PRINT(DebugLevel_Chatty | DebugSubSystem_DialogCtrl | DebugSubSystem_Dialog,
969  "%s - DLGC_PROP_NOTIFY (set) for window %d (%08xH)\n",
970  __FUNCTION__, (int)pCtrl->wID, (int)pCtrl->wID);
971 
972  DLGNotifySelf(pCtrl, aDLGC_PROP_NOTIFY, pPropVal->aProp, 0, 0, 0, 0);
973 
974  return 0; // success
975 }
976 
978 {
979 int i1, bNotify = 0;
980 WBDialogPropList *pPropList = pCtrl ? pCtrl->pPropList : NULL;
981 //WB_DIALOG_PROP *pProp2 = NULL;
982 WB_DIALOG_PROP sProp;
983 
984 
985  if(!pPropList)
986  {
987  return;
988  }
989 
990  for(i1=0; i1 < pPropList->nProps; i1++)
991  {
992  register WB_DIALOG_PROP *pProp = &(pPropList->aDlgProp[i1]);
993 
994  if(pProp && pProp->aProp == aProp)
995  {
996  if(pProp->pVal) // pointer?
997  {
998  if(pProp->aProp == aDLGC_LISTINFO)
999  {
1000  DLGCListInfoDestructor((LISTINFO *)(pProp->pVal));
1001  }
1002  else
1003  {
1004  WBFree(pProp->pVal);
1005  }
1006 
1007  pProp->pVal = NULL; // necessary, for the next step
1008  }
1009 
1010  memcpy(&sProp, pProp, sizeof(WB_DIALOG_PROP)); // make a copy of the thing
1011  bNotify = 1;
1012 
1013  // must remove this entry now
1014  for(i1++; i1 < pPropList->nProps; i1++)
1015  {
1016  pPropList->aDlgProp[i1 - 1] = pPropList->aDlgProp[i1];
1017  }
1018 
1019  pPropList->nProps--;
1020  bzero(&(pPropList->aDlgProp[pPropList->nProps]), sizeof(pPropList->aDlgProp[pPropList->nProps]));
1021 
1022  break;
1023  }
1024  }
1025 
1026  // last but not least, tell the dialog control its properties were altered
1027  // by directly calling its callback function with the 'property change' event
1028 
1029 // if(pProp2) NO NO NO! but this is how 'set' does it, since 'pProp2' is still valid
1030 // {
1031 // DLGNotifySelf(pCtrl, aDLGC_PROP_NOTIFY, pProp2->aProp, 0, 0, 0, 0);
1032 // }
1033 
1034  // TODO: find a better way to notify for a property that was deleted.
1035  // for now I copied the prop structure
1036 
1037  if(bNotify)
1038  {
1039  WB_DEBUG_PRINT(DebugLevel_Chatty | DebugSubSystem_DialogCtrl | DebugSubSystem_Dialog,
1040  "%s - DLGC_PROP_NOTIFY (del) for window %d (%08xH)\n",
1041  __FUNCTION__, (int)pCtrl->wID, (int)pCtrl->wID);
1042 
1043  DLGNotifySelf(pCtrl, aDLGC_PROP_NOTIFY, sProp.aProp, 0, 0, 0, 0);
1044  }
1045 
1046 }
1047 
1049 {
1050 int i1;
1051 WBDialogPropList *pPropList = pCtrl ? pCtrl->pPropList : NULL;
1052 
1053  if(!pPropList)
1054  {
1055  return NULL; // for NULL 'pCtrl' will always be the case
1056  }
1057 
1058  for(i1=0; i1 < pPropList->nProps; i1++)
1059  {
1060  register WB_DIALOG_PROP *pProp = &(pPropList->aDlgProp[i1]);
1061 
1062  if(pProp && pProp->aProp == aProp)
1063  {
1064  return pProp;
1065  }
1066  }
1067 
1068  return NULL; // not found
1069 }
1070 
1072 {
1073 int i1;
1074 
1075  if(!pPropList)
1076  {
1077  return;
1078  }
1079 
1080  for(i1=0; i1 < pPropList->nProps; i1++)
1081  {
1082  /*register*/ WB_DIALOG_PROP *pProp = &(pPropList->aDlgProp[i1]);
1083 
1084  if(pProp->pVal) // pointer?
1085  {
1086  if(pProp->aProp == aDLGC_LISTINFO)
1087  {
1088  DLGCListInfoDestructor((LISTINFO *)(pProp->pVal));
1089  }
1090  else
1091  {
1092  WBFree(pProp->pVal);
1093  }
1094 
1095 #if 0
1096  { // debug code to prevent re-free problems with b0rked list
1097  int i2;
1098 
1099  for(i2=i1+1; i2 < pPropList->nProps; i2++)
1100  {
1101  register WB_DIALOG_PROP *pProp2 = &(pPropList->aDlgProp[i2]);
1102 
1103  if(pProp->pVal == pProp2->pVal)
1104  {
1105  if(pProp->aProp == pProp2->aProp)
1106  {
1107  WB_DEBUG_PRINT(DebugLevel_ERROR | DebugSubSystem_DialogCtrl | DebugSubSystem_Dialog,
1108  "%s - %d %d matching property name %d and value %p detected\n",
1109  __FUNCTION__, i1, i2, (int)(pProp->aProp), pProp->pVal);
1110  }
1111 
1112  pProp2->pVal = NULL;
1113  pProp2->aProp = 0; // for now set this to zero as well
1114  }
1115  }
1116  }
1117 #endif // 0
1118  }
1119 
1120  bzero(pProp, sizeof(*pProp)); // zero out whatever used to be there (as a matter of course)
1121  }
1122 
1123  pPropList->nProps = 0; // matter of course
1124 
1125  WBFree(pPropList); // caller must ensure no duplicate destruction happens
1126 }
1127 
1128 
1129 
1131 // L I S T I N F O H A N D L E R S
1133 
1134 void * DLGCDefaultListInfoAllocator(const void *pData, int cbData)
1135 {
1136  void *pRval;
1137 
1138  if(cbData < 0)
1139  {
1140  if(pData)
1141  {
1142  cbData = strlen((const char *)pData) + 1;
1143  }
1144  else
1145  {
1146  return NULL;
1147  }
1148  }
1149 
1150  pRval = WBAlloc(cbData + 1);
1151 
1152  if(pRval)
1153  {
1154  if(cbData)
1155  {
1156  if(pData)
1157  {
1158  memcpy(pRval, pData, cbData);
1159  }
1160  else
1161  {
1162  bzero(pRval, cbData);
1163  }
1164  }
1165 
1166  ((char *)pRval)[cbData] = 0; // there will always be at least that one extra byte for the zero
1167  }
1168 
1169  return pRval;
1170 }
1171 
1173  void *(*pfnAllocator)(const void *,int), void (*pfnDestructor)(void *),
1174  void (*pfnDisplay)(WBDialogControl *, void *, int, WBGC, WB_GEOM *, WB_FONTC),
1175  int (*pfnSort)(const void *, const void *))
1176 {
1177 WB_DIALOG_PROP propTemp;
1178 int i1;
1179 
1180  if(!pfnDisplay)
1181  {
1182  pfnDisplay = DLGCDefaultListControlDisplayProc;
1183  }
1184 
1185  propTemp.aProp = aDLGC_LISTINFO;
1186  propTemp.lVal = 0;
1187  propTemp.pVal = DLGCListInfoConstructor(pCtrl->wID, DEFAULT_LISTINFO_MAX, nFlags,
1188  pfnAllocator, pfnDestructor, pfnDisplay, NULL);
1189 
1190  if(!propTemp.pVal)
1191  {
1192  WB_ERROR_PRINT("%s - DLGCListInfoConstructor returns NULL\n", __FUNCTION__);
1193  return -2;
1194  }
1195 
1196  i1 = WBDialogControlSetDialogProp(pCtrl, &propTemp);
1197 
1198  if(i1)
1199  {
1200  WB_ERROR_PRINT("%s - WBDialogControlSetDialogProp returns %d\n", __FUNCTION__, i1);
1201  DLGCListInfoDestructor(propTemp.pVal);
1202  }
1203 
1204  return i1; // 0 means 'success'
1205 }
1206 
1207 int DLGModifyControlListInfo(WBDialogControl *pCtrl, int bFlags, int nFlags,
1208  int bAllocator, void *(*pfnAllocator)(const void *,int),
1209  int bDestructor, void (*pfnDestructor)(void *),
1210  int bDisplay, void (*pfnDisplay)(WBDialogControl *, void *, int, WBGC, WB_GEOM *, WB_FONTC),
1211  int bSort, int (*pfnSort)(const void *, const void *))
1212 {
1213 WB_DIALOG_PROP propTemp;
1214 const WB_DIALOG_PROP *pProp;
1215 LISTINFO *pLI;
1216 //int i1;
1217 
1218 
1220 
1221  if(!pProp)
1222  {
1223  // see DLGInitControlListInfoDefault for canonical default values (this should match it actually)
1224 
1225  return DLGInitControlListInfo(pCtrl, bFlags ? nFlags : ListInfoFlags_SORTED,
1226  bAllocator ? pfnAllocator : DLGCDefaultListInfoAllocator,
1227  bDestructor ? pfnDestructor : WBFree,
1228  bDisplay ? pfnDisplay : NULL,
1229  bSort ? pfnSort : NULL);
1230  }
1231 
1232  memcpy(&propTemp, pProp, sizeof(propTemp));
1233 
1234  if(!propTemp.pVal)
1235  {
1236  WB_ERROR_PRINT("%s - DLGCListInfoConstructor returns NULL\n", __FUNCTION__);
1237  return -2;
1238  }
1239 
1240  pLI = (LISTINFO *)propTemp.pVal;
1241 
1242  // assuming it's ok, assign the various information as specified.
1243 
1244  if(bFlags)
1245  {
1246  pLI->nFlags = nFlags;
1247  }
1248 
1249  if(bAllocator)
1250  {
1251  pLI->pfnAllocator = pfnAllocator;
1252  }
1253 
1254  if(bDestructor)
1255  {
1256  pLI->pfnDestructor = pfnDestructor;
1257  }
1258 
1259  if(bDisplay)
1260  {
1261  if(pfnDisplay)
1262  {
1263  pLI->pfnDisplay = pfnDisplay;
1264  }
1265  else
1266  {
1268  }
1269  }
1270 
1271  if(bSort)
1272  {
1273  if(pfnSort)
1274  {
1275  pLI->pfnSort = pfnSort;
1276  }
1277  else
1278  {
1279  pLI->pfnSort = (int (*)(const void *,const void *))strcmp;
1280  }
1281  }
1282 
1283  return 0;
1284 }
1285 
1286 LISTINFO *DLGCListInfoConstructor(Window wOwner, int nMax, int nFlags,
1287  void *(*pfnAllocator)(const void *,int), void (*pfnDestructor)(void *),
1288  void (*pfnDisplay)(WBDialogControl *, void *, int, WBGC, WB_GEOM *, WB_FONTC),
1289  int (*pfnSort)(const void *, const void *))
1290 {
1291 LISTINFO *pRval = WBAlloc(sizeof(*pRval) + nMax * sizeof(const void *));
1292 
1293  if(pRval)
1294  {
1295  pRval->nItems = 0;
1296  pRval->nMaxItems = nMax;
1297  pRval->nPos = 0; // current scroll position (initially zero)
1298  pRval->nTop = 0; // index of top item that's visible
1299  pRval->nHeight = 0; // height of viewport in 'items'
1300  pRval->nFlags = nFlags;
1301  pRval->wOwner = wOwner;
1302  pRval->pfnAllocator = pfnAllocator;
1303  pRval->pfnDestructor = pfnDestructor;
1304  if(pfnDisplay)
1305  {
1306  pRval->pfnDisplay = pfnDisplay;
1307  }
1308  else
1309  {
1311  }
1312  if(pfnSort)
1313  {
1314  pRval->pfnSort = pfnSort;
1315  }
1316  else
1317  {
1318  pRval->pfnSort = (int (*)(const void *,const void *))strcmp;
1319  }
1320  }
1321 
1322  return pRval;
1323 }
1324 
1326 {
1327 int i1;
1328 void **paData;
1329 
1330  if(!pListInfo)
1331  {
1332  return;
1333  }
1334 
1335  paData = pListInfo->aItems;
1336 
1337  WB_DEBUG_PRINT(DebugLevel_Verbose | DebugSubSystem_DialogCtrl | DebugSubSystem_Dialog,
1338  "%s - destroying %d items using %p for %p\n",
1339  __FUNCTION__, pListInfo->nItems, pListInfo->pfnDestructor, pListInfo->aItems);
1340 
1341  for(i1=0; i1 < pListInfo->nItems; i1++)
1342  {
1343  WB_DEBUG_PRINT(DebugLevel_Verbose | DebugSubSystem_DialogCtrl | DebugSubSystem_Dialog,
1344  "%s - destroying item %d, value = %p\n",
1345  __FUNCTION__, i1, paData[i1]);
1346 
1347  if(pListInfo->pfnDestructor)
1348  {
1349  pListInfo->pfnDestructor(paData[i1]);
1350  }
1351  else if(paData[i1])
1352  {
1353  WBFree(paData[i1]);
1354  }
1355  }
1356 
1357  WBFree(pListInfo);
1358 }
1359 
1360 const char * DLGGetControlListText(WBDialogControl *pCtrl, int iIndex)
1361 {
1362  const LISTINFO *pListInfo;
1364 
1365  if(!pProp || !pProp->pVal)
1366  {
1367  return NULL;
1368  }
1369 
1370  pListInfo = (LISTINFO *)(pProp->pVal);
1371 
1372  if(iIndex == ControlListIndex_LAST)
1373  {
1374  iIndex = pListInfo->nItems - 1;
1375  }
1376 
1377  if(iIndex < 0 || iIndex >= pListInfo->nItems)
1378  {
1379  return NULL;
1380  }
1381 
1382  if(!(pListInfo->aItems[iIndex]))
1383  {
1384  return ""; // always a non-NULL return if the item exists
1385  }
1386 
1387  return (const char *)(pListInfo->aItems[iIndex]);
1388 }
1389 
1390 const void * DLGGetControlListData(WBDialogControl *pCtrl, int iIndex)
1391 {
1392  const LISTINFO *pListInfo;
1394 
1395  if(!pProp || !pProp->pVal)
1396  {
1397  return NULL;
1398  }
1399 
1400  pListInfo = (LISTINFO *)(pProp->pVal);
1401 
1402  if(iIndex == ControlListIndex_LAST)
1403  {
1404  iIndex = pListInfo->nItems - 1;
1405  }
1406 
1407  if(iIndex < 0 || iIndex >= pListInfo->nItems)
1408  {
1409  return NULL;
1410  }
1411 
1412  return pListInfo->aItems[iIndex];
1413 }
1414 
1415 static DECLARE_SORT_FUNCTION(_actual_sort_proc,p0,p1,p2)
1416 //static int _actual_sort_proc(void *p0, const void *p1, const void *p2)
1417 {
1418  const void *p1a = *((const void * const *)p1);
1419  const void *p2a = *((const void * const *)p2);
1420  LISTINFO *pListInfo = (LISTINFO *)p0;
1421 
1422  if(pListInfo->pfnSort)
1423  {
1424  return pListInfo->pfnSort(p1a, p2a);
1425  }
1426 
1427  return strcmp(p1a, p2a);
1428 }
1429 
1430 int DLGAddControlListEntry(WBDialogControl *pCtrl, const char *pData, long cbData, int iIndex)
1431 {
1432  LISTINFO *pListInfo, *pListInfo0;
1434  WB_DIALOG_PROP propTemp;
1435  int i1;
1436  void *pTemp;
1437 
1438  if(!pProp || !pProp->pVal)
1439  {
1440  if(!(pCtrl->ulFlags & CONTROL_SupportListInfo))
1441  {
1442  // check first for the property, then return an error if it's
1443  // not supported (you never know...)
1444 
1445  WB_ERROR_PRINT("%s - control does not support 'LISTINFO'\n", __FUNCTION__);
1446  return -3;
1447  }
1448 
1449  pListInfo0 = NULL;
1450 
1451  // use the default settings to initialize the LISTINFO
1452  propTemp.aProp = aDLGC_LISTINFO;
1453  propTemp.lVal = 0;
1454  propTemp.pVal = DLGCListInfoConstructor(pCtrl->wID, DEFAULT_LISTINFO_MAX, ListInfoFlags_SORTED,
1456  WBFree,
1458  NULL);
1459 
1460  if(!propTemp.pVal)
1461  {
1462  WB_ERROR_PRINT("%s - unable to allocate 'LISTINFO'\n", __FUNCTION__);
1463  return -3; // error (unable to allocate LISTINFO)
1464  }
1465  }
1466  else
1467  {
1468  propTemp.aProp = pProp->aProp;
1469  propTemp.lVal = pProp->lVal;
1470  propTemp.pVal = pProp->pVal;
1471 
1472  pListInfo0 = (LISTINFO *)propTemp.pVal;
1473  }
1474 
1475  pListInfo = (LISTINFO *)propTemp.pVal;
1476 
1477  if(iIndex == ControlListIndex_INSERT_FIRST)
1478  {
1479  iIndex = -1; // note - this should really have no effect at all
1480  }
1481  else if(iIndex == ControlListIndex_INSERT_LAST)
1482  {
1483  iIndex = pListInfo->nItems - 1;
1484  }
1485  else if(iIndex < 0 || iIndex >= pListInfo->nItems)
1486  {
1487  if(!pListInfo0)
1488  {
1489  DLGCListInfoDestructor(propTemp.pVal);
1490  }
1491 
1492  WB_ERROR_PRINT("%s - invalid index %d\n", __FUNCTION__, iIndex);
1493 
1494  return -2;
1495  }
1496 
1497  if((iIndex + 1) >= pListInfo->nMaxItems)
1498  {
1499  int nItems = pListInfo->nMaxItems;
1500  // time to re-allocate
1501 
1502  if(nItems <= 0x40000)
1503  {
1504  nItems *= 2;
1505  }
1506  else
1507  {
1508  nItems += 0x40000;
1509  }
1510 
1511  i1 = sizeof(*pListInfo)
1512  + nItems * sizeof(pListInfo->aItems[0]);
1513 
1514  propTemp.pVal = WBReAlloc(pListInfo, i1);
1515 
1516  if(!propTemp.pVal)
1517  {
1518  if(!pListInfo0) // extremely unlikely, if not impossible, extremely defensive code
1519  {
1520  WB_ERROR_PRINT("%s:%d %s - this should never happen\n", __FILE__, __LINE__, __FUNCTION__);
1521  DLGCListInfoDestructor(pListInfo); // destroy the one I just created
1522  }
1523 
1524  return -4;
1525  }
1526 
1527  pListInfo->nMaxItems = nItems;
1528  // now I must go to the property list entry itself and forcibly assign this new pointer
1529 
1530  if(pProp)
1531  {
1532  pProp->pVal = propTemp.pVal; // this prevents memory leaks in case of an error
1533  }
1534 
1535  pListInfo = (LISTINFO *)propTemp.pVal; // re-assign to new value
1536  }
1537 
1538  if(!cbData)
1539  {
1540 // WB_ERROR_PRINT("TEMPORARY: %s:%s:%d NULL cbData\n", __FILE__, __FUNCTION__, __LINE__);
1541  pTemp = (void *)pData;
1542  }
1543  else if(pListInfo->pfnAllocator)
1544  {
1545  pTemp = pListInfo->pfnAllocator(pData, cbData);
1546 
1548 // if(pTemp == pData)
1549 // {
1550 // WB_ERROR_PRINT("%s:%s:%d pData == pTemp %p\n", __FILE__, __FUNCTION__, __LINE__, pTemp);
1551 // }
1552  }
1553  else
1554  {
1555  pTemp = NULL;
1556  }
1557 
1558  if(pListInfo->nFlags & ListInfoFlags_SORTED) // regardless of index, when sorted, do this
1559  {
1560  // add to the end to simplify the process, then qsort
1561  pListInfo->aItems[pListInfo->nItems] = (void *)pTemp;
1562 
1563  pListInfo->nItems++;
1564 
1565  // note: QSORT_R macro needed because qsort_r differs between linux and BSD
1566  QSORT_R(pListInfo->aItems, pListInfo->nItems, sizeof(void *), pListInfo, _actual_sort_proc);
1567  }
1568  else
1569  {
1570  if(iIndex < pListInfo->nItems)
1571  {
1572  for(i1=pListInfo->nItems; i1 >= iIndex; i1--)
1573  {
1574  pListInfo->aItems[i1 + 1] = pListInfo->aItems[i1];
1575  }
1576  }
1577 
1578  pListInfo->aItems[iIndex] = (void *)pTemp;
1579 
1580  pListInfo->nItems++;
1581  }
1582 
1583  i1 = WBDialogControlSetDialogProp(pCtrl, &propTemp);
1584 
1585  if(i1)
1586  {
1587  if(!pListInfo0) // attempted to add new item and failed?
1588  {
1589  DLGCListInfoDestructor(propTemp.pVal);
1590  }
1591 
1592  return i1;
1593  }
1594 
1595 // WB_ERROR_PRINT("TEMPORARY: %s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);
1596 // DEBUG_DUMP_LIST(pCtrl);
1597 
1598  return 0; // meaning 'success'
1599 }
1600 
1601 void DLGDelControlListEntry(WBDialogControl *pCtrl, int iIndex)
1602 {
1603  LISTINFO *pListInfo;
1605  int i1;
1606 
1607  if(!pProp || !pProp->pVal)
1608  {
1609  WB_WARN_PRINT("%s - unable to get LISTINFO for window %d (%08xH), pProp=%p\n", __FUNCTION__,
1610  (int)pCtrl->wID, (int)pCtrl->wID, pProp);
1611  return;
1612  }
1613 
1614  pListInfo = (LISTINFO *)pProp->pVal;
1615 
1616  if(iIndex == ControlListIndex_LAST)
1617  {
1618  iIndex = pListInfo->nItems - 1;
1619  }
1620  else if(iIndex == ControlListIndex_DELETE_ALL)
1621  {
1622  if(pListInfo->pfnDestructor)
1623  {
1624  for(i1=0; i1 < pListInfo->nItems; i1++)
1625  {
1626  pListInfo->pfnDestructor(pListInfo->aItems[i1]);
1627  }
1628  }
1629 
1630  pListInfo->aItems[0] = NULL; // do this by convention
1631  pListInfo->nItems = 0;
1632 
1633  return;
1634  }
1635  else if(iIndex < 0 || iIndex >= pListInfo->nItems)
1636  {
1637  WB_ERROR_PRINT("%s - invalid index %d\n", __FUNCTION__, iIndex);
1638  return;
1639  }
1640 
1641  if(pListInfo->pfnDestructor)
1642  {
1643  pListInfo->pfnDestructor(pListInfo->aItems[iIndex]);
1644  }
1645 
1646  pListInfo->nItems--;
1647 
1648  for(i1=iIndex; i1 < pListInfo->nItems; i1++)
1649  {
1650  pListInfo->aItems[i1] = pListInfo->aItems[i1 + 1];
1651  }
1652 
1653  pListInfo->aItems[pListInfo->nItems] = NULL; // by convention
1654 
1655 // WB_ERROR_PRINT("TEMPORARY: %s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);
1656 // DEBUG_DUMP_LIST(pCtrl);
1657 }
1658 
1659 
1660 // getting "extension" structures from dialog control structure
1661 static WBListCurSel * __GetListCurSel(WBDialogControl *pCtrl)
1662 {
1663 WBListCurSel *pSel = (WBListCurSel *)(pCtrl + 1);
1664 
1665  if(!pCtrl || !(pCtrl->ulFlags & CONTROL_SupportListInfo)
1666  || (unsigned char *)(pSel + 1) > (((unsigned char *)pCtrl) + pCtrl->cbStructSize))
1667  {
1668  return NULL;
1669  }
1670 
1671  return pSel;
1672 }
1673 
1674 
1676 {
1678 WBListCurSel *pSel = __GetListCurSel(pCtrl);
1679 
1680  if(!pSel || !pProp || !pProp->pVal)
1681  {
1682  return ControlListIndex_NONE; // "no selection"
1683  }
1684 
1685  return pSel->iCurSel;
1686 }
1687 
1689 {
1691 WBListCurSel *pSel = __GetListCurSel(pCtrl);
1692 LISTINFO *pListInfo;
1693 int iOldIndex;
1694 
1695  if(!pSel || !pProp || !pProp->pVal)
1696  {
1697  WB_WARN_PRINT("%s - unable to get LISTINFO or 'selection info' for window %d (%08xH), pSel=%p, pProp=%p\n", __FUNCTION__,
1698  (int)pCtrl->wID, (int)pCtrl->wID, pSel, pProp);
1699  return;
1700  }
1701 
1702  pListInfo = (LISTINFO *)(pProp->pVal);
1703 
1704  iOldIndex = pSel->iCurSel;
1705 
1706  if(iIndex == ControlListIndex_LAST)
1707  {
1708  pSel->iCurSel = pListInfo->nItems - 1;
1709  }
1710  else if((iIndex >= 0 && iIndex < pListInfo->nItems)
1711  || iIndex == ControlListIndex_NONE)
1712  {
1713  pSel->iCurSel = iIndex;
1714  }
1715  else
1716  {
1717  WB_WARN_PRINT("%s - invalid index %d (nItems=%d)\n", __FUNCTION__, iIndex, pListInfo->nItems);
1718  return;
1719  }
1720 
1721  if(iOldIndex != pSel->iCurSel) // notify myself that something changed
1722  {
1723  DLGNotifySelf(pCtrl, aLIST_SELCHANGE, pSel->iCurSel, iOldIndex, 0, 0, 0);
1724  }
1725 }
1726 
1727 void DLGSetControlListSelectionValue(WBDialogControl *pCtrl, int iIndex, int iSelState)
1728 {
1729 }
1730 
1731 int DLGGetControlListSelectionBits(WBDialogControl *pCtrl, unsigned int *piBits, int nSize)
1732 {
1733  return 0; // for now (warning avoidance)
1734 }
1735 
1737 {
1738 int iSel = DLGGetControlListSelection(pCtrl);
1739 
1740  if(iSel >= 0)
1741  {
1742  return WBCopyString(DLGGetControlListText(pCtrl, iSel));
1743  }
1744 
1745  // TODO: multiple selections
1746 
1747  return NULL;
1748 }
1749 
1750 
1751 
1753 // the default list control display proc
1755 
1756 void DLGCDefaultListControlDisplayProc(WBDialogControl *pList, void *pData, int iSelected, WBGC gc, WB_GEOM *pGeom, WB_FONTC pFont)
1757 {
1758 int iHPos;
1759 Window wID = pList->wID;
1760 Display *pDisplay = WBGetWindowDisplay(wID);
1761 
1762 
1763  WB_DEBUG_PRINT(DebugLevel_Heavy | DebugSubSystem_Event | DebugSubSystem_DialogCtrl,
1764  "%s - Expose %d (%08xH) pData=%p\n", __FUNCTION__, (int)wID, (int)wID, pData);
1765 
1766  if(!pFont)
1767  {
1768  pFont = WBQueryWindowFont(wID);
1769 
1770  if(!pFont)
1771  {
1772  pFont = WBGetDefaultFont();
1773  }
1774  }
1775 
1776  if(!pFont)
1777  {
1778  // TODO: get font from dialog info
1779  WB_WARN_PRINT("%s - * BUG * line %d\n", __FUNCTION__, __LINE__);
1780  return;
1781  }
1782 
1783  iHPos = WBFontAvgCharWidth(pFont); // average character width is new horiz pos
1784 
1785  // font setup
1787 // XClearWindow(pDisplay, wID); // TODO: rather than erase background, see if I need to
1788  WBSetForeground(gc, iSelected ? pList->clrHBG.pixel : pList->clrBG.pixel);
1789  WBFillRectangle(pDisplay, wID, gc, pGeom->x, pGeom->y, pGeom->width, pGeom->height);
1791 
1792  if(iSelected)
1793  {
1794  WBDrawDashedRect(pDisplay, wID, gc, pGeom, pList->clrBD2.pixel);
1795  }
1796 
1797 
1798  // vertically centered text
1799 // iVPos = pFont->max_bounds.ascent + pFont->max_bounds.descent; // font height
1800 // iVPos = (pGeom->height - iVPos) >> 1; // half of the difference - top of text
1801 // iVPos += pFont->max_bounds.ascent;
1802 
1803  // painting the window text
1804 
1805  if(pData)
1806  {
1807  const char *szText = (const char *)pData;
1808  WB_RECT rctBounds;
1809 
1810  rctBounds.left = pGeom->x + iHPos;
1811  rctBounds.right = pGeom->x + pGeom->width - iHPos; // equal border on right side, too
1812  rctBounds.top = pGeom->y;
1813  rctBounds.bottom = pGeom->y + pGeom->height;
1814 
1815 
1816  WBSetForeground(gc, iSelected ? pList->clrHFG.pixel : pList->clrFG.pixel);
1817  WBSetBackground(gc, iSelected ? pList->clrHBG.pixel : pList->clrBG.pixel);
1818 
1819  if(*szText)
1820  {
1821  DTDrawSingleLineText(pFont, szText, pDisplay, gc, wID, 0, 0, &rctBounds,
1823  }
1824 
1825  if(iSelected) // selected item
1826  {
1827  WBSetForeground(gc, pList->clrFG.pixel);
1828  WBSetBackground(gc, pList->clrBG.pixel);
1829  }
1830  }
1831 
1832  // by convention, restore original objects/state
1833 
1835  WBSetForeground(gc, WBGetWindowFGColor(wID)); // restore it at the end
1837 }
1838 
1839 
1840 
1841 
1843 // S C R O L L B A R H A N D L E R
1845 
1846 int DLGScrollBarHandler(Window wID, WBDialogControl *pCtrl, XEvent *pEvent)
1847 {
1848 int iRval;
1849 WB_SCROLLINFO *pScrollInfo;
1850 
1851 
1852  if(pEvent->type != ClientMessage)
1853  {
1854  return 0;
1855  }
1856 
1857  // look for the following:
1858  // left-button click inside of scroll bar
1859  // left button click ON the knob
1860  // left button click above/below/right-of/left-of knob
1861  // left button click on top/bottom/left/right arrow
1862 
1863  if(pEvent->xclient.message_type == aWB_POINTER)
1864  {
1865  // pointer messages - cooked mousie clickie
1866  WB_ERROR_PRINT("TEMPORARY: %s mouse message %d (%08xH) %d %d %d %d %d\n",
1867  __FUNCTION__,
1868  (int)pEvent->xclient.window, (int)pEvent->xclient.window,
1869  (int)pEvent->xclient.data.l[0],
1870  (int)pEvent->xclient.data.l[1],
1871  (int)pEvent->xclient.data.l[2],
1872  (int)pEvent->xclient.data.l[3],
1873  (int)pEvent->xclient.data.l[4]);
1874 
1876 
1877  iRval = WBScrollBarEvent(wID, pEvent, pScrollInfo);
1878  if(pScrollInfo && iRval)
1879  {
1880  return iRval; // return whatever 'WBScrollBarEvent' says to return
1881  }
1882  }
1883  else if(pEvent->xclient.message_type == aWB_CHAR)
1884  {
1885  // handle cursors only - up, down, left, right, home, end, page up, page down, etc.
1886 
1887  long lKey = pEvent->xclient.data.l[0]; // return from WBKeyEventProcessKey
1888  long lAltCtrlShift = pEvent->xclient.data.l[1]; // *piAltCtrlShift from WBKeyEventProcessKey
1889 #ifndef NO_DEBUG
1890  int nChar = (int)pEvent->xclient.data.l[2]; // # of characters decoded into pBuf (below)
1891  char *pBuf = (char *)&(pEvent->xclient.data.l[3]); // decode buffer (at least 8 chars in length)
1892 #endif // !NO_DEBUG
1893 
1894 
1895  WB_ERROR_PRINT("TEMPORARY: %s char message %lx %ld %d %s\n", __FUNCTION__, lAltCtrlShift, lKey, nChar, pBuf);
1896 
1897  if(lAltCtrlShift & WB_KEYEVENT_KEYSYM) // symbol keys only for this part
1898  {
1900 
1901  if(WB_LIKELY(pScrollInfo != NULL))
1902  {
1903  int iShift = lAltCtrlShift & WB_KEYEVENT_SHIFT;
1904  int iCtrl = lAltCtrlShift & WB_KEYEVENT_CTRL;
1905  int iAlt = lAltCtrlShift & WB_KEYEVENT_ALT;
1906  int iBar = (int)WB_SCROLL_NA;
1907  int iDirection = (int)WB_SCROLL_NA;
1908 
1909  switch(lKey)
1910  {
1911  case XK_Up:
1912  if(iShift || iCtrl || iAlt)
1913  {
1914  return 0;
1915  }
1916 
1917  iBar = WB_SCROLL_VERTICAL;
1918  iDirection = WB_SCROLL_BACKWARD;
1919  break;
1920 
1921  case XK_Down:
1922  if(iShift || iCtrl || iAlt)
1923  {
1924  return 0;
1925  }
1926 
1927  iBar = WB_SCROLL_VERTICAL;
1928  iDirection = WB_SCROLL_FORWARD;
1929  break;
1930 
1931  case XK_Left:
1932  if(iShift || iCtrl || iAlt)
1933  {
1934  return 0;
1935  }
1936 
1937  iBar = WB_SCROLL_HORIZONTAL;
1938  iDirection = WB_SCROLL_BACKWARD;
1939  break;
1940 
1941  case XK_Right:
1942  if(iShift || iCtrl || iAlt)
1943  {
1944  return 0;
1945  }
1946 
1947  iBar = WB_SCROLL_HORIZONTAL;
1948  iDirection = WB_SCROLL_FORWARD;
1949  break;
1950 
1951  case XK_Home:
1952 
1953  if(iShift || iAlt)
1954  {
1955  return 0;
1956  }
1957 
1958  if(iCtrl)
1959  {
1960  iBar = WB_SCROLL_VERTICAL;
1961  }
1962  else
1963  {
1964  iBar = WB_SCROLL_HORIZONTAL;
1965  }
1966 
1967  iDirection = WB_SCROLL_FIRST;
1968  break;
1969 
1970  case XK_End:
1971 
1972  if(iShift || iAlt)
1973  {
1974  return 0;
1975  }
1976 
1977  if(iCtrl)
1978  {
1979  iBar = WB_SCROLL_VERTICAL;
1980  }
1981  else
1982  {
1983  iBar = WB_SCROLL_HORIZONTAL;
1984  }
1985 
1986  iDirection = WB_SCROLL_LAST;
1987  break;
1988 
1989  case XK_Page_Up:
1990 
1991  if(iShift || iAlt)
1992  {
1993  return 0;
1994  }
1995 
1996  if(!iCtrl)
1997  {
1998  iBar = WB_SCROLL_VERTICAL;
1999  }
2000  else
2001  {
2002  iBar = WB_SCROLL_HORIZONTAL;
2003  }
2004 
2005  iDirection = WB_SCROLL_PAGEBACK;
2006  break;
2007 
2008  case XK_Page_Down:
2009 
2010  if(iShift || iAlt)
2011  {
2012  return 0;
2013  }
2014 
2015  if(!iCtrl)
2016  {
2017  iBar = WB_SCROLL_VERTICAL;
2018  }
2019  else
2020  {
2021  iBar = WB_SCROLL_HORIZONTAL;
2022  }
2023 
2024  iDirection = WB_SCROLL_PAGEFWD;
2025  break;
2026 
2027  default:
2028  return 0;
2029  }
2030 
2031  // see if the bar is actually visible first
2032  if(iBar == WB_SCROLL_HORIZONTAL)
2033  {
2034  if(pScrollInfo->geomHBar.width <= 0 || pScrollInfo->geomHBar.height <= 0)
2035  {
2036  return 0; // no vertical scroll bar
2037  }
2038  }
2039  else // vertical
2040  {
2041  if(pScrollInfo->geomVBar.width <= 0 || pScrollInfo->geomVBar.height <= 0)
2042  {
2043  return 0; // no vertical scroll bar
2044  }
2045  }
2046 
2047  DLGNotifySelf(pCtrl, aSCROLL_NOTIFY, iBar, iDirection, 0, 0, 0);
2048  return 1; // keystroke eaten
2049  }
2050  }
2051  }
2052 
2053  return 0; // NOT handled
2054 }
2055 
2056 
2057 #ifndef NO_DEBUG
2058 void DEBUG_DUMP_LIST(WBDialogControl *pCtrl)
2059 {
2060  LISTINFO *pListInfo;
2061  WB_DIALOG_PROP *pProp;
2062  int i1;
2063  const char *p1;
2064 
2065 
2066  if(WB_LIKELY((WBGetDebugLevel() & DebugLevel_MASK) < (DebugLevel_Light & DebugLevel_MASK)) ||
2067  ((WBGetDebugLevel() & DebugSubSystem_MASK) && !(DebugSubSystem_DialogCtrl & WBGetDebugLevel())))
2068  {
2069  return;
2070  }
2071 
2073 
2074  if(!pProp || !pProp->pVal)
2075  {
2076  if(!(pCtrl->ulFlags & CONTROL_SupportListInfo))
2077  {
2078  WBDebugPrint("%s - control does not support 'LISTINFO'\n", __FUNCTION__);
2079  }
2080  else
2081  {
2082  WBDebugPrint("%s - 'LISTINFO' is empty\n", __FUNCTION__);
2083  }
2084 
2085  return;
2086  }
2087 
2088  pListInfo = (LISTINFO *)pProp->pVal;
2089 
2090  if(pListInfo->nFlags & ListInfoFlags_SORTED) // regardless of index, when sorted, do this
2091  {
2092  WBDebugPrint("%s - 'LISTINFO' is sorted\n", __FUNCTION__);
2093  }
2094 
2095  WBDebugPrint("%s - 'LISTINFO' %d items\n", __FUNCTION__, pListInfo->nItems);
2096 
2097  for(i1=0; i1 < pListInfo->nItems; i1++)
2098  {
2099  // for now assume string data
2100  WBDebugPrint(" %6d: %p %s\n", i1, pListInfo->aItems[i1], (char *)(pListInfo->aItems[i1]));
2101  }
2102 }
2103 #endif // NO_DEBUG
2104 
2105 
WBDialogPropList * pPropList
pointer to the property list (may be NULL)
#define WB_LIKELY(x)
optimization for code branching when condition is 'likely'. use within conditionals
Atom aLOSTFOCUS
CONTROL_NOTIFY ClientMessage for LOSTFOCUS event.
int iCurSel
current selection
Atom aDLGC_SCROLLINFO
dialog control SCROLLINFO property - see WB_SCROLLINFO structure
2nd parameter (direction) - up, left
'window helper' main header file for the X11workbench Toolkit API
void DLGCListInfoDestructor(LISTINFO *pListInfo)
Destroy a LISTINFO structure.
unsigned long ulFlags
generic flag bits
Atom aGOTFOCUS
CONTROL_NOTIFY ClientMessage for GOTFOCUS event.
Structure containing information about the current selection in a list.
Atom aDLGC_PROP_NOTIFY
DLGC_PROP_NOTIFY ClientMessage, notify control of property change.
Atom aDLGC_LISTINFO
dialog control LISTINFO property - see DLGInitControlListInfo() etc.
#define WB_DEBUG_PRINT(L,...)
Preferred method of implementing conditional debug output.
Definition: debug_helper.h:364
int nTop
scroll position of the top item currently displayed
void DLGDelControlListEntry(WBDialogControl *pCtrl, int iIndex)
Delete a list entry from a control's list info at a specified index (or deletes ALL entries)
Utilities for copying and drawing text, determining text extents, and so on.
Atom aDLGC_CONTROL_SET
CONTROL_SET ClientMessage - use this to set specific supported control properties by sending it to th...
this control supports a LISTINFO property.
Atom aPATH_TREE_CONTROL
Standard Dialog Control - path tree - directory hierarchy - see PATH_TREE_CONTROL_STR.
int WBFontAvgCharWidth(WB_FONTC pFont0)
Get the average character width for a font.
Definition: font_helper.c:343
generic 'NA' or 'UNDEFINED' value
Atom aMOUSE_DBLCLICK
CONTROL_NOTIFY ClientMessage for MOUSE_DBLCLICK event.
int WBScrollBarEvent(Window wID, XEvent *pEvent, WB_SCROLLINFO *pScrollInfo)
Event handler for scroll bars.
Atom aLIST_NOTIFY
CONTROL_NOTIFY ClientMessage for LIST_NOTIFY event.
int nMaxItems
max size of aItems (must re-alloc to increase nMaxItems)
#define WB_KEYEVENT_ALT
'AltCtrlShift' bit flag for ALT modifier for WBKeyEventProcessKey()
void(* pfnDestructor)(void *)
destructor to call for each item that's removed
Static 'Image' control structure.
void DLGCDefaultListControlDisplayProc(WBDialogControl *pList, void *pData, int iSelected, WBGC gc, WB_GEOM *pGeom, WB_FONTC pFont)
The default 'display proc' for displaying a list item from a LISTINFO structure.
Atom aDLGC_CONTROL_GET
CONTROL_GET ClientMessage - use this to get specific supported control properties by sending it to th...
void DLGSetControlListSelection(WBDialogControl *pCtrl, int iIndex)
Assign the current selection index for a single-selection list.
unsigned int width
Atom aKEY_DOWN
CONTROL_NOTIFY ClientMessage for KEY_DOWN event.
#define DECLARE_SORT_FUNCTION(fn_name, p0, p1, p2)
Wrapper to declare a sort function for QSORT_R.
int WBWindowDispatch(Window wID, XEvent *pEvent)
Dispatches a window XEvent. May be called directly.
int DLGAddControlListEntry(WBDialogControl *pCtrl, const char *pData, long cbData, int iIndex)
Add a list entry to a control's list info.
int DLGInitControlListInfo(WBDialogControl *pCtrl, int nFlags, void *(*pfnAllocator)(const void *, int), void(*pfnDestructor)(void *), void(*pfnDisplay)(WBDialogControl *, void *, int, WBGC, WB_GEOM *, WB_FONTC), int(*pfnSort)(const void *, const void *))
Initialize the 'List Entry' for a control, specifying various callbacks and flags.
1st parameter (bar) - The vertical scroll bar for the control or window.
Atom aDLGC_PATH
dialog control PATH property, for file and directory controls
Atom aDEFPUSHBUTTON_CONTROL
Standard Dialog Control - default Pushbutton control (has dark border, accepts <ENTER> as hotkey) - s...
WB_GEOM geomVBar
geometry for the vertical scroll bar excluding border (empty if not visible)
Atom aLIST_SELCHANGE
LIST_SELCHANGE ClientMessage, notify self of list selection change.
Atom aWB_CHAR
keystroke/character notifications generated by API
const void * DLGGetControlListData(WBDialogControl *pCtrl, int iIndex)
Retrieve the data pointer for a single list entry (listbox, combo, and tree controls only)
static __inline__ Display * WBGetDefaultDisplay(void)
Returns the default Display.
internal wrapper struct for X11 'geometry' definition
'configuration helper' main header file for the X11 Work Bench Toolkit API
void DTDrawSingleLineText(WB_FONTC pFont, const char *szText, Display *pDisplay, WBGC gc, Drawable dw, int iTabWidth, int iTabOrigin, const WB_RECT *prcBounds, int iAlignment)
draw single-line text
Definition: draw_text.c:1531
void * WBReAlloc(void *pBuf, int nNewSize)
High performance memory sub-allocator 're-allocate'.
Atom aDIALOG_INIT
DIALOG_INIT ClientMessage, sent to dialog window callback on frame create.
int(* pfnSort)(const void *, const void *)
Optional sort comparison function. NULL implies 'strcmp'.
int WBSetForeground(WBGC hGC, unsigned long foreground)
Assign foreground color, a wrapper for XSetForeground()
int nPos
current scroll position
Atom aWB_POINTER
pointer click/double-click/drag notifications generated by API
Atom aClass
basic control class atom
Atom aMOUSE_CLICK
CONTROL_NOTIFY ClientMessage for MOUSE_CLICK event.
int nFlags
flags (sorted, etc.)
WB_FONTC WBQueryWindowFont(Window wID)
Returns the WB_FONT assigned to the window (may be NULL), not a copy.
Atom aLIST_CONTROL
Standard Dialog Control - list - single, multi, extended select (h, v, multicol) - see LIST_CONTROL_S...
void WBDialogControlDelDialogProp(WBDialogControl *pCtrl, Atom aProp)
Low-level dialog control property removal.
Atom aRADIOBUTTON_CONTROL
Standard Dialog Control - radio button - see RADIOBUTTON_CONTROL_STR.
int nItems
current number of valid entries in 'aItems'
const char * WBDialogControlGetProperty(WBDialogControl *pCtrl, Atom aPropName)
Mid-level dialog control property retrieval (character string)
Atom aSCROLL_NOTIFY
Atom aSLIDER_CONTROL
Standard Dialog Control - volume control (slider bar) (h or v depending on geometry) - see SLIDER_CON...
void WBInvalidateGeom(Window wID, const WB_GEOM *pGeom, int bPaintNow)
'Paint' helper, invalidates a geometry for asynchronous Expose event generation
int nMaxProps
maximum number of available WB_DIALOG_PROP structures in aDlgProp
1st parameter (bar) - The horizontal scroll bar for the control or window
XColor clrBG
background color
void WBDialogControlSetIconPixmap(WBDialogControl *pCtrl, Pixmap pixmap, Pixmap pixmap2)
Assign the ICON (image) property for a control, which consists of 2 pixmaps.
unsigned long WBGetWindowFGColor(Window wID)
Returns the currently assigned foreground color.
void * pVal
pointer to data, as needed (may be allocated, some property types auto-free the data)
center using entire text height (ascent + descent for single line)
Definition: draw_text.h:86
Atom aTAB_CONTROL
Standard Dialog Control -'tab' container (auto enable/disable contents) - see TAB_CONTROL_STR.
2nd parameter (direction) - bottom, end
Atom aTEXT_CONTROL
Standard Dialog Control - static text (single or multi-line) - see TEXT_CONTROL_STR.
Atom aDLGC_FONT
dialog control FONT property - reserved
void * WBAlloc(int nSize)
High performance memory sub-allocator 'allocate'.
#define END_XCALL_DEBUG_WRAPPER
wrapper macro for calls into the X11 library. This macro follows the call(s)
Pixmap WBDialogControlGetPixmap(WBDialogControl *pCtrl)
Obtain the assigned PIXMAP (image) property for a control.
int WBDialogControlSetDialogProp(WBDialogControl *pCtrl, WB_DIALOG_PROP *pPropVal)
Low-level dialog control property assignment.
XColor clrFG
foreground color
Atom aCOMBO_CONTROL
Standard Dialog Control - classic 'combo box' control - see COMBO_CONTROL_STR.
int DLGGetControlListSelectionBits(WBDialogControl *pCtrl, unsigned int *piBits, int nSize)
Query the selection state for multiple items within a control's list info.
#define WB_ERROR_PRINT(...)
Preferred method of implementing an 'error level' debug message for all subsystems.
Definition: debug_helper.h:474
Atom aDLGC_CAPTION
dialog control CAPTION property - see WBDialogControlGetCaption()
char * DLGGetControlListSelectionText(WBDialogControl *pCtrl)
Query the selection text as multiple strings in an allocated buffer.
Atom aFILE_COMBO_CONTROL
Standard Dialog Control - file combo control - see FILE_COMBO_CONTROL_STR.
int WBDialogControlSetPropList(WBDialogControl *pCtrl, const char *szPropList)
Mid-level dialog control property list assignment.
Atom aVSCROLL_CONTROL
Standard Dialog Control - vertical scroll - see VSCROLL_CONTROL_STR.
XColor clrHFG
highlighted state-based foreground color
Atom aDLGC_TEXT
dialog control TEXT property - see WBDialogControlGetText()
#define QSORT_R(base, nmemb, size, thunk, compar)
Local implementation of qsort_r() for operating systems that do not have it.
struct s_WB_DIALOG_PROPLIST WBDialogPropList
Dialog Property List, container for WB_DIALOG_PROP.
void WBFree(void *pBuf)
High performance memory sub-allocator 'free'.
Window wID
Window ID of the dialog control window.
XColor clrBD2
3D border color 2 (light)
2nd parameter (direction) - pgup, pgleft
#define WB_KEYEVENT_SHIFT
'AltCtrlShift' bit flag for Shift modifier for WBKeyEventProcessKey()
Atom aCOMBOTREE_CONTROL
Standard Dialog Control - 'combo tree' (tree with interlocked edit/text box like combo box) - see COM...
WB_GEOM geomHBar
geometry for the horizontal scroll bar excluding border (empty if not visible)
void *(* pfnAllocator)(const void *, int)
pointer to the copy constructor to call for each item that's added
void WBUpdateWindow(Window wID)
'Paint' helper, generates an asynchronous Expose event for non-empty 'invalid' region
Atom aEDIT_CONTROL
Standard Dialog Control - editable text (single or multi-line, scrollable, clipboard) - see EDIT_CONT...
void(* pfnDisplay)(WBDialogControl *pControl, void *pData, int iSelected, WBGC gcPaint, WB_GEOM *pGeom, WB_FONTC pFont)
display callback function to paint the entry on the display surface
int WBDialogControlGetCheck(WBDialogControl *pCtrl)
Retrieve the 'CHECKED' property from a dialog control. Returns '0' (un-checked) if not applicable.
unsigned long lVal
'long' data value, assigned as needed
A 'C++'-like object for managing text, that can be overridden for custom behavior.
Atom aKEYSTROKE
CONTROL_NOTIFY ClientMessage for KEYSTROKE event.
void WBDrawDashedRect(Display *pDisplay, Drawable wID, WBGC gc, WB_GEOM *pgeomRect, unsigned long lColor)
Draw a 'dashed' rectangle.
void DLGCDestroyProperties(WBDialogPropList *pPropList)
Destroy Properties for a dialog control.
Dialog property storage structure.
XColor clrHBG
highlighted state-based background color
void * WBDialogControlGetProperty2(WBDialogControl *pCtrl, Atom aPropName)
Mid-level dialog control property list retrieval (generic pointer)
Atom aCANCELBUTTON_CONTROL
Standard Dialog Control - cancel pushbutton control (accepts <ESC> as hotkey) - see CANCELBUTTON_CONT...
int nProps
current number of (contiguous) properties in 'aDlgProp'
Atom aHSCROLL_CONTROL
Standard Dialog Control - horizontal scroll - see HSCROLL_CONTROL_STR.
2nd parameter (direction) - home, top
Atom aCHECKBUTTON_CONTROL
Standard Dialog Control - check[box] button - push-on/push-off with 'check mark' (or whatever) - see ...
Atom aKEY_UP
CONTROL_NOTIFY ClientMessage for KEY_UP event.
Atom aMOUSE_DRAG
CONTROL_NOTIFY ClientMessage for MOUSE_DRAG event.
unsigned int height
const char * WBDialogControlGetCaption(WBDialogControl *pCtrl)
Obtain a pointer to the assigned text for the 'CAPTION' property of a dialog control.
internal wrapper struct for 'rectangle' definition
int DLGModifyControlListInfo(WBDialogControl *pCtrl, int bFlags, int nFlags, int bAllocator, void *(*pfnAllocator)(const void *, int), int bDestructor, void(*pfnDestructor)(void *), int bDisplay, void(*pfnDisplay)(WBDialogControl *, void *, int, WBGC, WB_GEOM *, WB_FONTC), int bSort, int(*pfnSort)(const void *, const void *))
Modify the 'List Entry' for a control, specifying various callbacks and flags.
const WB_DIALOG_PROP * WBDialogControlGetDialogProp(WBDialogControl *pCtrl, Atom aProp)
Low-level dialog control property retrieval.
Atom aIMAGE_CONTROL
Standard Dialog Control - generic image/pixmap holder - see IMAGE_CONTROL_STR.
Atom aTEXTSELECT_CHANGE
CONTROL_NOTIFY ClientMessage for TEXTSELECT_CHANGE event.
char * pCaption
allocated pointer to caption, in lieu of using a WM_NAME property (may be NULL)
WB_DIALOG_PROP aDlgProp[1]
Pre-allocated array of (contiguous) structures for property storage.
Display * WBGetWindowDisplay(Window wID)
returns the Display associated with a window
void * aItems[1]
The array of item data, integrated into the memory block containing this structure.
int DLGGetControlListSelection(WBDialogControl *pCtrl)
Obtain the current selection index for a single-selection list.
void DLGSetControlListSelectionValue(WBDialogControl *pCtrl, int iIndex, int iSelState)
Assign the selection state for a specific index within a control's list info.
Atom aKNOB_CONTROL
Standard Dialog Control - "volume knob" (270 degrees of rotation, left to right) - see KNOB_CONTROL_S...
2nd parameter (direction) - pgdn, pgright
Atom aFIRSTRADIOBUTTON_CONTROL
Standard Dialog Control - 'first' radio button - defines start of radio button 'group' - see FIRSTRAD...
Atom aTREE_CONTROL
Standard Dialog Control - class 'tree' control - see TREE_CONTROL_STR.
Structure containing data for list-related dialog controls.
#define BEGIN_XCALL_DEBUG_WRAPPER
wrapper macro for calls into the X11 library. This macro precedes the call(s)
int nHeight
height (in items) of display area, recalculated on resize/expose
int DLGScrollBarHandler(Window wID, WBDialogControl *pCtrl, XEvent *pEvent)
Scroll bar event filter for dialog control callback function. Generates scroll events.
int WBFillRectangle(Display *display, Drawable d, WBGC gc, int x, int y, unsigned int width, unsigned int height)
Wrapper for XFillRectangle()
Atom aBUTTON_PRESS
CONTROL_NOTIFY ClientMessage for BUTTON_PRESS event.
int WBSetBackground(WBGC hGC, unsigned long background)
Assign background color, a wrapper for XSetBackground()
void WBDebugPrint(const char *pFmt,...) __attribute__((format(printf
conditional debug message output
#define WB_KEYEVENT_CTRL
'AltCtrlShift' bit flag for Control modifier for WBKeyEventProcessKey()
An allocated structure containing XFontStruct, XFontInfo, and XftFont [as applicable] for a specified...
Definition: font_helper.h:152
Atom aICON_CONTROL
Standard Dialog Control - icon container (has a nice 3D border) - see ICON_CONTROL_STR.
left-justified text
Definition: draw_text.h:77
Atom aTRISTATEBUTTON_CONTROL
Standard Dialog Control - tristate - like check, but with a third state - see TRISTATEBUTTON_CONTROL_...
static __inline__ void DLGNotifySelf(WBDialogControl *pDialogControl, Atom aNotify, long lData0, long lData1, long lData2, long lData3, long lData4)
Notify 'self' by calling the window's own callback function directly with an event.
char * WBCopyString(const char *pSrc)
A simple utility that returns a WBAlloc() copy of a 0-byte terminated string.
Atom aProp
Atom identifying the property.
Dialog Property List, container for WB_DIALOG_PROP.
Atom aFRAME_CONTROL
Standard Dialog Control - transparent frame with optional text - see FRAME_CONTROL_STR.
internal wrapper struct for GC with local cache
int WBDialogControlSetProperty(WBDialogControl *pCtrl, Atom aPropName, const char *szPropVal)
Mid-level dialog control property assignment (character string)
Atom aFILE_LIST_CONTROL
Standard Dialog Control - File List - see FILE_LIST_CONTROL_STR.
Pixmap WBDialogControlGetIconPixmap(WBDialogControl *pCtrl, Pixmap *pPixmap2)
Obtain the assigned ICON (image) property for a control, which consists of 2 pixmaps.
Structure that defines scroll bar info for both horizontal and vertical scroll bars.
2nd parameter (direction) - down, right
void * DLGCDefaultListInfoAllocator(const void *pData, int cbData)
The default 'List Info' data allocator for a control's list info.
void WBDialogControlSetCheck(WBDialogControl *pCtrl, int iCheck)
Assign the TEXT property for a control, which is different from the CAPTION or Title.
Atom aPUSHBUTTON_CONTROL
Standard Dialog Control - Pushbutton control - see PUSHBUTTON_CONTROL_STR.
Window wOwner
owning window [to be notified on change]
void WBDialogControlsInit(void)
Initialization function for dialog controls.
void WBDialogControlSetPixmap(WBDialogControl *pCtrl, Pixmap pixmap)
Assign the PIXMAP (image) property for a control.
always insert at beginning
const char * DLGGetControlListText(WBDialogControl *pCtrl, int iIndex)
Retrieve the text poiner for a single list entry (listbox, combo, and tree controls only)
void WBDialogControlSetCaption(WBDialogControl *pCtrl, const char *szCaption)
Assign text to the 'CAPTION' property of a dialog control.
Button 'pushbutton' control structure.
#define WB_WARN_PRINT(...)
Preferred method of implementing a 'warning level' debug message for all subsystems.
Definition: debug_helper.h:467
Structure identifying the properties of a dialog box control.
int cbStructSize
assigned at allocation time, the total size of this structure
LISTINFO * DLGCListInfoConstructor(Window wOwner, int nMax, int nFlags, void *(*pfnAllocator)(const void *, int), void(*pfnDestructor)(void *), void(*pfnDisplay)(WBDialogControl *, void *, int, WBGC, WB_GEOM *, WB_FONTC), int(*pfnSort)(const void *, const void *))
Create LISTINFO structure for a list type control.
void WBDialogControlSetProperty2(WBDialogControl *pCtrl, Atom aPropName, void *pPropVal)
Mid-level dialog control property list assignment (generic pointer)
Atom aTEXT_CHANGED
CONTROL_NOTIFY ClientMessage for TEXT_CHANGED event.
'checked' flag. when 'setting', -1 'toggles', 1 sets it, 0 clears it. when 'getting',...
static __inline__ WB_UINT64 WBGetDebugLevel(void)
Returns the current debug level assigned by WBSetDebugLevel.
Definition: debug_helper.h:185
#define WB_KEYEVENT_KEYSYM
'AltCtrlShift' bit flag for 'VK_' keys for WBKeyEventProcessKey()
WB_FONTC WBGetDefaultFont(void)
Returns a pointer to the default font WB_FONT for the default display. This is a shared resource; do ...