/* SrcGen: GadToolBox source generator for E

   SrcGen v0.5 updated by Jason R. Hulance (jason@fsel.com) from the
   excellent work by Wouter van Oortmerssen (with some extensions by
   Martin Kuchinka).

See SrcGen.doc for more details.

Changes in v0.5:
   - Can now open custom and public screens, not just Workbench
   - Can now generate code to use selected font
   - Added template function generation for common actions
   - Added (very efficient) multi-window processing
   - Added (rudimentary) support for GetFile button
   - Added SA_DISPLAYID decoding into constants
   - Can now handle ' and \ in strings
   - Can now handle illegal characters in project names
   - Tidied constant production code
   - Fixed AUTO_ADJUST bug!
   - Fixed decoding of WA_XXX constants
   - Fixed disabled menus/menuitems
   - Fixed IDCMP flags to use correct bits
   - Fixed window flags to use correct bits
   - Fixed production of SMART refresh flag
   - Fixed menu selection handling
*/

OPT OSVERSION=37

ENUM NONE,NOMEM,BADARGS,NOGTXLIB,LOADGUI,NOGUI,NOWINDOWS,NOFILEOUT

SET HASGADGETS,HASMENUS

MODULE 'gtx', 
       'gadtoolsbox/forms', 
       'gadtoolsbox/gui', 
       'gadtoolsbox/gtxbase',
       'graphics/text',
       'graphics/modeid',
       'nofrag', 
       'libraries/gadtools', 
       'utility', 
       'intuition/gadgetclass',
       'intuition/intuition',
       'intuition/iobsolete',
       'intuition/screens',
       'tools/ctype'

DEF guiptr:guidata,
    wlist:windowlist,
    kinds:PTR TO LONG,
    gttags1:PTR TO LONG,gttags2:PTR TO LONG,gatags:PTR TO LONG,
    pgatags:PTR TO LONG,latags:PTR TO LONG,strtags:PTR TO LONG,
    watags:PTR TO LONG,done_or=FALSE,has_getfile=FALSE,
    win[100]:LIST,
    infile[100]:STRING,outfile[100]:STRING,
    mainf=TRUE,erf=TRUE,mesf=TRUE,layoutf=TRUE,processf=TRUE,quietf=FALSE,
    lastkind,wname,templatef=TRUE,multif=TRUE,fontf=TRUE

PROC main() HANDLE
  DEF myargs:PTR TO LONG,rdargs=NIL,chain=NIL,gbase:PTR TO gtxbase,valid=NIL
  myargs:=[0,0,0,0,0,0,0,0,0,0]
  IF (rdargs:=ReadArgs('GUIFILE/A,NOMAIN/S,NOERR/S,NOMES/S,NOLAYOUT/S,NOPROCESS/S,QUIET/S,NOTEMPLATE/S,NOMULTI/S,NOFONT/S',myargs,NIL))=NIL THEN Raise(BADARGS)
  IF (gtxbase:=OpenLibrary('gadtoolsbox.library',0))=NIL THEN Raise(NOGTXLIB)
  IF myargs[1] THEN mainf:=FALSE    /* generate no PROC main() */
  IF myargs[2] THEN erf:=FALSE      /* no error report function */
  IF myargs[3] THEN mesf:=FALSE     /* no wait4message() */
  IF myargs[4] THEN layoutf:=FALSE  /* no layout: all tags on one line */
  IF myargs[5] THEN processf:=FALSE /* no process(): function */
  IF myargs[6] THEN quietf:=TRUE    /* no messages */
  IF myargs[7] THEN templatef:=FALSE /* no templates */
  IF myargs[8] THEN multif:=FALSE   /* no multi-window handling */
  IF myargs[9] THEN fontf:=FALSE    /* no font (use default) */
  IF quietf=FALSE THEN WriteF('GadToolsBox Amiga E Src Gen v0.5 (c) 1993-7, Wouter & Martin Kuchinka & Jason\n')
  StrCopy(infile,myargs[0])
  StrCopy(outfile,infile)
  StrAdd(infile,'.gui')
  StrAdd(outfile,'.e')
  gbase:=gtxbase
  nofragbase:=gbase.nofragbase
  utilitybase:=gbase.utilitybase
  IF (chain:=GetMemoryChain(4096))=NIL THEN Raise(NOMEM)
  IF GtX_LoadGUIA(chain,infile,[RG_GUI,guiptr,RG_WINDOWLIST,wlist,RG_VALID,{valid},NIL]) THEN Raise(LOADGUI)
  IF (valid AND VLF_GUI)=0 THEN Raise(NOGUI)
  IF (valid AND VLF_WINDOWLIST)=0 THEN Raise(NOWINDOWS)
  IF quietf=FALSE THEN WriteF('Generating source...\n\n')
  generate()
  Raise(NONE)
EXCEPT
  IF valid AND VLF_WINDOWLIST THEN GtX_FreeWindows(chain,wlist)
  IF chain THEN FreeMemoryChain(chain,TRUE)
  IF gtxbase THEN CloseLibrary(gtxbase)
  IF rdargs THEN FreeArgs(rdargs)
  IF quietf=FALSE
    WriteF('\s!\n',ListItem(['Done',
    'Out of Memory',
    'Bad args',
    'Could not open gadtoolsbox library',
    'Problems reading GUI file',
    'missing GUI definition',
    'missing window definitions',
    'problems while writing E source'],exception))
  ENDIF
ENDPROC

PROC generate()
  DEF fh
  IF ( fh:=Open(outfile,NEWFILE) )=NIL THEN Raise(NOFILEOUT)
  fh:=SetStdOut(fh)
  initlists()
  WriteF('/* GadToolsBox GUI: E source generated by SrcGen v0.5    */\n'+
         '/*                 (by Wouter & Martin Kuchinka & Jason) */\n\n'+
         'OPT OSVERSION=37,PREPROCESS\n\n' +
         'MODULE ''gadtools'',\n'+
         '       ''libraries/gadtools'',\n'+
         '       ''exec/memory'',\n'+
         '       ''exec/ports'',\n'+
         '       ''exec/lists'',\n'+
         '       ''exec/nodes'',\n'+
         '       ''graphics/modeid'',\n'+
         '       ''graphics/rastport'',\n'+
         '       ''intuition/intuition'',\n'+
         '       ''intuition/screens'',\n'+
         '       ''intuition/gadgetclass'',\n'+
         '       ''intuition/iobsolete'',\n'+
         '       ''utility/tagitem'',\n'+
         '       ''devices/inputevent'',\n'+
         '       ''graphics/text''\n\n')
  IF fontf
    WriteF('MODULE ''diskfont''\n\n')
  ENDIF
  WriteF(
         'ENUM ERROR_NONE,\n'+
         '     ERROR_CONTEXT,\n'+
         '     ERROR_GADGET,\n'+
         '     ERROR_SCRN,\n'+
         '     ERROR_VISUAL,\n'+
         '     ERROR_GT,\n'+
         '     ERROR_WINDOW,\n'+
         '     ERROR_MENUS,\n'+
         '     ERROR_PORT,\n'+
         '     ERROR_DF,\n'+
         '     ERROR_FONT\n\n')
  WriteF('DEF')
  IF mesf THEN WriteF(' infos:PTR TO gadget,\n')
  checkwindows()
  IF fontf THEN WriteF('    font=NIL,\n')
  WriteF('    scr=NIL:PTR TO screen,\n'+
         '    visual=NIL,\n'+
         '    offx,offy,\n'+
         '    tattr:PTR TO textattr,\n'+
         '    type,id,key,qual,item:PTR TO menuitem\n\n')
  IF templatef THEN gentemplates()
  genscreenstuff()
  genwindows()
  genprocess()
  genmain()
  Close(SetStdOut(fh))
ENDPROC

PROC genprocess()
  IF processf
    IF multif
      WriteF(
       'PROC multiprocess(sig)\n'+
       '  DEF win:PTR TO window\n')
    ELSE
      WriteF(
       'PROC process(win:PTR TO window)\n')
    ENDIF
    WriteF(
       '  DEF running=TRUE, func:PTR TO LONG\n'+
       '  WHILE running\n')
    IF multif
      WriteF(
       '    win:=multiwait4message(sig)\n')
    ELSE
      WriteF(
       '    wait4message(win)\n')
    ENDIF
    WriteF(
       '    SELECT type\n'+
       '    CASE IDCMP_CLOSEWINDOW\n')
    IF templatef
      WriteF(
       '      func:=win.userdata\n'+
       '      IF func THEN func:=func[]\n'+
       '      IF func THEN running:=func()\n'+
       '    CASE IDCMP_GADGETUP\n'+
       '      func:=infos.userdata\n'+
       '      IF func THEN running:=func()\n'+
       '    CASE IDCMP_MENUPICK\n'+
       '      WHILE infos<>MENUNULL\n'+
       '        item:=ItemAddress(win.menustrip,infos)\n'+
       '        func:=GTMENUITEM_USERDATA(item)\n'+
       '        IF func THEN running:=func()\n'+
       '      EXIT running=FALSE\n'+
       '        infos:=item.nextselect AND $FFFF\n'+
       '      ENDWHILE\n')
      WriteF(
       '    CASE IDCMP_IDCMPUPDATE\n'+
       '      func:=win.userdata\n'+
       '      IF func THEN func:=func[1]\n'+
       '      IF func THEN running:=func()\n'+
       '    CASE IDCMP_INTUITICKS\n'+
       '      func:=win.userdata\n'+
       '      IF func THEN func:=func[2]\n'+
       '      IF func THEN running:=func()\n'+
       '    CASE IDCMP_MOUSEBUTTONS\n'+
       '      func:=win.userdata\n'+
       '      IF func THEN func:=func[3]\n'+
       '      IF func THEN running:=func()\n')
    ELSE
      WriteF(
       '      running:=FALSE\n'+
       '    CASE IDCMP_GADGETUP\n'+
       '      SELECT id\n'+
       '      CASE NIL -> your gadget id\n'+
       '      ENDSELECT\n'+
       '    CASE IDCMP_MENUPICK\n'+
       '      infos:=mes.code AND $FFFF\n'+
       '      WHILE infos<>MENUNULL\n'+
       '        item:=ItemAddress(win.menustrip,infos)\n'+
       '        id:=GTMENUITEM_USERDATA(item)\n'+
       '        SELECT id\n'+
       '        CASE NIL -> your menu id...\n'+
       '        ENDSELECT\n'+
       '        infos:=item.nextselect AND $FFFF\n'+
       '      ENDWHILE\n')
    ENDIF
    IF templatef        
      WriteF(
       '    CASE IDCMP_VANILLAKEY\n'+
       '      func:=win.userdata\n'+
       '      IF func THEN func:=func[4]\n'+
       '      IF func THEN running:=func()\n')
    ELSE
      WriteF(
       '    CASE IDCMP_VANILLAKEY\n'+
       '      SELECT key\n'+
       '      CASE NIL -> eg.: "a"\n'+
       '      ENDSELECT\n')
    ENDIF
    WriteF(
       '    ENDSELECT\n'+
       '  ENDWHILE\n'+
       'ENDPROC\n\n')
  ENDIF
ENDPROC

PROC genwindows()
  DEF w:PTR TO projectwindow,wnum=0
  w:=wlist.first
  WHILE w.next
    wname:=w.name
    lastkind:=-1
    WriteF('PROC open\swindow(\s)\n',wname,IF multif THEN 'port' ELSE '')
    WriteF('  DEF g:PTR TO gadget\n')
    WriteF('  IF (g:=CreateContext({\sglist}))=NIL THEN RETURN ERROR_CONTEXT\n',wname)
    gengadgets(w)
    IF win[wnum] AND HASMENUS
      WriteF('  IF (\smenus:=CreateMenusA(\n'+
             '    [',wname)
      genmenus(w.menus)
      WriteF('0,0,0,0,0,0,0]:newmenu,NIL))=NIL THEN RETURN ERROR_MENUS\n')
      WriteF('  IF LayoutMenusA(\smenus,visual,NIL)=FALSE THEN RETURN ERROR_MENUS\n',wname)
    ENDIF
    WriteF('  IF (\swnd:=OpenWindowTagList(NIL,',wname)
    WriteF(IF layoutf THEN '\n    [' ELSE '[')
    createtags(w.tags,w)
    IF win[wnum] AND HASGADGETS
      WriteF('WA_GADGETS,\sglist,',wname)
      IF layoutf THEN WriteF('\n     ')
    ENDIF
    WriteF('TAG_END]))=NIL THEN RETURN ERROR_WINDOW\n')
    IF multif
      WriteF('  \swnd.userport:=port\n'+
             '  ModifyIDCMP(\swnd,',wname,wname)
      writeIDCMP(w.idcmp)
      WriteF(')\n')
    ENDIF
    IF templatef
      WriteF('  \swnd.userdata:=[',wname)
      WriteF(IF w.idcmp AND IDCMP_CLOSEWINDOW THEN '{\s_CloseWindow}' ELSE '0',wname)
      WriteF(IF w.idcmp AND IDCMP_IDCMPUPDATE THEN ',{\s_IDCMPUpdate}' ELSE ',0',wname)
      WriteF(IF w.idcmp AND IDCMP_INTUITICKS THEN ',{\s_IntuiTicks}' ELSE ',0',wname)
      WriteF(IF w.idcmp AND IDCMP_MOUSEBUTTONS THEN ',{\s_MouseButtons}' ELSE ',0',wname)
      WriteF(IF w.idcmp AND IDCMP_VANILLAKEY THEN ',{\s_Keys}]\n' ELSE ',0]\n',wname)
    ENDIF
    IF w.windowtext THEN gentexts(w)
    genboxes(w)
    IF win[wnum] AND HASMENUS
      WriteF('  IF SetMenuStrip(\swnd,\smenus)=FALSE THEN RETURN ERROR_MENUS\n',wname,wname)
    ENDIF
    WriteF('  Gt_RefreshWindow(\swnd,NIL)\n'+
           'ENDPROC\n\n'+
           'PROC close\swindow()\n'+
           '  IF \swnd\n',wname,wname,wname)
    IF multif
      WriteF('    clearwinport(\swnd)\n',wname)
    ENDIF
    IF win[wnum] AND HASMENUS
      WriteF('    ClearMenuStrip(\swnd)\n'+
             '    IF \smenus THEN FreeMenus(\smenus)\n',wname,wname,wname)
    ENDIF
    IF templatef
      WriteF('    IF \swnd.userdata THEN Dispose(\swnd.userdata)\n',wname,wname)
    ENDIF
    WriteF('    CloseWindow(\swnd)\n'+
           '  ENDIF\n'+
           '  IF \sglist THEN FreeGadgets(\sglist)\n'+
           'ENDPROC\n\n',wname,wname,wname)
    w:=w.next
    INC wnum
  ENDWHILE
  IF multif
    WriteF(
    'PROC clearwinport(win:PTR TO window)\n'+
    '  DEF msg:PTR TO intuimessage, succ\n'+
    '  IF win.userport\n'+
    '    Forbid()\n'+
    '    msg:=win.userport.msglist.head\n'+
    '    WHILE succ:=msg.execmessage.ln.succ\n'+
    '      IF msg.idcmpwindow=win\n'+
    '        Remove(msg)\n'+
    '        ReplyMsg(msg)\n'+
    '      ENDIF\n'+
    '      msg:=succ\n'+
    '    ENDWHILE\n'+
    '    win.userport:=NIL\n'+
    '    ModifyIDCMP(win,0)\n'+
    '    Permit()\n'+
    '  ENDIF\n'+
    'ENDPROC\n\n')
  ENDIF
ENDPROC

PROC gengadgets(w:PTR TO projectwindow)
  DEF egl:PTR TO extgadgetlist,eng:PTR TO extnewgadget,ng:PTR TO newgadget,kind
  egl:=w.gadgets; eng:=egl.first
  IF eng=NIL THEN RETURN
  WHILE eng.next
    ng:=eng.newgadget                     /* offx,offy */
    kind:=eng.kind
    WriteF('  IF (g:=CreateGadgetA(\s,g,',kinds[kind])
    IF layoutf THEN WriteF('\n    ')
    WriteF('[offx+\d,offy+\d,\d,\d,',
           ng.leftedge-w.leftborder,ng.topedge-w.topborder,ng.width,ng.height)
    writeString(ng.gadgettext)
    WriteF(',tattr,\d,',ng.gadgetid)
    done_or:=FALSE
    IF ng.flags AND PLACETEXT_LEFT THEN   orConst('PLACETEXT_LEFT')
    IF ng.flags AND PLACETEXT_RIGHT THEN  orConst('PLACETEXT_RIGHT')
    IF ng.flags AND PLACETEXT_ABOVE THEN  orConst('PLACETEXT_ABOVE')
    IF ng.flags AND PLACETEXT_BELOW THEN  orConst('PLACETEXT_BELOW')
    IF ng.flags AND PLACETEXT_IN THEN     orConst('PLACETEXT_IN')
    IF ng.flags AND NG_HIGHLABEL THEN     orConst('NG_HIGHLABEL')
    IF done_or=FALSE THEN WriteF('0')
    WriteF(',visual,')
    WriteF(IF templatef AND w.idcmp AND IDCMP_GADGETUP THEN '{\s_Clicked}' ELSE '0', eng.gadgetlabel)
    WriteF(']:newgadget,')
    WriteF(IF layoutf THEN '\n    [' ELSE '[')
    createtags(eng.tags)
    WriteF('TAG_END]))=NIL THEN RETURN ERROR_GADGET\n')
    IF kind=0 -> GENERIC (i.e., GetFile)
      has_getfile:=TRUE
      WriteF(
        '  g.flags:=g.flags OR GFLG_GADGIMAGE OR GFLG_GADGHCOMP\n'+
        '  g.activation:=g.activation OR GACT_RELVERIFY\n'+
        '  g.gadgetrender:=[0,0,20,14,2,getFileImage(),3,0,NIL]:image\n')
    ENDIF
    lastkind:=kind
    eng:=eng.next
  ENDWHILE
ENDPROC

PROC genmenus(eml:PTR TO extmenulist)
  DEF enm:PTR TO extnewmenu,nm:PTR TO newmenu
  enm:=eml.first
  IF enm=NIL THEN RETURN
  WHILE enm.next
    nm:=enm.newmenu
    IF nm.type=NM_TITLE;    WriteF('NM_TITLE')
    ELSEIF nm.type=NM_ITEM; WriteF(' NM_ITEM')
    ELSEIF nm.type=NM_SUB;  WriteF('  NM_SUB')
    ELSE;                   WriteF('$\h',nm.type)
    ENDIF
    WriteF(',0,')
    IF StrCmp(enm.menutitle,'NM_BARLABEL')
      WriteF('NM_BARLABEL')
    ELSE
      writeString(enm.menutitle)
    ENDIF
    WriteF(',')
    IF nm.commkey THEN writeString(nm.commkey) ELSE WriteF('0')
    WriteF(',')
    done_or:=FALSE
    IF nm.flags AND CHECKIT THEN            orConst('CHECKIT')
    IF nm.flags AND MENUTOGGLE THEN         orConst('MENUTOGGLE')
    IF nm.type=NM_TITLE
      IF nm.flags AND NM_MENUDISABLED THEN  orConst('NM_MENUDISABLED')
    ELSE
      IF nm.flags AND NM_ITEMDISABLED THEN  orConst('NM_ITEMDISABLED')
    ENDIF
    IF nm.flags AND CHECKED THEN            orConst('CHECKED')
    IF done_or=FALSE THEN WriteF('0')
    WriteF(',\d,',nm.mutualexclude)
    WriteF(IF templatef AND (enm.menulabel[]) THEN '{\s_\s},' ELSE '0,',
           wname, enm.menulabel)
    IF layoutf THEN WriteF('\n     ')
    IF enm.items THEN genmenus(enm.items)
    enm:=enm.next
  ENDWHILE
ENDPROC

PROC gentexts(w:PTR TO projectwindow)
  DEF i:PTR TO intuitext
  i:=w.windowtext
  WHILE i
    WriteF('  PrintIText(\swnd.rport,',wname)
    IF layoutf THEN WriteF('\n    ')
    WriteF('[\d,\d,\d,\d,\d,tattr,',
           i.frontpen,i.backpen,i.drawmode,i.leftedge-w.leftborder,i.topedge-w.topborder)
    writeString(i.itext)
    WriteF(',NIL]:intuitext,offx,offy)\n')
    i:=i.nexttext
  ENDWHILE
ENDPROC

PROC genboxes(w:PTR TO projectwindow)
  DEF bl:PTR TO bevellist,bb:PTR TO bevelbox
  bl:=w.boxes; bb:=bl.first
  IF bb=NIL THEN RETURN
  WHILE bb.next
    WriteF('  DrawBevelBoxA(\swnd.rport,offx+\d,offy+\d,\d,\d,',wname,bb.left-w.leftborder,bb.top-w.topborder,bb.width,bb.height)
    IF layoutf THEN WriteF('\n    ')
    WriteF('[GT_VISUALINFO,visual,')
    IF bb.flags AND BBF_RECESSED THEN WriteF('GTBB_RECESSED,TRUE,')
    IF bb.flags AND BBFT_BUTTON
      WriteF('GTBB_FRAMETYPE,BBFT_BUTTON,')
    ELSEIF bb.flags AND BBFT_RIDGE
      WriteF('GTBB_FRAMETYPE,BBFT_RIDGE,')
    ELSEIF bb.flags AND BBFT_ICONDROPBOX
      WriteF('GTBB_FRAMETYPE,BBFT_ICONDROPBOX,')
    ENDIF
    WriteF('TAG_END])\n')
    bb:=bb.next
  ENDWHILE
ENDPROC

PROC createtags(taglist,w=NIL:PTR TO projectwindow)
  DEF tag:PTR TO LONG,item,str1,v:PTR TO LONG,type
  WHILE tag:=NextTagItem({taglist})
    item:=tag[0]
    str1:=NIL;  type:=0
    IF (item>GT_TAGBASE) AND (GT_TAGBASE+65>item)
      item:=item-GT_TAGBASE
      IF (item>=4) AND (item<=24)
        item:=item-4*2
        str1:=gttags1[item];  type:=gttags1[item+1]
      ELSEIF (item>=38) AND (item<=64)
        item:=item-38*2
        str1:=gttags2[item];  type:=gttags2[item+1]
      ENDIF
    ELSEIF (item>GA_DUMMY) AND (GA_DUMMY+25>item)
      item:=item-GA_DUMMY-1*2
      str1:=gatags[item];  type:=gatags[item+1]
    ELSEIF (item>PGA_DUMMY) AND (PGA_DUMMY+11>item)
      item:=item-PGA_DUMMY-1*2
      str1:=pgatags[item];  type:=pgatags[item+1]
    ELSEIF (item>STRINGA_DUMMY) AND (STRINGA_DUMMY+$13>item)
      item:=item-STRINGA_DUMMY-1*2
      str1:=strtags[item];  type:=strtags[item+1]
    ELSEIF (item>LAYOUTA_DUMMY) AND (LAYOUTA_DUMMY+25>item)
      item:=item-LAYOUTA_DUMMY-1*2
      str1:=latags[item];  type:=latags[item+1]
    ELSEIF (item>=WA_LEFT) AND (item<=WA_NEWLOOKMENUS)
      item:=item-WA_LEFT*2
      str1:=watags[item];  type:=watags[item+1]
    ENDIF
    WriteF(IF str1 THEN str1 ELSE '$\h',tag[0])
    WriteF(',')
    item:=tag[0]
    v:=tag[1]
    /* 0=num, 1=(list), 2=array of text, 3=text, 4="NIL", 5="tattr", 6="visual"
       7="g/NIL", 8=(ptr to menu), 9="scr", 10="_", 11="+offx", 12="+offy" */
    SELECT type
    CASE 0
      SELECT item
      CASE GTCB_CHECKED
        writeBool(v)
      CASE GA_DISABLED
        writeBool(v)
      CASE WA_AUTOADJUST
        writeBool(v)
      CASE WA_NEWLOOKMENUS
        writeBool(v)
      CASE WA_FLAGS
        -> Use proper window flag bits
        IF w THEN v:=w.windowflags
        done_or:=FALSE
        IF v AND WFLG_SIZEGADGET THEN     orConst('WFLG_SIZEGADGET')
        IF v AND WFLG_DRAGBAR THEN        orConst('WFLG_DRAGBAR')
        IF v AND WFLG_DEPTHGADGET THEN    orConst('WFLG_DEPTHGADGET')
        IF v AND WFLG_CLOSEGADGET THEN    orConst('WFLG_CLOSEGADGET')
        IF v AND WFLG_SIZEBRIGHT THEN     orConst('WFLG_SIZEBRIGHT')
        IF v AND WFLG_SIZEBBOTTOM THEN    orConst('WFLG_SIZEBBOTTOM')
        IF v AND WFLG_REFRESHBITS=0 THEN  orConst('WFLG_SMART_REFRESH')
        IF v AND WFLG_SIMPLE_REFRESH THEN orConst('WFLG_SIMPLE_REFRESH')
        IF v AND WFLG_SUPER_BITMAP THEN   orConst('WFLG_SUPER_BITMAP')
        IF v AND WFLG_BACKDROP THEN       orConst('WFLG_BACKDROP')
        IF v AND WFLG_REPORTMOUSE THEN    orConst('WFLG_REPORTMOUSE')
        IF v AND WFLG_GIMMEZEROZERO THEN  orConst('WFLG_GIMMEZEROZERO')
        IF v AND WFLG_BORDERLESS THEN     orConst('WFLG_BORDERLESS')
        IF v AND WFLG_ACTIVATE THEN       orConst('WFLG_ACTIVATE')
        IF v AND WFLG_RMBTRAP THEN        orConst('WFLG_RMBTRAP')
        IF v AND WFLG_NEWLOOKMENUS THEN   orConst('WFLG_NEWLOOKMENUS')
        IF done_or=FALSE THEN WriteF('0')
      CASE WA_IDCMP
        IF multif
          WriteF('0')
        ELSE
          -> Use proper IDCMP bits
          writeIDCMP(IF w THEN w.idcmp ELSE v)
        ENDIF
      CASE PGA_FREEDOM
        SELECT v
        CASE LORIENT_NONE;  WriteF('LORIENT_NONE')
        CASE LORIENT_HORIZ; WriteF('LORIENT_HORIZ')
        CASE LORIENT_VERT;  WriteF('LORIENT_VERT')
        DEFAULT;            writeConst(v)
        ENDSELECT
      CASE STRINGA_JUSTIFICATION
        SELECT v
        CASE STRINGLEFT;    WriteF('STRINGLEFT')
        CASE STRINGRIGHT;   WriteF('STRINGRIGHT')
        CASE STRINGCENTER;  WriteF('STRINGCENTER')
        DEFAULT;            writeConst(v)
        ENDSELECT
      CASE GTTX_JUSTIFICATION
        SELECT v
        CASE GTJ_LEFT;    WriteF('GTJ_LEFT')
        CASE GTJ_RIGHT;   WriteF('GTJ_RIGHT')
        CASE GTJ_CENTER;  WriteF('GTJ_CENTER')
        DEFAULT;          writeConst(v)
        ENDSELECT
      DEFAULT
        writeConst(v)
      ENDSELECT
    CASE 2
      WriteF('[')
      WHILE v[]
        writeString(v[]++)
        WriteF(',')
      ENDWHILE
      WriteF('NIL]')
    CASE 3;  writeString(v)
    CASE 5;  WriteF('tattr')
    CASE 6;  WriteF('visual')
    CASE 7;  WriteF(IF lastkind=STRING_KIND THEN 'g' ELSE 'NIL')
    CASE 9;  WriteF('scr')
    CASE 10; WriteF('"_"')
    CASE 11; WriteF('offx+\d',v-w.leftborder)
    CASE 12; WriteF('offy+\d',v-w.topborder)
    DEFAULT; WriteF('NIL')
    ENDSELECT
    WriteF(',')
    IF layoutf THEN WriteF('\n     ')
  ENDWHILE
ENDPROC

PROC writeIDCMP(v)
  done_or:=FALSE
  IF v AND IDCMP_SIZEVERIFY THEN      orConst('IDCMP_SIZEVERIFY')
  IF v AND IDCMP_NEWSIZE THEN         orConst('IDCMP_NEWSIZE')
  IF v AND IDCMP_REFRESHWINDOW THEN   orConst('IDCMP_REFRESHWINDOW')
  IF v AND IDCMP_MOUSEBUTTONS THEN    orConst('IDCMP_MOUSEBUTTONS')
  IF v AND IDCMP_MOUSEMOVE THEN       orConst('IDCMP_MOUSEMOVE')
  IF v AND IDCMP_GADGETDOWN THEN      orConst('IDCMP_GADGETDOWN')
  IF v AND IDCMP_GADGETUP THEN        orConst('IDCMP_GADGETUP')
  IF v AND IDCMP_REQSET THEN          orConst('IDCMP_REQSET')
  IF v AND IDCMP_MENUPICK THEN        orConst('IDCMP_MENUPICK')
  IF v AND IDCMP_CLOSEWINDOW THEN     orConst('IDCMP_CLOSEWINDOW')
  IF v AND IDCMP_RAWKEY THEN          orConst('IDCMP_RAWKEY')
  IF v AND IDCMP_REQVERIFY THEN       orConst('IDCMP_REQVERIFY')
  IF v AND IDCMP_REQCLEAR THEN        orConst('IDCMP_REQCLEAR')
  IF v AND IDCMP_MENUVERIFY THEN      orConst('IDCMP_MENUVERIFY')
  IF v AND IDCMP_NEWPREFS THEN        orConst('IDCMP_NEWPREFS')
  IF v AND IDCMP_DISKINSERTED THEN    orConst('IDCMP_DISKINSERTED')
  IF v AND IDCMP_DISKREMOVED THEN     orConst('IDCMP_DISKREMOVED')
  IF v AND IDCMP_ACTIVEWINDOW THEN    orConst('IDCMP_ACTIVEWINDOW')
  IF v AND IDCMP_INACTIVEWINDOW THEN  orConst('IDCMP_INACTIVEWINDOW')
  IF v AND IDCMP_DELTAMOVE THEN       orConst('IDCMP_DELTAMOVE')
  IF v AND IDCMP_VANILLAKEY THEN      orConst('IDCMP_VANILLAKEY')
  IF v AND IDCMP_INTUITICKS THEN      orConst('IDCMP_INTUITICKS')
  IF v AND IDCMP_IDCMPUPDATE THEN     orConst('IDCMP_IDCMPUPDATE')
  IF v AND IDCMP_MENUHELP THEN        orConst('IDCMP_MENUHELP')
  IF v AND IDCMP_CHANGEWINDOW THEN    orConst('IDCMP_CHANGEWINDOW')
  IF done_or=FALSE THEN WriteF('0')
ENDPROC

PROC checkwindows()
  DEF w:PTR TO projectwindow,wname,fl,x
  DEF egl:PTR TO extgadgetlist,eng:PTR TO extnewgadget
  w:=wlist.first
  WHILE w.next
    wname:=w.name
    -> Important! Convert name to something sensible...
    fixString(wname)
    fl:=0
    WriteF('    \swnd:PTR TO window,\n',wname)
    x:=Long(w.menus)
    IF ^x
      fl:=HASMENUS
      WriteF('    \smenus,\n',wname)
    ENDIF
    egl:=w.gadgets; eng:=egl.first
    IF eng
      WHILE eng.next
        fl:=fl OR HASGADGETS
        -> Important! Turn label into something sensible...
        fixString(eng.gadgetlabel)
        eng:=eng.next
      ENDWHILE
    ENDIF
    WriteF('    \sglist,\n',wname)
    ListAdd(win,[fl])
    w:=w.next
  ENDWHILE
ENDPROC

PROC genscreenstuff()
  DEF i
  WriteF(
    'PROC setupscreen()\n'+
    '  IF (gadtoolsbase:=OpenLibrary(''gadtools.library'',37))=NIL THEN RETURN ERROR_GT\n')
  IF fontf
    -> Must lock font in memory while used by screen and gadgets
    WriteF(
    '  IF (diskfontbase:=OpenLibrary(''diskfont.library'',0))=NIL THEN RETURN ERROR_DF\n'+
    '  font:=OpenDiskFont(tattr:=[''\s'',\d,\d,$\h]:textattr)\n'+
    '  CloseLibrary(diskfontbase)\n'+
    '  IF font=NIL THEN RETURN ERROR_FONT\n',
    guiptr.fontname,guiptr.font.ysize,guiptr.font.style,guiptr.font.flags)
  ENDIF
  IF guiptr.flags0 AND GU0_CUSTOM
    WriteF('  IF (scr:=OpenScreenTagList(NIL,')
    IF layoutf THEN WriteF('\n    ')
    WriteF('[SA_LEFT,\d,', guiptr.left)
    IF layoutf THEN WriteF('\n     ')
    WriteF('SA_TOP,\d,', guiptr.top)
    IF layoutf THEN WriteF('\n     ')
    WriteF('SA_WIDTH,\d,', IF guiptr.width<>-1 THEN guiptr.width ELSE guiptr.stdscreenwidth)
    IF layoutf THEN WriteF('\n     ')
    WriteF('SA_HEIGHT,\d,', IF guiptr.height<>-1 THEN guiptr.height ELSE guiptr.stdscreenheight)
    IF layoutf THEN WriteF('\n     ')
    WriteF('SA_DEPTH,\d,',guiptr.depth)
    IF layoutf THEN WriteF('\n     ')
    IF guiptr.colors[].colorindex<>-1
      WriteF('SA_COLORS,[')
      FOR i:=0 TO MAXCOLORSPEC-1
      EXIT guiptr.colors[i].colorindex=-1
        WriteF('\d,$\z\h[2],$\z\h[2],$\z\h[2],',
               guiptr.colors[i].colorindex, guiptr.colors[i].red,
               guiptr.colors[i].green, guiptr.colors[i].blue)
        IF layoutf THEN WriteF('\n                ')
      ENDFOR
      WriteF('-1,0,0,0]:colorspec,')
      IF layoutf THEN WriteF('\n     ')
    ENDIF
    IF fontf
      WriteF('SA_FONT,tattr,')
      IF layoutf THEN WriteF('\n     ')
    ENDIF
    WriteF('SA_TYPE,CUSTOMSCREEN,')
    WriteF('\n     -> If the DisplayID data constant doesn''t compile, use $\h\n     ',guiptr.displayid)
    WriteF('SA_DISPLAYID,')
    writeDispID(guiptr.displayid)
    WriteF(',')
    IF layoutf THEN WriteF('\n     ')
    WriteF('SA_AUTOSCROLL,')
    writeBool(guiptr.flags0 AND GU0_AUTOSCROLL)
    WriteF(',')
    IF layoutf THEN WriteF('\n     ')
    WriteF('SA_OVERSCAN,')
    i:=guiptr.overscan
    SELECT i
    CASE OSCAN_TEXT;      WriteF('OSCAN_TEXT')
    CASE OSCAN_STANDARD;  WriteF('OSCAN_STANDARD')
    CASE OSCAN_MAX;       WriteF('OSCAN_TEXT')
    CASE OSCAN_VIDEO;     WriteF('OSCAN_VIDEO')
    DEFAULT;              WriteF('$\h', i)
    ENDSELECT
    WriteF(',')
    IF layoutf THEN WriteF('\n     ')
    WriteF('SA_PENS,[')
    FOR i:=0 TO MAXDRIPENS-1
    EXIT guiptr.dripens[i]=-1
      WriteF('\d,',guiptr.dripens[i])
    ENDFOR
    IF i<>0
      FOR i:=0 TO MAXMOREDRIPENS-1
      EXIT guiptr.moredripens[i]=-1
        WriteF('\d,',guiptr.moredripens[i])
      ENDFOR
    ENDIF
    WriteF('-1]:INT,')
    IF layoutf THEN WriteF('\n     ')
    WriteF('SA_TITLE,')
    writeString(guiptr.screentitle)
    WriteF(',')
    IF layoutf THEN WriteF('\n     ')
    WriteF('NIL]))=NIL THEN RETURN ERROR_SCRN\n')
  ELSE
    WriteF('  IF (scr:=LockPubScreen(\s))=NIL THEN RETURN ERROR_SCRN\n',
           IF guiptr.flags0 AND GU0_WORKBENCH THEN '''Workbench''' ELSE 'NIL')
  ENDIF
  IF fontf=FALSE
    WriteF('  tattr:=scr.font\n')
  ENDIF
  WriteF(
    '  IF (visual:=GetVisualInfoA(scr,NIL))=NIL THEN RETURN ERROR_VISUAL\n'+
    '  offx:=scr.wborleft\n'+
    '  offy:=scr.wbortop+scr.rastport.txheight+1\n'+
    'ENDPROC\n\n'+
    'PROC closedownscreen()\n'+
    '  IF visual THEN FreeVisualInfo(visual)\n')
  IF guiptr.flags0 AND GU0_CUSTOM
    WriteF('  IF scr THEN CloseScreen(scr)\n')
  ELSE
    WriteF('  IF scr THEN UnlockPubScreen(NIL,scr)\n')
  ENDIF
  IF fontf
    WriteF('  IF font THEN CloseFont(font)\n')
  ENDIF
  WriteF(
    '  IF gadtoolsbase THEN CloseLibrary(gadtoolsbase)\n'+
    'ENDPROC\n\n')
ENDPROC

PROC genmain()
  DEF w:PTR TO projectwindow,wname
  IF mesf
    IF multif
      WriteF(
        'PROC multiwait4message(port)\n'+
        '  DEF win:PTR TO window,mes:PTR TO intuimessage\n')
    ELSE
      WriteF(
        'PROC wait4message(win:PTR TO window)\n'+
        '  DEF mes:PTR TO intuimessage,port\n'+
        '  port:=win.userport\n')
    ENDIF
    WriteF(
      '  REPEAT\n'+
      '    type:=0\n'+
      '    IF mes:=Gt_GetIMsg(port)\n')
    IF multif
      WriteF(
      '      win:=mes.idcmpwindow\n')
    ENDIF
    WriteF(
      '      type:=mes.class\n'+
      '      SELECT type\n'+
      '      CASE IDCMP_MENUPICK\n'+
      '        infos:=mes.code\n'+
      '      CASE IDCMP_GADGETUP\n'+
      '        infos:=mes.iaddress\n'+
      '        id:=infos.gadgetid\n'+
      '      CASE IDCMP_VANILLAKEY\n'+
      '        key:=mes.code\n'+
      '        qual:=mes.qualifier AND $FFFF\n')
    WriteF(
      '      CASE IDCMP_MOUSEBUTTONS\n'+
      '        qual:=mes.qualifier AND $FFFF\n'+
      '      CASE IDCMP_REFRESHWINDOW\n'+
      '        Gt_BeginRefresh(win)\n' +
      '        Gt_EndRefresh(win,TRUE)\n' +
      '        type:=0\n' +
      '      ENDSELECT\n' +
      '      Gt_ReplyIMsg(mes)\n' +
      '    ELSE\n' +
      '      WaitPort(port)\n'+
      '    ENDIF\n' +
      '  UNTIL type\n' +
      'ENDPROC win\n\n')
  ENDIF
  IF erf
    WriteF(
      'PROC reporterr(er)\n'+
      '  DEF erlist:PTR TO LONG\n'+
      '  IF er\n'+
      '    erlist:=[''get context'',\n'+
      '             ''create gadget'',\n'+
      '             ''lock/open screen'',\n'+
      '             ''get visual infos'',\n'+
      '             ''open "gadtools.library" v37+'',\n'+
      '             ''open window'',\n'+
      '             ''create menus'',\n'+
      '             ''create port'',\n'+
      '             ''open "diskfont.library"'',\n'+
      '             ''open font'']\n'+
      '    EasyRequestArgs(0,[20,0,0,''Could not \\s!'',''OK''],0,[erlist[er-1]])\n'+
      '  ENDIF\n'+
      'ENDPROC er\n\n')
  ENDIF
  IF mainf
    WriteF('PROC main() HANDLE\n')
    IF multif
      WriteF('  DEF err=ERROR_NONE,port=NIL\n'+
             '  IF (port:=CreateMsgPort())=NIL THEN Raise(ERROR_PORT)\n')
    ELSE
      WriteF('  DEF err=ERROR_NONE\n')
    ENDIF
    WriteF('  IF (err:=setupscreen())<>ERROR_NONE THEN Raise(err)\n')
    w:=wlist.first
    WHILE w.next
      wname:=w.name
      WriteF(IF erf THEN '  reporterr(open\swindow(\s))\n' ELSE '  open\swindow(\s)\n',wname,IF multif THEN 'port' ELSE '')
      IF multif=FALSE
        IF mesf
          WriteF(IF processf THEN '  process(\swnd)\n' ELSE '  wait4message(\swnd)\n', wname)
        ELSE
          WriteF('  Delay(500)\n')
        ENDIF
        WriteF('  close\swindow()\n',wname)
        WriteF('  IF CtrlC() THEN Raise(ERROR_NONE)\n')
      ENDIF
      w:=w.next
    ENDWHILE
    IF multif
      IF mesf
        WriteF(IF processf THEN '  multiprocess(port)\n' ELSE '  multiwait4message(port)\n')
      ELSE
        WriteF('  Delay(500)\n')
      ENDIF
      w:=wlist.last
      WHILE w.prev
        wname:=w.name
        WriteF('  close\swindow()\n',wname)
        w:=w.prev
      ENDWHILE
    ENDIF
    WriteF('EXCEPT DO\n')
    IF multif THEN WriteF('  IF port THEN DeleteMsgPort(port)\n')
    WriteF('  closedownscreen()\n')
    IF erf THEN    WriteF('  reporterr(err)\n')
    WriteF('ENDPROC\n\n')
  ENDIF
  IF has_getfile
    WriteF(
      'PROC getFileImage()\n'+
      '  DEF data:PTR TO LONG\n'+
      '  data:=[NIL]\n'+
      '  IF data[]=NIL THEN data[]:=copyListToChip(\n'+
      '    [$00000000,$00001000,$003C1000,$00421000,\n'+
      '     $0F811000,$0FC11000,$0C3F1000,$0C011000,\n'+
      '     $0C011000,$0C011000,$0FFF1000,$00001000,\n'+
      '     $00001000,$7FFFF000,\n'+
      '     $FFFFE000,$80000000,$80000000,$80000000,\n'+
      '     $80000000,$80000000,$80000000,$80000000,\n'+
      '     $80000000,$80000000,$80000000,$80000000,\n'+
      '     $80000000,$00000000])\n'+
      'ENDPROC data[]\n\n')
    WriteF(
      'PROC copyListToChip(list) HANDLE\n'+
      '  DEF size, mem=NIL\n'+
      '  size:=ListLen(list)*SIZEOF LONG\n'+
      '  mem:=NewM(size,MEMF_CHIP)\n'+
      '  CopyMemQuick(list, mem, size)\n'+
      'EXCEPT\n'+
      'ENDPROC mem\n\n')
  ENDIF
ENDPROC

PROC gentemplates()
  DEF w:PTR TO projectwindow,key
  DEF egl:PTR TO extgadgetlist,eng:PTR TO extnewgadget
  WriteF('\n' +
    '-> ***************************\n' +
    '-> Start of templates section.\n' +
    '-> (Return FALSE to quit the GUI.)\n\n\n')
  w:=wlist.first
  WHILE w.next
    wname:=w.name
    WriteF(
      '-> Templates for window "\s":\n\n',wname)
    IF w.idcmp AND IDCMP_CLOSEWINDOW
      WriteF(
      'PROC \s_CloseWindow()\n' +
      '  -> Routine for "IDCMP_CLOSEWINDOW".\n' +
      'ENDPROC FALSE\n\n', wname, wname)
    ENDIF
    IF w.idcmp AND IDCMP_IDCMPUPDATE
      WriteF(
        'PROC \s_IDCMPUpdate()\n' +
        '  -> Routine for "IDCMP_IDCMPUPDATE".\n' +
        'ENDPROC TRUE\n\n', wname)
    ENDIF
    IF w.idcmp AND IDCMP_INTUITICKS
      WriteF(
        'PROC \s_IntuiTicks()\n' +
        '  -> Routine for "IDCMP_INTUITICKS".\n' +
        'ENDPROC TRUE\n\n', wname)
    ENDIF
    IF w.idcmp AND IDCMP_MOUSEBUTTONS
      WriteF(
        'PROC \s_MouseButtons()\n' +
        '  -> Routine for "IDCMP_MOUSEBUTTONS".\n' +
        'ENDPROC TRUE\n\n', wname)
    ENDIF
    IF w.idcmp AND IDCMP_VANILLAKEY
      WriteF(
        'PROC \s_Keys()\n' +
        '  -> Routine for "IDCMP_VANILLAKEY".\n' +
        '  SELECT key\n',wname)
      egl:=w.gadgets; eng:=egl.first
      IF eng
        WHILE eng.next
          IF key:=findKey(eng.gadgettext)
            WriteF(
              '  CASE "\c"\n'+
              '    -> Key for "\s" pressed\n',
              key,eng.gadgettext)
            IF key<>toupper(key)
              WriteF(
              '  CASE "\c"\n'+
              '    -> Key for "\s" pressed (shifted)\n',
              toupper(key),eng.gadgettext)
            ENDIF
          ENDIF
          eng:=eng.next
        ENDWHILE
      ENDIF
      WriteF(
        '  ENDSELECT\n' +
        'ENDPROC TRUE\n\n')
    ENDIF
    IF w.idcmp AND IDCMP_GADGETUP
      egl:=w.gadgets; eng:=egl.first
      IF eng
        WHILE eng.next
          WriteF(
            'PROC \s_Clicked()\n' +
            '  -> Routine when gadget "\s" is clicked.\n' +
            'ENDPROC TRUE\n\n', eng.gadgetlabel, eng.gadgettext)
          eng:=eng.next
        ENDWHILE
      ENDIF
    ENDIF
    IF w.idcmp AND IDCMP_MENUPICK THEN genmenutemplates(w.menus)
    WriteF('\n')
    w:=w.next
  ENDWHILE
  WriteF(
    '-> End of templates section.\n' +
    '-> *************************\n\n\n')
ENDPROC

PROC genmenutemplates(eml:PTR TO extmenulist)
  DEF enm:PTR TO extnewmenu
  enm:=eml.first
  IF enm=NIL THEN RETURN
  WHILE enm.next
    -> Important! Turn label into something sensible...
    IF enm.menulabel[]
      fixString(enm.menulabel,FALSE)
      WriteF('PROC \s_\s', wname, enm.menulabel)
      WriteF('()\n' +
        '  -> Routine when menu item "\s" is selected.\n' +
        'ENDPROC TRUE\n\n', enm.menutitle)
    ENDIF
    IF enm.items THEN genmenutemplates(enm.items)
    enm:=enm.next
  ENDWHILE
ENDPROC

PROC initlists()
  kinds:=['GENERIC_KIND','BUTTON_KIND','CHECKBOX_KIND','INTEGER_KIND',
          'LISTVIEW_KIND','MX_KIND','NUMBER_KIND','CYCLE_KIND','PALETTE_KIND',
          'SCROLLER_KIND','RESERVED_KIND','SLIDER_KIND','STRING_KIND','TEXT_KIND']

  /* GT_TAGBASE ($80080000) 4-23 */

  gttags1:=['GTCB_CHECKED',0,'GTLV_TOP',0,'GTLV_LABELS',1,'GTLV_READONLY',0,
            'GTLV_SCROLLWIDTH',0,'GTMX_LABELS',2,'GTMX_ACTIVE',0,'GTTX_TEXT',3,
            'GTTX_COPYTEXT',0,'GTNM_NUMBER',0,'GTCY_LABELS',2,'GTCY_ACTIVE',0,
            'GTPA_DEPTH',0,'GTPA_COLOR',0,'GTPA_COLOROFFSET',0,
            'GTPA_INDICATORWIDTH',0,'GTPA_INDICATORHEIGHT',0,'GTSC_TOP',0,
            'GTSC_TOTAL',0,'GTSC_VISIBLE',0]

  /* GT_TAGBASE ($80080000) 38-64 */

  gttags2:=['GTSL_MIN',0,'GTSL_MAX',0,'GTSL_LEVEL',0,'GTSL_MAXLEVELLEN',0,
            'GTSL_LEVELFORMAT',3,'GTSL_LEVELPLACE',0,'GTSL_DISPFUNC',4,
            'GTST_STRING',3,'GTST_MAXCHARS',0,'GTIN_NUMBER',0,
            'GTIN_MAXCHARS',0,'GTMN_TEXTATTR',5,'GTMN_FRONTPEN',0,
            'GTBB_RECESSED',0,'GT_VISUALINFO',6,'GTLV_SHOWSELECTED',7,
            'GTLV_SELECTED',0,'GT_RESERVED0',0,'GT_RESERVED1',0,
            'GTTX_BORDER',0,'GTNM_BORDER',0,'GTSC_ARROWS',0,'GTMN_MENU',8,
            'GTMX_SPACING',0,'GTMN_FULLMENU',0,'GTMN_SECONDARYERROR',4,
            'GT_UNDERSCORE',10]

  /* GA_DUMMY ($80030000), 1-$24 */

  gatags:=['GA_LEFT',0,'GA_RELRIGHT',0,'GA_TOP',0,'GA_RELBOTTOM',0,
           'GA_WIDTH',0,'GA_RELWIDTH',0,'GA_HEIGHT',0,'GA_RELHEIGHT',0,
           'GA_TEXT',0,'GA_IMAGE',0,'GA_BORDER',0,'GA_SELECTRENDER',0,
           'GA_HIGHLIGHT',0,'GA_DISABLED',0,'GA_GZZGADGET',0,'GA_ID',0,
           'GA_USERDATA',0,'GA_SPECIALINFO',0,'GA_SELECTED',0,
           'GA_ENDGADGET',0,'GA_IMMEDIATE',0,'GA_RELVERIFY',0,
           'GA_FOLLOWMOUSE',0,'GA_RIGHTBORDER',0,'GA_LEFTBORDER',0,
           'GA_TOPBORDER',0,'GA_BOTTOMBORDER',0,'GA_TOGGLESELECT',0,
           'GA_SYSGADGET',0,'GA_SYSGTYPE',0,'GA_PREVIOUS',0,'GA_NEXT',0,
           'GA_DRAWINFO',0,'GA_INTUITEXT',0,'GA_LABELIMAGE',0,'GA_TABCYCLE',0]

  /* PGADUMMY ($80031000), 1-$A */

  pgatags:=['PGA_FREEDOM',0,'PGA_BORDERLESS',0,'PGA_HORIZPOT',0,
            'PGA_HORIZBODY',0,'PGA_VERTPOT',0,'PGA_VERTBODY',0,'PGA_TOTAL',0,
            'PGA_VISIBLE',0,'PGA_TOP',0,'PGA_NEWLOOK',0]

  /* STRINGA_DUMMY ($80032000), 1-$13 */

  strtags:=['STRINGA_MAXCHARS',0,'STRINGA_BUFFER',0,'STRINGA_UNDOBUFFER',0,
            'STRINGA_WORKBUFFER',0,'STRINGA_BUFFERPOS',0,'STRINGA_DISPPOS',0,
            'STRINGA_ALTKEYMAP',0,'STRINGA_FONT',0,'STRINGA_PENS',0,
            'STRINGA_ACTIVEPENS',0,'STRINGA_EDITHOOK',0,'STRINGA_EDITMODES',0,
            'STRINGA_REPLACEMODE',0,'STRINGA_FIXEDFIELDMODE',0,
            'STRINGA_NOFILTERMODE',0,'STRINGA_JUSTIFICATION',0,
            'STRINGA_LONGVAL',0,'STRINGA_TEXTVAL',0,'STRINGA_EXITHELP',0]

  /* LAYOUTA_DUMMY ($80038000), 1-3 */

  latags:=['LAYOUTA_LAYOUTOBJ',0,'LAYOUTA_SPACING',0,'LAYOUTA_ORIENTATION',0]

  /* $8000000, $64-$93 */

  watags:=['WA_LEFT',0,'WA_TOP',12,'WA_WIDTH',11,'WA_HEIGHT',12,'WA_DETAILPEN',0,
           'WA_BLOCKPEN',0,'WA_IDCMP',0,'WA_FLAGS',0,'WA_GADGETS',0,
           'WA_CHECKMARK',0,'WA_TITLE',3,'WA_SCREENTITLE',0,
           'WA_CUSTOMSCREEN',9,'WA_SUPERBITMAP',0,'WA_MINWIDTH',0,
           'WA_MINHEIGHT',0,'WA_MAXWIDTH',0,'WA_MAXHEIGHT',0,'WA_INNERWIDTH',0,
           'WA_INNERHEIGHT',0,'WA_PUBSCREENNAME',0,'WA_PUBSCREEN',0,
           'WA_PUBSCREENFALLBACK',0,'WA_WINDOWNAME',0,'WA_COLORS',0,
           'WA_ZOOM',0,'WA_MOUSEQUEUE',0,'WA_BACKFILL',0,'WA_RPTQUEUE',0,
           'WA_SIZEGADGET',0,'WA_DRAGBAR',0,'WA_DEPTHGADGET',0,
           'WA_CLOSEGADGET',0,'WA_BACKDROP',0,'WA_REPORTMOUSE',0,
           'WA_NOCAREREFRESH',0,'WA_BORDERLESS',0,'WA_ACTIVATE',0,
           'WA_RMBTRAP',0,'WA_WBENCHWINDOW',0,'WA_SIMPLEREFRESH',0,
           'WA_SMARTREFRESH',0,'WA_SIZEBRIGHT',0,'WA_SIZEBBOTTOM',0,
           'WA_AUTOADJUST',0,'WA_GIMMEZEROZERO',0,'WA_MENUHELP',0,
           'WA_NEWLOOKMENUS',0]

ENDPROC

PROC writeDispID(id)
  DEF mon,flav
  mon:=id AND MONITOR_ID_MASK
  flav:=id AND Not(MONITOR_ID_MASK)
  SELECT mon
  CASE DEFAULT_MONITOR_ID
    WriteF('DEFAULT_MONITOR_ID')
    writeDispFlav1(flav)
  CASE NTSC_MONITOR_ID
    WriteF('NTSC_MONITOR_ID')
    writeDispFlav1(flav)
  CASE PAL_MONITOR_ID
    WriteF('PAL_MONITOR_ID')
    writeDispFlav1(flav)
  CASE VGA_MONITOR_ID
    WriteF('VGA_MONITOR_ID')
    writeDispFlav2(flav,'VGA')
  CASE A2024_MONITOR_ID
    WriteF('A2024_MONITOR_ID OR ')
    WriteF(IF flav AND A2024FIFTEENHERTZ_KEY THEN 'A2024FIFTEENHERTZ_KEY' ELSE 'A2024TENHERTZ_KEY')
  CASE EURO72_MONITOR_ID
    WriteF('EURO72_MONITOR_ID')
    writeDispFlav2(flav,'EURO72')
  CASE EURO36_MONITOR_ID
    WriteF('EURO36_MONITOR_ID')
    writeDispFlav1(flav)
  CASE SUPER72_MONITOR_ID
    WriteF('SUPER72_MONITOR_ID')
    writeDispFlav1(flav,'SUPER72')
  CASE DBLNTSC_MONITOR_ID
    WriteF('DBLNTSC_MONITOR_ID')
    writeDispFlav3(flav,'DBLNTSC')
  CASE DBLPAL_MONITOR_ID
    WriteF('DBLPAL_MONITOR_ID')
    writeDispFlav3(flav,'DBLPAL')
  DEFAULT
    writeConst(id)
  ENDSELECT
ENDPROC

-> DEFAULT/PAL/NTSC/EURO36/SUPER72
PROC writeDispFlav1(flav,type=NIL)
  DEF lores=FALSE
  WriteF(' OR ')
  IF flav AND LORESSDBL_KEY
    IF (flav AND HIRES_KEY)=0 THEN lores:=TRUE
    IF type THEN WriteF(type)
  ENDIF
  IF (flav AND SUPER_KEY)=SUPER_KEY;  WriteF('SUPER')
  ELSEIF flav AND HIRES_KEY;          WriteF('HIRES')
  ELSEIF (flav AND (SUPER_KEY OR HAM_KEY OR EXTRAHALFBRITE_KEY))=0; lores:=TRUE
  ENDIF
  IF lores THEN WriteF('LORES')
  IF flav AND HAM_KEY THEN WriteF('HAM')
  IF flav AND EXTRAHALFBRITE_KEY
    WriteF(IF flav AND Not(EXTRAHALFBRITELACE_KEY) THEN 'EHB' ELSE 'EXTRAHALFBRITE')
  ENDIF
  IF flav AND LORESLACE_KEY THEN WriteF('LACE')
  IF (flav AND LORESDPF2_KEY)=LORESDPF2_KEY;  WriteF('DPF2')
  ELSEIF flav AND LORESDPF_KEY;               WriteF('DPF')
  ENDIF
  IF flav AND LORESSDBL_KEY
    WriteF(IF type THEN 'DBL' ELSE 'SDBL')
  ENDIF
  WriteF('_KEY')
ENDPROC

-> VGA/EURO72
PROC writeDispFlav2(flav,type)
  DEF i,v
  v:=flav OR VGA_MONITOR_ID
  WriteF(' OR ')
  WriteF(type)
  i:=v AND VGAPRODUCTDBL_KEY
  SELECT i
  CASE VGAPRODUCTDBL_KEY;
    IF (v AND VGAEHB_KEY)<>VGAEHB_KEY THEN WriteF('PRODUCT')
  CASE VGALORESDBL_KEY;      WriteF('LORES')
  CASE VGAEXTRALORESDBL_KEY; WriteF('EXTRALORES')
  ENDSELECT
  IF flav AND VGAEXTRALORESHAMDBL_KEY THEN WriteF('HAM')
  IF flav AND VGAEXTRALORESEHBDBL_KEY THEN WriteF('EHB')
  IF (flav AND Not(VGAEXTRALORES_KEY)) AND VGAEXTRALORESLACE_KEY THEN WriteF('LACE')
  i:=v AND VGAEXTRALORESDPF2_KEY
  SELECT i
  CASE VGAEXTRALORESDPF2_KEY; WriteF('DPF2')
  CASE VGAEXTRALORESDPF_KEY;  WriteF('DPF')
  ENDSELECT
  IF (v AND VGAEXTRALORES_KEY)<>VGAEXTRALORES_KEY THEN WriteF('DBL')
  WriteF('_KEY')
ENDPROC

-> DBLNTSC/DBLPAL
PROC writeDispFlav3(flav,type)
  DEF i,v
  v:=flav OR DBLPAL_MONITOR_ID
  WriteF(' OR ')
  WriteF(type)
  i:=v AND (DBLPALHIRES_KEY OR DBLPALEXTRALORES_KEY)
  SELECT i
  CASE DBLPALHIRES_KEY;       WriteF('HIRES')
  CASE DBLPALEXTRALORES_KEY;  WriteF('EXTRALORES')
  DEFAULT;                    WriteF('LORES')
  ENDSELECT
  IF flav AND DBLPALLORESHAM_KEY THEN WriteF('HAM')
  IF flav AND DBLPALLORESEHB_KEY THEN WriteF('EHB')
  i:=v AND DBLPALLORESDPF2_KEY
  SELECT i
  CASE DBLPALLORESDPF2_KEY; WriteF('DPF2')
  CASE DBLPALLORESDPF_KEY;  WriteF('DPF')
  ENDSELECT
  i:=v AND DBLPALLORESLACE_KEY
  SELECT i
  CASE DBLPALLORESLACE_KEY; WriteF('LACE')
  CASE DBLPALLORESFF_KEY;   WriteF('FF')
  ENDSELECT
  WriteF('_KEY')
ENDPROC

PROC findKey(s)
  DEF key=0, c
  IF s
    WHILE c:=s[]++
      IF c="_" THEN key:=s[]
    ENDWHILE
  ENDIF
ENDPROC tolower(key)

PROC fixString(s,initlower=TRUE)
  DEF c
  IF initlower THEN IF c:=s[] THEN s[]++:=tolower(c)
  WHILE c:=s[] DO IF isalnum(c) THEN s++ ELSE s[]++:="_"
ENDPROC

PROC writeString(s)
  DEF c
  IF s
    WriteF('''')
    WHILE c:=s[]++
      IF c="'";       WriteF('''''')
      ELSEIF c="\\";  WriteF('\\\\')
      ELSE;           Out(stdout,c)
      ENDIF
    ENDWHILE
    WriteF('''')
  ELSE
    WriteF('NIL')
  ENDIF
ENDPROC

PROC writeConst(v) IS WriteF(IF (v>=-256) AND (v<=256) THEN '\d' ELSE '$\h',v)

PROC writeBool(v) IS WriteF(IF v THEN 'TRUE' ELSE 'FALSE')

PROC orConst(const)
  IF done_or THEN WriteF(' OR ') ELSE done_or:=TRUE
  WriteF(const)
ENDPROC

