home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 15 / AACD15.ISO / AACD / Programming / MultiDesktop / desk / desk.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-27  |  26.4 KB  |  1,282 lines

  1. /* MultiDesktop-Library - Memory, Timer, Locale, Requester */
  2. #include "multidesktop.h"
  3.  
  4. BOOL            StrIsGreaterThan();
  5. BOOL            StrIsLessThan();
  6. UBYTE          *AllocMemory();
  7. UBYTE          *GetLStr();
  8. UBYTE          *FindID();
  9. void            Seconds2StarDate();
  10. struct Library *OpenDevLibrary();
  11. void            FreeMemory();
  12. void            FreeMemoryBlock();
  13. void            ErrorL();
  14. void            OldError();
  15. void            CloseDevLibrary();
  16. void            RemoveLib();
  17. extern ULONG    HookEntry();
  18. extern UBYTE    ToUpper();
  19.  
  20. extern struct MultiDesktopBase *MultiDesktopBase;
  21. extern struct ExecBase         *SysBase;
  22.  
  23. struct Catalog                 *Catalog;
  24. struct Library                 *LocaleBase;
  25. struct Library                 *UtilityBase;
  26. struct Library                 *TimerBase;
  27. struct Library                 *InputBase;
  28. struct Library                 *BattClockBase;
  29. struct Library                 *IntuitionBase;
  30. struct Library                 *DOSBase;
  31.  
  32. extern ULONG  SleepPointerSize;
  33. extern UBYTE *SleepPointerData;
  34. UBYTE        *ChipData;
  35.  
  36. struct IntuiText t1=
  37. {
  38.  AUTOFRONTPEN,
  39.  AUTOBACKPEN,
  40.  AUTODRAWMODE,
  41.  AUTOLEFTEDGE,
  42.  AUTOTOPEDGE,
  43.  NULL,
  44.  NULL,
  45.  NULL
  46. };
  47.  
  48. struct IntuiText t2=
  49. {
  50.  AUTOFRONTPEN,
  51.  AUTOBACKPEN,
  52.  AUTODRAWMODE,
  53.  AUTOLEFTEDGE,
  54.  AUTOTOPEDGE,
  55.  NULL,
  56.  "Abort!",
  57.  NULL
  58. };
  59.  
  60. /* ---- Library initialisieren */
  61. ULONG InitLib()
  62. {
  63.  MultiDesktopBase->IntLib=OpenLibrary("intuition.library",0L);
  64.  if(MultiDesktopBase->IntLib==NULL)
  65.   { RemoveLib(); exit(0); }
  66.  
  67.  IntuitionBase=MultiDesktopBase->IntLib;
  68.  if(IntuitionBase->lib_Version<37) {
  69.    OldError("This software requires AmigaDOS 2.0 (V37)!");
  70.    RemoveLib(); return(0); }
  71.  
  72.  MultiDesktopBase->GfxLib=OpenLibrary("graphics.library",37L);
  73.  if(MultiDesktopBase->GfxLib==NULL)
  74.   { OldError("Unable to open graphics.library V37!");
  75.     RemoveLib(); exit(0); }
  76.  
  77.  MultiDesktopBase->DosLib=OpenLibrary("dos.library",37L);
  78.  if(MultiDesktopBase->DosLib==NULL)
  79.   { OldError("Unable to open dos.library V37!");
  80.     RemoveLib(); exit(0); }
  81.  DOSBase=MultiDesktopBase->DosLib;
  82.  
  83.  MultiDesktopBase->DiskfontLib=OpenLibrary("diskfont.library",36L);
  84.  if(MultiDesktopBase->DiskfontLib==NULL)
  85.   { OldError("Unable to open diskfont.library V36!");
  86.     RemoveLib(); exit(0); }
  87.  
  88.  MultiDesktopBase->GadToolsLib=OpenLibrary("gadtools.library",37L);
  89.  if(MultiDesktopBase->GadToolsLib==NULL)
  90.   { OldError("Unable to open gadtools.library V37!");
  91.     RemoveLib(); exit(0); }
  92.  
  93.  MultiDesktopBase->IconLib=OpenLibrary("icon.library",37L);
  94.  if(MultiDesktopBase->IconLib==NULL)
  95.   { OldError("Unable to open icon.library V37!");
  96.     RemoveLib(); exit(0); }
  97.  
  98.  MultiDesktopBase->LayersLib=OpenLibrary("layers.library",37L);
  99.  if(MultiDesktopBase->LayersLib==NULL)
  100.   { OldError("Unable to open layers.library V37!");
  101.     RemoveLib(); exit(0); }
  102.  
  103.  MultiDesktopBase->WorkbenchLib=OpenLibrary("workbench.library",37L);
  104.  if(MultiDesktopBase->WorkbenchLib==NULL)
  105.   { OldError("Unable to open workbench.library V37!");
  106.     RemoveLib(); exit(0); }
  107.  
  108.  MultiDesktopBase->ExpansionLib=OpenLibrary("expansion.library",37L);
  109.  if(MultiDesktopBase->ExpansionLib==NULL)
  110.   { OldError("Unable to open expansion.library V37!");
  111.     RemoveLib(); exit(0); }
  112.  
  113.  MultiDesktopBase->UtilityLib=OpenLibrary("utility.library",37L);
  114.  if(MultiDesktopBase->UtilityLib==NULL)
  115.   { OldError("Unable to open utility.library V37!");
  116.     RemoveLib(); exit(0); }
  117.  UtilityBase=MultiDesktopBase->UtilityLib;
  118.  
  119.  MultiDesktopBase->KeymapLib=OpenLibrary("keymap.library",37L);
  120.  if(MultiDesktopBase->KeymapLib==NULL)
  121.   { OldError("Unable to open keymap.library V37!");
  122.     RemoveLib(); exit(0); }
  123.  
  124.  
  125.  MultiDesktopBase->VersionLib=OpenLibrary("version.library",0L);
  126.  MultiDesktopBase->LocaleLib=OpenLibrary("locale.library",38L);
  127.  if(MultiDesktopBase->LocaleLib!=NULL)
  128.   {
  129.    LocaleBase=MultiDesktopBase->LocaleLib;
  130.    MultiDesktopBase->Locale=OpenLocale(NULL);
  131.    if(MultiDesktopBase->Locale!=NULL)
  132.     {
  133.      MultiDesktopBase->Catalog=OpenCatalogA(MultiDesktopBase->Locale,
  134.                                             "multidesktop.catalog",
  135.                                             NULL);
  136.      Catalog=MultiDesktopBase->Catalog;
  137.     }
  138.   }
  139.  
  140.  MultiDesktopBase->TimerLib=OpenDevLibrary("timer.device",0);
  141.  if(MultiDesktopBase->TimerLib==NULL) {
  142.    OldError("Unable to open timer.device!");
  143.    RemoveLib(); return(0); }
  144.  
  145.  MultiDesktopBase->ConsoleLib=OpenDevLibrary("console.device",0);
  146.  if(MultiDesktopBase->ConsoleLib==NULL) {
  147.    OldError("Unable to open console.device!");
  148.    RemoveLib(); return(0); }
  149.  
  150.  MultiDesktopBase->InputLib=OpenDevLibrary("input.device",0);
  151.  if(MultiDesktopBase->InputLib==NULL) {
  152.    OldError("Unable to open input.device!");
  153.    RemoveLib(); return(0); }
  154.  
  155.  ChipData=AllocMem(SleepPointerSize,MEMF_CHIP|MEMF_PUBLIC);
  156.  if(ChipData!=NULL)
  157.    CopyMemQuick(&SleepPointerData,ChipData,SleepPointerSize);
  158.  
  159.  MultiDesktopBase->BattClockLib=OpenResource("battclock.resource",0);
  160.  BattClockBase=MultiDesktopBase->BattClockLib;
  161.  
  162.  TimerBase=MultiDesktopBase->TimerLib;
  163.  InputBase=MultiDesktopBase->InputLib;
  164.  
  165.  return(1L);
  166. }
  167.  
  168. /* ---- Library entfernen */
  169. void RemoveLib()
  170. {
  171.  if(ChipData) FreeMem(ChipData,SleepPointerSize);
  172.  if(MultiDesktopBase->TimerLib) CloseDevLibrary(MultiDesktopBase->TimerLib);
  173.  if(MultiDesktopBase->ConsoleLib) CloseDevLibrary(MultiDesktopBase->ConsoleLib);
  174.  if(MultiDesktopBase->InputLib) CloseDevLibrary(MultiDesktopBase->InputLib);
  175.  
  176.  if(MultiDesktopBase->Catalog) CloseCatalog(MultiDesktopBase->Catalog);
  177.  if(MultiDesktopBase->Locale) CloseLocale(MultiDesktopBase->Locale);
  178.  if(MultiDesktopBase->LocaleLib) CloseLibrary(MultiDesktopBase->LocaleLib);
  179.  if(MultiDesktopBase->VersionLib) CloseLibrary(MultiDesktopBase->VersionLib);
  180.  if(MultiDesktopBase->KeymapLib) CloseLibrary(MultiDesktopBase->KeymapLib);
  181.  if(MultiDesktopBase->ExpansionLib) CloseLibrary(MultiDesktopBase->ExpansionLib);
  182.  if(MultiDesktopBase->UtilityLib) CloseLibrary(MultiDesktopBase->UtilityLib);
  183.  if(MultiDesktopBase->WorkbenchLib) CloseLibrary(MultiDesktopBase->WorkbenchLib);
  184.  if(MultiDesktopBase->LayersLib) CloseLibrary(MultiDesktopBase->LayersLib);
  185.  if(MultiDesktopBase->IconLib) CloseLibrary(MultiDesktopBase->IconLib);
  186.  if(MultiDesktopBase->GadToolsLib) CloseLibrary(MultiDesktopBase->GadToolsLib);
  187.  if(MultiDesktopBase->DiskfontLib) CloseLibrary(MultiDesktopBase->DiskfontLib);
  188.  if(MultiDesktopBase->GfxLib) CloseLibrary(MultiDesktopBase->GfxLib);
  189.  if(MultiDesktopBase->IntLib) CloseLibrary(MultiDesktopBase->IntLib);
  190.  if(MultiDesktopBase->DosLib) CloseLibrary(MultiDesktopBase->DosLib);
  191. }
  192.  
  193. /* ---- Multi-Requester */
  194. LONG MultiRequest(titel,text,gads)
  195.  UBYTE *titel,*text,*gads;
  196. {
  197.  struct EasyStruct easy;
  198.  
  199.  easy.es_StructSize=sizeof(struct EasyStruct);
  200.  easy.es_Flags=0;
  201.  easy.es_Title=titel;
  202.  easy.es_TextFormat=text;
  203.  easy.es_GadgetFormat=gads;
  204.  return(EasyRequestArgs(NULL,&easy,0L,0L));
  205. }
  206.  
  207. /* ---- Fehler-Requester */
  208. LONG ErrorRequest(titel,text,gads)
  209.  UBYTE *titel,*text,*gads;
  210. {
  211.  if(titel==NULL) titel=GetLStr(1,"MultiDesktop - Error!");
  212.  if(gads==NULL) gads=GetLStr(2,"Okay");
  213.  return(MultiRequest(FindID(Catalog,titel),
  214.                      FindID(Catalog,text),
  215.                      FindID(Catalog,gads)));
  216. }
  217.  
  218. /* ---- Okay-Requester */
  219. void OkayRequest(text)
  220.  UBYTE *text;
  221. {
  222.  MultiRequest("MultiDesktop",text,GetLStr(2,"Okay"));
  223. }
  224.  
  225. /* ---- Einzeiliger Requester, Kickstart 1.1-kompatibel */
  226. void OldError(text)
  227.  UBYTE *text;
  228. {
  229.  struct IntuiText it;
  230.  
  231.  CopyMemQuick(&t1,&it,sizeof(struct IntuiText));
  232.  it.IText=text;
  233.  AutoRequest(NULL,&it,&t2,&t2,0L,0L,320,75);
  234. }
  235.  
  236. /* ---- Fehler-Requester */
  237. void ErrorL(num,text)
  238.  int    num;
  239.  UBYTE *text;
  240. {
  241.  if(text==NULL) text="Not enough memory!";
  242.  MultiRequest(GetLStr(1,"MultiDesktop - Error!"),GetLStr(num,text),GetLStr(2,"Okay"));
  243. }
  244.  
  245. /* ---- Stringadresse ermitteln */
  246. UBYTE *GetLStr(num,def)
  247.  LONG   num;
  248.  UBYTE *def;
  249. {
  250.  if(Catalog==NULL) return(def);
  251.  return(GetCatalogStr(Catalog,num,def));
  252. }
  253.  
  254. struct ProcSegment
  255. {
  256.  ULONG Length;
  257.  BPTR  Next;
  258.  UWORD OpCode;
  259.  VOID (* Address)();
  260. };
  261.  
  262. /* ---- Neuen Prozess erstellen */
  263. struct Task *CreateNewProcess(function,stack,name,pri)
  264.  VOID   (* function)();
  265.  ULONG  stack;
  266.  UBYTE *name;
  267.  BYTE   pri;
  268. {
  269.  struct Process *proc;
  270.  struct ProcSegment *Segment;
  271.  
  272.  Segment=AllocMem(sizeof(struct ProcSegment),MEMF_CLEAR|MEMF_PUBLIC);
  273.  if(Segment==NULL) return(NULL);
  274.  Segment->Length=sizeof(struct ProcSegment);
  275.  Segment->Next=NULL;
  276.  Segment->OpCode=0x4EF9;
  277.  Segment->Address=function;
  278.  Segment=(LONG)(&(Segment->Next)) >> 2;
  279.  
  280.  proc=CreateProc(name,pri,Segment,stack);
  281.  if(proc==NULL) return(NULL);
  282.  
  283.  return((struct Task *)((ULONG)proc-(ULONG)sizeof(struct Task)));
  284. }
  285.  
  286. void SleepPointer(win)
  287.  struct Window *win;
  288. {
  289.  if(ChipData) SetPointer(win,ChipData,22,16,-7,-7);
  290. }
  291.  
  292. /* ---- User initialisieren */
  293. struct MultiDesktopUser *InitDesktopUser(task)
  294.  struct Task *task;
  295. {
  296.  struct MultiDesktopUser *mu;
  297.  
  298.  Forbid();
  299.  if(task==NULL) task=SysBase->ThisTask;
  300.  mu=task->tc_UserData;
  301.  if(mu==NULL)
  302.   {
  303.    mu=AllocMem(MULTI_SIZE,MEMF_CLEAR|MEMF_PUBLIC);
  304.    if(mu!=NULL)
  305.     {
  306.      mu->UserCount=1;
  307.      mu->MagicID=MAGIC_ID;
  308.      mu->TimerPort=CreatePort(0L,0L);
  309.      if(mu->TimerPort!=NULL)
  310.       {
  311.        mu->TimerReq=CreateIORequest(mu->TimerPort,sizeof(struct timerequest));
  312.        if(mu->TimerReq!=NULL)
  313.         {
  314.          mu->TimerDev=OpenDevice("timer.device",UNIT_VBLANK,mu->TimerReq,0);
  315.          if(mu->TimerDev==0)
  316.           {
  317.            task->tc_UserData=mu;
  318.            Permit();
  319.            return(mu);
  320.           }
  321.          else
  322.            ErrorL(6,"Unable to open timer.device!");
  323.          DeleteIORequest(mu->TimerReq);
  324.         }
  325.        else
  326.          ErrorL(0,0);
  327.        DeletePort(mu->TimerPort);
  328.       }
  329.      else
  330.        ErrorL(5,"Unable to create port!");
  331.      FreeMem(mu,MULTI_SIZE);
  332.      mu=NULL;
  333.     }
  334.   }
  335.  else
  336.   {
  337.    if(mu->MagicID!=MAGIC_ID)
  338.     {
  339.      mu=NULL;
  340.      ErrorL(4,"Task->tc_UserData is already used by another program or\n"
  341.               "the structure is invalid! Try to start the program again\n"
  342.               "with 'Run' or from Workbench!");
  343.     }
  344.    else
  345.      mu->UserCount++;
  346.   }
  347.  Permit();
  348.  return(mu);
  349. }
  350.  
  351. /* ---- User entfernen */
  352. void TerminateDesktopUser(task)
  353.  struct Task *task;
  354. {
  355.  struct MultiDesktopUser *mu;
  356.  
  357.  Forbid();
  358.  if(task==NULL) task=SysBase->ThisTask;
  359.  mu=task->tc_UserData;
  360.  if(mu!=NULL)
  361.   {
  362.    mu->UserCount--;
  363.    if(mu->UserCount==0)
  364.     {
  365.      AbortIO(mu->TimerReq);
  366.      CloseDevice(mu->TimerReq);
  367.      DeleteIORequest(mu->TimerReq);
  368.      DeletePort(mu->TimerPort);
  369.      if(mu->Remember.FirstRemember) FreeMemory(&mu->Remember);
  370.      FreeMem(mu,MULTI_SIZE);
  371.      task->tc_UserData=NULL;
  372.     }
  373.   }
  374.  Permit();
  375. }
  376.  
  377. /* ---- Speicher belegen */
  378. UBYTE *GetMem(size,flags)
  379.  ULONG size,flags;
  380. {
  381.  struct MultiDesktopUser *mu;
  382.  
  383.  mu=SysBase->ThisTask->tc_UserData;
  384.  return(AllocMemory(&mu->Remember,size,flags));
  385. }
  386.  
  387. /* ---- Speicher freigeben */
  388. void DisposeMem(block)
  389.  UBYTE *block;
  390. {
  391.  struct MultiDesktopUser *mu;
  392.  
  393.  mu=SysBase->ThisTask->tc_UserData;
  394.  if(block)
  395.    FreeMemoryBlock(&mu->Remember,block);
  396. }
  397.  
  398. /* ---- Speicher belegen */
  399. UBYTE *AllocMemory(rem,size,flags)
  400.  struct MultiRemember *rem;
  401.  ULONG                 size,flags;
  402. {
  403.  struct MultiRememberEntry *mem;
  404.  
  405.  Forbid();
  406.  mem=AllocMem(size+12L,flags);
  407.  if(mem)
  408.   {
  409.    mem->PrevRemember=NULL;
  410.    mem->NextRemember=NULL;
  411.    mem->MemorySize=size+12L;
  412.  
  413.    if(rem->FirstRemember==NULL)
  414.     {
  415.      rem->FirstRemember=mem;
  416.      rem->LastRemember=mem;
  417.     }
  418.    else
  419.     {
  420.      mem->PrevRemember=rem->LastRemember;
  421.      rem->LastRemember->NextRemember=mem;
  422.      rem->LastRemember=mem;
  423.     }
  424.  
  425.    mem=(ULONG)mem+12L;
  426.   }
  427.  Permit();
  428.  return(mem);
  429. }
  430.  
  431. /* ---- Speicher mit bestimmten Alignment belegen */
  432. UBYTE *AllocAlignedMemory(rem,size,flags,align)
  433.  struct MultiRemember *rem;
  434.  ULONG                 size,flags,align;
  435. {
  436.  ULONG                      add;
  437.  struct MultiRememberEntry *mem;
  438.  
  439.  Forbid();
  440.  mem=AllocMem(size+align+12L,flags);
  441.  add=((ULONG)mem % align);
  442.  if(add!=0)
  443.   {
  444.    FreeMem(mem,size+align+12L);
  445.    mem=AllocAbs(size+12L,mem+add);
  446.   }
  447.  if(mem)
  448.   {
  449.    mem->PrevRemember=NULL;
  450.    mem->NextRemember=NULL;
  451.    mem->MemorySize=size+12L;
  452.  
  453.    if(rem->FirstRemember==NULL)
  454.     {
  455.      rem->FirstRemember=mem;
  456.      rem->LastRemember=mem;
  457.     }
  458.    else
  459.     {
  460.      mem->PrevRemember=rem->LastRemember;
  461.      rem->LastRemember->NextRemember=mem;
  462.      rem->LastRemember=mem;
  463.     }
  464.  
  465.    mem=(ULONG)mem+12L;
  466.   }
  467.  Permit();
  468.  return(mem);
  469. }
  470.  
  471. /* ---- Speicher freigeben */
  472. void FreeMemory(rem)
  473.  struct MultiRemember *rem;
  474. {
  475.  UBYTE                     *m;
  476.  ULONG                      s;
  477.  struct MultiRememberEntry *mem;
  478.  
  479.  Forbid();
  480.  mem=rem->FirstRemember;
  481.  while(mem!=NULL)
  482.   {
  483.    m=mem;
  484.    s=mem->MemorySize;
  485.    mem=mem->NextRemember;
  486.    FreeMem(m,s);
  487.   }
  488.  rem->FirstRemember=NULL;
  489.  rem->LastRemember=NULL;
  490.  Permit();
  491. }
  492.  
  493. /* ---- Speicherblock freigeben */
  494. void FreeMemoryBlock(rem,block)
  495.  struct MultiRemember      *rem;
  496.  UBYTE                     *block;
  497. {
  498.  struct MultiRememberEntry *mem;
  499.  
  500.  mem=(ULONG)block-12L;
  501.  
  502.  Forbid();
  503.  if(mem->PrevRemember)
  504.    mem->PrevRemember->NextRemember=mem->NextRemember;
  505.  if(mem->NextRemember)
  506.    mem->NextRemember->PrevRemember=mem->PrevRemember;
  507.  if(mem==rem->FirstRemember) rem->FirstRemember=mem->NextRemember;
  508.  if(mem==rem->LastRemember) rem->LastRemember=mem->PrevRemember;
  509.  Permit();
  510.  
  511.  FreeMem(mem,mem->MemorySize);
  512. }
  513.  
  514. /* ---- Text einer ID-Nummer ermitteln */
  515. /*
  516.   ID-Nummer:
  517.  
  518.   "Text"       für keine Umwandlung, Ergebnis = "Text"
  519.   "xxx:Text"   für ID xxx aus dem angegebenen Katalog
  520.   "xxx§Text"   für ID xxx aus dem MultiDesktop-Katalog (System-ID)
  521. */
  522. UBYTE *FindID(cat,id)
  523.  struct Catalog *cat;
  524.  UBYTE           *id;
  525. {
  526.  UBYTE num[30];
  527.  BOOL  hasNum,sysID;
  528.  ULONG catID;
  529.  int   i;
  530.  
  531.  if(id==NULL) return(NULL);
  532.  
  533.  hasNum=sysID=FALSE;
  534.  i=0;
  535.  while((id[i]!=0x00)&&(i<20))
  536.   {
  537.    if(id[i]==':')
  538.     {
  539.      num[i]=0x00;
  540.      hasNum=TRUE;
  541.      break;
  542.     }
  543.    else if(id[i]==0xa7)
  544.     {
  545.      num[i]=0x00;
  546.      hasNum=TRUE;
  547.      sysID=TRUE;
  548.      break;
  549.     }
  550.    else
  551.      num[i]=id[i];
  552.    i++;
  553.   }
  554.  
  555.  if(!hasNum)
  556.    return(id);
  557.  
  558.  catID=atol(&num);
  559.  if(catID==0)
  560.    return(id);
  561.  
  562.  if(sysID)
  563.    cat=Catalog;
  564.  
  565.  return(GetCatalogStr(cat,catID,&id[i+1]));
  566. }
  567.  
  568. /* ---- Asynchroner Programmstart */
  569. void ASyncRun(name)
  570.  UBYTE *name;
  571. {
  572.  struct TagItem              tag[5];
  573.  register struct FileHandle *con;
  574.  
  575.  con=Open("CON:10/20/620/150/MultiDesktop/AUTO/WAIT/CLOSE",MODE_NEWFILE);
  576.  if(con!=NULL)
  577.   {
  578.    tag[0].ti_Tag=SYS_Input;
  579.    tag[0].ti_Data=NULL;
  580.    tag[1].ti_Tag=SYS_Output;
  581.    tag[1].ti_Data=con;
  582.    tag[2].ti_Tag=SYS_Asynch;
  583.    tag[2].ti_Data=TRUE;
  584.    tag[3].ti_Tag=SYS_UserShell;
  585.    tag[3].ti_Data=TRUE;
  586.    tag[4].ti_Tag=TAG_DONE;
  587.    SystemTagList(name,&tag);
  588.   }
  589.  else
  590.    ErrorL(3,"Unable to open AutoCon-window!");
  591. }
  592.  
  593. /* ---- Synchroner Programmstart */
  594. void SyncRun(name)
  595.  UBYTE *name;
  596. {
  597.  struct TagItem tag[3];
  598.  
  599.  tag[0].ti_Tag=SYS_Input;
  600.  tag[0].ti_Data=Input();
  601.  tag[1].ti_Tag=SYS_Output;
  602.  tag[1].ti_Data=Output();
  603.  tag[2].ti_Tag=TAG_DONE;
  604.  SystemTagList(name,&tag);
  605. }
  606.  
  607. /* ---- Node suchen */
  608. struct Node *FindNode(list,num)
  609.  struct List *list;
  610.  ULONG        num;
  611. {
  612.  register struct Node *node;
  613.  register ULONG        i;
  614.  
  615.  i=0;
  616.  for(node=list->lh_Head;node!=&list->lh_Tail;node=node->ln_Succ)
  617.   {
  618.    if(i==num) return(node);
  619.    i++;
  620.   }
  621.  return(NULL);
  622. }
  623.  
  624. /* ---- Nodes zählen */
  625. struct Node *CountNodes(list)
  626.  struct List *list;
  627. {
  628.  register struct Node *node;
  629.  register ULONG        i;
  630.  
  631.  i=0;
  632.  for(node=list->lh_Head;node!=&list->lh_Tail;node=node->ln_Succ)
  633.    i++;
  634.  return(i);
  635. }
  636.  
  637. /*
  638.    Stringvergleich für Sortierung:
  639.    =>  TRUE,  wenn String A > B
  640. */
  641. BOOL StrIsGreaterThan(a,b)
  642.  UBYTE *a,*b;
  643. {
  644.  register int l1,l2,l,i;
  645.  
  646.  l1=strlen(a);
  647.  l2=strlen(b);
  648.  
  649.  if(l1>l2) l=l2; else l=l1;
  650.  
  651.  for(i=0;i<l;i++)
  652.   {
  653.    if(ToUpper(a[i]) > ToUpper(b[i]))
  654.      return(TRUE);
  655.    else if(ToUpper(b[i]) > ToUpper(a[i]))
  656.      return(FALSE);
  657.   }
  658.  if(l1>l2) return(TRUE);
  659.  return(FALSE);
  660. }
  661.  
  662. /*
  663.    Stringvergleich für Sortierung:
  664.    =>  TRUE,  wenn String A < B
  665. */
  666. BOOL StrIsLessThan(a,b)
  667.  UBYTE *a,*b;
  668. {
  669.  register int l1,l2,l,i;
  670.  
  671.  l1=strlen(a);
  672.  l2=strlen(b);
  673.  
  674.  if(l1>l2) l=l2; else l=l1;
  675.  
  676.  for(i=0;i<l;i++)
  677.   {
  678.    if(ToUpper(a[i]) > ToUpper(b[i]))
  679.      return(FALSE);
  680.    else if(ToUpper(b[i]) > ToUpper(a[i]))
  681.      return(TRUE);
  682.   }
  683.  if(l1>l2) return(TRUE);
  684.  return(FALSE);
  685. }
  686.  
  687. /* ---- Sortiert einfügen */
  688. void InsertSort(list,node,place)
  689.  struct List *list;
  690.  struct Node *node;
  691.  UBYTE        place;
  692. {
  693.  BOOL         okay;
  694.  struct Node *old,*prev;
  695.  BOOL         sort;
  696.  
  697.  if(place==SORT_DESCENDING) sort=TRUE; else sort=FALSE;
  698.  prev=NULL; okay=FALSE;
  699.  for(old=list->lh_Head;old!=&list->lh_Tail;old=old->ln_Succ)
  700.   {
  701.    if((StrIsGreaterThan(node->ln_Name,old->ln_Name))==sort)
  702.     {
  703.      okay=TRUE;
  704.      if(prev==NULL)
  705.        AddHead(list,node);
  706.      else
  707.        Insert(list,node,prev);
  708.      break;
  709.     }
  710.    prev=old;
  711.   }
  712.  if(okay==FALSE) AddTail(list,node);
  713. }
  714.  
  715. /* ---- QuickSort-Hauptteil (Aufsteigend sortieren) */
  716. void QuickSortMainA(array,start,end)
  717.  struct Node  **array;
  718.  long           start,end;
  719. {
  720.  struct Node *help;
  721.  UBYTE       *vge;
  722.  long         i,j;
  723.  
  724.  vge=array[(start+end)/2]->ln_Name;
  725.  i=start;
  726.  j=end;
  727.  do
  728.   {
  729.    while((StrIsLessThan(array[i]->ln_Name,vge))) i++;
  730.    while((StrIsGreaterThan(array[j]->ln_Name,vge))) j--;
  731.  
  732.    if(i<=j)
  733.     {
  734.      help=array[i];
  735.      array[i]=array[j];
  736.      array[j]=help;
  737.      i++;
  738.      j--;
  739.     }
  740.   } while(i<=j);
  741.  
  742.  if(j>start) QuickSortMainA(array,start,j);
  743.  if(end>i) QuickSortMainA(array,i,end);
  744. }
  745.  
  746. /* ---- QuickSort-Hauptteil (Absteigend sortieren) */
  747. void QuickSortMainD(array,start,end)
  748.  struct Node  *array[];
  749.  long          start,end;
  750. {
  751.  struct Node *help;
  752.  UBYTE       *vge;
  753.  long         i,j;
  754.  
  755.  vge=array[(start+end)/2]->ln_Name;
  756.  i=start;
  757.  j=end;
  758.  do
  759.   {
  760.    while((StrIsGreaterThan(array[i]->ln_Name,vge))) i++;
  761.    while((StrIsLessThan(array[j]->ln_Name,vge))) j--;
  762.  
  763.    if(i<=j)
  764.     {
  765.      help=array[i];
  766.      array[i]=array[j];
  767.      array[j]=help;
  768.      i++;
  769.      j--;
  770.     }
  771.  
  772.   } while(i<=j);
  773.  if(j>start) QuickSortMainD(array,start,j);
  774.  if(end>i) QuickSortMainD(array,i,end);
  775. }
  776.  
  777. /* ---- Liste sortieren */
  778. BOOL SortList(list,place)
  779.  struct List *list;
  780.  UBYTE        place;
  781. {
  782.  REGISTER ULONG        i,count;
  783.  REGISTER ULONG       *array;
  784.  register struct Node *node;
  785.  
  786.  count=CountNodes(list);
  787.  if(count<2) return;
  788.  
  789.  array=AllocVec((count*4)+8,MEMF_ANY);
  790.  if(array)
  791.   {
  792.    for(node=list->lh_Head,i=0;node!=&list->lh_Tail;node=node->ln_Succ,i++)
  793.      array[i]=node;
  794.    NewList(list);
  795.  
  796.    if(place==SORT_DESCENDING)
  797.      QuickSortMainD(array,0,count-1);
  798.    else
  799.      QuickSortMainA(array,0,count-1);
  800.  
  801.    for(i=0;i<count;i++)
  802.      AddTail(list,array[i]);
  803.    FreeVec(array);
  804.   }
  805.  else
  806.   { ErrorL(0,0); return(FALSE); }
  807.  return(TRUE);
  808. }
  809.  
  810. /* ---- Listen zusammenfügen */
  811. void ConcatList(list,list2)
  812.  struct List *list,*list2;
  813. {
  814.  register struct Node *node,*succ;
  815.  
  816.  if(list==NULL) return;
  817.  if(list2==NULL) return;
  818.  
  819.  node=list2->lh_Head;
  820.  while(node!=&list2->lh_Tail)
  821.   {
  822.    succ=node->ln_Succ;
  823.    AddTail(list,node);
  824.    node=succ;
  825.   }
  826.  NewList(list2);
  827. }
  828.  
  829. /* ---- Liste duplizieren */
  830. struct List *DupList(list,size)
  831.  struct List *list;
  832. {
  833.  REGISTER ULONG        name;
  834.  register long         size2;
  835.  register struct Node *node;
  836.  register struct Node *xn;
  837.  register struct List *xl;
  838.  
  839.  if(list==NULL) return;
  840.  
  841.  size += (size % 4);
  842.  xl=GetMem(sizeof(struct List),MEMF_CLEAR|MEMF_PUBLIC);
  843.  if(xl==NULL) return(NULL);
  844.  NewList(xl);
  845.  
  846.  for(node=list->lh_Head;node!=&list->lh_Tail;node=node->ln_Succ)
  847.   {
  848.    size2=size;
  849.    if(node->ln_Name) size2+=strlen(node->ln_Name)+1;
  850.    xn=GetMem(size2,MEMF_PUBLIC);
  851.    if(xn!=NULL)
  852.     {
  853.      CopyMemQuick(node,xn,size);
  854.      if(node->ln_Name)
  855.       {
  856.        name=(ULONG)xn+(ULONG)size;
  857.        strcpy(name,node->ln_Name);
  858.        xn->ln_Name=name;
  859.       }
  860.      AddTail(xl,xn);
  861.     }
  862.   }
  863.  
  864.  return(xl);
  865. }
  866.  
  867. /* ---- Liste freigeben */
  868. void FreeList(list)
  869.  struct List *list;
  870. {
  871.  struct Node *node,*succ;
  872.  
  873.  if(list==NULL) return;
  874.  
  875.  node=list->lh_Head;
  876.  while(node!=&list->lh_Tail)
  877.   {
  878.    succ=node->ln_Succ;
  879.    DisposeMem(node);
  880.    node=succ;
  881.   }
  882.  DisposeMem(list);
  883. }
  884.  
  885. /* ---- Listen zusammenfügen mit Kopieren der Quellliste */
  886. void CopyConcatList(list,list2)
  887.  struct List *list,*list2;
  888. {
  889.  register struct List *list3;
  890.  
  891.  if(list==NULL) return;
  892.  if(list2==NULL) return;
  893.  
  894.  list3=DupList(list2);
  895.  if(list3)
  896.   {
  897.    ConcatList(list,list3);
  898.    DisposeMem(list3);
  899.   }
  900. }
  901.  
  902. /* ---- Hook-Entry-Prozedur */
  903. #asm
  904. H_SUBENTRY:   EQU 12
  905.  
  906.    public _HookEntry
  907. _HookEntry:
  908.    movem.l d0-d7/a0-a6,-(sp)
  909.    move.l a1,-(sp)
  910.    move.l a2,-(sp)
  911.    move.l a0,-(sp)
  912.  
  913.    move.l H_SUBENTRY(a0),a0
  914.    jsr (a0)
  915.  
  916.    lea 12(sp),sp
  917.    movem.l (sp)+,d0-d7/a0-a6
  918.    rts
  919. #endasm
  920.  
  921. /* ---- Hook initialisieren */
  922. void InitHook(hook,proc,data)
  923.  struct Hook *hook;
  924.  ULONG        (*proc)();
  925.  ULONG       *data;
  926. {
  927.  hook->h_MinNode.mln_Succ=NULL;
  928.  hook->h_MinNode.mln_Pred=NULL;
  929.  hook->h_Entry=HookEntry;
  930.  hook->h_SubEntry=proc;
  931.  hook->h_Data=data;
  932. }
  933.  
  934. /* ---- ID-Nummer ermitteln */
  935. ULONG GetTextID(id)
  936.  UBYTE *id;
  937. {
  938.  UBYTE         num[200];
  939.  REGISTER BOOL hasNum;
  940.  register int  i;
  941.  
  942.  if(id==NULL) return(NULL);
  943.  
  944.  hasNum=FALSE;
  945.  i=0;
  946.  while(id[i]!=0x00)
  947.   {
  948.    if(id[i]!=':')
  949.      num[i]=id[i];
  950.    else
  951.     {
  952.      num[i]=0x00;
  953.      hasNum=TRUE;
  954.      break;
  955.     }
  956.    i++;
  957.   }
  958.  
  959.  if(!hasNum)
  960.    return(0);
  961.  
  962.  return(atol(num));
  963. }
  964.  
  965. /* ---- Device als Library öffnen */
  966. struct Library *OpenDevLibrary(name,version)
  967.  UBYTE *name;
  968.  LONG   version;
  969. {
  970.  struct Library *lib;
  971.  
  972.  Forbid();
  973.  lib=FindName(&SysBase->DeviceList,name);
  974.  if(lib)
  975.   {
  976.    if(lib->lib_Version<version)
  977.      lib=NULL;
  978.    else
  979.      lib->lib_OpenCnt++;
  980.   }
  981.  Permit();
  982.  return(lib);
  983. }
  984.  
  985. /* ---- Mit OpenDevLibrary() geöffnetes Device schließen */
  986. void CloseDevLibrary(lib)
  987.  struct Library *lib;
  988. {
  989.  Forbid();
  990.  lib->lib_OpenCnt--;
  991.  Permit();
  992. }
  993.  
  994. /* ---- Sekunden in MultiTime umwandeln */
  995. void Seconds2Time(secs,mt)
  996.  ULONG             secs;
  997.  struct MultiTime *mt;
  998. {
  999.  struct ClockData cd;
  1000.  
  1001.  Amiga2Date(secs,&cd);
  1002.  mt->Day=cd.mday;
  1003.  mt->Month=cd.month;
  1004.  mt->Year=cd.year;
  1005.  mt->WDay=cd.wday;
  1006.  mt->Second=cd.sec;
  1007.  mt->Minute=cd.min;
  1008.  mt->Hour=cd.hour;
  1009.  mt->SecondsSince1978=secs;
  1010.  Seconds2StarDate(secs,mt);
  1011. }
  1012.  
  1013. /* ---- MultiTime in Sekunden umwandeln */
  1014. ULONG Time2Seconds(mt)
  1015.  struct MultiTime *mt;
  1016. {
  1017.  struct ClockData cd;
  1018.  
  1019.  cd.mday=mt->Day;
  1020.  cd.month=mt->Month;
  1021.  cd.year=mt->Year;
  1022.  cd.wday=mt->WDay;
  1023.  cd.sec=mt->Second;
  1024.  cd.min=mt->Minute;
  1025.  cd.hour=mt->Hour;
  1026.  return(Date2Amiga(&cd));
  1027. }
  1028.  
  1029. #define SECONDS_PER_STARDATE 32400L   /* 9 Stunden */
  1030. #define STARDATE_1978        (((((12*365)+3)*24)*60*60)/SECONDS_PER_STARDATE)
  1031.  
  1032. /* ---- Sekunden in Sternzeit umwandeln */
  1033. void Seconds2StarDate(secs,mt)
  1034.  ULONG             secs;
  1035.  struct MultiTime *mt;
  1036. {
  1037.  ULONG a;
  1038.  FLOAT b;
  1039.  
  1040.  mt->StarDate[0]=(secs / SECONDS_PER_STARDATE) + STARDATE_1978;
  1041.  a=secs % SECONDS_PER_STARDATE;
  1042.  b=(FLOAT)a*(100000.0/(FLOAT)SECONDS_PER_STARDATE);
  1043.  mt->StarDate[1]=(ULONG)b/10L;
  1044. }
  1045.  
  1046. /* ---- Sekunden in Sternzeit umwandeln */
  1047. ULONG StarDate2Seconds(mt)
  1048.  struct MultiTime *mt;
  1049. {
  1050.  ULONG a;
  1051.  FLOAT b;
  1052.  
  1053.  b=(FLOAT)mt->StarDate[1]*10.0;
  1054.  a=(ULONG)(b*((FLOAT)SECONDS_PER_STARDATE/100000.0));
  1055.  return(a+(mt->StarDate[0]-STARDATE_1978)*SECONDS_PER_STARDATE);
  1056. }
  1057.  
  1058. /* ---- Datum und Uhrzeit ermitteln */
  1059. void GetTime(mt)
  1060.  struct MultiTime *mt;
  1061. {
  1062.  struct timeval tv;
  1063.  
  1064.  GetSysTime(&tv);
  1065.  Seconds2Time(tv.tv_secs,mt);
  1066. }
  1067.  
  1068. /* ---- Datum und Uhrzeit setzen */
  1069. void SetTime(mt)
  1070.  struct MultiTime *mt;
  1071. {
  1072.  struct MultiDesktopUser *mu;
  1073.  struct timerequest      *tr;
  1074.  struct timeval           tv;
  1075.  
  1076.  mu=SysBase->ThisTask->tc_UserData;
  1077.  tr=mu->TimerReq;
  1078.  AbortIO(tr);
  1079.  tr->tr_time.tv_secs=Time2Seconds(mt);
  1080.  tr->tr_time.tv_micro=0;
  1081.  tr->tr_node.io_Command=TR_SETSYSTIME;
  1082.  DoIO(tr);
  1083. }
  1084.  
  1085. /* ---- BattClock: Datum und Uhrzeit ermitteln */
  1086. void GetBattClockTime(mt)
  1087.  struct MultiTime *mt;
  1088. {
  1089.  if(BattClockBase)
  1090.    Seconds2Time(ReadBattClock(),mt);
  1091. }
  1092.  
  1093. /* ---- BattClock: Datum und Uhrzeit setzen */
  1094. void SetBattClockTime(mt)
  1095.  struct MultiTime *mt;
  1096. {
  1097.  if(BattClockBase)
  1098.    WriteBattClock(Time2Seconds(mt));
  1099. }
  1100.  
  1101. /* ---- Uhrzeiten addieren */
  1102. void AddTimes(source,dest)
  1103.  struct MultiTime *source,*dest;
  1104. {
  1105.  struct timeval t1,t2;
  1106.  
  1107.  t1.tv_secs=Time2Seconds(source);
  1108.  t1.tv_micro=0;
  1109.  t2.tv_secs=Time2Seconds(dest);
  1110.  t2.tv_micro=0;
  1111.  AddTime(&t2,&t1);
  1112.  Seconds2Time(t2.tv_secs,&dest);
  1113. }
  1114.  
  1115. /* ---- Uhrzeiten subtrahieren */
  1116. void SubTimes(source,dest)
  1117.  struct MultiTime *source,*dest;
  1118. {
  1119.  struct timeval t1,t2;
  1120.  
  1121.  t1.tv_secs=Time2Seconds(source);
  1122.  t1.tv_micro=0;
  1123.  t2.tv_secs=Time2Seconds(dest);
  1124.  t2.tv_micro=0;
  1125.  SubTime(&t2,&t1);
  1126.  Seconds2Time(t2.tv_secs,&dest);
  1127. }
  1128.  
  1129. /* ---- Uhrzeiten subtrahieren */
  1130. int CompareTimes(mt1,mt2)
  1131.  struct MultiTime *mt1,*mt2;
  1132. {
  1133.  struct timeval t1,t2;
  1134.  
  1135.  t1.tv_secs=Time2Seconds(mt1);
  1136.  t1.tv_micro=0;
  1137.  t2.tv_secs=Time2Seconds(mt2);
  1138.  t2.tv_micro=0;
  1139.  return(CmpTime(&t2,&t1));
  1140. }
  1141.  
  1142. /* ---- Warten */
  1143. void WaitTime(ticks)
  1144.  ULONG ticks;
  1145. {
  1146.  struct timerequest      *tr;
  1147.  struct MultiDesktopUser *mu;
  1148.  
  1149.  mu=SysBase->ThisTask->tc_UserData;
  1150.  tr=mu->TimerReq;
  1151.  AbortIO(tr);
  1152.  tr->tr_time.tv_secs=ticks / 50;
  1153.  tr->tr_time.tv_micro=(ticks % 50)*20000;
  1154.  tr->tr_node.io_Command=TR_ADDREQUEST;
  1155.  DoIO(tr);
  1156. }
  1157.  
  1158. /* ---- Alarm setzen */
  1159. void SetAlarm(ticks)
  1160.  ULONG ticks;
  1161. {
  1162.  struct timerequest      *tr;
  1163.  struct MultiDesktopUser *mu;
  1164.  
  1165.  mu=SysBase->ThisTask->tc_UserData;
  1166.  tr=mu->TimerReq;
  1167.  AbortIO(tr);
  1168.  tr->tr_time.tv_secs=ticks / 50;
  1169.  tr->tr_time.tv_micro=(ticks % 50)*20000;
  1170.  tr->tr_node.io_Command=TR_ADDREQUEST;
  1171.  SendIO(tr);
  1172. }
  1173.  
  1174. /* ---- Alarm testen */
  1175. BOOL CheckAlarm()
  1176. {
  1177.  struct timerequest      *tr;
  1178.  struct MultiDesktopUser *mu;
  1179.  
  1180.  mu=SysBase->ThisTask->tc_UserData;
  1181.  tr=CheckIO(mu->TimerReq);
  1182.  if(tr!=NULL) return(TRUE);
  1183.  return(FALSE);
  1184. }
  1185.  
  1186. /* ---- Alarm abwarten */
  1187. void WaitAlarm()
  1188. {
  1189.  struct MultiDesktopUser *mu;
  1190.  
  1191.  mu=SysBase->ThisTask->tc_UserData;
  1192.  WaitIO(mu->TimerReq);
  1193. }
  1194.  
  1195. /* ---- Alarm testen */
  1196. void AbortAlarm()
  1197. {
  1198.  struct MultiDesktopUser *mu;
  1199.  
  1200.  mu=SysBase->ThisTask->tc_UserData;
  1201.  AbortIO(mu->TimerReq);
  1202. }
  1203.  
  1204. /* ---- MultiTime-Struktur initialisieren */
  1205. void InitTime(mt,day,month,year,h,m,s)
  1206.  struct MultiTime *mt;
  1207.  UBYTE             day,month;
  1208.  UWORD             year;
  1209.  UBYTE             h,m,s;
  1210. {
  1211.  ULONG sec;
  1212.  
  1213.  mt->Day=day;
  1214.  mt->Month=month;
  1215.  mt->Year=year;
  1216.  mt->Hour=h;
  1217.  mt->Minute=m;
  1218.  mt->Second=s;
  1219.  sec=Time2Seconds(mt);
  1220.  sec=sec/(60*60*24);
  1221.  mt->WDay=(sec % 7);
  1222. }
  1223.  
  1224. /* ---- Speicher ermitteln */
  1225. ULONG AvailChipMem()
  1226. {
  1227.  return(AvailMem(MEMF_CHIP|MEMF_PUBLIC));
  1228. }
  1229.  
  1230. /* ---- Speicher ermitteln */
  1231. ULONG AvailFastMem()
  1232. {
  1233.  return(AvailMem(MEMF_FAST|MEMF_PUBLIC));
  1234. }
  1235.  
  1236. /* ---- Speicher ermitteln */
  1237. ULONG AvailVMem()
  1238. {
  1239.  return(AvailMem(MEMF_ANY)-AvailMem(MEMF_PUBLIC));
  1240. }
  1241.  
  1242. /* ---- Speicher ermitteln */
  1243. ULONG AvailPublicMem()
  1244. {
  1245.  return(AvailMem(MEMF_PUBLIC));
  1246. }
  1247.  
  1248. /* ---- Speicher ermitteln */
  1249. ULONG AvailMemory()
  1250. {
  1251.  return(AvailMem(MEMF_ANY));
  1252. }
  1253.  
  1254. /* ---- BString in CString umwandeln */
  1255. UBYTE *CString(src,dest)
  1256.  BSTR   src;
  1257.  UBYTE *dest;
  1258. {
  1259.  UWORD  i;
  1260.  UBYTE *Help;
  1261.  
  1262.  Help=(UBYTE *)BADDR(src);
  1263.  for(i=0;i<(*Help);i++)
  1264.   dest[i]=*(Help+i+1);
  1265.  dest[i]=0x00;
  1266.  return(dest);
  1267. }
  1268.  
  1269. /* ---- CString in BString umwandeln */
  1270. UBYTE *BString(src,dest)
  1271.  UBYTE *src;
  1272.  UBYTE *dest;
  1273. {
  1274.  UWORD  i;
  1275.  
  1276.  dest[0]=strlen(src);
  1277.  for(i=0;i<dest[0];i++)
  1278.   dest[i+1]=src[i];
  1279.  return(dest);
  1280. }
  1281.  
  1282.