home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 3 / CDPDIII.bin / pd / utilities / misc / windowshuffle / windowshuffle.c < prev    next >
C/C++ Source or Header  |  1991-08-22  |  22KB  |  691 lines

  1. /*
  2.  *  WindowShuffle.c
  3.  *
  4.  *  Commodity
  5.  *
  6.  *  Author: Stefan Sticht
  7.  *
  8.  *  Copyright: source is public domain, no copyright
  9.  *
  10.  *  Version history:
  11.  *
  12.  *  V1.00   initial release
  13.  *  V1.02   recompiled with main.c V1.02
  14.  *  V1.03   completly rewritten; shared commodity code thrown away; smaller, uses less CPU time
  15.  *  V1.04   now refuses to activate windows specified with REFUSE
  16.  *          second pair of hotkeys for only Activate without WindowToFront()
  17.  *          changed Priority to 21 to block out intuition for safety reasons
  18.  *  V1.05   some really minor changes
  19.  *  V1.06   recompiled with changed (for 68040 compatiblity) cback.o
  20.  *          removed error when started from WB: taskpri wasn't set to 21
  21.  *          thanks to Uwe Röhm
  22.  *  V1.07   small changes, moved UnlockIBase() in processmessages()
  23.  */
  24.  
  25. #define VERSION "V1.07"
  26.  
  27. /********************************************************************
  28.  *                             interfacing                          *
  29.  ********************************************************************/
  30.  
  31. /*
  32.  *  include files
  33.  */
  34.  
  35. #include <stdarg.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include <intuition/intuitionbase.h>
  39. #include <libraries/commodities.h>
  40.  
  41. #include <clib/alib_protos.h>
  42. #include <clib/commodities_protos.h>
  43. #include <pragmas/commodities_pragmas.h>
  44. #include <clib/dos_protos.h>
  45. #include <pragmas/dos_pragmas.h>
  46. #include <clib/exec_protos.h>
  47. #include <pragmas/exec_pragmas.h>
  48. #include <clib/intuition_protos.h>
  49. #include <pragmas/intuition_pragmas.h>
  50.  
  51. #ifdef DEBUG
  52. #define printf KPrintF
  53. #include <clib/dlib_protos.h>
  54. #endif
  55.  
  56. /*
  57.  *  prototypes
  58.  */
  59. long request(char *title, char *gadgets, char *text, ...);
  60. struct Library *myopenlibrary(char *name, unsigned long version);
  61. struct Window *lastwindow(struct Window *win);
  62. struct Window *nextwindow(struct Window *win);
  63. struct Window *prevwindow(struct Window *win);
  64. void *retryallocmem(unsigned long size, long mode);
  65. void processmessages(void);
  66.  
  67. /*
  68.  *  global data defined in other moduls
  69.  *
  70.  *  libraries opened by startup code; basepointers needed by function pragmas
  71.  */
  72. extern struct Library *DOSBase;
  73. extern struct Library *SysBase;
  74.  
  75. /*
  76.  *  Disable SAS/C CTRL/C handling
  77.  */
  78. void chkabort(void) {}
  79.  
  80. /********************************************************************
  81.  *                             global data                          *
  82.  ********************************************************************/
  83.  
  84. #define TT_PREVAC  "PREV_ACTIVE"
  85. #define TT_NEXTAC  "NEXT_ACTIVE"
  86. #define TT_PREVBO  "PREV_BOTH"
  87. #define TT_NEXTBO  "NEXT_BOTH"
  88.  
  89. /*
  90.  *  definition of all messages (multi language support not completed yet)
  91.  */
  92. #ifdef GERMAN
  93.  
  94. #define RETRY_GADGETS           "Wiederholen|Abbrechen"
  95. #define RESUME_GADGETS          "Weiter"
  96. #define MSG_OUTOFMEM            "Leider ein Speicherblock von %ld bytes\nnicht alloziert werden!"
  97. #define MSG_LIBRARY_OPENERR     "Die %s (V%ld+) kann nicht geöffnet werden!"
  98. #define COM_NAME                "Fensterln"
  99. #define COM_DESCR               "Nächstes/letztes Fenster aktivieren"
  100. #define TT_BACKDROP             "BACKDROP"
  101. #define TT_NOWINTITLE           "OHNETITEL"
  102. #define TT_REFUSE               "DIESENICHT"
  103. #define MSG_REFUSE_TOO_COMPLEX  "Leider muß " TT_REFUSE " ignoriert werden,\nda der Ausdruck zu komplex ist."
  104. #define NO                      "NEIN"
  105. #define YES                     "JA"
  106.  
  107. #else
  108.  
  109. #define RETRY_GADGETS           "Retry|Cancel"
  110. #define RESUME_GADGETS          "Resume"
  111. #define MSG_OUTOFMEM            "Failure allocting %ld bytes of memory!"
  112. #define MSG_LIBRARY_OPENERR     "%s (V%ld+) can't be opened!"
  113. #define COM_NAME                "WindowShuffle"
  114. #define COM_DESCR               "Activate next/previous window"
  115. #define TT_BACKDROP             "BACKDROP"
  116. #define TT_NOWINTITLE           "WITHOUTTITLE"
  117. #define TT_REFUSE               "REFUSE"
  118. #define MSG_REFUSE_TOO_COMPLEX  TT_REFUSE " will be ignored\nas the pattern is too complex!"
  119. #define YES                     "YES"
  120. #define NO                      "NO"
  121.  
  122. #endif
  123.  
  124. #define COM_TITLE           COM_NAME " " VERSION
  125. #define CX_PRIORITY         "CX_PRIORITY"
  126. #define DEF_CX_PRIORITY     0
  127.  
  128. #define DEF_TT_PREVAC       "lcommand lshift j"
  129. #define DEF_TT_NEXTAC       "lcommand lshift k"
  130. #define DEF_TT_PREVBO       "lcommand j"
  131. #define DEF_TT_NEXTBO       "lcommand k"
  132. #define DEF_TT_BACKDROP     NO
  133. #define DEF_TT_NOWINTITLE   NO
  134. #define DEF_TT_REFUSE       ""
  135.  
  136. /*
  137.  *  data for cback.o
  138.  */
  139. long _stack = 4096l;
  140. char *_procname = COM_NAME;
  141. #define PRIORITY 21l
  142. long _priority = PRIORITY;
  143. long _BackGroundIO = 1;
  144. extern BPTR _Backstdout;
  145.  
  146. /*
  147.  *  library base pointers
  148.  */
  149. struct IntuitionBase *IntuitionBase;
  150. struct Library *CxBase;
  151. struct Library *IconBase;
  152.  
  153. /*
  154.  *  message port
  155.  */
  156. struct MsgPort *cxport = NULL;
  157.  
  158. /*
  159.  *  signal flag
  160.  */
  161. unsigned long cxsigflag = 0l;
  162.  
  163. /*
  164.  *  programtitle and version for Version command
  165.  */
  166. char versionstring[] ="\0$VER: " COM_NAME " " VERSION;
  167.  
  168. /*
  169.  *  helpstring
  170.  */
  171. #ifdef GERMAN
  172. char helpstring[] =
  173. "\033[1m" COM_NAME "\033[0m " VERSION " (Public Domain) von Stefan Sticht\n"\
  174. "Aufruf: " COM_NAME " ["\
  175. CX_PRIORITY "=<Zahl>] [" TT_NEXTAC "=<Zeichenkette>] [" TT_PREVAC "=<Zeichenkette>] ["\
  176. TT_NEXTBO "=<Zeichenkette>] [" TT_PREVBO "=<Zeichenkette>] [" TT_BACKDROP "=" YES "|" NO "] ["\
  177. TT_NOWINTITLE "=" YES "|" NO "] [" TT_REFUSE "=<Zeichenkette>]\n";
  178. #else
  179. char helpstring[] =
  180. "\033[1m" COM_NAME "\033[0m " VERSION " (Public Domain) by Stefan Sticht\n"
  181. "Usage: " COM_NAME " ["\
  182. CX_PRIORITY "=<number>] [" TT_NEXTAC "=<string>] [" TT_PREVAC "=<string>] ["\
  183. TT_NEXTBO "=<string>] [" TT_PREVBO "=<string>] [" TT_BACKDROP "=" YES "|" NO "] ["\
  184. TT_NOWINTITLE "=" YES "|" NO "] [" TT_REFUSE "=<string>]\n";
  185. #endif
  186.  
  187. /*
  188.  *  the tooltypearray
  189.  */
  190. char **tooltypes;
  191.  
  192. /*
  193.  *  our broker
  194.  */
  195. CxObj *broker = NULL;
  196.  
  197. struct NewBroker newbroker = {
  198.     NB_VERSION,                         /* BYTE nb_Version               */
  199.     COM_NAME,                           /* BYTE *nb_Name                 */
  200.     COM_TITLE,                          /* BYTE *nb_Title                */
  201.     COM_DESCR,                          /* BYTE *nb_Descr                */
  202.     NBU_NOTIFY | NBU_UNIQUE,            /* SHORT nb_Unique               */
  203.     0,                                  /* SHORT nb_Flags                */
  204.     0,                                  /* BYTE nb_Pri                   */
  205.     NULL,                               /* struct MsgPort nb_Port        */
  206.     0                                   /* WORD nb_ReservedChannel       */
  207. };
  208.  
  209. #define NEXTAC  1
  210. #define PREVAC  2
  211. #define NEXTBO  3
  212. #define PREVBO  4
  213.  
  214. /*
  215.  *  pointer to refuse tokens
  216.  */
  217. char *refusetokens = NULL;
  218. /*
  219.  *  booleans for activation of backdrop windows and windows w/o title
  220.  */
  221. unsigned short backdrop;
  222. unsigned short nowintitle;
  223.  
  224. /********************************************************************
  225.  *                             functions                            *
  226.  ********************************************************************/
  227.  
  228. /*
  229.  *  request(): a glue routine to EasyRequest as simple as printf plus
  230.  *             titlestring, gadgettexts
  231.  *
  232.  *  Input: char *title:         pointer to the title of the requester
  233.  *         char *gadgets:       pointer to gadgettext
  234.  *         char *text:          text displayed in requester
  235.  *
  236.  *  Result: same as EasyrequestArgs()
  237.  *
  238.  * !!! for more info see EasyRequestArgs() in Autodocs/intuition.doc !!!
  239.  */
  240. long request(char *title, char *gadgets, char *text, ...)
  241. {
  242.     /*
  243.      *  structure textreq only needed in this function, so hide it here
  244.      *  must be static, in order to be initialized only once
  245.      */
  246.     static struct EasyStruct textreq = {
  247.         sizeof (struct EasyStruct), /* ULONG es_StructSize      */
  248.         0l,                         /* ULONG es_Flags           */
  249.         NULL,                       /* UBYTE *es_Title          */
  250.         NULL,                       /* UBYTE *es_TextFormat     */
  251.         NULL,                       /* UBYTE *es_GadgetFormat   */
  252.         };
  253.     va_list ap;
  254.     long rc;
  255.  
  256.     /*
  257.      *  get start of variable arguments
  258.      */
  259.     va_start(ap, text);
  260.  
  261.     /*
  262.      *  update textreq
  263.      */
  264.     textreq.es_Title = (UBYTE *)title;
  265.     textreq.es_TextFormat = (UBYTE *)text;
  266.     textreq.es_GadgetFormat = (UBYTE *)gadgets;
  267.  
  268.     /*
  269.      *  win may be NULL
  270.      */
  271.     rc = EasyRequestArgs(NULL, &textreq, NULL, ap);
  272.  
  273.     va_end(ap);
  274.  
  275.     return(rc);
  276. }
  277.  
  278. /*
  279.  *  myopenlibrary(): same as OpenLibrary(), but opens a retry-requester
  280.  *                   if OpenLibrary() fails, to give the user a chance to
  281.  *                   copy the library to libs: and retry
  282.  *                   requires request(), see above
  283.  */
  284. struct Library *myopenlibrary(char *name, unsigned long version)
  285. {
  286.     static char errortext[] = MSG_LIBRARY_OPENERR;
  287.     struct Library *libptr;
  288.     long ok = TRUE;
  289.  
  290.     do {
  291.         if (!(libptr = OpenLibrary((UBYTE *)name, version))) {
  292.             if (IntuitionBase) ok = request(COM_NAME ":", RETRY_GADGETS, errortext, name, version);
  293.             else ok = FALSE;
  294.             }
  295.         } while (!libptr && ok);
  296.  
  297.     #ifdef DEBUG
  298.     printf("myopenlibrary(%s, %ld) = 0x%lx\n", name, version, libptr);
  299.     #endif
  300.     return(libptr);
  301. }
  302.  
  303. void *retryallocmem(unsigned long size, long mode)
  304. {
  305.     void *addr;
  306.  
  307.     do {
  308.  
  309.         if (!(addr = AllocMem(size, mode))) {
  310.             if (!(request(COM_NAME ":", RETRY_GADGETS, MSG_OUTOFMEM, size))) return(NULL);
  311.             }
  312.  
  313.         } while (!addr);
  314.  
  315.     return(addr);
  316. }
  317.  
  318. void main(int argc, char *argv[])
  319. {
  320.     CxObj *nextacfilter = NULL;
  321.     CxObj *prevacfilter = NULL;
  322.     CxObj *nextbofilter = NULL;
  323.     CxObj *prevbofilter = NULL;
  324.     struct Message *msg;
  325.     char *refuse;
  326.     char *nextackey;
  327.     char *prevackey;
  328.     char *nextbokey;
  329.     char *prevbokey;
  330.     unsigned long size = 0l;
  331.  
  332.     if ((argc > 1) && (*argv[1] == '?')) {
  333.         /*
  334.          *  display help string
  335.          */
  336.         if (_Backstdout) {
  337.             Write(_Backstdout, helpstring, sizeof(helpstring) - 1l);
  338.             Close(_Backstdout);
  339.             }
  340.         return;
  341.         }
  342.     else if (argc && _Backstdout) Close(_Backstdout);
  343.     else if (!argc) {
  344.         /*
  345.          *  started from Workbench: cback.o doesn't change our priority,
  346.          *  so we do here
  347.          */
  348.         struct Task *mytask;
  349.         if (mytask = FindTask(NULL)) SetTaskPri(mytask, PRIORITY);
  350.         }
  351.  
  352.     /*
  353.      *  open required libraries first
  354.      */
  355.     if (IntuitionBase = (struct IntuitionBase *)myopenlibrary("intuition.library", 37l)) {
  356.  
  357.         if (CxBase = myopenlibrary("commodities.library", 37l)) {
  358.  
  359.             if (IconBase = myopenlibrary("icon.library", 37l)) {
  360.  
  361.                 /*
  362.                  * create tooltypes array (requires icon.library open!!!)
  363.                  */
  364.                 tooltypes = (char **)ArgArrayInit(argc, argv);
  365.  
  366.                 /*
  367.                  *  create our message port
  368.                  */
  369.                 if (cxport = CreateMsgPort()) {
  370.  
  371.                     cxsigflag = 1l << cxport->mp_SigBit;
  372.                     /*
  373.                      * set up some broker data
  374.                      */
  375.                     newbroker.nb_Pri = ArgInt(tooltypes, CX_PRIORITY, DEF_CX_PRIORITY);
  376.                     newbroker.nb_Port = cxport;
  377.  
  378.                     if (broker = CxBroker(&newbroker, NULL)) {
  379.  
  380.                         if ((nextackey = ArgString(tooltypes, TT_NEXTAC, DEF_TT_NEXTAC)) &&
  381.                             *nextackey) {
  382.  
  383.                             if (nextacfilter = HotKey(nextackey, cxport, NEXTAC))
  384.                                 AttachCxObj(broker, nextacfilter);
  385.  
  386.                             } /* if nextackey */
  387.  
  388.                         if ((prevackey = ArgString(tooltypes, TT_PREVAC, DEF_TT_PREVAC)) &&
  389.                             *prevackey) {
  390.  
  391.                             if (prevacfilter = HotKey(prevackey, cxport, PREVAC))
  392.                                 AttachCxObj(broker, prevacfilter);
  393.  
  394.                             } /* if prevackey */
  395.  
  396.                         if ((nextbokey = ArgString(tooltypes, TT_NEXTBO, DEF_TT_NEXTBO)) &&
  397.                             *nextbokey) {
  398.  
  399.                             if (nextbofilter = HotKey(nextbokey, cxport, NEXTBO))
  400.                                 AttachCxObj(broker, nextbofilter);
  401.  
  402.                             } /* if nextbokey */
  403.  
  404.                         if ((prevbokey = ArgString(tooltypes, TT_PREVBO, DEF_TT_PREVBO)) &&
  405.                             *prevbokey) {
  406.  
  407.                             if (prevbofilter = HotKey(prevbokey, cxport, PREVBO))
  408.                                 AttachCxObj(broker, prevbofilter);
  409.  
  410.                             } /* if prevbokey */
  411.  
  412.                         backdrop = (strcmpi((char *)ArgString(tooltypes, TT_BACKDROP, DEF_TT_BACKDROP),
  413.                                     YES)) ? FALSE : TRUE;
  414.  
  415.                         nowintitle = (strcmpi((char *)ArgString(tooltypes, TT_NOWINTITLE, DEF_TT_NOWINTITLE),
  416.                                     YES)) ? FALSE : TRUE;
  417.  
  418.                         refuse = (char *)ArgString(tooltypes, TT_REFUSE, DEF_TT_REFUSE);
  419.  
  420.                         #ifdef DEBUG
  421.                         if (refuse) printf("WindowShuffle: refuse = %s\n", refuse);
  422.                         #endif
  423.  
  424.                         if (*refuse && (size = (strlen(refuse) << 1)) &&
  425.                             (refusetokens = retryallocmem(size, 0l))) {
  426.  
  427.                             #ifdef DEBUG
  428.                             printf("WindowShuffle: size = %ld, refusetokens = 0x%lx\n", size, refusetokens);
  429.                             #endif
  430.  
  431.                             if (ParsePattern(refuse, refusetokens, size) == -1l)
  432.                                 request(COM_NAME ":", RESUME_GADGETS, MSG_REFUSE_TOO_COMPLEX);
  433.  
  434.                             #ifdef DEBUG
  435.                             printf("WindowShuffle: refusetokens = %s\n", refusetokens);
  436.                             #endif
  437.  
  438.                             }
  439.  
  440.                         if ((nextacfilter && !CxObjError(nextacfilter)) ||
  441.                             (prevacfilter && !CxObjError(prevacfilter)) ||
  442.                             (nextbofilter && !CxObjError(nextbofilter)) ||
  443.                             (prevbofilter && !CxObjError(prevbofilter))) {
  444.                             /*
  445.                              *  activate our commodity
  446.                              */
  447.                             ActivateCxObj(broker, 1l);
  448.                             /*
  449.                              *  now watch our numerous ports
  450.                              */
  451.                             processmessages();
  452.  
  453.                             } /* if !CxObjError() */
  454.  
  455.                         DeleteCxObjAll(broker);
  456.  
  457.                         if (refusetokens) FreeMem(refusetokens, size);
  458.  
  459.                         } /* if broker */
  460.  
  461.                     #ifdef DEBUG
  462.                     else printf("main(): CxBroker() failed!\n");
  463.                     #endif
  464.  
  465.                     /*
  466.                      *  delete our message port after replying all pending messages
  467.                      */
  468.                     while (msg = GetMsg(cxport)) ReplyMsg(msg);
  469.                     DeleteMsgPort(cxport);
  470.                     } /* if cxport */
  471.  
  472.                 #ifdef DEBUG
  473.                 else printf("main(): CraeteMsgPort() failed!\n");
  474.                 #endif
  475.  
  476.                 ArgArrayDone();
  477.  
  478.                 CloseLibrary(IconBase);
  479.                 } /* if IconBase */
  480.  
  481.             CloseLibrary(CxBase);
  482.             } /* if CxBase */
  483.  
  484.     CloseLibrary((struct Library *)IntuitionBase);
  485.     } /* if IntuitionBase */
  486.  
  487. } /* main() */
  488.  
  489. #define PREV    1
  490. #define TOF     2
  491. #define AC      4
  492. #define BO      6
  493.  
  494. void processmessages(void)
  495. {
  496.     struct Window *win;
  497.     struct Message *msg;
  498.     unsigned long sigreceived;
  499.     unsigned long msgtype;
  500.     unsigned long msgid;
  501.     unsigned long lock;
  502.     unsigned short quit = FALSE;
  503.     unsigned char mode;
  504.  
  505.     while (!quit) {
  506.  
  507.         sigreceived = Wait(SIGBREAKF_CTRL_C | cxsigflag);
  508.  
  509.         #ifdef DEBUG
  510.         printf("processmessages(): signal received\n");
  511.         #endif
  512.  
  513.         if (sigreceived & SIGBREAKF_CTRL_C) quit = TRUE;
  514.  
  515.         if (sigreceived & cxsigflag) {
  516.  
  517.             while (msg = (struct Message *)GetMsg(cxport)) {
  518.  
  519.                 msgid = CxMsgID((CxMsg *)msg);
  520.                 msgtype = CxMsgType((CxMsg *)msg);
  521.  
  522.                 ReplyMsg(msg);
  523.  
  524.                 switch (msgtype) {
  525.  
  526.                     case CXM_IEVENT:
  527.                         mode = 0;
  528.                         switch (msgid) {
  529.  
  530.                             case PREVAC:    mode = PREV;
  531.                             case NEXTAC:    mode |= AC;
  532.                                             break;
  533.  
  534.                             case PREVBO:    mode = PREV;
  535.                             case NEXTBO:    mode |= BO;
  536.                                             break;
  537.  
  538.                             } /* switch msgid */
  539.  
  540.                         lock = LockIBase(0l);
  541.                         if (mode & PREV) {
  542.                             /*
  543.                              *  get previous window
  544.                              */
  545.                             if (!(win = prevwindow(IntuitionBase->ActiveWindow))) {
  546.                                 /*
  547.                                  *  no prev window; get last window;
  548.                                  *  if last window = backdrop || nowintitle ||
  549.                                  *  refusewindow get predecessor of lastwindow
  550.                                  */
  551.                                 if ((win = lastwindow(IntuitionBase->ActiveWindow)) &&
  552.                                     ((!backdrop && (win->Flags & WFLG_BACKDROP)) ||
  553.                                     (!nowintitle && !win->Title)) ||
  554.                                     (refusetokens && win->Title && MatchPattern(refusetokens, win->Title)))
  555.                                     win = prevwindow(win);
  556.                                     }
  557.                             }
  558.                         else {
  559.                             /*
  560.                              *  get next window
  561.                              */
  562.                             if (!(win = nextwindow(IntuitionBase->ActiveWindow))) {
  563.                                 /*
  564.                                  *  no next window; get first window;
  565.                                  *  if first window = backdrop || nowintitle ||
  566.                                  *  refusewindow get first window->NextWindow
  567.                                  */
  568.                                 if ((win = IntuitionBase->ActiveScreen->FirstWindow) &&
  569.                                     ((!backdrop && (win->Flags & WFLG_BACKDROP)) ||
  570.                                     (!nowintitle && !win->Title)) ||
  571.                                     (refusetokens && win->Title && MatchPattern(refusetokens, win->Title)))
  572.                                     win = nextwindow(win);
  573.                                 }
  574.                             }
  575.  
  576.                         /*
  577.                          *  now activate and windowtofront the window if (win != NULL)
  578.                          */
  579.                         if (win) {
  580.  
  581.                             if ((mode & AC) && (win != IntuitionBase->ActiveWindow))
  582.                                 ActivateWindow(win);
  583.                             if ((mode & TOF) && (!(win->Flags & WFLG_BACKDROP)))
  584.                                 WindowToFront(win);
  585.  
  586.                             }
  587.  
  588.                         UnlockIBase(lock);
  589.  
  590.                         break;
  591.  
  592.                     case CXM_COMMAND:
  593.                         switch (msgid) {
  594.  
  595.                             case CXCMD_UNIQUE:
  596.                             case CXCMD_KILL:
  597.                                 quit = TRUE;
  598.                                 break;
  599.  
  600.                             case CXCMD_DISABLE:
  601.                                 ActivateCxObj(broker, 0l);
  602.                                 break;
  603.  
  604.                             case CXCMD_ENABLE:
  605.                                 ActivateCxObj(broker, 1l);
  606.                                 break;
  607.  
  608.                             }
  609.                         break;
  610.  
  611.                     } /* switch msgtype */
  612.  
  613.                 } /* while CxMsg */
  614.  
  615.             } /* if (sigreceived & cxsigflag) */
  616.  
  617.         } /* while !quit */
  618.  
  619.     ActivateCxObj(broker, 0l);
  620. }
  621.  
  622. /*
  623.  *  commodity functions
  624.  *
  625.  *  get next window
  626.  */
  627. struct Window *nextwindow(register struct Window *win)
  628. {
  629.     register struct Window *w = NULL;
  630.  
  631.     if (win) {
  632.  
  633.         while (!w && win->NextWindow) {
  634.  
  635.             w = win = win->NextWindow;
  636.  
  637.             if ((!backdrop && (w->Flags & WFLG_BACKDROP)) ||
  638.                 (!nowintitle && !w->Title) ||
  639.                 (refusetokens && w->Title && MatchPattern(refusetokens, w->Title)))
  640.                 w = NULL;
  641.  
  642.             } /* while !w */
  643.  
  644.         } /* if win */
  645.  
  646.     return(w);
  647. }
  648.  
  649. /*
  650.  *  get previous window
  651.  */
  652. struct Window *prevwindow(register struct Window *win)
  653. {
  654.     register struct Window *w = NULL;
  655.  
  656.     if (win) {
  657.  
  658.         while (!w && (win != win->WScreen->FirstWindow)) {
  659.  
  660.             for (w = win->WScreen->FirstWindow; w->NextWindow != win; w = w->NextWindow);
  661.  
  662.             if ((!backdrop && (w->Flags & WFLG_BACKDROP)) ||
  663.                 (!nowintitle && !w->Title) ||
  664.                 (refusetokens && w->Title && MatchPattern(refusetokens, w->Title))) {
  665.  
  666.                 win = w;
  667.                 w = NULL;
  668.  
  669.                 }
  670.  
  671.             } /* while !w */
  672.  
  673.         } /* if win */
  674.  
  675.     return(w);
  676. }
  677.  
  678. /*
  679.  *  get last window
  680.  */
  681. struct Window *lastwindow(register struct Window *win)
  682. {
  683.     if (win) {
  684.  
  685.         while (win->NextWindow) win = win->NextWindow;
  686.  
  687.         } /* if win */
  688.  
  689.     return(win);
  690. }
  691.