00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifdef HAVE_CONFIG_H
00032 #include <config.h>
00033 #endif
00034 #include <gimp-print/gimp-print.h>
00035 #include "gimp-print-internal.h"
00036 #include <gimp-print/gimp-print-intl-internal.h>
00037 #include <stdlib.h>
00038 #include <stdio.h>
00039 #include <string.h>
00040
00041 struct stp_list_item
00042 {
00043 void *data;
00044 struct stp_list_item *prev;
00045 struct stp_list_item *next;
00046 };
00047
00048 struct stp_list
00049 {
00050 int icache;
00051 int length;
00052 struct stp_list_item *start;
00053 struct stp_list_item *end;
00054 struct stp_list_item *cache;
00055 stp_node_freefunc freefunc;
00056 stp_node_copyfunc copyfunc;
00057 stp_node_namefunc namefunc;
00058 stp_node_namefunc long_namefunc;
00059 stp_node_sortfunc sortfunc;
00060 char *name_cache;
00061 struct stp_list_item *name_cache_node;
00062 char *long_name_cache;
00063 struct stp_list_item *long_name_cache_node;
00064 };
00065
00066 static void
00067 set_name_cache(stp_list_t *list,
00068 const char *name,
00069 stp_list_item_t *cache)
00070 {
00071 if (list->name_cache)
00072 stp_free(list->name_cache);
00073 list->name_cache = NULL;
00074 if (name)
00075 list->name_cache = stp_strdup(name);
00076 list->name_cache_node = cache;
00077 }
00078
00079 static void
00080 set_long_name_cache(stp_list_t *list,
00081 const char *long_name,
00082 stp_list_item_t *cache)
00083 {
00084 if (list->long_name_cache)
00085 stp_free(list->long_name_cache);
00086 list->long_name_cache = NULL;
00087 if (long_name)
00088 list->long_name_cache = stp_strdup(long_name);
00089 list->long_name_cache_node = cache;
00090 }
00091
00092 static inline void
00093 clear_cache(stp_list_t *list)
00094 {
00095 set_name_cache(list, NULL, NULL);
00096 set_long_name_cache(list, NULL, NULL);
00097 }
00098
00099
00100
00101 void
00102 stp_list_node_free_data (void *item)
00103 {
00104 stp_free(item);
00105 stp_deprintf(STP_DBG_LIST, "stp_list_node_free_data destructor\n");
00106 }
00107
00108 static void
00109 null_list(void)
00110 {
00111 stp_erprintf("Null stp_list_t! Please report this bug.\n");
00112 stp_abort();
00113 }
00114
00115 static inline void
00116 check_list(const stp_list_t *list)
00117 {
00118 if (list == NULL)
00119 null_list();
00120 }
00121
00122 static inline stp_list_item_t *
00123 get_start_internal(const stp_list_t *list)
00124 {
00125 check_list(list);
00126 return list->start;
00127 }
00128
00129 static inline stp_list_item_t *
00130 get_end_internal(const stp_list_t *list)
00131 {
00132 check_list(list);
00133 return list->end;
00134 }
00135
00136
00137
00138
00139
00140
00141
00142 stp_list_t *
00143 stp_list_create(void)
00144 {
00145 stp_list_t *list =
00146 stp_malloc(sizeof(stp_list_t));
00147
00148
00149 list->icache = 0;
00150 list->length = 0;
00151 list->start = NULL;
00152 list->end = NULL;
00153 list->cache = NULL;
00154 list->freefunc = NULL;
00155 list->namefunc = NULL;
00156 list->long_namefunc = NULL;
00157 list->sortfunc = NULL;
00158 list->copyfunc = NULL;
00159 list->name_cache = NULL;
00160 list->name_cache_node = NULL;
00161 list->long_name_cache = NULL;
00162 list->long_name_cache_node = NULL;
00163
00164 stp_deprintf(STP_DBG_LIST, "stp_list_head constructor\n");
00165 return list;
00166 }
00167
00168 stp_list_t *
00169 stp_list_copy(const stp_list_t *list)
00170 {
00171 stp_list_t *ret;
00172 stp_node_copyfunc copyfunc = stp_list_get_copyfunc(list);
00173 stp_list_item_t *item = get_start_internal(list);
00174
00175 check_list(list);
00176
00177 ret = stp_list_create();
00178 stp_list_set_copyfunc(ret, stp_list_get_copyfunc(list));
00179
00180 if (stp_list_get_copyfunc(list))
00181 stp_list_set_freefunc(ret, stp_list_get_freefunc(list));
00182 stp_list_set_namefunc(ret, stp_list_get_namefunc(list));
00183 stp_list_set_long_namefunc(ret, stp_list_get_long_namefunc(list));
00184 stp_list_set_sortfunc(ret, stp_list_get_sortfunc(list));
00185 while (item)
00186 {
00187 void *data = item->data;
00188 if (copyfunc)
00189 stp_list_item_create (ret, NULL, (*copyfunc)(data));
00190 else
00191 stp_list_item_create(ret, NULL, data);
00192 item = stp_list_item_next(item);
00193 }
00194 return ret;
00195 }
00196
00197
00198 int
00199 stp_list_destroy(stp_list_t *list)
00200 {
00201 stp_list_item_t *cur;
00202 stp_list_item_t *next;
00203
00204 check_list(list);
00205 clear_cache(list);
00206 cur = get_start_internal(list);
00207 while(cur)
00208 {
00209 next = cur->next;
00210 stp_list_item_destroy(list, cur);
00211 cur = next;
00212 }
00213 stp_deprintf(STP_DBG_LIST, "stp_list_head destructor\n");
00214 stp_free(list);
00215
00216 return 0;
00217 }
00218
00219 int
00220 stp_list_get_length(const stp_list_t *list)
00221 {
00222 check_list(list);
00223 return list->length;
00224 }
00225
00226
00227
00228
00229
00230 stp_list_item_t *
00231 stp_list_get_start(const stp_list_t *list)
00232 {
00233 return get_start_internal(list);
00234 }
00235
00236
00237
00238 stp_list_item_t *
00239 stp_list_get_end(const stp_list_t *list)
00240 {
00241 return get_end_internal(list);
00242 }
00243
00244
00245 stp_list_item_t *
00246 stp_list_get_item_by_index(const stp_list_t *list, int idx)
00247 {
00248 stp_list_item_t *node = NULL;
00249 int i;
00250 int d = 0;
00251 int c = 0;
00252 check_list(list);
00253
00254 if (idx >= list->length)
00255 return NULL;
00256
00257
00258 if (list->icache)
00259 {
00260 if (idx < (list->length/2))
00261 {
00262 if (idx > abs(idx - list->icache))
00263 c = 1;
00264 else
00265 d = 0;
00266 }
00267 else
00268 {
00269 if (list->length - 1 - idx >
00270 abs (list->length - 1 - idx - list->icache))
00271 c = 1;
00272 else
00273 d = 1;
00274 }
00275 }
00276
00277
00278 if (c)
00279 {
00280 if (idx > list->icache)
00281 d = 0;
00282 else
00283 d = 1;
00284 i = list->icache;
00285 node = list->cache;
00286 }
00287 else
00288 {
00289 if (d)
00290 {
00291 i = list->length - 1;
00292 node = get_end_internal(list);
00293 }
00294 else
00295 {
00296 i = 0;
00297 node = get_start_internal(list);
00298 }
00299 }
00300
00301 while (node && i != idx)
00302 {
00303 if (d)
00304 {
00305 i--;
00306 node = node->prev;
00307 }
00308 else
00309 {
00310 i++;
00311 node = node->next;
00312 }
00313 }
00314
00315
00316 ((stp_list_t *)list)->icache = i;
00317 ((stp_list_t *)list)->cache = node;
00318
00319 return node;
00320 }
00321
00322 static stp_list_item_t *
00323 stp_list_get_item_by_name_internal(const stp_list_t *list, const char *name)
00324 {
00325 stp_list_item_t *node = get_start_internal(list);
00326 while (node && strcmp(name, list->namefunc(node->data)))
00327 {
00328 node = node->next;
00329 }
00330 return node;
00331 }
00332
00333
00334
00335 stp_list_item_t *
00336 stp_list_get_item_by_name(const stp_list_t *list, const char *name)
00337 {
00338 stp_list_item_t *node = NULL;
00339 check_list(list);
00340
00341 if (!list->namefunc)
00342 return NULL;
00343
00344 if (list->name_cache && name && list->name_cache_node)
00345 {
00346 const char *new_name;
00347 node = list->name_cache_node;
00348
00349 if (strcmp(name, list->name_cache) == 0 &&
00350 strcmp(name, list->namefunc(node->data)) == 0)
00351 return node;
00352
00353
00354 node = node->next;
00355 if (node)
00356 {
00357 new_name = list->namefunc(node->data);
00358 if (strcmp(name, new_name) == 0)
00359 {
00360 set_name_cache((stp_list_t *) list, new_name, node);
00361 return node;
00362 }
00363 }
00364
00365 node = list->cache;
00366 if (node)
00367 {
00368 new_name = list->namefunc(node->data);
00369 if (strcmp(name, new_name) == 0)
00370 {
00371 set_name_cache((stp_list_t *) list, new_name, node);
00372 return node;
00373 }
00374 }
00375 }
00376
00377 node = stp_list_get_item_by_name_internal(list, name);
00378
00379 if (node)
00380 set_name_cache((stp_list_t *) list, name, node);
00381
00382 return node;
00383 }
00384
00385
00386 static stp_list_item_t *
00387 stp_list_get_item_by_long_name_internal(const stp_list_t *list,
00388 const char *long_name)
00389 {
00390 stp_list_item_t *node = get_start_internal(list);
00391 while (node && strcmp(long_name, list->long_namefunc(node->data)))
00392 {
00393 node = node->next;
00394 }
00395 return node;
00396 }
00397
00398
00399
00400 stp_list_item_t *
00401 stp_list_get_item_by_long_name(const stp_list_t *list, const char *long_name)
00402 {
00403 stp_list_item_t *node = NULL;
00404 check_list(list);
00405
00406 if (!list->long_namefunc)
00407 return NULL;
00408
00409 if (list->long_name_cache && long_name && list->long_name_cache_node)
00410 {
00411 const char *new_long_name;
00412 node = list->long_name_cache_node;
00413
00414 if (strcmp(long_name, list->long_name_cache) == 0 &&
00415 strcmp(long_name, list->long_namefunc(node->data)) == 0)
00416 return node;
00417
00418
00419 node = node->next;
00420 if (node)
00421 {
00422 new_long_name = list->long_namefunc(node->data);
00423 if (strcmp(long_name, new_long_name) == 0)
00424 {
00425 set_long_name_cache((stp_list_t*) list, new_long_name, node);
00426 return node;
00427 }
00428 }
00429
00430 node = list->cache;
00431 if (node)
00432 {
00433 new_long_name = list->long_namefunc(node->data);
00434 if (strcmp(long_name, new_long_name) == 0)
00435 {
00436 set_long_name_cache((stp_list_t *) list, new_long_name, node);
00437 return node;
00438 }
00439 }
00440 }
00441
00442 node = stp_list_get_item_by_long_name_internal(list, long_name);
00443
00444 if (node)
00445 set_long_name_cache((stp_list_t *) list, long_name, node);
00446
00447 return node;
00448 }
00449
00450
00451
00452 void
00453 stp_list_set_freefunc(stp_list_t *list, stp_node_freefunc freefunc)
00454 {
00455 check_list(list);
00456 list->freefunc = freefunc;
00457 }
00458
00459 stp_node_freefunc
00460 stp_list_get_freefunc(const stp_list_t *list)
00461 {
00462 check_list(list);
00463 return list->freefunc;
00464 }
00465
00466
00467 void
00468 stp_list_set_copyfunc(stp_list_t *list, stp_node_copyfunc copyfunc)
00469 {
00470 check_list(list);
00471 list->copyfunc = copyfunc;
00472 }
00473
00474 stp_node_copyfunc
00475 stp_list_get_copyfunc(const stp_list_t *list)
00476 {
00477 check_list(list);
00478 return list->copyfunc;
00479 }
00480
00481
00482 void
00483 stp_list_set_namefunc(stp_list_t *list, stp_node_namefunc namefunc)
00484 {
00485 check_list(list);
00486 list->namefunc = namefunc;
00487 }
00488
00489 stp_node_namefunc
00490 stp_list_get_namefunc(const stp_list_t *list)
00491 {
00492 check_list(list);
00493 return list->namefunc;
00494 }
00495
00496
00497 void
00498 stp_list_set_long_namefunc(stp_list_t *list, stp_node_namefunc long_namefunc)
00499 {
00500 check_list(list);
00501 list->long_namefunc = long_namefunc;
00502 }
00503
00504 stp_node_namefunc
00505 stp_list_get_long_namefunc(const stp_list_t *list)
00506 {
00507 check_list(list);
00508 return list->long_namefunc;
00509 }
00510
00511
00512 void
00513 stp_list_set_sortfunc(stp_list_t *list, stp_node_sortfunc sortfunc)
00514 {
00515 check_list(list);
00516 list->sortfunc = sortfunc;
00517 }
00518
00519 stp_node_sortfunc
00520 stp_list_get_sortfunc(const stp_list_t *list)
00521 {
00522 check_list(list);
00523 return list->sortfunc;
00524 }
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538 int
00539 stp_list_item_create(stp_list_t *list,
00540 stp_list_item_t *next,
00541 const void *data)
00542 {
00543 stp_list_item_t *ln;
00544 stp_list_item_t *lnn;
00545
00546 check_list(list);
00547
00548 clear_cache(list);
00549
00550 ln = stp_malloc(sizeof(stp_list_item_t));
00551 ln->prev = ln->next = NULL;
00552
00553 if (data)
00554 ln->data = (void *) data;
00555 else
00556 {
00557 stp_free(ln);
00558 return 1;
00559 }
00560
00561 if (list->sortfunc)
00562 {
00563
00564 lnn = get_end_internal(list);
00565 while (lnn)
00566 {
00567 if (list->sortfunc(lnn->data, ln->data) <= 0)
00568 break;
00569 lnn = lnn->prev;
00570 }
00571 }
00572 #if 0
00573
00574
00575
00576
00577
00578 else if (stpi_get_debug_level() & STPI_DBG_LIST)
00579 {
00580 if (next)
00581 {
00582 lnn = get_start_internal(list);
00583 while (lnn)
00584 {
00585 if (lnn == next)
00586 break;
00587 lnn = lnn->prev;
00588 }
00589 }
00590 else
00591 lnn = NULL;
00592 }
00593 #endif
00594 else
00595 lnn = next;
00596
00597
00598
00599
00600 ln->next = lnn;
00601
00602 if (!ln->prev)
00603 {
00604 if (list->start)
00605 ln->prev = list->end;
00606 else
00607 list->start = ln;
00608 list->end = ln;
00609 }
00610
00611
00612
00613 if (!ln->prev && ln->next)
00614 ln->prev = ln->next->prev;
00615
00616 if (list->start == ln->next)
00617 {
00618 list->start = ln;
00619 }
00620
00621
00622 if (ln->next)
00623 ln->next->prev = ln;
00624
00625
00626 if (ln->prev)
00627 ln->prev->next = ln;
00628
00629
00630 list->length++;
00631
00632 stp_deprintf(STP_DBG_LIST, "stp_list_node constructor\n");
00633 return 0;
00634 }
00635
00636
00637 int
00638 stp_list_item_destroy(stp_list_t *list, stp_list_item_t *item)
00639 {
00640 check_list(list);
00641
00642 clear_cache(list);
00643
00644 list->length--;
00645
00646 if (list->freefunc)
00647 list->freefunc((void *) item->data);
00648 if (item->prev)
00649 item->prev->next = item->next;
00650 else
00651 list->start = item->next;
00652 if (item->next)
00653 item->next->prev = item->prev;
00654 else
00655 list->end = item->prev;
00656 stp_free(item);
00657
00658 stp_deprintf(STP_DBG_LIST, "stp_list_node destructor\n");
00659 return 0;
00660 }
00661
00662
00663 stp_list_item_t *
00664 stp_list_item_prev(const stp_list_item_t *item)
00665 {
00666 return item->prev;
00667 }
00668
00669
00670 stp_list_item_t *
00671 stp_list_item_next(const stp_list_item_t *item)
00672 {
00673 return item->next;
00674 }
00675
00676
00677 void *
00678 stp_list_item_get_data(const stp_list_item_t *item)
00679 {
00680 return item->data;
00681 }
00682
00683
00684 int
00685 stp_list_item_set_data(stp_list_item_t *item, void *data)
00686 {
00687 if (data)
00688 {
00689 item->data = data;
00690 return 0;
00691 }
00692 return 1;
00693 }