1 /*
2 * Author: William Chia-Wei Cheng (bill.cheng@acm.org)
3 *
4 * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5 *
6 * This file may be distributed under the terms of the Q Public License
7 * as defined by Trolltech AS of Norway and appearing in the file
8 * LICENSE.QPL included in the packaging of this file.
9 *
10 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12 * PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * @(#)$Header: /mm2/home/cvs/bc-src/tgif/attr.c,v 1.15 2011/05/16 16:21:56 william Exp $
19 */
20
21 #define _INCLUDE_FROM_ATTR_C_
22
23 #include "tgifdefs.h"
24
25 #include "attr.e"
26 #include "auxtext.e"
27 #include "button.e"
28 #include "choice.e"
29 #include "choose.e"
30 #include "cmd.e"
31 #include "color.e"
32 #include "cursor.e"
33 #include "dialog.e"
34 #include "drawing.e"
35 #include "dup.e"
36 #include "file.e"
37 #include "font.e"
38 #include "grid.e"
39 #include "mainloop.e"
40 #include "mainmenu.e"
41 #include "mark.e"
42 #include "menu.e"
43 #include "miniline.e"
44 #include "move.e"
45 #include "msg.e"
46 #include "names.e"
47 #include "obj.e"
48 #include "pattern.e"
49 #include "raster.e"
50 #include "rect.e"
51 #include "ruler.e"
52 #include "select.e"
53 #include "setup.e"
54 #include "stk.e"
55 #include "strtbl.e"
56 #include "text.e"
57 #include "util.e"
58 #include "wb.e"
59
60 int dropObsIconAttrWhenUpdate=FALSE;
61 int maxAttrGroups=0;
62
63 AttrGroupInfo **gAttrGroupInfo=NULL;
64 EditAttrInfo *gpEditAttrInEditorAttrInfo=NULL;
65
66 static struct AttrRec *topAttr=NULL, *botAttr=NULL;
67
LinkInAttr(PrevPtr,NextPtr,AttrPtr)68 void LinkInAttr(PrevPtr, NextPtr, AttrPtr)
69 struct AttrRec *PrevPtr, *NextPtr, *AttrPtr;
70 /* add AttrPtr between PrevPtr and NextPtr */
71 {
72 AttrPtr->prev = PrevPtr;
73 AttrPtr->next = NextPtr;
74
75 if (PrevPtr == NULL) {
76 topAttr = AttrPtr;
77 } else {
78 PrevPtr->next = AttrPtr;
79 }
80 if (NextPtr == NULL) {
81 botAttr = AttrPtr;
82 } else {
83 NextPtr->prev = AttrPtr;
84 }
85 }
86
FreeAttr(AttrPtr)87 void FreeAttr(AttrPtr)
88 struct AttrRec *AttrPtr;
89 /* This routine only frees the attribute record, not */
90 /* the text record, which must be freed explicitly. */
91 {
92 if (AttrPtr->attr_name.s != NULL) free(AttrPtr->attr_name.s);
93 if (AttrPtr->attr_value.s != NULL) free(AttrPtr->attr_value.s);
94 free(AttrPtr);
95 }
96
UnlinkAttr(AttrPtr)97 void UnlinkAttr(AttrPtr)
98 struct AttrRec *AttrPtr;
99 {
100 struct ObjRec *own_ptr;
101 struct AttrRec **top_attr_ad;
102 struct AttrRec **bot_attr_ad;
103
104 own_ptr = AttrPtr->owner;
105
106 top_attr_ad = &(own_ptr->fattr);
107 bot_attr_ad = &(own_ptr->lattr);
108
109 if (*top_attr_ad == AttrPtr) {
110 *top_attr_ad = AttrPtr->next;
111 } else {
112 AttrPtr->prev->next = AttrPtr->next;
113 }
114 if (*bot_attr_ad == AttrPtr) {
115 *bot_attr_ad = AttrPtr->prev;
116 } else {
117 AttrPtr->next->prev = AttrPtr->prev;
118 }
119 }
120
UpdAttrOwner(first_attr,owner_obj)121 void UpdAttrOwner(first_attr, owner_obj)
122 struct AttrRec *first_attr;
123 struct ObjRec *owner_obj;
124 {
125 while (first_attr != NULL) {
126 first_attr->owner = owner_obj;
127 first_attr = first_attr->next;
128 }
129 }
130
131 static
FindEqual(s)132 char *FindEqual(s)
133 char *s;
134 {
135 while (*s != '=' && *s != '\0') s++;
136 return ((*s == '=') ? (s) : (char*)NULL);
137 }
138
ParseAttrStr(buf,name,name_sz,value,value_sz)139 void ParseAttrStr(buf, name, name_sz, value, value_sz)
140 char *buf, *name, *value;
141 int name_sz, value_sz;
142 {
143 char *eq_ptr=NULL, *str_ptr=NULL, *psz=NULL;
144
145 if ((eq_ptr=FindEqual(buf)) != NULL) {
146 eq_ptr++;
147 if (name != NULL) {
148 int index=0;
149
150 psz = name;
151 str_ptr = buf;
152 for (;;) {
153 *psz = *str_ptr;
154 psz++;
155 str_ptr++;
156 index++;
157 if (str_ptr == eq_ptr) {
158 break;
159 } else if (index >= name_sz-2) {
160 *psz++ = '=';
161 break;
162 }
163 }
164 *psz = '\0';
165 }
166 if (value != NULL) {
167 int index=0;
168
169 str_ptr = eq_ptr;
170 psz = value;
171 do {
172 *psz = *str_ptr;
173 psz++;
174 str_ptr++;
175 index++;
176 } while (*str_ptr != '\0' && index < value_sz-1);
177
178 *psz = '\0';
179 }
180 } else {
181 if (name != NULL) *name = '\0';
182 if (value != NULL) UtilStrCpyN(value, value_sz, buf);
183 }
184 }
185
UpdateAttr(TextPtr,AttrPtr)186 void UpdateAttr(TextPtr, AttrPtr)
187 struct TextRec *TextPtr;
188 struct AttrRec *AttrPtr;
189 /* This routine updates the name and value in the AttrRec */
190 /* and its ObjRec after an attribute was edited. */
191 {
192 if (AttrPtr->nameshown) {
193 char *s=GetTextPtrFirstStrSeg(TextPtr)->dyn_str.s;
194 int buf_sz=(strlen(s)<<1)+5;
195 char *name=(char*)malloc(buf_sz), *value=(char*)malloc(buf_sz);
196
197 if (name == NULL || value == NULL) FailAllocMessage();
198 *name = *value = '\0';
199 ParseAttrStr(GetTextPtrFirstStrSeg(TextPtr)->dyn_str.s,
200 name, buf_sz, value, buf_sz);
201 DynStrSet(&AttrPtr->attr_value, value);
202 DynStrSet(&AttrPtr->attr_name, name);
203 strcat(name, value);
204 DynStrSet(&GetTextPtrFirstStrSeg(TextPtr)->dyn_str, name);
205 free(name);
206 free(value);
207 } else {
208 char *value=GetTextPtrFirstStrSeg(TextPtr)->dyn_str.s;
209
210 DynStrSet(&AttrPtr->attr_value, value);
211 DynStrSet(&GetTextPtrFirstStrSeg(TextPtr)->dyn_str, value);
212 }
213 UpdTextBBox(AttrPtr->obj);
214 AdjObjCache(AttrPtr->obj);
215 }
216
DrawAttrs(Win,XOff,YOff,AttrPtr)217 void DrawAttrs(Win, XOff, YOff, AttrPtr)
218 Window Win;
219 int XOff, YOff;
220 struct AttrRec *AttrPtr;
221 {
222 struct AttrRec *ptr;
223
224 for (ptr=AttrPtr; ptr != NULL; ptr=ptr->next) {
225 if (ptr->shown) {
226 if (!editingText) {
227 /* UpdAttr(ptr); */ /* ALERT - not sure if this is needed. */
228 }
229 DrawTextObj(Win, XOff, YOff, ptr->obj);
230 }
231 }
232 }
233
MoveAttrs(AttrPtr,Dx,Dy)234 void MoveAttrs(AttrPtr, Dx, Dy)
235 int Dx, Dy;
236 struct AttrRec *AttrPtr;
237 {
238 struct AttrRec *attr_ptr;
239
240 for (attr_ptr=AttrPtr; attr_ptr != NULL; attr_ptr=attr_ptr->next) {
241 MoveObj(attr_ptr->obj, Dx, Dy);
242 }
243 }
244
DelAllAttrs(AttrPtr)245 void DelAllAttrs(AttrPtr)
246 struct AttrRec *AttrPtr;
247 {
248 struct AttrRec *ptr, *next_attr;
249
250 for (ptr=AttrPtr; ptr != NULL; ptr=next_attr) {
251 next_attr = ptr->next;
252 FreeObj(ptr->obj);
253 FreeAttr(ptr);
254 }
255 }
256
AddAttrByNameAndValue(ObjPtr,AttrName,AttrValue)257 struct AttrRec *AddAttrByNameAndValue(ObjPtr, AttrName, AttrValue)
258 struct ObjRec *ObjPtr;
259 char *AttrName, *AttrValue;
260 {
261 struct ObjRec *text_obj_ptr=NULL;
262 struct TextRec *text_ptr=NULL;
263 struct AttrRec *attr_ptr=NULL;
264 StrSegInfo *pStrSeg=NULL;
265 MiniLinesInfo *minilines=NULL;
266 char *buf=(char*)malloc(strlen(AttrName)+strlen(AttrValue)+1);
267
268 if (buf == NULL) FailAllocMessage();
269 sprintf(buf, "%s%s", AttrName, AttrValue);
270
271 text_obj_ptr = (struct ObjRec *)malloc(sizeof(struct ObjRec));
272 text_ptr = (struct TextRec *)malloc(sizeof(struct TextRec));
273 attr_ptr = (struct AttrRec *)malloc(sizeof(struct AttrRec));
274 if (text_obj_ptr == NULL || text_ptr == NULL || attr_ptr == NULL) {
275 FailAllocMessage();
276 }
277 memset(text_obj_ptr, 0, sizeof(struct ObjRec));
278 memset(text_ptr, 0, sizeof(struct TextRec));
279 memset(attr_ptr, 0, sizeof(struct AttrRec));
280
281 minilines = (&text_ptr->minilines);
282 CreateMiniLineFromString("", &minilines->first, &minilines->last);
283 minilines->first->owner_minilines = minilines;
284
285 CopyCurInfoIntoTextPtr(text_obj_ptr, text_ptr);
286 text_ptr->lines = 1;
287 text_ptr->cached_zoom = 0;
288 text_ptr->cached_zoomed = FALSE;
289 text_ptr->cached_bitmap = None;
290
291 pStrSeg = GetTextPtrFirstStrSeg(text_ptr);
292
293 DynStrSet(&pStrSeg->dyn_str, buf);
294
295 pStrSeg->font = curFont;
296 pStrSeg->style = curStyle;
297 pStrSeg->sz_unit = GetCurSzUnit();
298 pStrSeg->underline_on = curUnderlineOn;
299 pStrSeg->overline_on = curOverlineOn;
300
301 pStrSeg->asc = canvasFontAsc;
302 pStrSeg->des = canvasFontDes;
303 pStrSeg->direction = canvasFontDirection;
304 pStrSeg->dontreencode = canvasFontDontReencode;
305 pStrSeg->double_byte = canvasFontDoubleByte;
306 pStrSeg->double_byte_mod_bytes = canvasFontDoubleByteModBytes;
307 pStrSeg->double_byte_vertical = canvasFontDoubleByteVertical;
308
309 text_obj_ptr->x = ObjPtr->obbox.ltx;
310 text_obj_ptr->y = ObjPtr->obbox.rby;
311 text_obj_ptr->type = OBJ_TEXT;
312 text_obj_ptr->color = ObjPtr->color;
313 memcpy(text_obj_ptr->color_str, ObjPtr->color_str,
314 sizeof(text_obj_ptr->color_str));
315 text_obj_ptr->dirty = FALSE;
316 text_obj_ptr->id = objId++;
317 text_obj_ptr->rotation = 0;
318 text_obj_ptr->locked = FALSE;
319 text_obj_ptr->ctm = NULL;
320 text_obj_ptr->detail.t = text_ptr;
321
322 UpdTextBBox(text_obj_ptr);
323
324 attr_ptr->shown = FALSE;
325 attr_ptr->nameshown = TRUE;
326 attr_ptr->inherited = FALSE;
327 attr_ptr->obj = text_obj_ptr;
328 attr_ptr->owner = ObjPtr;
329 DynStrSet(&attr_ptr->attr_name, AttrName);
330 DynStrSet(&attr_ptr->attr_value, AttrValue);
331
332 text_ptr->attr = attr_ptr;
333
334 attr_ptr->prev = NULL;
335 attr_ptr->next = ObjPtr->fattr;
336 if (ObjPtr->fattr == NULL) {
337 ObjPtr->lattr = attr_ptr;
338 } else {
339 ObjPtr->fattr->prev = attr_ptr;
340 }
341 ObjPtr->fattr = attr_ptr;
342 AdjObjBBox(ObjPtr);
343 return attr_ptr;
344 }
345
346 static
NewAttr(OwnerObjPtr,ObjPtr,Inherited)347 struct AttrRec *NewAttr(OwnerObjPtr, ObjPtr, Inherited)
348 struct ObjRec *ObjPtr;
349 struct ObjRec *OwnerObjPtr;
350 short Inherited;
351 {
352 struct AttrRec *attr_ptr;
353
354 attr_ptr = (struct AttrRec *)malloc(sizeof(struct AttrRec));
355 if (attr_ptr == NULL) FailAllocMessage();
356 memset(attr_ptr, 0, sizeof(struct AttrRec));
357 attr_ptr->shown = TRUE;
358 attr_ptr->nameshown = TRUE;
359 attr_ptr->inherited = Inherited;
360 attr_ptr->obj = ObjPtr;
361 attr_ptr->next= attr_ptr->prev = NULL;
362 attr_ptr->owner = OwnerObjPtr;
363 DynStrSet(&attr_ptr->attr_name, "");
364 DynStrSet(&attr_ptr->attr_value, "");
365 ObjPtr->detail.t->attr = attr_ptr;
366
367 return attr_ptr;
368 }
369
370 static
DupAnAttr(FromAttrPtr,ToAttrPtr)371 void DupAnAttr(FromAttrPtr, ToAttrPtr)
372 struct AttrRec *FromAttrPtr, *ToAttrPtr;
373 {
374 struct ObjRec *text_obj_ptr;
375
376 text_obj_ptr = (struct ObjRec *)malloc(sizeof(struct ObjRec));
377 if (text_obj_ptr == NULL) FailAllocMessage();
378 memset(text_obj_ptr, 0, sizeof(struct ObjRec));
379 DupObjBasics(FromAttrPtr->obj, text_obj_ptr);
380 DupTextObj(FromAttrPtr->obj->detail.t, FromAttrPtr->obj, text_obj_ptr);
381
382 DynStrCpy(&ToAttrPtr->attr_name, &FromAttrPtr->attr_name);
383 DynStrCpy(&ToAttrPtr->attr_value, &FromAttrPtr->attr_value);
384 ToAttrPtr->shown = FromAttrPtr->shown;
385 ToAttrPtr->nameshown = FromAttrPtr->nameshown;
386 ToAttrPtr->inherited = FromAttrPtr->inherited;
387 ToAttrPtr->obj = text_obj_ptr;
388 ToAttrPtr->next= ToAttrPtr->prev = NULL;
389 text_obj_ptr->detail.t->attr = ToAttrPtr;
390 }
391
DupAttrs(FromObjPtr,ToObjPtr)392 void DupAttrs(FromObjPtr, ToObjPtr)
393 struct ObjRec *FromObjPtr, *ToObjPtr;
394 {
395 struct AttrRec *to_attr_ptr, *from_attr_ptr;
396
397 topAttr = botAttr = NULL;
398 from_attr_ptr = FromObjPtr->lattr;
399 for ( ; from_attr_ptr != NULL; from_attr_ptr=from_attr_ptr->prev) {
400 to_attr_ptr = (struct AttrRec *)malloc(sizeof(struct AttrRec));
401 if (to_attr_ptr == NULL) FailAllocMessage();
402 memset(to_attr_ptr, 0, sizeof(struct AttrRec));
403 to_attr_ptr->owner = ToObjPtr;
404 DupAnAttr(from_attr_ptr, to_attr_ptr);
405 LinkInAttr((struct AttrRec *)NULL, topAttr, to_attr_ptr);
406 }
407 ToObjPtr->fattr = topAttr;
408 ToObjPtr->lattr = botAttr;
409 }
410
411 static
AddAttr(ObjPtr,TextObjPtr)412 void AddAttr(ObjPtr, TextObjPtr)
413 struct ObjRec *ObjPtr, *TextObjPtr;
414 {
415 struct AttrRec *attr_ptr=NULL;
416 struct TextRec *text_ptr=TextObjPtr->detail.t;
417
418 topAttr = ObjPtr->fattr;
419 botAttr = ObjPtr->lattr;
420
421 UnlinkObj(TextObjPtr);
422 TextObjPtr->next = TextObjPtr->prev = NULL;
423 attr_ptr = NewAttr(ObjPtr, TextObjPtr, FALSE);
424 UpdateAttr(text_ptr, attr_ptr);
425 LinkInAttr((struct AttrRec *)NULL, topAttr, attr_ptr);
426
427 ObjPtr->fattr = topAttr;
428 ObjPtr->lattr = botAttr;
429 }
430
AddAttrs()431 void AddAttrs()
432 {
433 struct ObjRec *owner_ptr=NULL;
434 struct SelRec *sel_ptr;
435 int text_count=0, sel_ltx, sel_lty, sel_rbx, sel_rby;
436 int locked_text_count=0;
437
438 if (topSel == NULL) {
439 MsgBox(TgLoadString(STID_SELECT_AT_LEAST_ONE_TEXT), TOOL_NAME, INFO_MB);
440 return;
441 }
442 for (sel_ptr=topSel; sel_ptr != NULL; sel_ptr=sel_ptr->next) {
443 switch (sel_ptr->obj->type) {
444 case OBJ_TEXT: text_count++; break;
445
446 default:
447 if (owner_ptr != NULL) {
448 MsgBox(TgLoadString(STID_MORE_THAN_ONE_NON_TEXT), TOOL_NAME,
449 INFO_MB);
450 return;
451 }
452 owner_ptr = sel_ptr->obj;
453 break;
454 }
455 }
456
457 if (text_count == 0) {
458 MsgBox(TgLoadString(STID_NO_TEXT_SELECTED_ADD_ATTRS), TOOL_NAME,
459 INFO_MB);
460 return;
461 }
462 if (owner_ptr == NULL) {
463 MsgBox(TgLoadString(STID_NO_NON_TEXT_SELECTED), TOOL_NAME, INFO_MB);
464 return;
465 }
466 HighLightReverse();
467 PrepareToRecord(CMD_REPLACE, topSel, botSel, numObjSelected);
468 sel_ltx = selLtX; sel_lty = selLtY;
469 sel_rbx = selRbX; sel_rby = selRbY;
470
471 for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
472 if (sel_ptr->obj->type == OBJ_TEXT) {
473 if (sel_ptr->obj->locked) {
474 locked_text_count++;
475 sel_ptr->obj->locked = FALSE;
476 }
477 AddAttr(owner_ptr, sel_ptr->obj);
478 }
479 }
480
481 RemoveAllSel();
482 UnlinkObj(owner_ptr);
483 AddObj(NULL, topObj, owner_ptr);
484 topSel = botSel = (struct SelRec *)malloc(sizeof(struct SelRec));
485 if (topSel == NULL) FailAllocMessage();
486 topSel->obj = owner_ptr;
487 topSel->prev = NULL;
488 botSel->next = NULL;
489 AdjObjBBox(owner_ptr);
490 UpdSelBBox();
491 RecordCmd(CMD_MANY_TO_ONE, NULL, topSel, botSel, 1);
492 RedrawAreas(botObj, sel_ltx-GRID_ABS_SIZE(1), sel_lty-GRID_ABS_SIZE(1),
493 sel_rbx+GRID_ABS_SIZE(1), sel_rby+GRID_ABS_SIZE(1),
494 selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
495 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
496 HighLightForward();
497 SetFileModified(TRUE);
498 justDupped = FALSE;
499 if (locked_text_count==0) {
500 Msg(TgLoadString(STID_TEXT_ATTACHED));
501 } else {
502 Msg(TgLoadString(STID_TEXT_UNLOCKED_AND_ATTACHED));
503 }
504 }
505
506 static
SaveAttr(FP,AttrPtr)507 void SaveAttr(FP, AttrPtr)
508 FILE *FP;
509 struct AttrRec *AttrPtr;
510 {
511 struct TextRec *text_ptr=AttrPtr->obj->detail.t;
512
513 if (fprintf(FP, "attr(\"") == EOF) writeFileFailed = TRUE;
514 if (GetTextPtrFirstStrSeg(text_ptr)->double_byte) {
515 SaveDoubleByteString(FP, AttrPtr->attr_name.s);
516 } else {
517 SaveString(FP, AttrPtr->attr_name.s);
518 }
519 if (fprintf(FP, "\", \"") == EOF) writeFileFailed = TRUE;
520 if (GetTextPtrFirstStrSeg(text_ptr)->double_byte) {
521 SaveDoubleByteString(FP, AttrPtr->attr_value.s);
522 } else {
523 SaveString(FP, AttrPtr->attr_value.s);
524 }
525 if (fprintf(FP, "\", %1d, %1d, %1d,\n",
526 AttrPtr->shown, AttrPtr->nameshown, AttrPtr->inherited) == EOF) {
527 writeFileFailed = TRUE;
528 }
529 SaveTextObj(FP, AttrPtr->obj);
530 if (fprintf(FP, ")") == EOF) writeFileFailed = TRUE;
531 }
532
SaveAttrs(FP,BotAttrPtr)533 void SaveAttrs(FP, BotAttrPtr)
534 FILE *FP;
535 struct AttrRec *BotAttrPtr;
536 {
537 struct AttrRec *ptr;
538
539 if (fprintf(FP, "[\n") == EOF) writeFileFailed = TRUE;
540
541 for (ptr=BotAttrPtr; ptr != NULL; ptr=ptr->prev) {
542 SaveAttr(FP, ptr);
543 if (ptr->prev != NULL) {
544 if (fprintf(FP, ",\n") == EOF) {
545 writeFileFailed = TRUE;
546 }
547 }
548 }
549 if (BotAttrPtr == NULL) {
550 if (fprintf(FP, "]") == EOF) writeFileFailed = TRUE;
551 } else {
552 if (fprintf(FP, "\n]") == EOF) writeFileFailed = TRUE;
553 }
554 }
555
ReadAttrString(Str)556 char *ReadAttrString(Str)
557 char *Str;
558 {
559 char *s;
560
561 for (s=Str; *s != '\0'; s++) {
562 if (*s == '"') {
563 if (s[1] == '"') {
564 s++;
565 } else {
566 break;
567 }
568 } else if (*s == '\\') {
569 s++;
570 }
571 }
572 if (*s == '"') s++;
573 return s;
574 }
575
576 static
FreeBufAndReturn(line,rc)577 int FreeBufAndReturn(line, rc)
578 char *line;
579 int rc;
580 {
581 if (line != NULL) free(line);
582 return rc;
583 }
584
ReadAttr(FP,AttrPtr)585 int ReadAttr(FP, AttrPtr)
586 FILE *FP;
587 struct AttrRec **AttrPtr;
588 {
589 struct ObjRec *TextObj;
590 char *s, *line;
591 char *name, *value;
592 int len, shown, nameshown, inherited;
593
594 if ((line=UtilGetALine(FP)) == NULL) {
595 sprintf(gszMsgBox, TgLoadString(STID_UNEXPECTED_EOF_IN_ABORT_READ),
596 scanFileName, scanLineNum, "ReadAttr()");
597 if (PRTGIF) {
598 fprintf(stderr, "%s\n", gszMsgBox);
599 } else {
600 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
601 }
602 return FALSE;
603 }
604 scanLineNum++;
605
606 if (*line == ']') return FreeBufAndReturn(line, FALSE);
607
608 *AttrPtr = NULL;
609 len = strlen(line);
610
611 name = (char *)malloc((len+1)*sizeof(char));
612 if (name == NULL) FailAllocMessage();
613 s = FindChar((int)'"', line);
614 strcpy(name, s);
615 s = ReadAttrString(s);
616 s = FindChar((int)',', s);
617 value = (char *)malloc((len+1)*sizeof(char));
618 if (value == NULL) FailAllocMessage();
619 strcpy(value, FindChar((int)'"', s));
620 s = ReadAttrString(value);
621 s = FindChar((int)',', s);
622
623 InitScan(s, "\t\n ,");
624 if (GETINT("attribute", shown, "shown") == INVALID ||
625 GETINT("attribute", nameshown, "name shown") == INVALID ||
626 GETINT("attribute", inherited, "inherited") == INVALID) {
627 free(name);
628 free(value);
629 return FreeBufAndReturn(line, FALSE);
630 }
631
632 *AttrPtr = (struct AttrRec *)malloc(sizeof(struct AttrRec));
633 if (*AttrPtr == NULL) FailAllocMessage();
634 memset(*AttrPtr, 0, sizeof(struct AttrRec));
635
636 s = ReadString(name);
637 *(--s) = '\0';
638 DynStrSet(&((*AttrPtr)->attr_name), name);
639 s = ReadString(value);
640 *(--s) = '\0';
641 DynStrSet(&((*AttrPtr)->attr_value), value);
642
643 free(name);
644 free(value);
645
646 (*AttrPtr)->shown = shown;
647 (*AttrPtr)->nameshown = nameshown;
648 (*AttrPtr)->inherited = inherited;
649
650 if (ReadObj(FP, &TextObj) == FALSE) {
651 free(*AttrPtr);
652 *AttrPtr = NULL;
653 return FreeBufAndReturn(line, FALSE);
654 }
655 TextObj->detail.t->attr = *AttrPtr;
656 (*AttrPtr)->obj = TextObj;
657
658 return FreeBufAndReturn(line, TRUE);
659 }
660
FindTopLevelObjWithType(type_str)661 struct ObjRec *FindTopLevelObjWithType(type_str)
662 char *type_str;
663 {
664 struct ObjRec *obj_ptr=NULL;
665
666 for (obj_ptr=botObj; obj_ptr != NULL; obj_ptr=obj_ptr->prev) {
667 struct AttrRec *attr_ptr=NULL;
668
669 for (attr_ptr=obj_ptr->fattr; attr_ptr != NULL; attr_ptr=attr_ptr->next) {
670 if (strcmp(attr_ptr->attr_name.s, "type=") == 0 &&
671 strcmp(attr_ptr->attr_value.s, type_str) == 0) {
672 return obj_ptr;
673 }
674 }
675 }
676 return NULL;
677 }
678
679 static
ObjMightChangeForShowAndUpdAttrNames(ObjPtr)680 int ObjMightChangeForShowAndUpdAttrNames(ObjPtr)
681 struct ObjRec *ObjPtr;
682 {
683 struct AttrRec *attr_ptr;
684
685 if ((attr_ptr=ObjPtr->fattr) != NULL) {
686 for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next) {
687 if (!(attr_ptr->nameshown)) {
688 return TRUE;
689 }
690 }
691 }
692 return FALSE;
693 }
694
695 static
UpdateFirstTextStringWithAttrNameAndValue(ObjPtr,AttrPtr)696 void UpdateFirstTextStringWithAttrNameAndValue(ObjPtr, AttrPtr)
697 struct ObjRec *ObjPtr;
698 struct AttrRec *AttrPtr;
699 {
700 char *buf=(char*)malloc(AttrPtr->attr_name.sz+AttrPtr->attr_value.sz);
701
702 /* one extra char allocated, no big deal */
703 if (buf == NULL) FailAllocMessage();
704 sprintf(buf, "%s%s", AttrPtr->attr_name.s, AttrPtr->attr_value.s);
705 DynStrSet(&GetTextObjFirstStrSeg(ObjPtr)->dyn_str, buf);
706 free(buf);
707 }
708
709 static
DoShowAndUpdAttrNames(ObjPtr,Force)710 int DoShowAndUpdAttrNames(ObjPtr, Force)
711 struct ObjRec *ObjPtr;
712 int Force;
713 /* Force will force attribute name to be shown whether the attribute */
714 /* is inherited or not. */
715 {
716 struct AttrRec *attr_ptr=ObjPtr->fattr;
717 int picture_changed=FALSE;
718
719 for ( ; attr_ptr != NULL; attr_ptr=attr_ptr->next) {
720 if (!(attr_ptr->nameshown) && (Force || !(attr_ptr->inherited))) {
721 UpdateFirstTextStringWithAttrNameAndValue(attr_ptr->obj, attr_ptr);
722
723 attr_ptr->nameshown = TRUE;
724 UpdTextBBox(attr_ptr->obj);
725 if (attr_ptr->shown) {
726 picture_changed = TRUE;
727
728 if (attr_ptr->obj->detail.t->cached_bitmap != None) {
729 XFreePixmap(mainDisplay,
730 attr_ptr->obj->detail.t->cached_bitmap);
731 }
732 attr_ptr->obj->detail.t->cached_zoom = 0;
733 attr_ptr->obj->detail.t->cached_bitmap = None;
734 }
735 }
736 }
737 AdjObjBBox(ObjPtr);
738
739 return picture_changed;
740 }
741
742 static
ShowAndUpdAttrNames()743 int ShowAndUpdAttrNames()
744 /* returns TRUE if any attribute names are updated */
745 /* This routine concatinate the 'name' and 's' first of every */
746 /* attribute of the selected object and assign that to the */
747 /* first line of the text object the attribute pointer points to. */
748 {
749 struct SelRec *sel_ptr;
750 int picture_changed=FALSE;
751
752 for (sel_ptr=topSel; sel_ptr != NULL; sel_ptr=sel_ptr->next) {
753 if (ObjMightChangeForShowAndUpdAttrNames(sel_ptr->obj)) {
754 PrepareToReplaceAnObj(sel_ptr->obj);
755 picture_changed = DoShowAndUpdAttrNames(sel_ptr->obj, TRUE);
756 RecordReplaceAnObj(sel_ptr->obj);
757 }
758 }
759 return picture_changed;
760 }
761
ShowAllAttrNames()762 void ShowAllAttrNames()
763 {
764 HighLightReverse();
765 StartCompositeCmd();
766 if (ShowAndUpdAttrNames()) {
767 UpdSelBBox();
768 RedrawAnArea(botObj, selLtX-GRID_ABS_SIZE(1),
769 selLtY-GRID_ABS_SIZE(1), selRbX+GRID_ABS_SIZE(1),
770 selRbY+GRID_ABS_SIZE(1));
771 SetFileModified(TRUE);
772 }
773 EndCompositeCmd();
774 HighLightForward();
775 }
776
777 static
ShowAndUpdAttrs()778 int ShowAndUpdAttrs()
779 /* returns TRUE if any attribute was not shown before */
780 {
781 struct SelRec *sel_ptr;
782 struct ObjRec *obj_ptr;
783 struct AttrRec *attr_ptr;
784 int picture_changed=FALSE;
785
786 for (sel_ptr=topSel; sel_ptr != NULL; sel_ptr=sel_ptr->next) {
787 obj_ptr = sel_ptr->obj;
788 attr_ptr = obj_ptr->fattr;
789 if (attr_ptr != NULL) {
790 int obj_changed=FALSE;
791
792 for ( ; attr_ptr != NULL; attr_ptr=attr_ptr->next) {
793 if (!attr_ptr->shown) {
794 obj_changed = TRUE;
795 break;
796 }
797 }
798 if (obj_changed) {
799 PrepareToReplaceAnObj(obj_ptr);
800 for (attr_ptr=obj_ptr->fattr; attr_ptr!=NULL;
801 attr_ptr=attr_ptr->next) {
802 if (!attr_ptr->shown) {
803 attr_ptr->shown = TRUE;
804 }
805 }
806 picture_changed = TRUE;
807 AdjObjBBox(obj_ptr);
808 RecordReplaceAnObj(obj_ptr);
809 }
810 }
811 }
812 return picture_changed;
813 }
814
ShowAllAttrs()815 void ShowAllAttrs()
816 {
817 HighLightReverse();
818 StartCompositeCmd();
819 if (ShowAndUpdAttrs()) {
820 UpdSelBBox();
821 RedrawAnArea(botObj, selLtX-GRID_ABS_SIZE(1),
822 selLtY-GRID_ABS_SIZE(1), selRbX+GRID_ABS_SIZE(1),
823 selRbY+GRID_ABS_SIZE(1));
824 SetFileModified(TRUE);
825 }
826 EndCompositeCmd();
827 HighLightForward();
828 }
829
830 static
HideAndUpdAttrs()831 int HideAndUpdAttrs()
832 /* returns TRUE if any attribute was shown */
833 {
834 struct SelRec *sel_ptr;
835 struct ObjRec *obj_ptr;
836 struct AttrRec *attr_ptr;
837 int picture_changed=FALSE;
838
839 for (sel_ptr=topSel; sel_ptr != NULL; sel_ptr=sel_ptr->next) {
840 obj_ptr = sel_ptr->obj;
841 attr_ptr = obj_ptr->fattr;
842 if (attr_ptr != NULL) {
843 int obj_changed= FALSE;
844
845 for ( ; attr_ptr != NULL; attr_ptr=attr_ptr->next) {
846 if (attr_ptr->shown) {
847 obj_changed = TRUE;
848 break;
849 }
850 }
851 if (obj_changed) {
852 PrepareToReplaceAnObj(obj_ptr);
853 for (attr_ptr=obj_ptr->fattr; attr_ptr!=NULL;
854 attr_ptr=attr_ptr->next) {
855 if (attr_ptr->shown) {
856 attr_ptr->shown = FALSE;
857 }
858 }
859 picture_changed = TRUE;
860 AdjObjBBox(obj_ptr);
861 RecordReplaceAnObj(obj_ptr);
862 }
863 }
864 }
865 return picture_changed;
866 }
867
HideAllAttrs()868 void HideAllAttrs()
869 {
870 int sel_ltx, sel_lty, sel_rbx, sel_rby;
871
872 sel_ltx = selLtX; sel_lty = selLtY; sel_rbx = selRbX; sel_rby = selRbY;
873
874 HighLightReverse();
875 StartCompositeCmd();
876 if (HideAndUpdAttrs()) {
877 UpdSelBBox();
878 RedrawAnArea(botObj, sel_ltx-GRID_ABS_SIZE(1),
879 sel_lty-GRID_ABS_SIZE(1), sel_rbx+GRID_ABS_SIZE(1),
880 sel_rby+GRID_ABS_SIZE(1));
881 SetFileModified(TRUE);
882 }
883 EndCompositeCmd();
884 HighLightForward();
885 }
886
887 static
HideAndUpdAttrNames()888 int HideAndUpdAttrNames()
889 /* returns TRUE if any attribute names are updated */
890 /* For all the first line of the selected object's attributes, */
891 /* this routine change them to the 's' field of the attribute. */
892 {
893 struct SelRec *sel_ptr;
894 struct ObjRec *obj_ptr;
895 struct AttrRec *attr_ptr;
896 int picture_changed=FALSE;
897
898 for (sel_ptr=topSel; sel_ptr != NULL; sel_ptr=sel_ptr->next) {
899 obj_ptr = sel_ptr->obj;
900 attr_ptr = obj_ptr->fattr;
901 if (attr_ptr != NULL) {
902 int obj_change=FALSE;
903
904 for ( ; attr_ptr != NULL; attr_ptr=attr_ptr->next) {
905 if (attr_ptr->nameshown && *(attr_ptr->attr_name.s) != '\0') {
906 obj_change = TRUE;
907 break;
908 }
909 }
910 if (obj_change) {
911 PrepareToReplaceAnObj(obj_ptr);
912 for (attr_ptr=obj_ptr->fattr; attr_ptr!=NULL;
913 attr_ptr=attr_ptr->next) {
914 if (attr_ptr->nameshown && *(attr_ptr->attr_name.s) != '\0') {
915 struct TextRec *text_ptr=attr_ptr->obj->detail.t;
916
917 attr_ptr->nameshown = FALSE;
918 DynStrCpy(
919 &GetTextPtrFirstStrSeg(text_ptr)->dyn_str,
920 &attr_ptr->attr_value);
921 UpdTextBBox(attr_ptr->obj);
922 if (attr_ptr->shown) {
923 picture_changed = TRUE;
924
925 if (attr_ptr->obj->detail.t->cached_bitmap != None) {
926 XFreePixmap(mainDisplay,
927 attr_ptr->obj->detail.t->cached_bitmap);
928 }
929 attr_ptr->obj->detail.t->cached_zoom = 0;
930 attr_ptr->obj->detail.t->cached_bitmap = None;
931 }
932 }
933 }
934 AdjObjBBox(obj_ptr);
935 RecordReplaceAnObj(obj_ptr);
936 }
937 }
938 }
939 return picture_changed;
940 }
941
HideAllAttrNames()942 void HideAllAttrNames()
943 {
944 int sel_ltx, sel_lty, sel_rbx, sel_rby;
945
946 sel_ltx = selLtX; sel_lty = selLtY; sel_rbx = selRbX; sel_rby = selRbY;
947
948 HighLightReverse();
949 StartCompositeCmd();
950 if (HideAndUpdAttrNames()) {
951 UpdSelBBox();
952 RedrawAnArea(botObj, sel_ltx-GRID_ABS_SIZE(1),
953 sel_lty-GRID_ABS_SIZE(1), sel_rbx+GRID_ABS_SIZE(1),
954 sel_rby+GRID_ABS_SIZE(1));
955 SetFileModified(TRUE);
956 }
957 EndCompositeCmd();
958 HighLightForward();
959 }
960
DetachGroupAttrs(ObjPtr,TopSelPtr,BotSelPtr)961 void DetachGroupAttrs(ObjPtr, TopSelPtr, BotSelPtr)
962 struct ObjRec *ObjPtr;
963 struct SelRec ** TopSelPtr, **BotSelPtr;
964 {
965 struct AttrRec *attr_ptr, *next_attr;
966 struct SelRec *new_sel_ptr;
967
968 for (attr_ptr=ObjPtr->fattr; attr_ptr!=NULL; attr_ptr=next_attr) {
969 next_attr = attr_ptr->next;
970 if (!(attr_ptr->nameshown)) {
971 UpdateFirstTextStringWithAttrNameAndValue(attr_ptr->obj, attr_ptr);
972 UpdTextBBox(attr_ptr->obj);
973 }
974
975 attr_ptr->obj->detail.t->attr = NULL;
976
977 attr_ptr->obj->prev = NULL;
978 attr_ptr->obj->next = ObjPtr->detail.r->first;
979
980 if (attr_ptr->obj->next == NULL) {
981 ObjPtr->detail.r->last = attr_ptr->obj;
982 } else {
983 attr_ptr->obj->next->prev = attr_ptr->obj;
984 }
985 ObjPtr->detail.r->first = attr_ptr->obj;
986
987 new_sel_ptr = (struct SelRec *)malloc(sizeof(struct SelRec));
988 if (new_sel_ptr == NULL) FailAllocMessage();
989 new_sel_ptr->obj = attr_ptr->obj;
990
991 new_sel_ptr->prev = NULL;
992 new_sel_ptr->next = *TopSelPtr;
993
994 if (new_sel_ptr->next == NULL) {
995 *BotSelPtr = new_sel_ptr;
996 } else {
997 (*TopSelPtr)->prev = new_sel_ptr;
998 }
999 *TopSelPtr = new_sel_ptr;
1000
1001 FreeAttr(attr_ptr);
1002 }
1003 }
1004
DetachAllObjAttrs(obj_ptr,TopSelPtr,BotSelPtr)1005 void DetachAllObjAttrs(obj_ptr, TopSelPtr, BotSelPtr)
1006 struct ObjRec *obj_ptr;
1007 struct SelRec **TopSelPtr, **BotSelPtr;
1008 {
1009 struct AttrRec *attr_ptr, *prev_attr;
1010
1011 DoShowAndUpdAttrNames(obj_ptr, FALSE);
1012
1013 (*TopSelPtr) = (*BotSelPtr) = (struct SelRec *)malloc(sizeof(struct SelRec));
1014 if (*TopSelPtr == NULL) FailAllocMessage();
1015 (*TopSelPtr)->next = (*TopSelPtr)->prev = NULL;
1016 (*TopSelPtr)->obj = obj_ptr;
1017
1018 topAttr = botAttr = NULL;
1019 for (attr_ptr=obj_ptr->lattr; attr_ptr!=NULL; attr_ptr=prev_attr) {
1020 struct SelRec *tmp_sel_ptr;
1021
1022 prev_attr = attr_ptr->prev;
1023
1024 tmp_sel_ptr = (struct SelRec *)malloc(sizeof(struct SelRec));
1025 if (tmp_sel_ptr == NULL) FailAllocMessage();
1026
1027 tmp_sel_ptr->prev = NULL;
1028 tmp_sel_ptr->next = (*TopSelPtr);
1029 (*TopSelPtr)->prev = tmp_sel_ptr;
1030 (*TopSelPtr) = tmp_sel_ptr;
1031 tmp_sel_ptr->obj = attr_ptr->obj;
1032
1033 attr_ptr->obj->detail.t->attr = NULL;
1034 AddObj(obj_ptr->prev, obj_ptr, attr_ptr->obj);
1035 FreeAttr(attr_ptr);
1036 }
1037 obj_ptr->fattr = obj_ptr->lattr = NULL;
1038 }
1039
DetachAttrs()1040 void DetachAttrs()
1041 {
1042 struct SelRec *sel_ptr, *new_sel_ptr;
1043 struct ObjRec *obj_ptr;
1044 struct AttrRec *attr_ptr, *next_attr;
1045 int picture_changed=FALSE, name_changed=FALSE;
1046
1047 HighLightReverse();
1048 StartCompositeCmd();
1049
1050 for (sel_ptr=topSel; sel_ptr != NULL; sel_ptr=sel_ptr->next) {
1051 obj_ptr = sel_ptr->obj;
1052 attr_ptr = obj_ptr->fattr;
1053 if (attr_ptr != NULL) {
1054 int obj_change=FALSE;
1055
1056 for ( ; attr_ptr != NULL; attr_ptr=attr_ptr->next) {
1057 if (!attr_ptr->inherited) {
1058 obj_change = TRUE;
1059 break;
1060 }
1061 }
1062 if (obj_change) {
1063 struct SelRec *tmp_top_sel, *tmp_bot_sel;
1064 struct SelRec *tmp_sel_ptr, *next_sel;
1065 int count;
1066
1067 PrepareToReplaceAnObj(obj_ptr);
1068 if (DoShowAndUpdAttrNames(obj_ptr, FALSE)) name_changed = TRUE;
1069
1070 tmp_top_sel = tmp_bot_sel = (struct SelRec *)malloc(
1071 sizeof(struct SelRec));
1072 if (tmp_top_sel == NULL) FailAllocMessage();
1073 tmp_top_sel->next = tmp_top_sel->prev = NULL;
1074 tmp_top_sel->obj = obj_ptr;
1075 count = 1;
1076
1077 topAttr = botAttr = NULL;
1078 for (attr_ptr=obj_ptr->fattr; attr_ptr!=NULL; attr_ptr=next_attr) {
1079 next_attr = attr_ptr->next;
1080 if (attr_ptr->inherited &&
1081 (obj_ptr->type == OBJ_ICON || obj_ptr->type == OBJ_PIN)) {
1082 LinkInAttr((struct AttrRec *)NULL, topAttr, attr_ptr);
1083 continue;
1084 }
1085 picture_changed = TRUE;
1086
1087 tmp_sel_ptr = (struct SelRec *)malloc(sizeof(struct SelRec));
1088 if (tmp_sel_ptr == NULL) FailAllocMessage();
1089 tmp_sel_ptr->next = tmp_bot_sel;
1090 tmp_sel_ptr->obj = attr_ptr->obj;
1091 if (tmp_top_sel == tmp_bot_sel) {
1092 tmp_sel_ptr->prev = NULL;
1093 tmp_top_sel->prev = tmp_sel_ptr;
1094 tmp_top_sel = tmp_sel_ptr;
1095 } else {
1096 tmp_sel_ptr->prev = tmp_bot_sel->prev;
1097 tmp_bot_sel->prev->next = tmp_sel_ptr;
1098 tmp_bot_sel->prev = tmp_sel_ptr;
1099 }
1100 count++;
1101
1102 attr_ptr->obj->detail.t->attr = NULL;
1103 AddObj(obj_ptr->prev, obj_ptr, attr_ptr->obj);
1104 new_sel_ptr = (struct SelRec *)malloc(sizeof(struct SelRec));
1105 if (new_sel_ptr == NULL) FailAllocMessage();
1106 new_sel_ptr->obj = obj_ptr->prev;
1107 AddSel(sel_ptr->prev, sel_ptr, new_sel_ptr);
1108 FreeAttr(attr_ptr);
1109 }
1110 obj_ptr->fattr = topAttr;
1111 obj_ptr->lattr = botAttr;
1112 AdjObjBBox(obj_ptr);
1113 RecordCmd(CMD_ONE_TO_MANY, NULL, tmp_top_sel, tmp_bot_sel, count);
1114
1115 for (tmp_sel_ptr=tmp_top_sel; tmp_sel_ptr!=NULL;
1116 tmp_sel_ptr=next_sel) {
1117 next_sel = tmp_sel_ptr->next;
1118 free(tmp_sel_ptr);
1119 }
1120 }
1121 }
1122 }
1123 EndCompositeCmd();
1124 UpdSelBBox();
1125 if (picture_changed || name_changed) {
1126 RedrawAnArea(botObj, selLtX-GRID_ABS_SIZE(1),
1127 selLtY-GRID_ABS_SIZE(1), selRbX+GRID_ABS_SIZE(1),
1128 selRbY+GRID_ABS_SIZE(1));
1129 SetFileModified(TRUE);
1130 }
1131 HighLightForward();
1132 }
1133
UpdAttr(AttrPtr)1134 void UpdAttr(AttrPtr)
1135 struct AttrRec *AttrPtr;
1136 /* Update the text object's string value associated with AttrPtr */
1137 {
1138 if (AttrPtr->nameshown) {
1139 UpdateFirstTextStringWithAttrNameAndValue(AttrPtr->obj, AttrPtr);
1140 } else {
1141 struct TextRec *text_ptr=AttrPtr->obj->detail.t;
1142
1143 DynStrCpy(&GetTextPtrFirstStrSeg(text_ptr)->dyn_str,
1144 &AttrPtr->attr_value);
1145 }
1146 UpdTextBBox(AttrPtr->obj);
1147 }
1148
1149 static
MoveOneAttr(ObjPtr,AttrPtr)1150 int MoveOneAttr(ObjPtr, AttrPtr)
1151 struct ObjRec *ObjPtr;
1152 struct AttrRec *AttrPtr;
1153 {
1154 struct ObjRec *text_obj_ptr;
1155 int x, y, grid_x, grid_y, dx, dy, placing=TRUE;
1156 int ltx, lty, rbx, rby;
1157 int orig_x, orig_y, grid_orig_x, grid_orig_y;
1158 char buf[80], x_buf[80], y_buf[80];
1159 XEvent input, ev;
1160
1161 text_obj_ptr = AttrPtr->obj;
1162 Msg(TgLoadString(STID_MOVE_ONE_ATTR_MOUSE_MSG));
1163 SetMouseStatus(TgLoadString(STID_SHOW_MOVE_ATTR),
1164 TgLoadString(STID_TOGGLE_NAME_SHOWN), TgLoadString(STID_HIDE_ATTR));
1165
1166 orig_x = OFFSET_X(text_obj_ptr->x);
1167 orig_y = OFFSET_Y(text_obj_ptr->y);
1168 GridXY(orig_x, orig_y, &grid_orig_x, &grid_orig_y);
1169 ltx = OFFSET_X(text_obj_ptr->bbox.ltx);
1170 lty = OFFSET_Y(text_obj_ptr->bbox.lty);
1171 rbx = OFFSET_X(text_obj_ptr->bbox.rbx)+1;
1172 rby = OFFSET_Y(text_obj_ptr->bbox.rby)+1;
1173
1174 if (!debugNoPointerGrab) {
1175 XGrabPointer(mainDisplay, drawWindow, FALSE,
1176 PointerMotionMask | ButtonPressMask,
1177 GrabModeAsync, GrabModeAsync, None, handCursor, CurrentTime);
1178 }
1179 XWarpPointer(mainDisplay, None, drawWindow, 0, 0, 0, 0, orig_x, orig_y);
1180
1181 dx = dy = 0;
1182 grid_x = grid_orig_x; grid_y = grid_orig_y;
1183
1184 SelBox(drawWindow, revDefaultGC, ltx+dx, lty+dy, rbx+dx, rby+dy);
1185 PixelToMeasurementUnit(x_buf, 0);
1186 PixelToMeasurementUnit(y_buf, 0);
1187 sprintf(buf, "dx=%s\ndy=%s", x_buf, y_buf);
1188 StartShowMeasureCursor(ltx, lty-(defaultFontHeight<<1), buf, TRUE);
1189 while (placing) {
1190 XNextEvent(mainDisplay, &input);
1191
1192 if (input.type == Expose || input.type == VisibilityNotify) {
1193 PixelToMeasurementUnit(x_buf, ABS_SIZE(dx));
1194 PixelToMeasurementUnit(y_buf, ABS_SIZE(dy));
1195 sprintf(buf, "dx=%s\ndy=%s", x_buf, y_buf);
1196 ShowMeasureCursor(ltx+dx, lty-(defaultFontHeight<<1)+dy, buf, TRUE);
1197 SelBox(drawWindow, revDefaultGC, ltx+dx, lty+dy, rbx+dx, rby+dy);
1198 ExposeEventHandler(&input, TRUE);
1199 SelBox(drawWindow, revDefaultGC, ltx+dx, lty+dy, rbx+dx, rby+dy);
1200 PixelToMeasurementUnit(x_buf, ABS_SIZE(dx));
1201 PixelToMeasurementUnit(y_buf, ABS_SIZE(dy));
1202 sprintf(buf, "dx=%s\ndy=%s", x_buf, y_buf);
1203 ShowMeasureCursor(ltx+dx, lty-(defaultFontHeight<<1)+dy, buf, TRUE);
1204 } else if (input.type == MotionNotify) {
1205 x = input.xmotion.x;
1206 y = input.xmotion.y;
1207 GridXY(x, y, &grid_x, &grid_y);
1208
1209 if (grid_x != grid_orig_x+dx || grid_y != grid_orig_y+dy) {
1210 PixelToMeasurementUnit(x_buf, ABS_SIZE(dx));
1211 PixelToMeasurementUnit(y_buf, ABS_SIZE(dy));
1212 sprintf(buf, "dx=%s\ndy=%s", x_buf, y_buf);
1213 ShowMeasureCursor(ltx+dx, lty-(defaultFontHeight<<1)+dy, buf, TRUE);
1214 SelBox(drawWindow, revDefaultGC, ltx+dx, lty+dy, rbx+dx, rby+dy);
1215 dx = grid_x - grid_orig_x;
1216 dy = grid_y - grid_orig_y;
1217 SelBox(drawWindow, revDefaultGC, ltx+dx, lty+dy, rbx+dx, rby+dy);
1218 PixelToMeasurementUnit(x_buf, ABS_SIZE(dx));
1219 PixelToMeasurementUnit(y_buf, ABS_SIZE(dy));
1220 sprintf(buf, "dx=%s\ndy=%s", x_buf, y_buf);
1221 ShowMeasureCursor(ltx+dx, lty-(defaultFontHeight<<1)+dy, buf, TRUE);
1222 MarkRulers(grid_x, grid_y);
1223 }
1224 while (XCheckMaskEvent(mainDisplay, PointerMotionMask, &ev)) ;
1225 } else if (input.type == ButtonPress) {
1226 XUngrabPointer(mainDisplay, CurrentTime);
1227 XSync(mainDisplay, False);
1228 placing = FALSE;
1229 SelBox(drawWindow, revDefaultGC, ltx+dx, lty+dy, rbx+dx, rby+dy);
1230 PixelToMeasurementUnit(x_buf, ABS_SIZE(dx));
1231 PixelToMeasurementUnit(y_buf, ABS_SIZE(dy));
1232 sprintf(buf, "dx=%s\ndy=%s", x_buf, y_buf);
1233 EndShowMeasureCursor(ltx+dx, lty-(defaultFontHeight<<1)+dy, buf, TRUE);
1234 Msg("");
1235 SetMouseStatus("", "", "");
1236 switch (input.xbutton.button) {
1237 case Button1:
1238 if (dx != 0 || dy != 0) {
1239 if (ObjPtr->locked) {
1240 MsgBox(TgLoadString(STID_CANNOT_MOVE_ATTR_IF_LOCKED),
1241 TOOL_NAME, INFO_MB);
1242 return FALSE;
1243 }
1244 HighLightReverse();
1245 PrepareToReplaceAnObj(ObjPtr);
1246 AttrPtr->shown = TRUE;
1247 MoveObj(text_obj_ptr, ABS_SIZE(dx), ABS_SIZE(dy));
1248 AdjObjBBox(ObjPtr);
1249 RecordReplaceAnObj(ObjPtr);
1250 return TRUE;
1251 } else if (!(AttrPtr->shown)) {
1252 HighLightReverse();
1253 PrepareToReplaceAnObj(ObjPtr);
1254 AttrPtr->shown = TRUE;
1255 AdjObjBBox(ObjPtr);
1256 RecordReplaceAnObj(ObjPtr);
1257 return TRUE;
1258 }
1259 return FALSE;
1260 case Button2:
1261 if (*(AttrPtr->attr_name.s) != '\0') {
1262 PrepareToReplaceAnObj(ObjPtr);
1263 }
1264 if (!(AttrPtr->nameshown && *(AttrPtr->attr_name.s)=='\0')) {
1265 AttrPtr->nameshown = !AttrPtr->nameshown;
1266 }
1267 UpdAttr(AttrPtr);
1268 if (AttrPtr->shown) {
1269 HighLightReverse();
1270 AdjObjCache(ObjPtr);
1271 AdjObjBBox(ObjPtr);
1272 if (*(AttrPtr->attr_name.s) != '\0') {
1273 RecordReplaceAnObj(ObjPtr);
1274 }
1275 return TRUE;
1276 }
1277 if (*(AttrPtr->attr_name.s) != '\0') RecordReplaceAnObj(ObjPtr);
1278 return FALSE;
1279 case Button3:
1280 if (AttrPtr->shown) {
1281 HighLightReverse();
1282 PrepareToReplaceAnObj(ObjPtr);
1283 AttrPtr->shown = FALSE;
1284 AdjObjBBox(ObjPtr);
1285 RecordReplaceAnObj(ObjPtr);
1286 return TRUE;
1287 }
1288 return FALSE;
1289 default: break;
1290 }
1291 }
1292 }
1293 return FALSE;
1294 }
1295
1296 static
ChangeAttrJust(ObjPtr,AttrPtr)1297 int ChangeAttrJust(ObjPtr, AttrPtr)
1298 struct ObjRec *ObjPtr;
1299 struct AttrRec *AttrPtr;
1300 {
1301 struct ObjRec *text_obj_ptr;
1302 int x, y, grid_x, grid_y, dx, dy, placing=TRUE;
1303 int ltx, lty, rbx, rby;
1304 int orig_x, orig_y, grid_orig_x, grid_orig_y;
1305 int old_just, new_just=0;
1306 XEvent input, ev;
1307
1308 text_obj_ptr = AttrPtr->obj;
1309 Msg(TgLoadString(STID_CHANGE_ATTR_JUST_MOUSE_MSG));
1310 SetMouseStatus(TgLoadString(STID_LEFT_JUSTIFY),
1311 TgLoadString(STID_CENTER_JUSTIFY), TgLoadString(STID_RIGHT_JUSTIFY));
1312
1313 orig_x = OFFSET_X(text_obj_ptr->x);
1314 orig_y = OFFSET_Y(text_obj_ptr->y);
1315 GridXY(orig_x, orig_y, &grid_orig_x, &grid_orig_y);
1316 ltx = OFFSET_X(text_obj_ptr->bbox.ltx);
1317 lty = OFFSET_Y(text_obj_ptr->bbox.lty);
1318 rbx = OFFSET_X(text_obj_ptr->bbox.rbx)+1;
1319 rby = OFFSET_Y(text_obj_ptr->bbox.rby)+1;
1320
1321 if (!debugNoPointerGrab) {
1322 XGrabPointer(mainDisplay, drawWindow, FALSE,
1323 PointerMotionMask | ButtonPressMask,
1324 GrabModeAsync, GrabModeAsync, None, handCursor, CurrentTime);
1325 }
1326 XWarpPointer(mainDisplay, None, drawWindow, 0, 0, 0, 0, orig_x, orig_y);
1327
1328 dx = dy = 0;
1329 grid_x = grid_orig_x; grid_y = grid_orig_y;
1330
1331 SelBox(drawWindow, revDefaultGC, ltx+dx, lty+dy, rbx+dx, rby+dy);
1332 StartShowMeasureCursor(ltx, lty, NULL, TRUE);
1333 while (placing) {
1334 XNextEvent(mainDisplay, &input);
1335
1336 if (input.type == Expose || input.type == VisibilityNotify) {
1337 SelBox(drawWindow, revDefaultGC, ltx+dx, lty+dy, rbx+dx, rby+dy);
1338 ExposeEventHandler(&input, TRUE);
1339 SelBox(drawWindow, revDefaultGC, ltx+dx, lty+dy, rbx+dx, rby+dy);
1340 } else if (input.type == MotionNotify) {
1341 x = input.xmotion.x;
1342 y = input.xmotion.y;
1343 GridXY(x, y, &grid_x, &grid_y);
1344
1345 if (grid_x != grid_orig_x+dx || grid_y != grid_orig_y+dy) {
1346 SelBox(drawWindow, revDefaultGC, ltx+dx, lty+dy, rbx+dx, rby+dy);
1347 dx = grid_x - grid_orig_x;
1348 dy = grid_y - grid_orig_y;
1349 SelBox(drawWindow, revDefaultGC, ltx+dx, lty+dy, rbx+dx, rby+dy);
1350 MarkRulers(grid_x, grid_y);
1351 }
1352 while (XCheckMaskEvent(mainDisplay, PointerMotionMask, &ev)) ;
1353 } else if (input.type == ButtonPress) {
1354 XUngrabPointer(mainDisplay, CurrentTime);
1355 XSync(mainDisplay, False);
1356 placing = FALSE;
1357 SelBox(drawWindow, revDefaultGC, ltx+dx, lty+dy, rbx+dx, rby+dy);
1358 EndShowMeasureCursor(ltx+dx, lty+dy, NULL, TRUE);
1359 Msg("");
1360 SetMouseStatus("", "", "");
1361 old_just = text_obj_ptr->detail.t->minilines.just;
1362 switch (input.xbutton.button) {
1363 case Button1: new_just = JUST_L; break;
1364 case Button2: new_just = JUST_C; break;
1365 case Button3: new_just = JUST_R; break;
1366 }
1367 if (old_just != new_just) {
1368 HighLightReverse();
1369 PrepareToReplaceAnObj(ObjPtr);
1370 text_obj_ptr->detail.t->minilines.just = new_just;
1371 /* UpdAttr(AttrPtr); */ /* ALERT - not sure if this is needed. */
1372 AdjObjCache(ObjPtr);
1373 UpdTextBBox(text_obj_ptr);
1374 AdjObjBBox(ObjPtr);
1375 RecordReplaceAnObj(ObjPtr);
1376 return TRUE;
1377 }
1378 }
1379 }
1380 return FALSE;
1381 }
1382
CreateAttrMenu(parent_menu,x,y,num_items,menu_strings,status_strings,pixels)1383 TgMenu *CreateAttrMenu(parent_menu, x, y, num_items, menu_strings,
1384 status_strings, pixels)
1385 TgMenu *parent_menu;
1386 int x, y, num_items, *pixels;
1387 char **menu_strings, **status_strings;
1388 {
1389 int i=0;
1390 TgMenu *menu=NULL;
1391 TgMenuInfo stMenuInfo;
1392 TgMenuItemInfo *item_info=NULL;
1393
1394 memset(&stMenuInfo, 0, sizeof(TgMenuInfo));
1395 stMenuInfo.type = TGMUTYPE_TEXT;
1396 stMenuInfo.items = (TgMenuItemInfo*)malloc(
1397 (num_items+1)*sizeof(TgMenuItemInfo));
1398 if (stMenuInfo.items == NULL) FailAllocMessage();
1399 memset(stMenuInfo.items, 0, (num_items+1)*sizeof(TgMenuItemInfo));
1400 for (item_info=stMenuInfo.items, i=0; i < num_items; item_info++, i++) {
1401 if (menu_strings[i] == TGMUITEM_SEPARATOR) {
1402 item_info->menu_str = TGMUITEM_SEPARATOR;
1403 } else {
1404 item_info->menu_str = UtilStrDup(menu_strings[i]);
1405 if (item_info->menu_str == NULL) FailAllocMessage();
1406 }
1407 if (status_strings != NULL && status_strings[i] != NULL) {
1408 item_info->status_str = UtilStrDup(status_strings[i]);
1409 if (item_info->status_str == NULL) FailAllocMessage();
1410 }
1411 item_info->submenu_info = NULL;
1412 item_info->cmdid = INVALID;
1413 }
1414 stMenuInfo.items[num_items].cmdid = INVALID;
1415
1416 if (num_items >= menuRowsBeforeScroll) {
1417 stMenuInfo.type |= TGMUTYPE_CANSCROLL;
1418 }
1419 /*
1420 * Since these are real attribute names and values, no translation is needed.
1421 */
1422 menu = TgCreateMenuFromMenuInfo(parent_menu, x, y, &stMenuInfo, TRUE);
1423 for (item_info=stMenuInfo.items, i=0; i < num_items; item_info++, i++) {
1424 UtilFree(item_info->status_str);
1425 }
1426 memset(stMenuInfo.items, 0, (num_items+1)*sizeof(TgMenuItemInfo));
1427 free(stMenuInfo.items);
1428 stMenuInfo.items = NULL;
1429 if (menu != NULL) {
1430 TgMenuItem stMenuItem;
1431
1432 menu->track_menubar = FALSE;
1433 memset(&stMenuItem, 0, sizeof(TgMenuItem));
1434 for (i=0; i < num_items; i++) {
1435 TgMenuItem *menu_item=(&menu->menuitems[i]);
1436
1437 if (pixels != NULL) {
1438 stMenuItem.multicolor_pixel = pixels[i];
1439 if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_MULTICOLOR,
1440 &stMenuItem)) {
1441 return TgDestroyMenu(menu, TRUE);
1442 }
1443 }
1444 menu_item->menu_str_allocated = TRUE;
1445 }
1446 }
1447 return menu;
1448 }
1449
FreeEditAttrInfo(pEditAttrInfo)1450 void FreeEditAttrInfo(pEditAttrInfo)
1451 EditAttrInfo *pEditAttrInfo;
1452 /* pEditAttrInfo will also be freed before returning */
1453 {
1454 int i=0, num_attrs=0, *fore_colors=NULL, *attr_indices=NULL;
1455 char **attr_names=NULL, **attr_values=NULL, **attr_strings=NULL;
1456 char **status_strings=NULL;
1457
1458 if (pEditAttrInfo == NULL) return;
1459
1460 num_attrs = pEditAttrInfo->num_attrs;
1461 fore_colors = pEditAttrInfo->fore_colors;
1462 attr_indices = pEditAttrInfo->attr_indices;
1463 attr_names = pEditAttrInfo->attr_names;
1464 attr_values = pEditAttrInfo->attr_values;
1465 attr_strings = pEditAttrInfo->attr_strings;
1466 status_strings = pEditAttrInfo->status_strings;
1467
1468 if (pEditAttrInfo->fore_colors != NULL) free(pEditAttrInfo->fore_colors);
1469 if (pEditAttrInfo->attr_indices != NULL) free(pEditAttrInfo->attr_indices);
1470
1471 for (i=0; i < num_attrs; i++) {
1472 if (attr_names != NULL) UtilFree(attr_names[i]);
1473 if (attr_values != NULL) UtilFree(attr_values[i]);
1474 if (attr_strings != NULL) {
1475 if (attr_strings[i] != TGMUITEM_SEPARATOR) UtilFree(attr_strings[i]);
1476 }
1477 if (status_strings != NULL) UtilFree(status_strings[i]);
1478 }
1479 if (attr_names != NULL) free(attr_names);
1480 if (attr_values != NULL) free(attr_values);
1481 if (attr_strings != NULL) free(attr_strings);
1482 if (status_strings != NULL) free(status_strings);
1483
1484 free(pEditAttrInfo);
1485 }
1486
HasEditAttrsInContextMenu(obj_ptr,pp_name_attr)1487 int HasEditAttrsInContextMenu(obj_ptr, pp_name_attr)
1488 struct ObjRec *obj_ptr;
1489 struct AttrRec **pp_name_attr;
1490 {
1491 struct AttrRec *attr_ptr=NULL;
1492
1493 if (pp_name_attr != NULL) *pp_name_attr = NULL;
1494 for (attr_ptr=obj_ptr->lattr; attr_ptr!=NULL; attr_ptr=attr_ptr->prev) {
1495 if (strcmp(attr_ptr->attr_name.s, "edit_attrs_in_context_menu=") == 0) {
1496 if (pp_name_attr != NULL) *pp_name_attr = attr_ptr;
1497 return TRUE;
1498 }
1499 }
1500 return FALSE;
1501 }
1502
FreeRestrictedAttrNames(ppsz_restricted,num_restricted)1503 void FreeRestrictedAttrNames(ppsz_restricted, num_restricted)
1504 char **ppsz_restricted;
1505 int num_restricted;
1506 {
1507 if (ppsz_restricted != NULL) {
1508 int i=0;
1509
1510 for (i=0; i < num_restricted; i++) {
1511 if (ppsz_restricted[i] != NULL) {
1512 UtilFree(ppsz_restricted[i]);
1513 }
1514 }
1515 free(ppsz_restricted);
1516 }
1517 }
1518
GetRestrictedAttrNames(restricted_attr_obj,pppsz_restricted,pn_num_restricted)1519 void GetRestrictedAttrNames(restricted_attr_obj, pppsz_restricted,
1520 pn_num_restricted)
1521 struct ObjRec *restricted_attr_obj;
1522 char ***pppsz_restricted;
1523 int *pn_num_restricted;
1524 {
1525 MiniLinesInfo *minilines=(&restricted_attr_obj->detail.t->minilines);
1526 MiniLineInfo *miniline=minilines->first->next;
1527 char **ppsz_restricted=NULL;
1528 int num_restricted=0, index=0;
1529
1530 if (pppsz_restricted != NULL) (*pppsz_restricted) = NULL;
1531 if (pn_num_restricted != NULL) (*pn_num_restricted) = 0;
1532 if (miniline == NULL) return;
1533
1534 for ( ; miniline != NULL; miniline=miniline->next, num_restricted++) {
1535 }
1536 ppsz_restricted = (char**)malloc(num_restricted*sizeof(char*));
1537 if (ppsz_restricted == NULL) FailAllocMessage();
1538 memset(ppsz_restricted, 0, num_restricted*sizeof(char*));
1539
1540 miniline = minilines->first->next;
1541 for ( ; miniline != NULL; miniline=miniline->next) {
1542 int need_to_free_tmp_buf=FALSE;
1543 char *tmp_buf=ConvertMiniLineToString(miniline, &need_to_free_tmp_buf);
1544
1545 if (tmp_buf != NULL) {
1546 UtilTrimBlanks(tmp_buf);
1547 if (*tmp_buf == '\0') {
1548 num_restricted--;
1549 } else {
1550 int len=strlen(tmp_buf)+2; /* extra char for '=' */
1551
1552 ppsz_restricted[index] = (char*)malloc((len+1)*sizeof(char));
1553 if (ppsz_restricted[index] == NULL) FailAllocMessage();
1554 sprintf(ppsz_restricted[index], "%s=", tmp_buf);
1555 index++;
1556 }
1557 if (need_to_free_tmp_buf) UtilFree(tmp_buf);
1558 } else {
1559 num_restricted--;
1560 }
1561 if (num_restricted <= 0) break;
1562 }
1563 if (num_restricted <= 0) {
1564 free(pppsz_restricted);
1565 } else {
1566 if (pppsz_restricted != NULL) (*pppsz_restricted) = ppsz_restricted;
1567 if (pn_num_restricted != NULL) (*pn_num_restricted) = num_restricted;
1568 }
1569 }
1570
GetAttrGroupAttrNames(restricted_attr_obj,group_index,pppsz_restricted,pn_num_restricted)1571 void GetAttrGroupAttrNames(restricted_attr_obj, group_index, pppsz_restricted,
1572 pn_num_restricted)
1573 struct ObjRec *restricted_attr_obj;
1574 int group_index, *pn_num_restricted;
1575 char ***pppsz_restricted;
1576 {
1577 char **ppsz_restricted=NULL, **attr_name_array=NULL;
1578 int num_attrs_in_attr_group=0, i=0;
1579
1580 num_attrs_in_attr_group = gAttrGroupInfo[group_index]->num_attrs;
1581 attr_name_array = gAttrGroupInfo[group_index]->attr_name;
1582
1583 if (pppsz_restricted != NULL) (*pppsz_restricted) = NULL;
1584 if (pn_num_restricted != NULL) (*pn_num_restricted) = 0;
1585
1586 ppsz_restricted = (char**)malloc(num_attrs_in_attr_group*sizeof(char*));
1587 if (ppsz_restricted == NULL) FailAllocMessage();
1588 memset(ppsz_restricted, 0, num_attrs_in_attr_group*sizeof(char*));
1589
1590 for (i=0; i < num_attrs_in_attr_group; i++) {
1591 int len=strlen(attr_name_array[i])+2; /* extra char for '=' */
1592
1593 ppsz_restricted[i] = (char*)malloc((len+1)*sizeof(char));
1594 if (ppsz_restricted[i] == NULL) FailAllocMessage();
1595 sprintf(ppsz_restricted[i], "%s=", attr_name_array[i]);
1596 }
1597 if (pppsz_restricted != NULL) (*pppsz_restricted) = ppsz_restricted;
1598 if (pn_num_restricted != NULL) {
1599 (*pn_num_restricted) = num_attrs_in_attr_group;
1600 }
1601 }
1602
IsRestrictedAttr(attr_name,ppsz_restricted,num_restricted)1603 int IsRestrictedAttr(attr_name, ppsz_restricted, num_restricted)
1604 char *attr_name, **ppsz_restricted;
1605 int num_restricted;
1606 {
1607 int i=0;
1608
1609 for (i=0; i < num_restricted; i++) {
1610 if (strcmp(attr_name, ppsz_restricted[i]) == 0) {
1611 return TRUE;
1612 }
1613 }
1614 return FALSE;
1615 }
1616
CreateEditAttrInfo(obj_ptr)1617 EditAttrInfo *CreateEditAttrInfo(obj_ptr)
1618 struct ObjRec *obj_ptr;
1619 {
1620 int i=0, num_attrs=0, *fore_colors=NULL, *pixel_ptr=NULL, restricted=FALSE;
1621 int num_restricted=0, num_created=0, *attr_indices=NULL;
1622 struct AttrRec *attr_ptr=NULL, *attr_ptr1=NULL, *restricted_attr=NULL;
1623 EditAttrInfo *pEditAttrInfo=NULL;
1624 char **attr_names=NULL, **attr_values=NULL, **attr_strings=NULL;
1625 char **status_strings=NULL, **ppsz_restricted=NULL;
1626
1627 pEditAttrInfo = (EditAttrInfo*)malloc(sizeof(EditAttrInfo));
1628 if (pEditAttrInfo == NULL) FailAllocMessage();
1629 memset(pEditAttrInfo, 0, sizeof(EditAttrInfo));
1630
1631 attr_ptr1 = attr_ptr = obj_ptr->fattr;
1632 for ( ; attr_ptr1 != NULL; attr_ptr1=attr_ptr1->next, num_attrs++) {
1633 }
1634 if (num_attrs == 0) {
1635 free(pEditAttrInfo);
1636 return NULL;
1637 }
1638 restricted = HasEditAttrsInContextMenu(obj_ptr, &restricted_attr);
1639 if (restricted) {
1640 GetRestrictedAttrNames(restricted_attr->obj, &ppsz_restricted,
1641 &num_restricted);
1642 if (ppsz_restricted == NULL || num_restricted <= 0) {
1643 free(pEditAttrInfo);
1644 return NULL;
1645 }
1646 }
1647 attr_names = (char**)malloc(num_attrs*sizeof(char*));
1648 attr_values = (char**)malloc(num_attrs*sizeof(char*));
1649 attr_strings = (char**)malloc(num_attrs*sizeof(char*));
1650 status_strings = (char**)malloc(num_attrs*sizeof(char*));
1651 fore_colors = pixel_ptr = (int*)malloc(num_attrs*sizeof(int));
1652 attr_indices = (int*)malloc(num_attrs*sizeof(int));
1653 if (attr_names == NULL || attr_values == NULL || attr_strings == NULL ||
1654 status_strings == NULL || fore_colors == NULL ||
1655 attr_indices == NULL) {
1656 FailAllocMessage();
1657 }
1658 attr_ptr1 = attr_ptr;
1659 for (i=0; i < num_attrs; i++, attr_ptr1=attr_ptr1->next) {
1660 int need_to_free_tmp_buf=FALSE;
1661 char *tmp_buf=NULL;
1662 MiniLinesInfo *minilines=(&attr_ptr1->obj->detail.t->minilines);
1663
1664 tmp_buf = ConvertAttrNameFirstMiniLineToString(attr_ptr1,
1665 &need_to_free_tmp_buf);
1666
1667 if (restricted) {
1668 if (!IsRestrictedAttr(attr_ptr1->attr_name.s, ppsz_restricted,
1669 num_restricted)) {
1670 if (need_to_free_tmp_buf) UtilFree(tmp_buf);
1671 continue;
1672 }
1673 }
1674 attr_names[num_created] = UtilStrDup(attr_ptr1->attr_name.s);
1675 attr_values[num_created] = UtilStrDup(attr_ptr1->attr_value.s);
1676 attr_strings[num_created] = UtilStrDup(tmp_buf);
1677 sprintf(gszMsgBox, TgLoadCachedString(CSTID_EDIT_ATTR_IN_EDITOR),
1678 tmp_buf);
1679 status_strings[num_created] = UtilStrDup(gszMsgBox);
1680 if (attr_names[num_created] == NULL || attr_values[num_created] == NULL ||
1681 attr_strings[num_created] == NULL ||
1682 status_strings[num_created] == NULL) {
1683 FailAllocMessage();
1684 }
1685 pixel_ptr[num_created] =
1686 colorPixels[minilines->first->first_block->seg->color];
1687 attr_indices[num_created] = i;
1688
1689 if (need_to_free_tmp_buf) UtilFree(tmp_buf);
1690 num_created++;
1691 }
1692 pEditAttrInfo->num_attrs = num_created;
1693 pEditAttrInfo->fore_colors = fore_colors;
1694 pEditAttrInfo->attr_indices = attr_indices;
1695 pEditAttrInfo->attr_names = attr_names;
1696 pEditAttrInfo->attr_values = attr_values;
1697 pEditAttrInfo->attr_strings = attr_strings;
1698 pEditAttrInfo->status_strings = status_strings;
1699
1700 FreeRestrictedAttrNames(ppsz_restricted, num_restricted);
1701
1702 return pEditAttrInfo;
1703 }
1704
CreateEditAttrGroupInfo(obj_ptr)1705 EditAttrInfo *CreateEditAttrGroupInfo(obj_ptr)
1706 struct ObjRec *obj_ptr;
1707 {
1708 int i=0, num_attrs=maxAttrGroups, *fore_colors=NULL;
1709 EditAttrInfo *pEditAttrInfo=NULL;
1710 char **attr_strings=NULL, **status_strings=NULL;
1711
1712 if (num_attrs == 0) {
1713 return NULL;
1714 }
1715 pEditAttrInfo = (EditAttrInfo*)malloc(sizeof(EditAttrInfo));
1716 if (pEditAttrInfo == NULL) FailAllocMessage();
1717 memset(pEditAttrInfo, 0, sizeof(EditAttrInfo));
1718
1719 /*
1720 * For this function, we do not need to call HasEditAttrsInContextMenu()
1721 * because the "edit_attrs_in_context_menu=" attribute is only for the
1722 * "Edit Attribute In Editor" submenu and *not* for the
1723 * "Edit Attribute Group In Editor" submenu.
1724 */
1725 attr_strings = (char**)malloc(num_attrs*sizeof(char*));
1726 status_strings = (char**)malloc(num_attrs*sizeof(char*));
1727 fore_colors = (int*)malloc(num_attrs*sizeof(int));
1728
1729 if (attr_strings == NULL || status_strings == NULL || fore_colors == NULL) {
1730 FailAllocMessage();
1731 }
1732 for (i=0; i < num_attrs; i++) {
1733 attr_strings[i] = UtilStrDup(gAttrGroupInfo[i]->group_name);
1734 sprintf(gszMsgBox, TgLoadCachedString(CSTID_EDIT_ATTR_GROUP_IN_EDITOR),
1735 gAttrGroupInfo[i]->group_name, gAttrGroupInfo[i]->displayed_names);
1736 status_strings[i] = UtilStrDup(gszMsgBox);
1737
1738 if (attr_strings[i] == NULL || status_strings[i] == NULL) {
1739 FailAllocMessage();
1740 }
1741 fore_colors[i] = myFgPixel;
1742 }
1743 pEditAttrInfo->num_attrs = num_attrs;
1744 pEditAttrInfo->attr_strings = attr_strings;
1745 pEditAttrInfo->status_strings = status_strings;
1746 pEditAttrInfo->fore_colors = fore_colors;
1747
1748 return pEditAttrInfo;
1749 }
1750
MoveAttr()1751 void MoveAttr()
1752 {
1753 struct ObjRec *obj_ptr=NULL;
1754 struct AttrRec *attr_ptr=NULL, *attr_ptr1=NULL;
1755 int num_attrs=0, i, index=INVALID, x, y;
1756 int sel_ltx, sel_lty, sel_rbx, sel_rby;
1757 int *fore_colors=NULL, *pixel_ptr=NULL;
1758 char **attr_strings=NULL;
1759 unsigned int button;
1760
1761 if (topSel != botSel || topSel == NULL) {
1762 MsgBox(TgLoadString(STID_SELECT_ONLY_ONE_OBJ), TOOL_NAME, INFO_MB);
1763 return;
1764 }
1765 obj_ptr = topSel->obj;
1766 attr_ptr1 = attr_ptr = obj_ptr->fattr;
1767 for ( ; attr_ptr1 != NULL; attr_ptr1=attr_ptr1->next, num_attrs++) {
1768 }
1769 if (num_attrs == 0) {
1770 MsgBox(TgLoadString(STID_SELECT_HAS_NO_ATTR), TOOL_NAME, INFO_MB);
1771 return;
1772 }
1773 attr_strings = (char**)malloc(num_attrs*sizeof(char*));
1774 fore_colors = pixel_ptr = (int*)malloc(num_attrs*sizeof(int));
1775 if (attr_strings == NULL || fore_colors == NULL) {
1776 FailAllocMessage();
1777 }
1778 attr_ptr1 = attr_ptr;
1779 for (i=0; i < num_attrs; i++, attr_ptr1=attr_ptr1->next) {
1780 int need_to_free_tmp_buf=FALSE;
1781 char *tmp_buf=NULL;
1782 MiniLinesInfo *minilines=(&attr_ptr1->obj->detail.t->minilines);
1783
1784 tmp_buf = ConvertAttrNameFirstMiniLineToString(attr_ptr1,
1785 &need_to_free_tmp_buf);
1786 if ((attr_strings[i]=UtilStrDup(tmp_buf)) == NULL) FailAllocMessage();
1787
1788 *pixel_ptr++ = colorPixels[minilines->first->first_block->seg->color];
1789
1790 if (need_to_free_tmp_buf) UtilFree(tmp_buf);
1791 }
1792
1793 Msg(TgLoadString(STID_DRAG_LEFT_BTN_TO_SEE_ATTR));
1794 SetMouseStatus(TgLoadString(STID_SHOW_MOVE_ATTR),
1795 TgLoadString(STID_CHANGE_ATTR_JUST),
1796 TgLoadCachedString(CSTID_PARANED_NONE));
1797 button = CornerLoop(&x, &y);
1798 activeMenu = INVALID;
1799 if (button == Button1 || button == Button2) {
1800 TgMenu *menu=CreateAttrMenu(NULL, x, y, num_attrs, attr_strings, NULL,
1801 fore_colors);
1802
1803 if (menu != NULL) {
1804 index = TgMenuLoop(menu);
1805 TgDestroyMenu(menu, TRUE);
1806 }
1807 free(fore_colors);
1808 }
1809 if (index != INVALID) {
1810 attr_ptr1 = attr_ptr;
1811 for (i=0; i < index; i++, attr_ptr1=attr_ptr1->next) {
1812 }
1813 sel_ltx = selLtX; sel_lty = selLtY; sel_rbx = selRbX; sel_rby = selRbY;
1814 if (button == Button1) {
1815 if (MoveOneAttr(obj_ptr, attr_ptr1)) {
1816 /* HighLightReverse() is expected to be called */
1817 UpdSelBBox();
1818 RedrawAreas(botObj, sel_ltx-GRID_ABS_SIZE(1),
1819 sel_lty-GRID_ABS_SIZE(1),
1820 sel_rbx+GRID_ABS_SIZE(1), sel_rby+GRID_ABS_SIZE(1),
1821 selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
1822 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
1823 SetFileModified(TRUE);
1824 HighLightForward();
1825 }
1826 } else if (button == Button2) {
1827 if (ChangeAttrJust(obj_ptr, attr_ptr1)) {
1828 /* HighLightReverse() is expected to be called */
1829 UpdSelBBox();
1830 RedrawAreas(botObj, sel_ltx-GRID_ABS_SIZE(1),
1831 sel_lty-GRID_ABS_SIZE(1), sel_rbx+GRID_ABS_SIZE(1),
1832 sel_rby+GRID_ABS_SIZE(1), selLtX-GRID_ABS_SIZE(1),
1833 selLtY-GRID_ABS_SIZE(1), selRbX+GRID_ABS_SIZE(1),
1834 selRbY+GRID_ABS_SIZE(1));
1835 SetFileModified(TRUE);
1836 HighLightForward();
1837 }
1838 }
1839 }
1840 for (i=0; i < num_attrs; i++) UtilFree(attr_strings[i]);
1841 free(attr_strings);
1842 justDupped = FALSE;
1843 }
1844
CopyAndUpdateAttrs(ToObjPtr,FromObjPtr)1845 void CopyAndUpdateAttrs(ToObjPtr, FromObjPtr)
1846 struct ObjRec *ToObjPtr, *FromObjPtr;
1847 {
1848 struct AttrRec *to_attr_ptr, *from_attr_ptr;
1849 int confirm_status=MB_ID_CANCEL;
1850
1851 topAttr = botAttr = NULL;
1852 from_attr_ptr = FromObjPtr->fattr;
1853 for ( ; from_attr_ptr != NULL; from_attr_ptr=from_attr_ptr->next) {
1854 to_attr_ptr = ToObjPtr->fattr;
1855 for ( ; to_attr_ptr != NULL; to_attr_ptr=to_attr_ptr->next) {
1856 if (from_attr_ptr->obj->color==to_attr_ptr->obj->color &&
1857 strcmp(from_attr_ptr->attr_name.s,
1858 to_attr_ptr->attr_name.s)==0) {
1859 if (*(from_attr_ptr->attr_value.s) != '\0') {
1860 DynStrCpy(&to_attr_ptr->attr_value, &from_attr_ptr->attr_value);
1861 UpdAttr(to_attr_ptr);
1862 }
1863 break;
1864 }
1865 }
1866 if (to_attr_ptr == NULL) {
1867 /* cannot find the same attribute in the new one */
1868 confirm_status = MB_ID_NO;
1869
1870 if (from_attr_ptr->inherited) {
1871 char msg[MAXSTRING];
1872
1873 /* obsolete attribute? */
1874 confirm_status = (dropObsIconAttrWhenUpdate) ? MB_ID_YES :
1875 MB_ID_CANCEL;
1876 if (*from_attr_ptr->attr_name.s == '\0') {
1877 sprintf(msg, TgLoadString(STID_IS_ATTR_OBSOLETE_FOR_ICON_YNC),
1878 from_attr_ptr->attr_value.s, FromObjPtr->detail.r->s);
1879 } else {
1880 sprintf(msg, TgLoadString(STID_IS_ATTR_OBSOLETE_FOR_ICON_YNC),
1881 from_attr_ptr->attr_name.s, FromObjPtr->detail.r->s);
1882 }
1883 while (confirm_status == MB_ID_CANCEL) {
1884 confirm_status = MsgBox(msg, TOOL_NAME, YN_MB);
1885 if (confirm_status == MB_ID_CANCEL) {
1886 MsgBox(TgLoadCachedString(CSTID_CANCEL_NOT_AVAIL), TOOL_NAME,
1887 INFO_MB);
1888 }
1889 }
1890 }
1891 if (confirm_status == MB_ID_NO) {
1892 /* new attribute */
1893 to_attr_ptr = (struct AttrRec *)malloc(sizeof(struct AttrRec));
1894 if (to_attr_ptr == NULL) FailAllocMessage();
1895 memset(to_attr_ptr, 0, sizeof(struct AttrRec));
1896 to_attr_ptr->owner = ToObjPtr;
1897 DupAnAttr(from_attr_ptr, to_attr_ptr);
1898 LinkInAttr((struct AttrRec *)NULL, topAttr, to_attr_ptr);
1899 }
1900 } else {
1901 to_attr_ptr->shown = from_attr_ptr->shown;
1902 to_attr_ptr->nameshown = from_attr_ptr->nameshown;
1903 }
1904 }
1905 if (topAttr != NULL) {
1906 topAttr->prev = NULL;
1907 botAttr->next = ToObjPtr->fattr;
1908
1909 if (ToObjPtr->fattr != NULL) ToObjPtr->fattr->prev = botAttr;
1910 ToObjPtr->fattr = topAttr;
1911 if (ToObjPtr->lattr == NULL) ToObjPtr->lattr = botAttr;
1912 }
1913 AdjObjBBox(ToObjPtr);
1914 }
1915
ToggleNamedAttrShown(attr_name)1916 void ToggleNamedAttrShown(attr_name)
1917 char *attr_name;
1918 {
1919 char *paren_ptr;
1920 struct AttrRec *attr_ptr;
1921 int ltx, lty, rbx, rby;
1922
1923 if (topSel != botSel || topSel == NULL) {
1924 MsgBox(TgLoadString(STID_SELECT_ONLY_ONE_OBJ), TOOL_NAME, INFO_MB);
1925 return;
1926 }
1927 if ((paren_ptr=strchr(attr_name, ')')) == NULL) {
1928 MsgBox(TgLoadString(STID_BAD_FORMAT_IN_SHORTCUT_SPEC), TOOL_NAME,
1929 INFO_MB);
1930 return;
1931 }
1932 *paren_ptr = '\0';
1933 if ((attr_ptr=FindAttrWithName(topSel->obj, attr_name, NULL)) == NULL) {
1934 char msg[MAXSTRING+1];
1935
1936 sprintf(msg, TgLoadString(STID_CANNOT_FIND_NAMED_ATTR), attr_name);
1937 MsgBox(msg, TOOL_NAME, INFO_MB);
1938 return;
1939 }
1940 ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
1941 HighLightReverse();
1942 PrepareToReplaceAnObj(topSel->obj);
1943 attr_ptr->shown = !attr_ptr->shown;
1944 AdjObjBBox(topSel->obj);
1945 RecordReplaceAnObj(topSel->obj);
1946 UpdSelBBox();
1947 RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
1948 rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
1949 selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
1950 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
1951 SetFileModified(TRUE);
1952 HighLightForward();
1953 }
1954
ToggleEqAttrShown()1955 void ToggleEqAttrShown()
1956 {
1957 char buf[80];
1958
1959 strcpy(buf, "eq=)");
1960 ToggleNamedAttrShown(buf);
1961 }
1962
AddFileAttrs()1963 void AddFileAttrs()
1964 {
1965 struct SelRec *sel_ptr;
1966 int ltx, lty, rbx, rby;
1967
1968 if (gstWBInfo.do_whiteboard) {
1969 /*
1970 * Now it's allowed.
1971 *
1972 * MsgBox(TgLoadString(STID_ATTACH_FILE_ATTRS_IN_WB), TOOL_NAME, INFO_MB);
1973 * return;
1974 */
1975 }
1976 if (topSel == NULL) {
1977 MsgBox(TgLoadString(STID_SELECT_AT_LEAST_ONE_TEXT), TOOL_NAME, INFO_MB);
1978 return;
1979 }
1980 for (sel_ptr=topSel; sel_ptr!=NULL; sel_ptr=sel_ptr->next) {
1981 if (sel_ptr->obj->type != OBJ_TEXT) {
1982 MsgBox(TgLoadString(STID_CANNOT_ATTACH_NON_TEXT_OBJ), TOOL_NAME,
1983 INFO_MB);
1984 return;
1985 }
1986 }
1987
1988 ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
1989
1990 HighLightReverse();
1991 AddObj(NULL, topObj, tgifObj);
1992 AddNewSelObj(topObj);
1993 PrepareToRecord(CMD_REPLACE, topSel, botSel, numObjSelected);
1994
1995 for (sel_ptr=topSel->next; sel_ptr!=NULL; sel_ptr=sel_ptr->next) {
1996 AddAttr(topObj, sel_ptr->obj);
1997 }
1998 RemoveAllSel();
1999 AddNewSelObj(topObj);
2000 UpdSelBBox();
2001
2002 recordCmdIncludeTgifObj = TRUE;
2003 RecordCmd(CMD_MANY_TO_ONE, NULL, topSel, botSel, 1);
2004 recordCmdIncludeTgifObj = FALSE;
2005 RemoveAllSel();
2006 UnlinkObj(topObj);
2007 RedrawAnArea(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
2008 rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1));
2009 SetFileModified(TRUE);
2010 justDupped = FALSE;
2011 }
2012
DetachFileAttrs()2013 void DetachFileAttrs()
2014 {
2015 struct AttrRec *attr_ptr, *next_attr;
2016 struct SelRec *sel_ptr;
2017
2018 if (gstWBInfo.do_whiteboard) {
2019 /*
2020 * Now it's allowed.
2021 *
2022 * MsgBox(TgLoadString(STID_DETACH_FILE_ATTRS_IN_WB), TOOL_NAME, INFO_MB);
2023 * return;
2024 */
2025 }
2026 if (tgifObj->fattr == NULL) {
2027 MsgBox(TgLoadString(STID_FILE_CONTAINS_NO_ATTRS), TOOL_NAME, INFO_MB);
2028 return;
2029 }
2030 MakeQuiescent();
2031
2032 AddObj(NULL, topObj, tgifObj);
2033 AddNewSelObj(topObj);
2034 PrepareToReplaceAnObj(topObj);
2035
2036 for (attr_ptr=topObj->fattr; attr_ptr!=NULL; attr_ptr=next_attr) {
2037 next_attr = attr_ptr->next;
2038
2039 sel_ptr = (struct SelRec *)malloc(sizeof(struct SelRec));
2040 if (sel_ptr == NULL) FailAllocMessage();
2041 sel_ptr->obj = attr_ptr->obj;
2042 AddSel(topSel, topSel->next, sel_ptr);
2043
2044 attr_ptr->obj->detail.t->attr = NULL;
2045 AddObj(topObj, topObj->next, attr_ptr->obj);
2046 FreeAttr(attr_ptr);
2047 }
2048 topObj->fattr = topObj->lattr = NULL;
2049 recordCmdIncludeTgifObj = TRUE;
2050 RecordCmd(CMD_ONE_TO_MANY, NULL, topSel, botSel, numObjSelected);
2051 recordCmdIncludeTgifObj = FALSE;
2052
2053 UnlinkObj(topObj);
2054 FreeTopSel();
2055
2056 RedrawAnArea(botObj, selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
2057 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
2058 HighLightForward();
2059 SetFileModified(TRUE);
2060 justDupped = FALSE;
2061 SetCurChoice(curChoiceBeforeMakeQuiescent);
2062 }
2063
2064 #define SHOWN_COL 0
2065 #define NSHOWN_COL 1
2066
2067 static DspList *fileAttrNameDspPtr=NULL;
2068
2069 static
FileAttrNameListing(ObjPtr,pn_entries,pCheckArray)2070 DspList *FileAttrNameListing(ObjPtr, pn_entries, pCheckArray)
2071 /*
2072 * If pCheckArray != NULL, this routine sets pCheckArray->num_cols,
2073 * pCheckArray->num_rows and pCheckArray->value.
2074 */
2075 struct ObjRec *ObjPtr;
2076 int *pn_entries;
2077 struct CheckArrayRec *pCheckArray;
2078 {
2079 int i, num_rows=0;
2080 DspList *dsp_ptr;
2081 struct AttrRec *attr_ptr;
2082
2083 for (num_rows=0, attr_ptr=ObjPtr->fattr; attr_ptr!=NULL;
2084 attr_ptr=attr_ptr->next, num_rows++) {
2085 }
2086 if (pCheckArray != NULL) {
2087 pCheckArray->num_cols = 2;
2088 pCheckArray->num_rows = num_rows;
2089 pCheckArray->value = (int**)malloc(2*sizeof(int*));
2090 if (pCheckArray->value == NULL) FailAllocMessage();
2091 memset(pCheckArray->value, 0, 2*sizeof(int*));
2092 pCheckArray->value[SHOWN_COL] = (int*)malloc(num_rows*sizeof(int));
2093 pCheckArray->value[NSHOWN_COL] = (int*)malloc(num_rows*sizeof(int));
2094 if (pCheckArray->value[SHOWN_COL] == NULL ||
2095 pCheckArray->value[NSHOWN_COL] == NULL) {
2096 FailAllocMessage();
2097 }
2098 memset(pCheckArray->value[SHOWN_COL], 0, num_rows*sizeof(int));
2099 memset(pCheckArray->value[NSHOWN_COL], 0, num_rows*sizeof(int));
2100 }
2101 fileAttrNameDspPtr = (DspList*)malloc(num_rows*sizeof(DspList));
2102 if (fileAttrNameDspPtr == NULL) FailAllocMessage();
2103 memset(fileAttrNameDspPtr, 0, num_rows*sizeof(DspList));
2104 for (i=1, dsp_ptr=fileAttrNameDspPtr, attr_ptr=ObjPtr->fattr;
2105 i<=num_rows; i++, dsp_ptr++, attr_ptr=attr_ptr->next) {
2106 if (*attr_ptr->attr_name.s == '\0') {
2107 UtilStrCpyN(dsp_ptr->itemstr, sizeof(dsp_ptr->itemstr),
2108 attr_ptr->attr_value.s);
2109 } else {
2110 sprintf(gszMsgBox, "%s%s", attr_ptr->attr_name.s,
2111 attr_ptr->attr_value.s);
2112 UtilStrCpyN(dsp_ptr->itemstr, sizeof(dsp_ptr->itemstr), gszMsgBox);
2113 }
2114 /* use the directory field for inherited */
2115 dsp_ptr->directory = attr_ptr->inherited;
2116 dsp_ptr->next = ((i == num_rows) ? NULL : &dsp_ptr[1]);
2117 if (pCheckArray != NULL) {
2118 if (attr_ptr->shown) pCheckArray->value[SHOWN_COL][i-1] = TRUE;
2119 if (attr_ptr->nameshown) pCheckArray->value[NSHOWN_COL][i-1] = TRUE;
2120 }
2121 }
2122 *pn_entries = num_rows;
2123 return fileAttrNameDspPtr;
2124 }
2125
2126 static
EditAttrCheckUpdate(pp_dsp_ptr,ppsz_entries,pn_num_entries,pn_marked_index,pp_check_array,cur_buf,col,row,p_void)2127 int EditAttrCheckUpdate(pp_dsp_ptr, ppsz_entries, pn_num_entries,
2128 pn_marked_index, pp_check_array, cur_buf, col, row, p_void)
2129 DspList **pp_dsp_ptr;
2130 char ***ppsz_entries, *cur_buf;
2131 int *pn_num_entries, *pn_marked_index, col, row;
2132 struct CheckArrayRec **pp_check_array;
2133 void *p_void;
2134 {
2135 char *psz=NULL, saved_ch='\0', *buf=NULL;
2136 int shown=FALSE, nameshown=FALSE;
2137
2138 if (ppsz_entries == NULL || *ppsz_entries == NULL ||
2139 (*ppsz_entries)[row] == NULL || pp_check_array == NULL ||
2140 (*pp_check_array) == NULL || (*pp_check_array)->value == NULL) {
2141 return FALSE;
2142 }
2143 buf = (*ppsz_entries)[row];
2144 shown = (*pp_check_array)->value[SHOWN_COL][row];
2145 nameshown = (*pp_check_array)->value[NSHOWN_COL][row];
2146
2147 psz = strchr(buf, '=');
2148 if (psz != NULL) {
2149 saved_ch = *psz;
2150 *psz = '\0';
2151 if (shown) {
2152 if (nameshown) {
2153 sprintf(gszMsgBox, TgLoadString(STID_SHOW_ATTR_NAME_AND_VALUE),
2154 buf);
2155 } else {
2156 sprintf(gszMsgBox, TgLoadString(STID_SHOW_ATTR_VALUE_ONLY), buf);
2157 }
2158 } else {
2159 sprintf(gszMsgBox, TgLoadString(STID_NOT_SHOW_ATTR), buf);
2160 }
2161 *psz = saved_ch;
2162 } else {
2163 if (shown) {
2164 sprintf(gszMsgBox, TgLoadString(STID_SHOW_ATTR), buf);
2165 } else {
2166 sprintf(gszMsgBox, TgLoadString(STID_WONT_SHOW_VALUE), buf);
2167 }
2168 }
2169 SetStringStatus(gszMsgBox);
2170
2171 return TRUE;
2172 }
2173
2174 static
EditAttrNames(TopStr,ObjAttrDspList,entries,num_entries,pCheckArray)2175 int EditAttrNames(TopStr, ObjAttrDspList, entries, num_entries, pCheckArray)
2176 char *TopStr, **entries;
2177 DspList *ObjAttrDspList;
2178 int num_entries;
2179 struct CheckArrayRec *pCheckArray;
2180 {
2181 char win_name[128];
2182
2183 sprintf(win_name, TgLoadString(STID_TGIF_EDIT_ATTR_NAMES), TOOL_NAME);
2184 ResetNamesInfo();
2185 NamesSetTitle(TopStr);
2186 NamesAddButton(TgLoadCachedString(CSTID_OK), BUTTON_OK);
2187 NamesAddButton(TgLoadCachedString(CSTID_CANCEL), BUTTON_CANCEL);
2188 /* ignore double-click and <CR> */
2189 NamesSetDefaultBtnId(BUTTON_OK, INVALID);
2190 NamesSetStyle(NAMES_EDIT_ATTR, NAMES_LOOP_ONCE);
2191 if (pCheckArray != NULL) {
2192 NamesSetCallback(NULL, NULL, (CheckUpdateFunc*)EditAttrCheckUpdate);
2193 }
2194 NamesSetEntries(ObjAttrDspList, entries, num_entries, pCheckArray,
2195 TRUE, INVALID, 0);
2196 return (Names(win_name, NULL, NULL, 0, NULL)==BUTTON_OK);
2197 }
2198
BlankStr(s)2199 int BlankStr(s)
2200 char *s;
2201 {
2202 while (*s == ' ') s++;
2203 return (*s == '\0');
2204 }
2205
EditFileAttrs()2206 void EditFileAttrs()
2207 {
2208 int i, num_entries=0;
2209 DspList *dsp_ptr;
2210 char **entries=NULL;
2211
2212 if (gstWBInfo.do_whiteboard) {
2213 /*
2214 * Now it's allowed.
2215 *
2216 * MsgBox(TgLoadString(STID_EDIT_FILE_ATTRS_IN_WB), TOOL_NAME, INFO_MB);
2217 * return;
2218 */
2219 }
2220 if (tgifObj->fattr == NULL) {
2221 MsgBox(TgLoadString(STID_FILE_CONTAINS_NO_ATTRS), TOOL_NAME, INFO_MB);
2222 return;
2223 }
2224 MakeQuiescent();
2225
2226 dsp_ptr = FileAttrNameListing(tgifObj, &num_entries, NULL);
2227 ignoreDirectoryFlag = TRUE;
2228 entries = MakeNameDspItemArray(num_entries, dsp_ptr);
2229 ignoreDirectoryFlag = FALSE;
2230 if (EditAttrNames(TgLoadString(STID_EDIT_FILE_ATTRS_DOTS), NULL, entries,
2231 num_entries, NULL)) {
2232 int modified=FALSE;
2233 struct AttrRec *attr_ptr, *next_attr;
2234
2235 AddObj(NULL, topObj, tgifObj);
2236 AddNewSelObj(topObj);
2237 PrepareToReplaceAnObj(topObj);
2238
2239 for (attr_ptr=tgifObj->fattr, i=0; attr_ptr!=NULL;
2240 attr_ptr=next_attr, i++) {
2241 int blank_str=BlankStr(entries[i]);
2242 struct TextRec *text_ptr=attr_ptr->obj->detail.t;
2243
2244 next_attr = attr_ptr->next;
2245 if ((blank_str &&
2246 text_ptr->minilines.first==text_ptr->minilines.last) ||
2247 strcmp(GetTextPtrFirstStrSeg(text_ptr)->dyn_str.s,
2248 entries[i]) != 0) {
2249 modified = TRUE;
2250 if (blank_str &&
2251 text_ptr->minilines.first==text_ptr->minilines.last) {
2252 UnlinkAttr(attr_ptr);
2253 FreeTextObj(attr_ptr->obj);
2254 FreeAttr(attr_ptr);
2255 } else {
2256 DynStrSet(&GetTextPtrFirstStrSeg(text_ptr)->dyn_str,
2257 entries[i]);
2258 UpdateAttr(text_ptr, attr_ptr);
2259 }
2260 }
2261 }
2262 if (modified) {
2263 recordCmdIncludeTgifObj = TRUE;
2264 RecordReplaceAnObj(topObj);
2265 recordCmdIncludeTgifObj = FALSE;
2266
2267 RemoveAllSel();
2268 UnlinkObj(topObj);
2269
2270 SetFileModified(TRUE);
2271 Msg(TgLoadString(STID_FILE_ATTRS_UPDATED));
2272 } else {
2273 AbortPrepareCmd(CMD_REPLACE);
2274
2275 RemoveAllSel();
2276 UnlinkObj(topObj);
2277 }
2278 }
2279 free(dsp_ptr);
2280 free(*entries);
2281 free(entries);
2282 fileAttrNameDspPtr = NULL;
2283 Msg("");
2284 SetCurChoice(curChoiceBeforeMakeQuiescent);
2285 }
2286
EditAttrs()2287 void EditAttrs()
2288 {
2289 int i, num_entries=0;
2290 DspList *dsp_ptr;
2291 char **entries=NULL;
2292 struct CheckArrayRec check_array, orig_check_array;
2293
2294 if (topSel == NULL || topSel != botSel) {
2295 MsgBox(TgLoadString(STID_SELECT_ONE_OBJ_FOR_EDITATTRS), TOOL_NAME,
2296 INFO_MB);
2297 return;
2298 }
2299 if (topSel->obj->fattr == NULL) {
2300 MsgBox(TgLoadString(STID_OBJ_CONTAINS_NO_ATTRS), TOOL_NAME, INFO_MB);
2301 return;
2302 }
2303 memset(&check_array, 0, sizeof(struct CheckArrayRec));
2304 memset(&orig_check_array, 0, sizeof(struct CheckArrayRec));
2305 dsp_ptr = FileAttrNameListing(topSel->obj, &num_entries, &check_array);
2306 ignoreDirectoryFlag = TRUE;
2307 entries = MakeNameDspItemArray(num_entries, dsp_ptr);
2308 ignoreDirectoryFlag = FALSE;
2309 CopyCheckArray(&orig_check_array, &check_array);
2310 if (EditAttrNames(TgLoadString(STID_EDIT_OBJ_ATTRS_DOTS), dsp_ptr, entries,
2311 num_entries, &check_array)) {
2312 int modified=FALSE, sel_ltx, sel_lty, sel_rbx, sel_rby;
2313 struct AttrRec *attr_ptr, *next_attr;
2314
2315 sel_ltx = selLtX; sel_lty = selLtY; sel_rbx = selRbX; sel_rby = selRbY;
2316 HighLightReverse();
2317 PrepareToReplaceAnObj(topSel->obj);
2318
2319 for (attr_ptr=topSel->obj->fattr, i=0; attr_ptr!=NULL;
2320 attr_ptr=next_attr, i++) {
2321 int blank_str=BlankStr(entries[i]);
2322 char orig_str[MAXPATHLENGTH+1];
2323 struct TextRec *text_ptr=attr_ptr->obj->detail.t;
2324
2325 next_attr = attr_ptr->next;
2326 if (*attr_ptr->attr_name.s == '\0') {
2327 strcpy(orig_str, attr_ptr->attr_value.s);
2328 } else {
2329 sprintf(orig_str, "%s%s", attr_ptr->attr_name.s,
2330 attr_ptr->attr_value.s);
2331 }
2332 if ((blank_str &&
2333 text_ptr->minilines.first==text_ptr->minilines.last) ||
2334 strcmp(orig_str, entries[i]) != 0 ||
2335 (check_array.value[SHOWN_COL][i] !=
2336 orig_check_array.value[SHOWN_COL][i]) ||
2337 (check_array.value[NSHOWN_COL][i] !=
2338 orig_check_array.value[NSHOWN_COL][i])) {
2339 modified = TRUE;
2340 if (blank_str &&
2341 text_ptr->minilines.first==text_ptr->minilines.last) {
2342 UnlinkAttr(attr_ptr);
2343 FreeTextObj(attr_ptr->obj);
2344 FreeAttr(attr_ptr);
2345 } else {
2346 int saved_nameshown;
2347
2348 attr_ptr->shown = check_array.value[SHOWN_COL][i];
2349 attr_ptr->nameshown = check_array.value[NSHOWN_COL][i];
2350 saved_nameshown = attr_ptr->nameshown;
2351 DynStrSet(&GetTextPtrFirstStrSeg(text_ptr)->dyn_str,
2352 entries[i]);
2353 attr_ptr->nameshown = TRUE;
2354 UpdateAttr(text_ptr, attr_ptr);
2355 if (!saved_nameshown) {
2356 if (*attr_ptr->attr_name.s != '\0') {
2357 attr_ptr->nameshown = saved_nameshown;
2358 }
2359 UpdAttr(attr_ptr);
2360 UpdateAttr(text_ptr, attr_ptr);
2361 }
2362 }
2363 }
2364 }
2365 if (modified) {
2366 AdjObjBBox(topSel->obj);
2367 RecordReplaceAnObj(topSel->obj);
2368 UpdSelBBox();
2369 RedrawAreas(botObj, sel_ltx-GRID_ABS_SIZE(1),
2370 sel_lty-GRID_ABS_SIZE(1),
2371 sel_rbx+GRID_ABS_SIZE(1), sel_rby+GRID_ABS_SIZE(1),
2372 selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
2373 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
2374 SetFileModified(TRUE);
2375 justDupped = FALSE;
2376 Msg(TgLoadString(STID_OBJ_ATTRS_UPDATED));
2377 } else {
2378 AbortPrepareCmd(CMD_REPLACE);
2379 }
2380 HighLightForward();
2381 }
2382 free(dsp_ptr);
2383 free(*entries);
2384 free(entries);
2385 CleanUpCheckArray(&orig_check_array);
2386 CleanUpCheckArray(&check_array);
2387 fileAttrNameDspPtr = NULL;
2388 Msg("");
2389 }
2390
2391 static
GetAttrNamesCount(buf)2392 int GetAttrNamesCount(buf)
2393 char *buf;
2394 {
2395 int count=0;
2396
2397 while (*buf != '\0') {
2398 char *psz=NULL;
2399
2400 if (*buf == ':') return INVALID;
2401
2402 psz = strchr(buf, ':');
2403 if (psz == NULL) {
2404 count++;
2405 break;
2406 } else {
2407 count++;
2408 buf = (&psz[1]);
2409 }
2410 }
2411 return count;
2412 }
2413
2414 static
SetAttrGroupInfoDisplayedNames(pagi)2415 void SetAttrGroupInfoDisplayedNames(pagi)
2416 AttrGroupInfo *pagi;
2417 {
2418 int i=0, total=0;
2419 char *psz=NULL;
2420
2421 for (i=0; i < pagi->num_attrs; i++) {
2422 total += strlen(pagi->attr_name[i])+1;
2423 }
2424 total += 1;
2425
2426 pagi->displayed_names = (char*)malloc(total*sizeof(char));
2427 if (pagi->displayed_names == NULL) FailAllocMessage();
2428 memset(pagi->displayed_names, 0, total*sizeof(char));
2429
2430 for (i=0, psz=pagi->displayed_names; i < pagi->num_attrs; i++) {
2431 if (i == pagi->num_attrs-1) {
2432 sprintf(psz, "%s", pagi->attr_name[i]);
2433 psz += strlen(pagi->attr_name[i]);
2434 } else {
2435 sprintf(psz, "%s:", pagi->attr_name[i]);
2436 psz += strlen(pagi->attr_name[i])+1;
2437 }
2438 }
2439 }
2440
2441 static
FreeAttrGroupInfo(pagi)2442 void FreeAttrGroupInfo(pagi)
2443 AttrGroupInfo *pagi;
2444 {
2445 UtilFree(pagi->group_name);
2446 UtilFree(pagi->group_value);
2447 UtilFree(pagi->displayed_names);
2448 if (pagi->num_attrs > 0 && pagi->attr_name != NULL) {
2449 free(pagi->attr_name);
2450 }
2451 }
2452
2453 static
CleanUpAttrGroup()2454 void CleanUpAttrGroup()
2455 {
2456 int i=0;
2457
2458 if (maxAttrGroups != 0 && gAttrGroupInfo != NULL) {
2459 for (i=0; i < maxAttrGroups; i++) {
2460 FreeAttrGroupInfo(gAttrGroupInfo[i]);
2461 free(gAttrGroupInfo[i]);
2462 }
2463 free(gAttrGroupInfo);
2464 }
2465 maxAttrGroups = 0;
2466 gAttrGroupInfo = NULL;
2467 }
2468
CleanUpAttr()2469 void CleanUpAttr()
2470 {
2471 CleanUpAttrGroup();
2472 }
2473
2474 static
ParseAttrGroupXDef(group_index,xdef_line,buf)2475 int ParseAttrGroupXDef(group_index, xdef_line, buf)
2476 int group_index;
2477 char *xdef_line, *buf;
2478 {
2479 char *psz_attr_names=strchr(buf, ':'), *psz_attr=NULL;
2480 int count=0, index=0;
2481
2482 if (psz_attr_names == NULL) {
2483 if (xdef_line == NULL) {
2484 fprintf(stderr, TgLoadString(STID_INVALID_COMPILER_OPT),
2485 "DEFATTRGROUP", buf);
2486 } else {
2487 fprintf(stderr, TgLoadString(STID_INVALID_XDEF), TOOL_NAME,
2488 xdef_line, buf);
2489 }
2490 fprintf(stderr, "\n");
2491 return FALSE;
2492 }
2493 *psz_attr_names++ = '\0';
2494 count = GetAttrNamesCount(psz_attr_names);
2495 if (count == INVALID) {
2496 if (xdef_line == NULL) {
2497 fprintf(stderr, TgLoadString(STID_INVALID_COMPILER_OPT),
2498 "DEFATTRGROUP", buf);
2499 } else {
2500 fprintf(stderr, TgLoadString(STID_INVALID_XDEF), TOOL_NAME,
2501 xdef_line, buf);
2502 }
2503 fprintf(stderr, "\n");
2504 return FALSE;
2505 }
2506 gAttrGroupInfo[group_index]->group_name = UtilStrDup(buf);
2507 if (gAttrGroupInfo[group_index]->group_name == NULL) {
2508 FailAllocMessage();
2509 }
2510 UtilTrimBlanks(gAttrGroupInfo[group_index]->group_name);
2511
2512 gAttrGroupInfo[group_index]->group_value = UtilStrDup(psz_attr_names);
2513 if (gAttrGroupInfo[group_index]->group_value == NULL) {
2514 FailAllocMessage();
2515 }
2516 UtilTrimBlanks(gAttrGroupInfo[group_index]->group_value);
2517
2518 gAttrGroupInfo[group_index]->attr_name = (char**)malloc(
2519 count*sizeof(char*));
2520 if (gAttrGroupInfo[group_index]->attr_name == NULL) {
2521 FailAllocMessage();
2522 }
2523 memset(gAttrGroupInfo[group_index]->attr_name, 0, count*sizeof(char*));
2524
2525 psz_attr = gAttrGroupInfo[group_index]->group_value;
2526 while (*psz_attr != '\0') {
2527 char *psz_colon=strchr(psz_attr, ':');
2528
2529 if (psz_colon != NULL) *psz_colon = '\0';
2530
2531 UtilTrimBlanks(psz_attr);
2532 gAttrGroupInfo[group_index]->attr_name[index] = psz_attr;
2533
2534 index++;
2535 if (psz_colon != NULL) {
2536 psz_attr = ++psz_colon;
2537 } else {
2538 break;
2539 }
2540 }
2541 gAttrGroupInfo[group_index]->num_attrs = count;
2542 SetAttrGroupInfoDisplayedNames(gAttrGroupInfo[group_index]);
2543
2544 return TRUE;
2545 }
2546
InitAttr()2547 int InitAttr()
2548 {
2549 char *c_ptr=NULL, buf[MAXSTRING];
2550 int i=0, attr_group_in_xdef=TRUE;
2551
2552 maxAttrGroups = 0;
2553 if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"MaxAttributeGroups")) !=
2554 NULL) {
2555 maxAttrGroups = atoi(c_ptr);
2556 }
2557 if (cmdLineTgrm2) {
2558 #ifdef DEFATTRGROUP
2559 if (maxAttrGroups == 0) {
2560 maxAttrGroups = 1;
2561 attr_group_in_xdef = FALSE;
2562 }
2563 #endif /* DEFATTRGROUP */
2564 }
2565 if (maxAttrGroups > 0) {
2566 gAttrGroupInfo = (AttrGroupInfo**)malloc(maxAttrGroups *
2567 sizeof(AttrGroupInfo*));
2568 if (gAttrGroupInfo == NULL) FailAllocMessage();
2569 memset(gAttrGroupInfo, 0, maxAttrGroups*sizeof(AttrGroupInfo*));
2570
2571 for (i=0; i < maxAttrGroups; i++) {
2572 gAttrGroupInfo[i] = (AttrGroupInfo*)malloc(sizeof(AttrGroupInfo));
2573 if (gAttrGroupInfo[i] == NULL) FailAllocMessage();
2574 memset(gAttrGroupInfo[i], 0, sizeof(AttrGroupInfo));
2575
2576 if (attr_group_in_xdef) {
2577 sprintf(buf, "AttributeGroup%1d", i);
2578 if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,buf)) != NULL) {
2579 ParseAttrGroupXDef(i, buf, c_ptr);
2580 } else {
2581 fprintf(stderr, TgLoadString(STID_CANNOT_GET_X_DEFAULT),
2582 TOOL_NAME, buf);
2583 fprintf(stderr, "\n");
2584 }
2585 } else if (cmdLineTgrm2) {
2586 #ifdef DEFATTRGROUP
2587 char *tmp_buf=UtilStrDup(DEFATTRGROUP);
2588
2589 if (tmp_buf == NULL) FailAllocMessage();
2590 if (!ParseAttrGroupXDef(i, NULL, tmp_buf)) {
2591 CleanUpAttrGroup();
2592 }
2593 UtilFree(tmp_buf);
2594 #endif /* DEFATTRGROUP */
2595 }
2596 }
2597 } else if (maxAttrGroups == 0) {
2598 /* nothing to do */
2599 } else {
2600 fprintf(stderr, TgLoadString(STID_INVALID_XDEF_USE_ALT_VALUE),
2601 TOOL_NAME, "MaxAttributeGroups", c_ptr, 0);
2602 fprintf(stderr, "\n");
2603 }
2604 return TRUE;
2605 }
2606