~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/programs/Xserver/XIE/mixie/control/strip.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Xorg: strip.c,v 1.4 2001/02/09 02:04:23 xorgcvs Exp $ */
 
2
/* AGE Logic - Oct 15 1995 - Larry Hare */
 
3
/**** module strip.c ****/
 
4
/*****************************************************************************
 
5
 
 
6
Copyright 1993, 1994, 1998  The Open Group
 
7
 
 
8
Permission to use, copy, modify, distribute, and sell this software and its
 
9
documentation for any purpose is hereby granted without fee, provided that
 
10
the above copyright notice appear in all copies and that both that
 
11
copyright notice and this permission notice appear in supporting
 
12
documentation.
 
13
 
 
14
The above copyright notice and this permission notice shall be included in
 
15
all copies or substantial portions of the Software.
 
16
 
 
17
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
18
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
19
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 
20
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 
21
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
22
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
23
 
 
24
Except as contained in this notice, the name of The Open Group shall not be
 
25
used in advertising or otherwise to promote the sale, use or other dealings
 
26
in this Software without prior written authorization from The Open Group.
 
27
 
 
28
 
 
29
                                NOTICE
 
30
                              
 
31
This software is being provided by AGE Logic, Inc. under the
 
32
following license.  By obtaining, using and/or copying this software,
 
33
you agree that you have read, understood, and will comply with these
 
34
terms and conditions:
 
35
 
 
36
     Permission to use, copy, modify, distribute and sell this
 
37
     software and its documentation for any purpose and without
 
38
     fee or royalty and to grant others any or all rights granted
 
39
     herein is hereby granted, provided that you agree to comply
 
40
     with the following copyright notice and statements, including
 
41
     the disclaimer, and that the same appears on all copies and
 
42
     derivative works of the software and documentation you make.
 
43
     
 
44
     "Copyright 1993, 1994 by AGE Logic, Inc."
 
45
     
 
46
     THIS SOFTWARE IS PROVIDED "AS IS".  AGE LOGIC MAKES NO
 
47
     REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.  By way of
 
48
     example, but not limitation, AGE LOGIC MAKE NO
 
49
     REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS
 
50
     FOR ANY PARTICULAR PURPOSE OR THAT THE SOFTWARE DOES NOT
 
51
     INFRINGE THIRD-PARTY PROPRIETARY RIGHTS.  AGE LOGIC 
 
52
     SHALL BEAR NO LIABILITY FOR ANY USE OF THIS SOFTWARE.  IN NO
 
53
     EVENT SHALL EITHER PARTY BE LIABLE FOR ANY INDIRECT,
 
54
     INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS
 
55
     OF PROFITS, REVENUE, DATA OR USE, INCURRED BY EITHER PARTY OR
 
56
     ANY THIRD PARTY, WHETHER IN AN ACTION IN CONTRACT OR TORT OR
 
57
     BASED ON A WARRANTY, EVEN IF AGE LOGIC LICENSEES
 
58
     HEREUNDER HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
 
59
     DAMAGES.
 
60
    
 
61
     The name of AGE Logic, Inc. may not be used in
 
62
     advertising or publicity pertaining to this software without
 
63
     specific, written prior permission from AGE Logic.
 
64
 
 
65
     Title to this software shall at all times remain with AGE
 
66
     Logic, Inc.
 
67
*****************************************************************************
 
68
  
 
69
        strip.c -- DDXIE machine independent data flo manager
 
70
  
 
71
        Robert NC Shelley -- AGE Logic, Inc. April, 1993
 
72
  
 
73
*****************************************************************************/
 
74
/* $XFree86: xc/programs/Xserver/XIE/mixie/control/strip.c,v 3.7 2001/12/14 19:58:17 dawes Exp $ */
 
75
 
 
76
/*
 
77
 *  Include files
 
78
 */
 
79
 
 
80
/*
 
81
 *  Core X Includes
 
82
 */
 
83
#include <X.h>
 
84
#include <Xproto.h>
 
85
/*
 
86
 *  XIE Includes
 
87
 */
 
88
#include <XIE.h>
 
89
#include <XIEproto.h>
 
90
/*
 
91
 *  more X server includes.
 
92
 */
 
93
#include <misc.h>
 
94
#include <dixstruct.h>
 
95
/*
 
96
 *  Server XIE Includes
 
97
 */
 
98
#include <error.h>
 
99
#include <macro.h>
 
100
#include <flostr.h>
 
101
#include <element.h>
 
102
#include <texstr.h>
 
103
#include <memory.h>
 
104
 
 
105
/* routines exported to DIXIE via the photoflo management vector
 
106
 */
 
107
static int import_data(
 
108
                        floDefPtr flo,
 
109
                        peDefPtr ped,
 
110
                        CARD8 band,
 
111
                        CARD8 *data,
 
112
                        CARD32 len,
 
113
                        BOOL final);
 
114
static int export_data(
 
115
                        floDefPtr flo,
 
116
                        peDefPtr ped,
 
117
                        CARD8 band,
 
118
                        CARD32 maxLen,
 
119
                        BOOL term);
 
120
static int query_data(
 
121
                        floDefPtr flo,
 
122
                        xieTypPhototag **list,
 
123
                        CARD16 *pending,
 
124
                        CARD16 *available);
 
125
 
 
126
/* routines exported to elements via the data manager's vector
 
127
 */
 
128
static CARD8    *make_bytes(
 
129
                        floDefPtr flo,
 
130
                        peTexPtr pet,
 
131
                        bandPtr bnd,
 
132
                        CARD32 contig,
 
133
                        Bool purge);
 
134
static CARD8    *make_lines(
 
135
                        floDefPtr flo,
 
136
                        peTexPtr pet,
 
137
                        bandPtr bnd,
 
138
                        Bool purge);
 
139
static Bool      map_data(
 
140
                        floDefPtr flo,
 
141
                        peTexPtr pet,
 
142
                        bandPtr bnd,
 
143
                        CARD32 map,
 
144
                        CARD32 unit,
 
145
                        CARD32 len,
 
146
                        Bool purge);
 
147
static CARD8    *get_data(
 
148
                        floDefPtr flo,
 
149
                        peTexPtr pet,
 
150
                        bandPtr bnd,
 
151
                        CARD32 contig,
 
152
                        Bool purge);
 
153
static Bool      put_data(floDefPtr flo, peTexPtr pet, bandPtr dbnd);
 
154
static void      free_data(floDefPtr flo, peTexPtr pet, bandPtr dbnd);
 
155
static Bool      pass_strip(
 
156
                        floDefPtr flo,
 
157
                        peTexPtr pet,
 
158
                        bandPtr bnd,
 
159
                        stripPtr strip);
 
160
static Bool      import_strips(
 
161
                        floDefPtr flo,
 
162
                        peTexPtr pet,
 
163
                        bandPtr bnd,
 
164
                        stripLstPtr strips);
 
165
static Bool      alter_src(floDefPtr flo, peTexPtr pet, stripPtr strip);
 
166
static void      bypass_src(floDefPtr flo, peTexPtr pet, bandPtr dbnd);
 
167
static void      disable_src(floDefPtr flo, peTexPtr pet, bandPtr bnd, Bool purge);
 
168
static void      disable_dst(floDefPtr flo, peTexPtr pet, bandPtr dbnd);
 
169
 
 
170
/* routines used internal to this module
 
171
 */
 
172
static stripPtr  alter_data(floDefPtr flo, peTexPtr pet, bandPtr db);
 
173
static stripPtr  contig_data(
 
174
                        floDefPtr flo,
 
175
                        peTexPtr pet,
 
176
                        bandPtr bnd,
 
177
                        stripPtr i_strip,
 
178
                        CARD32 contig);
 
179
static stripPtr  make_strip(
 
180
                        floDefPtr flo,
 
181
                        formatPtr fmt,
 
182
                        CARD32    start,
 
183
                        CARD32    units,
 
184
                        CARD32    bytes,
 
185
                        Bool      allocData);
 
186
static stripPtr  clone_strip(floDefPtr flo, stripPtr in_strip);
 
187
static bandMsk   put_strip(floDefPtr flo, peTexPtr pet, stripPtr strip);
 
188
static void      forward_strip(floDefPtr flo, peTexPtr pet, stripPtr fwd);
 
189
static stripPtr  free_strip(floDefPtr flo, stripPtr strip);
 
190
 
 
191
/* DDXIE client data manager entry points
 
192
 */
 
193
static dataVecRec dataManagerVec = {
 
194
  (xieIntProc)import_data,
 
195
  (xieIntProc)export_data,
 
196
  (xieIntProc)query_data
 
197
  };
 
198
 
 
199
/* DDXIE photoflo manager entry points
 
200
 */
 
201
static stripVecRec stripManagerVec = {
 
202
  make_bytes,
 
203
  make_lines,
 
204
  map_data,
 
205
  get_data,
 
206
  put_data,
 
207
  free_data,
 
208
  pass_strip,
 
209
  import_strips,
 
210
  alter_src,
 
211
  bypass_src,
 
212
  disable_src,
 
213
  disable_dst
 
214
  };
 
215
 
 
216
INT32  STRIPS = 0; /* DEBUG */
 
217
INT32  BYTES  = 0; /* DEBUG */
 
218
 
 
219
/*------------------------------------------------------------------------
 
220
-------------------------- Initialize Data Manager -----------------------
 
221
------------------------------------------------------------------------*/
 
222
int InitStripManager(floDefPtr flo)
 
223
{
 
224
  /* plug in the DDXIE client data management vector */
 
225
  flo->dataVec = &dataManagerVec;
 
226
 
 
227
  /* plug in the strip manager vector */
 
228
  flo->stripVec = &stripManagerVec;
 
229
 
 
230
  /* init the strip cache */
 
231
  ListInit(&flo->floTex->stripHead);
 
232
 
 
233
  /* choose the best strip size for this flo (a constant value for now) */
 
234
  flo->floTex->stripSize = STANDARD_STRIP_SIZE;
 
235
 
 
236
  /* clear the count of strips passed */
 
237
  flo->floTex->putCnt = 0;
 
238
 
 
239
  return(TRUE);
 
240
}                               /* end InitStripManager */
 
241
 
 
242
 
 
243
/*------------------------------------------------------------------------
 
244
----------- discard parent headers from a whole list of strips -----------
 
245
-----------   and copy data if multiple references are found   -----------
 
246
----------- then transfer them all to their final destination  -----------
 
247
------------------------------------------------------------------------*/
 
248
int DebriefStrips(
 
249
     stripLstPtr i_head,
 
250
     stripLstPtr o_head)
 
251
{
 
252
  stripPtr child, parent;
 
253
 
 
254
  /* NOTE: we might want to consider (re)allocing strip buffers to
 
255
   *       strip->length instead of leaving them an strip->bufSiz.
 
256
   */
 
257
  for(child = i_head->flink; !ListEnd(child,i_head); child = child->flink) {
 
258
    while ((parent = child->parent) != 0)
 
259
      if(parent->refCnt == 1) {         /* discard a cloned header        */
 
260
        child->parent = parent->parent;
 
261
        XieFree(parent);
 
262
        --STRIPS; /*DEBUG*/
 
263
      } else {                          /* copy multiply referenced data  */
 
264
        if(!(child->data = (CARD8*)XieMalloc(child->bufSiz)))
 
265
          return(FALSE);
 
266
        memcpy((char*)child->data, (char*)parent->data, (int)child->bufSiz);
 
267
        child->parent = NULL;           /* de-reference child from parent */
 
268
        --parent->refCnt;
 
269
        BYTES += child->bufSiz; /*DEBUG*/
 
270
      }
 
271
    child->format = NULL;               /* kill per-strip format pointer  */
 
272
  }
 
273
  /* transfer the entire list of input strips to the output
 
274
   */
 
275
  if(ListEmpty(i_head))
 
276
    ListInit(o_head);
 
277
  else {
 
278
    i_head->flink->blink = (stripPtr)o_head;
 
279
    i_head->blink->flink = (stripPtr)o_head;
 
280
    *o_head = *i_head;
 
281
    ListInit(i_head);
 
282
  }
 
283
  return(TRUE);
 
284
}                               /* end DebriefStrips */
 
285
 
 
286
 
 
287
/*------------------------------------------------------------------------
 
288
------------------------- Free a whole list of strips --------------------
 
289
------------------------------------------------------------------------*/
 
290
void  FreeStrips(stripLstPtr head)
 
291
{
 
292
  while( !ListEmpty(head) ) {
 
293
    stripPtr strip;
 
294
    
 
295
    RemoveMember(strip, head->flink);
 
296
    free_strip(NULL, strip);
 
297
  }
 
298
}                               /* end FreeStrips */
 
299
 
 
300
 
 
301
/*------------------------------------------------------------------------
 
302
------------------------ Input from PutClientData ------------------------
 
303
------------------------------------------------------------------------*/
 
304
static int import_data(
 
305
     floDefPtr flo,
 
306
     peDefPtr  ped,
 
307
     CARD8    band,
 
308
     CARD8   *data,
 
309
     CARD32    len,
 
310
     BOOL    final)
 
311
{
 
312
  peTexPtr    pet =  ped->peTex;
 
313
  receptorPtr rcp = &pet->receptor[IMPORT];
 
314
  bandPtr     bnd = &rcp->band[band];
 
315
  bandMsk     msk = 1<<band;
 
316
  stripPtr  strip;
 
317
 
 
318
  if(!((rcp->admit | rcp->bypass) & msk))
 
319
    return(TRUE);                               /* drop unwanted data */
 
320
 
 
321
  /* make a strip and fill it in the info from the client
 
322
   * (the format info was supplied with the element and technique parameters)
 
323
   */
 
324
  if(!(strip = make_strip(flo,bnd->format,bnd->maxGlobal,len,len,FALSE)))
 
325
    AllocError(flo,ped, return(FALSE));
 
326
  strip->final  = final;
 
327
  strip->data   = data;
 
328
  strip->bufSiz = len;
 
329
 
 
330
  if(rcp->bypass & msk) {
 
331
    put_strip(flo,pet,strip);                   /* pass it downstream */
 
332
    if(!strip->flink)
 
333
      free_strip(flo,strip);                    /* nobody wanted it   */
 
334
  } else {
 
335
    bnd->maxGlobal  = strip->end + 1;
 
336
    bnd->available += len;
 
337
    rcp->ready     |= msk;
 
338
    InsertMember(strip,bnd->stripLst.blink);
 
339
    if ((bnd->final = final) != 0) {
 
340
      if(!(rcp->admit &= ~msk))
 
341
        --pet->admissionCnt;
 
342
      --flo->floTex->imports;
 
343
    }
 
344
  }
 
345
  /* fire up the scheduler -- then we're outa here */
 
346
  return( Execute(flo,pet) );
 
347
}                               /* end import_data */
 
348
 
 
349
 
 
350
/*------------------------------------------------------------------------
 
351
-------------------------- Output for GetClientData ----------------------
 
352
------------------------------------------------------------------------*/
 
353
static int export_data(
 
354
     floDefPtr flo,
 
355
     peDefPtr  ped,
 
356
     CARD8    band,
 
357
     CARD32 maxLen,
 
358
     BOOL     term)
 
359
{
 
360
  BOOL       release = FALSE, final = FALSE;
 
361
  stripLstPtr    lst = &ped->outFlo.output[band];
 
362
  stripPtr     strip = NULL;
 
363
  CARD32 bytes, want = maxLen;
 
364
  CARD8  state, *data;
 
365
 
 
366
  /* if this is multi-byte data, make sure we send/swap complete aggregates
 
367
   */
 
368
  if(ped->swapUnits[band] > 1)
 
369
    want &= ~(ped->swapUnits[band]-1);
 
370
 
 
371
  if ((bytes = ListEmpty(lst) ? 0 : min(lst->flink->length, want)) != 0) {
 
372
    strip = lst->flink;
 
373
    data  = strip->data + (strip->bitOff>>3);
 
374
    if(strip->length -= bytes) {
 
375
      strip->start   += bytes;
 
376
      strip->bitOff  += bytes<<3;  
 
377
    } else {
 
378
      RemoveMember(strip, strip);
 
379
      final   = strip->final;
 
380
      release = TRUE;
 
381
      if(ListEmpty(lst))
 
382
        ped->outFlo.ready &= ~(1<<band);
 
383
    }
 
384
  } else {
 
385
    data = NULL;
 
386
  }
 
387
  if(final)
 
388
    flo->floTex->exports--;
 
389
  else if(term) {
 
390
    /* shut down the output band prematurely */
 
391
    ped->outFlo.ready &= ~(1<<band);
 
392
    disable_dst(flo,ped->peTex,&ped->peTex->emitter[band]);
 
393
  }
 
394
  /* figure out our current state and send a reply to the client
 
395
   */
 
396
  state = ped->outFlo.ready  & 1<<band ? xieValExportMore
 
397
        : ped->outFlo.active & 1<<band ? xieValExportEmpty
 
398
        : xieValExportDone;
 
399
  SendClientData(flo,ped,data,bytes,ped->swapUnits[band],state);
 
400
  if(release)
 
401
    free_strip(flo,strip);
 
402
 
 
403
  return(bytes ? Execute(flo,NULL) : TRUE);
 
404
}                               /* end export_data */
 
405
 
 
406
 
 
407
/*------------------------------------------------------------------------
 
408
----------- Query flo elements involved in client data transport ---------
 
409
------------------------------------------------------------------------*/
 
410
static int query_data(
 
411
     floDefPtr         flo,
 
412
     xieTypPhototag **list,
 
413
     CARD16       *pending,
 
414
     CARD16     *available)
 
415
{
 
416
  peDefPtr ped;
 
417
  pedLstPtr lst = ListEmpty(&flo->optDAG) ? &flo->defDAG : &flo->optDAG;
 
418
  CARD32 exdex;
 
419
  
 
420
  *pending = *available = 0;
 
421
  if(!(*list = (xieTypPhototag *)XieMalloc(flo->peCnt * sz_xieTypPhototag)))
 
422
    FloAllocError(flo,0,0, return(FALSE));
 
423
 
 
424
  /* find all the import elements that need client data */
 
425
  for(ped = lst->flink; ped; ped = ped->clink)
 
426
    if(ped->flags.putData && ped->peTex->admissionCnt)
 
427
      *list[(*pending)++] = ped->phototag;
 
428
 
 
429
  /* find all the export elements that have client data */
 
430
  exdex = *pending + (*pending & 1);
 
431
  for(ped = lst->blink; ped; ped = ped->clink)
 
432
    if(ped->flags.getData && ped->outFlo.ready)
 
433
      *list[exdex + (*available)++] = ped->phototag;
 
434
 
 
435
  return(TRUE);
 
436
}                               /* end query_data */
 
437
 
 
438
 
 
439
/*------------------------------------------------------------------------
 
440
---- make a strip containing the specified number of contiguous bytes ----
 
441
------------------------------------------------------------------------*/
 
442
static CARD8* make_bytes(
 
443
     floDefPtr  flo,
 
444
     peTexPtr   pet,
 
445
     bandPtr    bnd,
 
446
     CARD32  contig,
 
447
     Bool     purge)
 
448
{
 
449
  stripPtr strip = bnd->stripLst.blink;
 
450
  CARD32 limit, size, units;
 
451
  Bool avail = (!ListEmpty(&bnd->stripLst) && bnd->current >= strip->start &&
 
452
                bnd->current + contig <= strip->start + strip->bufSiz);
 
453
 
 
454
  if(purge && !avail && put_data(flo,pet,bnd))
 
455
    return(bnd->data = NULL);       /* force element to suspend processing */
 
456
  
 
457
  if(_is_global(bnd))
 
458
    return(get_data(flo,pet,bnd,contig,FALSE));  /* "current" is available */
 
459
 
 
460
  if(avail) {
 
461
    /* extend the available space in our current strip
 
462
     */
 
463
    limit = bnd->current + contig;
 
464
    bnd->available += limit - bnd->maxGlobal;
 
465
    bnd->maxGlobal  = limit;
 
466
    strip->end      = limit - 1;
 
467
    strip->length   = limit - strip->start;
 
468
  } else {
 
469
    /* time to make a fresh strip
 
470
     */
 
471
    units = bnd->current + contig - bnd->maxGlobal;
 
472
    size  = units + Align(units,flo->floTex->stripSize);
 
473
    if(!(strip = make_strip(flo,bnd->format,bnd->maxGlobal,units,size,TRUE)))
 
474
      AllocError(flo,pet->peDef, return(NULL));
 
475
 
 
476
    bnd->available += strip->length;
 
477
    bnd->maxGlobal  = strip->end + 1;
 
478
    InsertMember(strip,bnd->stripLst.blink);
 
479
  }  
 
480
  /* update our bandRec with the results */
 
481
  bnd->strip    = strip;
 
482
  bnd->minLocal = max(bnd->minGlobal,strip->start);
 
483
  bnd->maxLocal = strip->end + 1;
 
484
  return(bnd->data = _byte_ptr(bnd));
 
485
}                               /* end make_bytes */
 
486
 
 
487
 
 
488
/*------------------------------------------------------------------------
 
489
--- Find or make a strip containing the unit specified by bnd->current ---
 
490
------------------------------------------------------------------------*/
 
491
static CARD8* make_lines(
 
492
     floDefPtr  flo,
 
493
     peTexPtr   pet,
 
494
     bandPtr    bnd,
 
495
     Bool     purge)
 
496
{
 
497
  stripPtr strip = NULL;
 
498
  formatPtr  fmt;
 
499
  CARD32 size, units;
 
500
  
 
501
  if(purge && _release_ok(bnd) && put_data(flo,pet,bnd))
 
502
    return(bnd->data = NULL);   /* force element to suspend processing */
 
503
  
 
504
  if(_is_global(bnd))           /* we already have it, just go find it */
 
505
    return(get_data(flo,pet,bnd,(CARD32) 1,FALSE));
 
506
  
 
507
  fmt = bnd->format;
 
508
  if(bnd->current >= fmt->height)
 
509
    return(NULL);                       /* trying to go beyond end of image */
 
510
  
 
511
  while(bnd->current >= bnd->maxGlobal) {
 
512
    /*
 
513
     * re-use src if we're allowed to alter the data
 
514
     */
 
515
    if(!bnd->inPlace || !(strip = alter_data(flo,pet,bnd))) {
 
516
      size  = flo->floTex->stripSize;
 
517
      units = size / bnd->pitch;
 
518
      if(units == 0) {                  /* image bigger than standard strip */
 
519
        units = 1;
 
520
        size  = bnd->pitch;
 
521
      } else if(bnd->current + units > fmt->height)     /* at end of image  */
 
522
        units = fmt->height - bnd->current;
 
523
      strip = make_strip(flo,fmt,bnd->maxGlobal,units,size,TRUE);
 
524
    }
 
525
    if(!strip)
 
526
      AllocError(flo,pet->peDef, return(NULL));
 
527
    bnd->available += strip->length;
 
528
    bnd->maxGlobal  = strip->end + 1;
 
529
    if(bnd->maxGlobal == fmt->height)
 
530
      bnd->final = strip->final = TRUE;
 
531
    InsertMember(strip,bnd->stripLst.blink);
 
532
  }
 
533
  /* update our bandRec with the results */
 
534
  bnd->strip    = strip;
 
535
  bnd->minLocal = max(bnd->minGlobal,strip->start);
 
536
  bnd->maxLocal = strip->end + 1;
 
537
  return(bnd->data = _line_ptr(bnd));
 
538
}                               /* end make_lines */
 
539
 
 
540
 
 
541
/*------------------------------------------------------------------------
 
542
-------------- load data map with pointers to specified data -------------
 
543
------------------------------------------------------------------------*/
 
544
static Bool map_data(
 
545
     floDefPtr  flo,
 
546
     peTexPtr   pet,
 
547
     bandPtr    bnd,
 
548
     CARD32     map,
 
549
     CARD32     unit,
 
550
     CARD32     len,
 
551
     Bool       purge)
 
552
{
 
553
  CARD32 line, pitch;
 
554
  CARD8 *next = (CARD8 *)NULL, *last = (CARD8 *)NULL;
 
555
  CARD8 **ptr = bnd->dataMap + map;
 
556
  stripPtr strip;
 
557
 
 
558
  /* first map the last unit and then the first unit -- if we have to make
 
559
   * strips, or if input strips aren't there, we may as well handle it now
 
560
   */
 
561
  if(len && map + len <= bnd->mapSize)
 
562
    if(bnd->isInput) {
 
563
      last = (CARD8*)GetSrc(flo,pet,bnd,unit+len-1,KEEP);
 
564
      next = (CARD8*)GetSrc(flo,pet,bnd,unit,purge);
 
565
    } else {
 
566
      last = (CARD8*)GetDst(flo,pet,bnd,unit+len-1,KEEP);
 
567
      next = (CARD8*)GetDst(flo,pet,bnd,unit,purge);
 
568
    }
 
569
  if(!next || !last)
 
570
    return(FALSE);      /* map too small or can't map first and last unit */
 
571
 
 
572
  /* now walk through the strips and map all the lines (or bytes!)
 
573
   */
 
574
  strip = bnd->strip;
 
575
  pitch = bnd->pitch;
 
576
  line  = unit;
 
577
  while((*ptr++ = next) != last)
 
578
    if(++line <= strip->end)
 
579
      next += pitch;
 
580
    else {
 
581
      strip = strip->flink;
 
582
      next  = strip->data;
 
583
    }
 
584
  return(TRUE);
 
585
}                               /* end map_data */
 
586
 
 
587
 
 
588
/*------------------------------------------------------------------------
 
589
------ Find the strip containing the unit specified by bnd->current ------
 
590
------------------------------------------------------------------------*/
 
591
static CARD8* get_data(
 
592
     floDefPtr  flo,
 
593
     peTexPtr   pet,
 
594
     bandPtr    bnd,
 
595
     CARD32  contig,
 
596
     Bool     purge)
 
597
{
 
598
  /* NOTE: get_data assumes that the caller has already verified that the
 
599
   *       beginning of the requested data is available in bnd->stripLst.
 
600
   */
 
601
  stripPtr strip = bnd->strip ? bnd->strip : bnd->stripLst.flink;
 
602
  
 
603
  /* first get rid of extra baggage if we can
 
604
   */
 
605
  if(purge && _release_ok(bnd))
 
606
    free_data(flo,pet,bnd);
 
607
 
 
608
  strip = bnd->strip ? bnd->strip : bnd->stripLst.flink;
 
609
  while(!ListEnd(strip,&bnd->stripLst))
 
610
    if(bnd->current > strip->end)
 
611
      strip = strip->flink;                     /* try the next strip        */
 
612
    else if(bnd->current < strip->start)
 
613
      strip = strip->blink;                     /* try the previous strip    */
 
614
    else if(bnd->current+contig-1 <= strip->end ||
 
615
            (strip = contig_data(flo,pet,bnd,strip,contig)))
 
616
      break;                                    /* we found or assembled it  */
 
617
    else
 
618
      return(NULL);                             /* couldn't get enough bytes */
 
619
 
 
620
  /* update our bandRec with the results
 
621
   */
 
622
  bnd->strip    = strip;
 
623
  bnd->minLocal = max(bnd->minGlobal,strip->start);
 
624
  bnd->maxLocal = strip->end + 1;
 
625
  bnd->data     = _is_local_contig(bnd,contig) ? _line_ptr(bnd) : NULL;
 
626
  return(bnd->data);
 
627
}                               /* end get_data */
 
628
 
 
629
 
 
630
/*------------------------------------------------------------------------
 
631
------- move strip(s) onto awaiting receptor(s) or an export outFlo ------
 
632
------------------------------------------------------------------------*/
 
633
static Bool put_data(
 
634
     floDefPtr  flo,
 
635
     peTexPtr   pet,
 
636
     bandPtr    bnd)
 
637
{
 
638
  bandMsk suspend = 0;
 
639
  stripPtr strip;
 
640
  
 
641
  /* transfer strips until we run out or reach the one we're working in
 
642
   */
 
643
  while(_release_ok(bnd)) {
 
644
    RemoveMember(strip, bnd->stripLst.flink);
 
645
    bnd->available -= strip->length;
 
646
    bnd->minGlobal  = strip->end + 1;
 
647
    
 
648
    if(!(pet->emitting & 1<<bnd->band))
 
649
      free_strip(flo,strip);                    /* output disabled    */
 
650
    else {
 
651
      strip->flink = NULL;
 
652
      suspend |= put_strip(flo,pet,strip);      /* send it downstream */
 
653
      if(!strip->flink)
 
654
        free_strip(flo,strip);                  /* nobody wanted it!  */
 
655
    }
 
656
  }
 
657
  if(ListEmpty(&bnd->stripLst)) {
 
658
    bnd->strip = NULL;
 
659
    bnd->data  = NULL;
 
660
    if(bnd->final)
 
661
      disable_dst(flo,pet,bnd);
 
662
  }
 
663
  return(suspend != 0);
 
664
}                               /* end put_data */
 
665
 
 
666
 
 
667
/*------------------------------------------------------------------------
 
668
---------- free strip(s) from a receptor band or an emitter band ---------
 
669
------------------------------------------------------------------------*/
 
670
static void free_data(
 
671
     floDefPtr   flo,
 
672
     peTexPtr    pet,
 
673
     bandPtr     bnd)
 
674
{
 
675
  bandMsk  msk = 1<<bnd->band;
 
676
  
 
677
  /* free strips until we run out or reach the one we're working in
 
678
   */
 
679
  while(_release_ok(bnd)) {
 
680
    stripPtr strip;
 
681
 
 
682
    RemoveMember(strip, bnd->stripLst.flink);
 
683
    bnd->available -= strip->length - (bnd->minGlobal - strip->start);
 
684
    bnd->minGlobal  = strip->end + 1;
 
685
    if(bnd->isInput && bnd->receptor->forward & msk)
 
686
      forward_strip(flo,pet,strip);
 
687
    else
 
688
      free_strip(flo,strip);
 
689
  }
 
690
  /* a little bookkeeping to let the scheduler know where we're at
 
691
   */
 
692
  bnd->available -= bnd->current - bnd->minGlobal;
 
693
  bnd->minGlobal  = bnd->current;
 
694
  if(bnd->isInput) {
 
695
    CheckSrcReady(bnd,msk);
 
696
  }
 
697
  if(bnd->final && bnd->isInput && ListEmpty(&bnd->stripLst)) {
 
698
    bnd->receptor->active &= ~msk;
 
699
    bnd->receptor->attend &= ~msk;
 
700
  }
 
701
  if(!(bnd->data = _is_local(bnd) ? _line_ptr(bnd) : NULL))
 
702
    bnd->strip = NULL;
 
703
}                               /* end free_data */
 
704
 
 
705
 
 
706
/*------------------------------------------------------------------------
 
707
---- take list of strips passed in (most likely from a photomap), clone --
 
708
---- the headers, and hang them on the input receptor to make the data  --
 
709
---- accessable by standard macros                                      --
 
710
------------------------------------------------------------------------*/
 
711
static Bool import_strips(
 
712
     floDefPtr   flo,
 
713
     peTexPtr    pet,
 
714
     bandPtr     bnd,
 
715
     stripLstPtr strips)
 
716
{
 
717
  stripPtr  strip = strips->flink, clone = NULL;
 
718
  receptorPtr rcp = pet->receptor; 
 
719
  CARD8 msk = 1<<bnd->band;
 
720
  
 
721
  for(strip = strips->flink; !ListEnd(strip,strips); strip = strip->flink) {
 
722
    
 
723
    if(!(clone = clone_strip(flo, strip)))
 
724
      AllocError(flo,pet->peDef, return(FALSE));
 
725
    
 
726
    clone->format = bnd->format;          /* this had better be right! */
 
727
    
 
728
    bnd->available += clone->length;
 
729
    
 
730
    InsertMember(clone,bnd->stripLst.blink);
 
731
  }
 
732
  bnd->final     = clone->final;
 
733
  bnd->maxGlobal = clone->end + 1;
 
734
  
 
735
  if(!(rcp->admit &= ~msk))
 
736
    --pet->admissionCnt;
 
737
  
 
738
  return(TRUE);
 
739
}                               /* end import_strips */
 
740
 
 
741
 
 
742
/*------------------------------------------------------------------------
 
743
--------- Clone a strip and pass it on to the element's recipients -------
 
744
------------------------------------------------------------------------*/
 
745
static Bool pass_strip(
 
746
     floDefPtr  flo,
 
747
     peTexPtr   pet,
 
748
     bandPtr    bnd,
 
749
     stripPtr strip)
 
750
{
 
751
  stripPtr clone;
 
752
 
 
753
  if(!(pet->emitting & 1<<bnd->band))
 
754
    return(TRUE);                         /* output disabled */
 
755
 
 
756
  if(!(clone = clone_strip(flo, strip)))
 
757
    AllocError(flo,pet->peDef, return(FALSE));
 
758
 
 
759
  clone->format = bnd->format;            /* this had better be right!    */
 
760
 
 
761
  put_strip(flo,pet,clone);               /* give to downstream receptors */
 
762
  if(!clone->flink)
 
763
    free_strip(flo,clone);                /* nobody wanted it */
 
764
 
 
765
  if ((bnd->final = strip->final) != 0)
 
766
    disable_dst(flo,pet,bnd);
 
767
 
 
768
  return(TRUE);
 
769
}                               /* end pass_strip */
 
770
 
 
771
 
 
772
/*------------------------------------------------------------------------
 
773
------------ see if it's ok to over write the data in a src strip --------
 
774
------------------------------------------------------------------------*/
 
775
static Bool alter_src(
 
776
     floDefPtr flo,
 
777
     peTexPtr  pet,
 
778
     stripPtr  strip)
 
779
{
 
780
  stripPtr chk;
 
781
  
 
782
  if(!strip->data || strip->Xowner)
 
783
    return(FALSE);
 
784
 
 
785
  /* make sure there are no other users of this strip's data
 
786
   */
 
787
  for(chk = strip; chk->parent && chk->refCnt == 1; chk = chk->parent);
 
788
  return(chk->refCnt == 1);
 
789
}                               /* end alter_src */
 
790
 
 
791
 
 
792
/*------------------------------------------------------------------------
 
793
--------- pass all remaining input for this band straight through --------
 
794
------------------------------------------------------------------------*/
 
795
static void bypass_src(
 
796
     floDefPtr  flo,
 
797
     peTexPtr   pet,
 
798
     bandPtr   sbnd)
 
799
{
 
800
  stripPtr  strip;
 
801
  bandPtr    dbnd = &pet->emitter[sbnd->band];
 
802
  CARD8      *src;
 
803
  CARD8      *dst;
 
804
 
 
805
  if(sbnd->receptor->active & 1<<sbnd->band) {
 
806
    /*
 
807
     * if there's lingering data, see that it gets to its destination
 
808
     */
 
809
    for(src = (CARD8*)GetCurrentSrc(flo,pet,sbnd),
 
810
        dst = (CARD8*)GetCurrentDst(flo,pet,dbnd);
 
811
        src && dst;
 
812
        src = (CARD8*)GetNextSrc(flo,pet,sbnd,KEEP),
 
813
        dst = (CARD8*)GetNextDst(flo,pet,dbnd,!src)) {
 
814
      if(src != dst)
 
815
        memcpy((char*)dst, (char*)src, (int)dbnd->pitch);
 
816
    }
 
817
    /* if there's a partial strip still here, adjust its length
 
818
     */
 
819
    if(!ListEmpty(&dbnd->stripLst)) {
 
820
      strip = dbnd->stripLst.blink;
 
821
      if(strip->start < dbnd->current) {
 
822
        strip->end    = dbnd->current - 1;
 
823
        strip->length = dbnd->current - strip->start;
 
824
        put_data(flo,pet,dbnd);
 
825
      }
 
826
    }
 
827
    /* shut down the src band, or the dst band if we're all done
 
828
     */
 
829
    if(pet->emitting &= ~(1<<dbnd->band))
 
830
      disable_src(flo,pet,sbnd,FLUSH);
 
831
    else
 
832
      disable_dst(flo,pet,dbnd);
 
833
  }    
 
834
  /* if we're still accepting input, the remainder will bypass this element
 
835
   */
 
836
  sbnd->receptor->bypass |= 1<<sbnd->band;
 
837
}                               /* end bypass_src */
 
838
 
 
839
 
 
840
/*------------------------------------------------------------------------
 
841
---------- disable src band and discard any remaining input data ---------
 
842
------------------------------------------------------------------------*/
 
843
static void disable_src(
 
844
     floDefPtr  flo,
 
845
     peTexPtr   pet,
 
846
     bandPtr    bnd,
 
847
     Bool       purge)
 
848
{
 
849
  bandMsk msk = 1<<bnd->band;
 
850
 
 
851
  if(bnd->receptor->admit & msk && pet->peDef->flags.putData)
 
852
    --flo->floTex->imports;             /* one less import client band    */
 
853
 
 
854
  if(bnd->receptor->admit && !(bnd->receptor->admit &= ~msk))
 
855
    --pet->admissionCnt;                /* one less receptor needing data */
 
856
 
 
857
  bnd->final = TRUE;
 
858
 
 
859
  if(purge)
 
860
    FreeData(flo,pet,bnd,bnd->maxGlobal);
 
861
}                               /* end disable_src */
 
862
 
 
863
 
 
864
/*------------------------------------------------------------------------
 
865
--- disable dst band -- also disables all src's if no dst bands remain ---
 
866
------------------------------------------------------------------------*/
 
867
static void disable_dst(
 
868
     floDefPtr  flo,
 
869
     peTexPtr   pet,
 
870
     bandPtr    dbnd)
 
871
{
 
872
  peDefPtr    ped = pet->peDef;
 
873
  receptorPtr rcp, rend = &pet->receptor[ped->inCnt];
 
874
  bandMsk mask;
 
875
  bandPtr sbnd;
 
876
 
 
877
  /* if this is the last emitter band to turn off and this isn't an import 
 
878
   * client element, we'll step thru all the receptor bands and kill them too
 
879
   */
 
880
  if(!(pet->emitting &= ~(1<<dbnd->band)) && !ped->flags.putData)
 
881
    for(rcp = pet->receptor; rcp < rend; ++rcp)
 
882
      for(mask = 1, sbnd = rcp->band; rcp->active; mask <<= 1, ++sbnd)
 
883
        if(rcp->active & mask)
 
884
          disable_src(flo,pet,sbnd,TRUE);
 
885
  if(ped->flags.getData) {
 
886
    ped->outFlo.active &= ~(1<<dbnd->band);
 
887
    if(!(ped->outFlo.ready & 1<<dbnd->band))
 
888
      flo->floTex->exports--;
 
889
  }
 
890
}                               /* end disable_dst */
 
891
/*------------------------------------------------------------------------
 
892
- Get permission for an emitter to write into an existing receptor strip -
 
893
------------------------------------------------------------------------*/
 
894
static stripPtr alter_data(
 
895
     floDefPtr flo,
 
896
     peTexPtr  pet,
 
897
     bandPtr   db)
 
898
{
 
899
  bandPtr  sb = db->inPlace;
 
900
  stripPtr chk, strip = sb->strip ? sb->strip : sb->stripLst.flink;
 
901
  
 
902
  /* search through the source data for the corresponding line number
 
903
   */
 
904
  while(!ListEnd(strip,&sb->stripLst))
 
905
    if(db->current > strip->end)
 
906
      strip = strip->flink;
 
907
    else if(db->current < strip->start)
 
908
      strip = strip->blink;
 
909
    else if(!strip->data || strip->Xowner)
 
910
      break;
 
911
    else {
 
912
      /* make sure there are no other users of this strip's data
 
913
       */
 
914
      for(chk = strip; chk->parent && chk->refCnt == 1; chk = chk->parent);
 
915
      if(chk->refCnt > 1)
 
916
        break;
 
917
      return(clone_strip(flo,strip));    /* return a clone of the src strip */
 
918
    }
 
919
  return(NULL);
 
920
}                               /* end alter_data */
 
921
 
 
922
 
 
923
/*------------------------------------------------------------------------
 
924
---------- enter with a strip containing at least one byte of data  ------
 
925
----------    {if a new strip must be created (to hold at least     ------
 
926
----------     contig bytes), available data will be copied to it}  ------
 
927
---------- return with a strip containing "contig" contiguous bytes ------
 
928
------------------------------------------------------------------------*/
 
929
static stripPtr contig_data(
 
930
     floDefPtr  flo,
 
931
     peTexPtr   pet,
 
932
     bandPtr    bnd,
 
933
     stripPtr   i_strip,
 
934
     CARD32     contig)
 
935
{
 
936
  stripPtr o_strip, n_strip;
 
937
  CARD32   limit, start, skip, avail = i_strip->end - bnd->current + 1;
 
938
  
 
939
  if(contig <= i_strip->bufSiz - i_strip->length + avail)
 
940
    o_strip = i_strip;
 
941
  else {
 
942
    /* i_strip too small, make a new one and copy available data into it
 
943
     */
 
944
    if(!(o_strip = make_strip(flo, bnd->format, bnd->current, avail,
 
945
                              contig + Align(contig, flo->floTex->stripSize),
 
946
                              TRUE)))
 
947
      AllocError(flo,pet->peDef, return(NULL));
 
948
    InsertMember(o_strip,i_strip);
 
949
    memcpy((char*)o_strip->data,
 
950
           (char*)&i_strip->data[bnd->current-i_strip->start], (int)avail);
 
951
    if(i_strip->length -= avail)
 
952
       i_strip->end    -= avail;
 
953
    else {
 
954
      RemoveMember(n_strip,i_strip);
 
955
      o_strip->final = n_strip->final;
 
956
      free_strip(flo, n_strip);
 
957
    }
 
958
  }
 
959
  /* determine how far we can extend our o_strip
 
960
   */
 
961
  if(bnd->current + contig <= bnd->maxGlobal)
 
962
    limit = bnd->current + contig;              /* limit to data needed     */
 
963
  else
 
964
    limit = bnd->maxGlobal;                     /* limit to data available  */
 
965
 
 
966
  /* if there are more strips beyond "o_strip", transfer the needed amount of
 
967
   * data into our mega-strip (free any strips that we completely consume)
 
968
   */
 
969
  for(start = o_strip->end+1; start < limit; start += avail) {
 
970
    n_strip = o_strip->flink;
 
971
    skip    = start - n_strip->start;
 
972
    avail   = min(n_strip->length - skip, limit - start);
 
973
    memcpy((char*)&o_strip->data[o_strip->length],
 
974
           (char*)&n_strip->data[skip], (int)avail);
 
975
    o_strip->end    += avail;
 
976
    o_strip->length += avail;
 
977
    if(avail+skip == n_strip->length) {
 
978
      RemoveMember(n_strip, n_strip);
 
979
      o_strip->final = n_strip->final;
 
980
      free_strip(flo, n_strip);
 
981
    }
 
982
  }
 
983
 if(!bnd->isInput) {
 
984
    limit = bnd->current + contig;
 
985
    bnd->available += limit - bnd->maxGlobal;
 
986
    bnd->maxGlobal  = limit;
 
987
    o_strip->end    = limit - 1;
 
988
    o_strip->length = limit - o_strip->start;
 
989
  }
 
990
  return(o_strip);
 
991
}                               /* end contig_data */
 
992
 
 
993
 
 
994
/*------------------------------------------------------------------------
 
995
---------------------------- Make a new strip ----------------------------
 
996
------------------------------------------------------------------------*/
 
997
static stripPtr make_strip(
 
998
     floDefPtr flo,
 
999
     formatPtr fmt,
 
1000
     CARD32    start,
 
1001
     CARD32    units,
 
1002
     CARD32    bytes,
 
1003
     Bool      allocData)
 
1004
{
 
1005
  stripPtr    strip;
 
1006
  stripLstPtr cache = &flo->floTex->stripHead;
 
1007
  Bool     cachable = allocData && bytes == flo->floTex->stripSize;
 
1008
 
 
1009
  if(!ListEmpty(cache) && (cachable || !cache->blink->data))
 
1010
    RemoveMember(strip, cachable ? cache->flink : cache->blink);
 
1011
  else if ((strip = (stripPtr) XieMalloc(sizeof(stripRec))) != 0) {
 
1012
      strip->data  = NULL;
 
1013
      ++STRIPS; /*DEBUG*/
 
1014
  }
 
1015
  if(strip) {
 
1016
    strip->flink   = NULL;
 
1017
    strip->parent  = NULL;
 
1018
    strip->format  = fmt;
 
1019
    strip->refCnt  = 1;
 
1020
    strip->Xowner  = !allocData;
 
1021
    strip->canonic = IsCanonic(fmt->class);
 
1022
    strip->final   = FALSE;
 
1023
    strip->cache   = cachable;
 
1024
    strip->start   = start;
 
1025
    strip->end     = start + units - 1;
 
1026
    strip->length  = units;
 
1027
    strip->bitOff  = 0;
 
1028
    strip->bufSiz  = bytes;
 
1029
 
 
1030
    if(allocData && bytes && !strip->data)
 
1031
      if ((strip->data = (CARD8 *) XieCalloc(bytes)) != 0) /* calloc to hush purify */
 
1032
        BYTES += bytes; /*DEBUG*/
 
1033
      else
 
1034
        strip  = free_strip(NULL,strip);
 
1035
  }
 
1036
  return(strip);
 
1037
}                               /* end make_strip */
 
1038
 
 
1039
 
 
1040
/*------------------------------------------------------------------------
 
1041
---- Clone a new modifiable strip wrapper for existing read-only data ----
 
1042
------------------------------------------------------------------------*/
 
1043
static stripPtr clone_strip(floDefPtr flo, stripPtr in_strip)
 
1044
{
 
1045
  stripLstPtr  cache = &flo->floTex->stripHead;
 
1046
  stripPtr out_strip;
 
1047
 
 
1048
  if(ListEmpty(cache) || cache->blink->data) {
 
1049
    out_strip = (stripPtr) XieMalloc(sizeof(stripRec));
 
1050
    ++STRIPS; /*DEBUG*/
 
1051
  } else {
 
1052
    RemoveMember(out_strip, cache->blink);
 
1053
  }
 
1054
  if(out_strip) {
 
1055
    *out_strip         = *in_strip;
 
1056
     out_strip->flink  =  NULL;
 
1057
     out_strip->parent =  in_strip;
 
1058
     out_strip->refCnt =  1;
 
1059
    ++in_strip->refCnt;
 
1060
  }
 
1061
  return(out_strip);
 
1062
}                               /* end clone_strip */
 
1063
 
 
1064
 
 
1065
/*------------------------------------------------------------------------
 
1066
---------------- Put strip on each receptor fed by an element ------------
 
1067
------------------------------------------------------------------------*/
 
1068
static bandMsk put_strip(floDefPtr flo, peTexPtr pet, stripPtr strip)
 
1069
{
 
1070
  peTexPtr    dst;
 
1071
  inFloPtr    inf;
 
1072
  bandPtr     bnd;
 
1073
  stripPtr  clone;
 
1074
  receptorPtr rcp;
 
1075
  CARD8      band = strip->format->band;
 
1076
  bandMsk  repmsk, mask = 1<<band, suspend = 0;
 
1077
 
 
1078
  if(pet->peDef->flags.export) {
 
1079
    pet->outFlo->ready |= mask;
 
1080
    /*
 
1081
     * give to DIXIE via our outFlo; if we're not first in line, make a clone
 
1082
     */
 
1083
    if(!(clone = strip->flink ? clone_strip(flo,strip) : strip))
 
1084
      AllocError(flo,pet->peDef, return(suspend));
 
1085
    InsertMember(clone,pet->outFlo->output[band].blink);
 
1086
    ++flo->floTex->putCnt;
 
1087
    return(suspend);
 
1088
  }
 
1089
  /* hang this strip on the receptor of each of our interested recipients
 
1090
   */
 
1091
  for(inf = pet->outFlo->outChain; inf; inf = inf->outChain) {
 
1092
    if(inf->format[band].class != strip->format->class)
 
1093
      continue;
 
1094
    dst =  inf->ownDef->peTex;
 
1095
    rcp = &dst->receptor[inf->index];
 
1096
    bnd = &rcp->band[band];
 
1097
      
 
1098
    if(rcp->bypass & mask) {
 
1099
      suspend |= put_strip(flo,dst,strip);      /* just passin' through */
 
1100
      continue;
 
1101
    } else if(!(rcp->admit & mask)) {
 
1102
      continue;                                 /* data not wanted here */
 
1103
    }
 
1104
    if(strip->final && !(rcp->admit &= ~mask))
 
1105
      --dst->admissionCnt;                      /* all bands complete   */
 
1106
    /*
 
1107
     * give the data to the intended receptor band
 
1108
     */
 
1109
    for(repmsk = mask; repmsk <= rcp->active; ++bnd, repmsk <<= 1) {
 
1110
      if(rcp->active & repmsk) {
 
1111
        bnd->final      = strip->final;
 
1112
        bnd->maxGlobal  = strip->end + 1;
 
1113
        bnd->available += strip->length;
 
1114
        Schedule(flo,dst,rcp,bnd,repmsk);       /* schedule if runnable */
 
1115
        suspend |= dst->scheduled;
 
1116
        /*
 
1117
         * first recipient gets the original, all others get clones
 
1118
         */
 
1119
        if(!(clone = strip->flink ? clone_strip(flo,strip) : strip))
 
1120
          AllocError(flo,dst->peDef, break);
 
1121
        InsertMember(clone,bnd->stripLst.blink);
 
1122
        ++flo->floTex->putCnt;
 
1123
      }
 
1124
      /* see if we should replicate the data through the other bands
 
1125
       */
 
1126
      if(!rcp->band[0].replicate) break;
 
1127
    }
 
1128
  }
 
1129
  return(suspend);
 
1130
}                               /* end put_strip */
 
1131
 
 
1132
 
 
1133
/*------------------------------------------------------------------------
 
1134
------------ forward input data downstream (re-buffer if Xowner)  --------
 
1135
------------ primarily used to pass compressed data to a photomap --------
 
1136
------------------------------------------------------------------------*/
 
1137
static void forward_strip(floDefPtr flo, peTexPtr pet, stripPtr fwd)
 
1138
{
 
1139
  if(!pet->peDef->flags.putData) {
 
1140
    /* non-client data -- just pass it along
 
1141
     */
 
1142
    fwd->flink = NULL;
 
1143
    put_strip(flo,pet,fwd);               /* give to downstream receptors */
 
1144
    if(!fwd->flink)
 
1145
      free_strip(flo,fwd);                /* hmm, nobody wanted it        */
 
1146
  } else {
 
1147
    /* since this is client data we must copy it before passing it along
 
1148
     */
 
1149
    stripLstPtr lst = &pet->outFlo->output[fwd->format->band];
 
1150
    stripPtr    tmp =  ListEmpty(lst) ? NULL : lst->flink;
 
1151
    int      maxlen =  flo->floTex->stripSize, datlen;
 
1152
    int     overlap =  tmp ? tmp->end - fwd->start + 1 : 0;
 
1153
    int       start =  fwd->start  + overlap;
 
1154
    int        size =  fwd->length - overlap;
 
1155
    CARD8     *data = &fwd->data[overlap];
 
1156
    Bool      final = FALSE;
 
1157
 
 
1158
    while(!final) {
 
1159
      if(ListEmpty(lst))
 
1160
        if ((tmp = make_strip(flo, fwd->format, start, 0, maxlen, TRUE)) != 0) {
 
1161
          InsertMember(tmp,lst->flink);
 
1162
        } else {
 
1163
          free_strip(flo,fwd);
 
1164
          AllocError(flo,pet->peDef, return);
 
1165
        }
 
1166
      if(size) {
 
1167
        datlen = min(size, tmp->bufSiz - tmp->length);
 
1168
        memcpy((char*)&tmp->data[tmp->length], (char*)data, (int)datlen);
 
1169
        tmp->length += datlen;
 
1170
        tmp->end    += datlen;
 
1171
        data        += datlen;
 
1172
        size        -= datlen;
 
1173
      }
 
1174
      if((!size && fwd->final) || tmp->length == tmp->bufSiz) {
 
1175
        RemoveMember(tmp,lst->flink);
 
1176
        start        = tmp->start + tmp->length;
 
1177
        tmp->final   = final = fwd->final && !size;
 
1178
        tmp->canonic = fwd->canonic;
 
1179
        tmp->flink   = NULL;
 
1180
        put_strip(flo,pet,tmp);           /* give to downstream receptors */
 
1181
        if(!tmp->flink)
 
1182
          free_strip(flo,tmp);
 
1183
      }
 
1184
      if(!size)   break;
 
1185
    }
 
1186
    free_strip(flo,fwd);
 
1187
  }
 
1188
}                               /* end forward_strip */
 
1189
 
 
1190
 
 
1191
/*------------------------------------------------------------------------
 
1192
----------------------------- Get rid of a strip -------------------------
 
1193
------------------------------------------------------------------------*/
 
1194
static stripPtr free_strip(floDefPtr flo, stripPtr strip)
 
1195
{
 
1196
  lstPtr cache;
 
1197
 
 
1198
  if(strip && !--strip->refCnt) {
 
1199
    /* since this was the last reference we're going to nuke this strip,
 
1200
     * if this was a clone, free the parent and forget where the data was
 
1201
     */
 
1202
    if(strip->parent) {
 
1203
      free_strip(flo, strip->parent);
 
1204
      strip->data = NULL;
 
1205
    } else if(strip->data) {
 
1206
      /* if the data buffer belongs to coreX or is uncachable, nuke it */
 
1207
      if(strip->Xowner)
 
1208
        strip->data = NULL;
 
1209
      else if(!flo || !strip->cache) {
 
1210
        strip->data = (CARD8 *) XieFree(strip->data);
 
1211
        BYTES -= strip->bufSiz; /*DEBUG*/
 
1212
      }
 
1213
    }
 
1214
    if(flo) {
 
1215
      /* strips with standard data buffers are cached at the front
 
1216
       * strips without data buffers go at the back
 
1217
       */
 
1218
      strip->refCnt = 1;
 
1219
      strip->parent = NULL;
 
1220
      cache = (strip->data
 
1221
               ? (lstPtr)&flo->floTex->stripHead
 
1222
               : (lstPtr) flo->floTex->stripHead.blink);
 
1223
      InsertMember(strip,cache);
 
1224
    } else {
 
1225
      XieFree(strip);
 
1226
      --STRIPS; /*DEBUG*/
 
1227
    }
 
1228
  }
 
1229
  return(NULL);
 
1230
}                               /* end free_strip */
 
1231
 
 
1232
/* end module strip.c */