/*! \todo Finish function documentation!!! * \brief * \par Function Description * * \note * The object passed in should be the REAL object, NOT any copy in any * selection list */ void o_text_change(GschemToplevel *w_current, OBJECT *object, char *string, int visibility, int show) { GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current); TOPLEVEL *toplevel = gschem_page_view_get_toplevel (page_view); PAGE *page = gschem_page_view_get_page (page_view); g_return_if_fail (toplevel != NULL); g_return_if_fail (page != NULL); if (object == NULL) { return; } if (object->type != OBJ_TEXT) { return; } o_text_set_string (toplevel, object, string); o_set_visibility (toplevel, object, visibility); object->show_name_value = show; o_text_recreate(toplevel, object); /* handle slot= attribute, it's a special case */ if (object->attached_to != NULL && g_ascii_strncasecmp (string, "slot=", 5) == 0) { o_slot_end (w_current, object->attached_to, string); } gschem_toplevel_page_content_changed (w_current, page); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_edit_show_specific_text (GSCHEM_TOPLEVEL *w_current, const GList *o_list, char *stext) { TOPLEVEL *toplevel = w_current->toplevel; OBJECT *o_current; const GList *iter; iter = o_list; while (iter != NULL) { o_current = (OBJECT *)iter->data; if (o_current->type == OBJ_TEXT) { const gchar *str = o_text_get_string (w_current->toplevel, o_current); if (!strncmp (stext, str, strlen (stext))) { if (!o_is_visible (toplevel, o_current)) { o_set_visibility (toplevel, o_current, VISIBLE); o_text_recreate(toplevel, o_current); toplevel->page_current->CHANGED = 1; } } } iter = g_list_next (iter); } o_undo_savestate(w_current, UNDO_ALL); }
/*! \brief Complete the text edit * * \par Function Description * This function completes the text edit by setting all the selected text * objects to the desired values. * * \param [in] w_current The topleval gschem struct. * \param [in] string The text to set the selected text objects to. If this * string is NULL or has zero length, then this function * leaves the text unchanged. * \param [in] color The color to set the selected text to. If the color * is less than zero, then this function leaves the color * unchanged. * \param [in] align The text alignment to set the selected text to. If * the alignment is less than zero, this function leaves * the alignment unchanged. * \param [in] rotate The rotation angle to set the selected text to. If * the rotation angle is less than zero, this function * leaves the rotation angle unchanged. * \param [in] size The size to set all the selected text to. If the * size is less than or equal to zero, this function * leaves the size unchanged. */ void o_text_edit_end(GschemToplevel *w_current, char *string, int color, int align, int rotate, int size) { GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current); TOPLEVEL *toplevel = gschem_page_view_get_toplevel (page_view); PAGE *page = gschem_page_view_get_page (page_view); OBJECT *object; GList *s_current; char *textstr = string; g_return_if_fail (toplevel != NULL); g_return_if_fail (page != NULL); if ((textstr != NULL) && (g_utf8_strlen(textstr, -1) == 0)) { textstr = NULL; } /* skip over head */ s_current = geda_list_get_glist (page->selection_list); while(s_current != NULL) { object = (OBJECT *) s_current->data; if (object) { if (object->type == OBJ_TEXT) { if (size > 0) { object->text->size = size; } if (align >= 0) { object->text->alignment = align; } if (color >= 0) { object->color = color; } if (rotate >= 0) { object->text->angle = rotate; } if (textstr != NULL) { o_text_set_string (toplevel, object, textstr); /* handle slot= attribute, it's a special case */ if (object->attached_to != NULL && g_ascii_strncasecmp (textstr, "slot=", 5) == 0) { o_slot_end (w_current, object->attached_to, textstr); } } o_text_recreate(toplevel, object); } } s_current = g_list_next(s_current); } gschem_toplevel_page_content_changed (w_current, page); o_undo_savestate(w_current, page, UNDO_ALL); }
/*! \brief Change visibility status of attribute object. * \par Function Description * This function toggles the visibility status of the attribute \a * object and updates it. The object is erased or redrawn if * necessary. * * \param [in] w_current The GschemToplevel object. * \param [in] object The attribute object. */ void o_attrib_toggle_visibility(GschemToplevel *w_current, OBJECT *object) { TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current); g_return_if_fail (object != NULL && object->type == OBJ_TEXT); if (o_is_visible (object)) { /* only erase if we are not showing hidden text */ if (!toplevel->show_hidden_text) { o_invalidate (w_current, object); } o_set_visibility (toplevel, object, INVISIBLE); if (toplevel->show_hidden_text) { /* draw text so that little I is drawn */ o_invalidate (w_current, object); } } else { /* if we are in the special show hidden mode, then erase text first */ /* to get rid of the little I */ if (toplevel->show_hidden_text) { o_invalidate (w_current, object); } o_set_visibility (toplevel, object, VISIBLE); o_text_recreate(toplevel, object); } gschem_toplevel_page_content_changed (w_current, toplevel->page_current); }
/*! \brief rotate a text object around a centerpoint * \par Function Description * This function rotates a text \a object around the point * (\a world_centerx, \a world_centery). * * \param [in] toplevel The TOPLEVEL object * \param [in] world_centerx x-coord of the rotation center * \param [in] world_centery y-coord of the rotation center * \param [in] angle The angle to rotate the text object * \param [in] object The text object * \note only steps of 90 degrees are allowed for the \a angle */ void geda_text_object_rotate (TOPLEVEL *toplevel, int world_centerx, int world_centery, int angle, OBJECT *object) { int x, y; int newx, newy; g_return_if_fail (object != NULL); g_return_if_fail (object->text != NULL); g_return_if_fail (object->type == OBJ_TEXT); g_return_if_fail (geda_angle_is_ortho (angle)); object->text->angle = geda_angle_normalize (object->text->angle + angle); x = object->text->x + (-world_centerx); y = object->text->y + (-world_centery); geda_point_rotate_90 (x, y, angle, &newx, &newy); x = newx + (world_centerx); y = newy + (world_centery); geda_text_object_translate (object, x-object->text->x, y-object->text->y); o_text_recreate(toplevel, object); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_edit_show_specific_text (GschemToplevel *w_current, const GList *o_list, const char *stext) { TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current); OBJECT *o_current; const GList *iter; iter = o_list; while (iter != NULL) { o_current = (OBJECT *)iter->data; if (o_current->type == OBJ_TEXT) { const gchar *str = o_text_get_string (w_current->toplevel, o_current); if (!strncmp (stext, str, strlen (stext))) { if (!o_is_visible (toplevel, o_current)) { o_set_visibility (toplevel, o_current, VISIBLE); o_text_recreate(toplevel, o_current); gschem_toplevel_page_content_changed (w_current, toplevel->page_current); } } } iter = g_list_next (iter); } o_undo_savestate_old(w_current, UNDO_ALL); }
/*! \brief Set what part of an attribute is shown. * \par Function Description * This function changes what part (name, value or both) of an * attribute is shown by its attribute object. The attribute object * is erased, updated and finally redrawn. * * \param [in] w_current The GschemToplevel object. * \param [in] object The attribute object. * \param [in] show_name_value The new display flag for attribute. */ void o_attrib_toggle_show_name_value(GschemToplevel *w_current, OBJECT *object, int show_name_value) { TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current); g_return_if_fail (object != NULL && object->type == OBJ_TEXT); o_invalidate (w_current, object); object->show_name_value = show_name_value; o_text_recreate(toplevel, object); gschem_toplevel_page_content_changed (w_current, toplevel->page_current); }
/*! \brief Set what part of an attribute is shown. * \par Function Description * This function changes what part (name, value or both) of an * attribute is shown by its attribute object. The attribute object * is erased, updated and finally redrawn. * * \param [in] w_current The GSCHEM_TOPLEVEL object. * \param [in] object The attribute object. * \param [in] show_name_value The new display flag for attribute. */ void o_attrib_toggle_show_name_value(GSCHEM_TOPLEVEL *w_current, OBJECT *object, int show_name_value) { TOPLEVEL *toplevel = w_current->toplevel; g_return_if_fail (object != NULL && object->type == OBJ_TEXT); o_invalidate (w_current, object); object->show_name_value = show_name_value; o_text_recreate(toplevel, object); toplevel->page_current->CHANGED = 1; }
/*! \brief Set the string displayed by a text object. * \par Function Description * Updates the text object with a new text string. * * \param [in] toplevel The TOPLEVEL object. * \param [in] obj The text object. * \param [in] new_string The new value. */ void o_text_set_string (TOPLEVEL *toplevel, OBJECT *obj, const gchar *new_string) { g_return_if_fail (toplevel != NULL); g_return_if_fail (obj != NULL); g_return_if_fail (obj->type == OBJ_TEXT); g_return_if_fail (obj->text != NULL); g_return_if_fail (new_string != NULL); g_free (obj->text->string); obj->text->string = g_strdup (new_string); o_text_recreate (toplevel, obj); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_edit_show_hidden_lowlevel (GSCHEM_TOPLEVEL *w_current, const GList *o_list) { TOPLEVEL *toplevel = w_current->toplevel; OBJECT *o_current; const GList *iter; iter = o_list; while (iter != NULL) { o_current = (OBJECT *)iter->data; if (o_current->type == OBJ_TEXT && !o_is_visible (toplevel, o_current)) { /* don't toggle the visibility flag */ o_text_recreate (toplevel, o_current); } if (o_current->type == OBJ_COMPLEX || o_current->type == OBJ_PLACEHOLDER) { o_edit_show_hidden_lowlevel(w_current, o_current->complex->prim_objs); o_recalc_single_object(toplevel, o_current); } iter = g_list_next (iter); } }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_edit_show_hidden_lowlevel (GschemToplevel *w_current, const GList *o_list) { TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current); OBJECT *o_current; const GList *iter; iter = o_list; while (iter != NULL) { o_current = (OBJECT *)iter->data; if (o_current->type == OBJ_TEXT && !o_is_visible (toplevel, o_current)) { /* don't toggle the visibility flag */ o_text_recreate (toplevel, o_current); } if (o_current->type == OBJ_COMPLEX || o_current->type == OBJ_PLACEHOLDER) { o_edit_show_hidden_lowlevel(w_current, o_current->complex->prim_objs); o_current->w_bounds_valid_for = NULL; } iter = g_list_next (iter); } }
/*! \brief Copy attributes from OBJECT to OBJECT. * \par Function Description * This function will perform a slot copy of the <B>original</B> OBJECT * to the <B>target</B> OBJECT. * * \param [in] toplevel The TOPLEVEL object. * \param [in] original The original OBJECT to slot copy from. * \param [out] target The target OBJECT to slot copy to. */ void o_attrib_slot_copy(TOPLEVEL *toplevel, OBJECT *original, OBJECT *target) { OBJECT *o_current; OBJECT *o_slot_attrib; OBJECT *o_pin_object; OBJECT *o_pinnum_object; char *string; char *slotdef; int slot; int pin_counter; char* current_pin; char* cptr; o_current = original; string = o_attrib_search_slot(o_current, &o_slot_attrib); if (!string) { /* s_log_message("Did not find slot= attribute\n"); */ /* not a serious error */ return; } slot = atoi(string); g_free(string); slotdef = o_attrib_search_slotdef(o_current, slot); if (!slotdef) { s_log_message(_("Did not find slotdef=#:#,#,#... attribute\n")); return; } if (!strstr(slotdef, ":")) { /*! \todo didn't proper slotdef=#:... TODO into log*/ return; } /* skip over slotdef number */ /* slotdef is in the form #:#,#,# */ /* this code skips first #: */ cptr = slotdef; while (*cptr != '\0' && *cptr != ':') { cptr++; } cptr++; /* skip colon */ if (*cptr == '\0') { s_log_message(_("Did not find proper slotdef=#:#,#,#... attribute\n")); return; } pin_counter = 1; current_pin = strtok(cptr, DELIMITERS); while(current_pin != NULL) { o_pin_object = o_attrib_search_pinseq(target->complex->prim_objs, pin_counter); if (o_pin_object) { string = o_attrib_search_name_single(o_pin_object, "pinnumber", &o_pinnum_object); if (string && o_pinnum_object && o_pinnum_object->type == OBJ_TEXT && o_pinnum_object->text->string) { g_free(string); g_free(o_pinnum_object->text->string); o_pinnum_object->text->string = g_strdup_printf ("pinnumber=%s", current_pin); o_text_recreate(toplevel, o_pinnum_object); } pin_counter++; } else { s_log_message(_("component missing pinseq= attribute\n")); } current_pin = strtok(NULL, DELIMITERS); } g_free(slotdef); }
/*! \brief Update all slot attributes in an object. * \par Function Description * Update pinnumber attributes in a graphic object. * The interesting case is where the object is an * instantiation of a slotted part. This means that * o_attrib_slot_update iterates through all pins * found on object and sets the pinnumber= attrib * on each. This doesn't matter for non-slotted * parts, but on slotted parts, this is what sets the * pinnumber= attribute on slots 2, 3, 4.... * * \param [in] toplevel The TOPLEVEL object. * \param [in,out] object The OBJECT to update. */ void o_attrib_slot_update(TOPLEVEL *toplevel, OBJECT *object) { OBJECT *o_current; /* o_current points to the sch level complex object */ OBJECT *o_slot_attrib; OBJECT *o_pin_object; OBJECT *o_pinnum_object; char *string; char *slotdef; int slot; int slot_string; int pin_counter; /* Internal pin counter private to this fcn. */ char* current_pin; /* text from slotdef= to be made into pinnumber= */ char* cptr; /* char pointer pointing to pinnumbers in slotdef=#:#,#,# string */ o_current = object; /* For this particular graphic object (component instantiation) */ /* get the slot number as a string */ string = o_attrib_search_slot(o_current, &o_slot_attrib); if (!string) { /* "Did not find slot= attribute", this is true if * * there is no slot attribut * * or the slot attribute was deleted and we have to assume to use the * first slot now */ slot = 1; slot_string = 0; } else { slot_string = 1; slot = atoi(string); g_free(string); } /* OK, now that we have the slot number, use it to get the */ /* corresponding slotdef=#:#,#,# string. */ slotdef = o_attrib_search_slotdef(o_current, slot); if (!slotdef) { if (slot_string) /* only an error if there's a slot string */ s_log_message(_("Did not find slotdef=#:#,#,#... attribute\n")); return; } if (!strstr(slotdef, ":")) { /* Didn't find proper slotdef=#:... put warning into log */ s_log_message(_("Improper slotdef syntax: missing \":\".\n")); g_free(slotdef); return; } /* skip over slotdef number */ /* slotdef is in the form #:#,#,# */ /* this code skips first #: */ cptr = slotdef; while (*cptr != '\0' && *cptr != ':') { cptr++; } cptr++; /* skip colon */ if (*cptr == '\0') { s_log_message(_("Did not find proper slotdef=#:#,#,#... attribute\n")); g_free(slotdef); return; } /* loop on all pins found in slotdef= attribute */ pin_counter = 1; /* internal pin_counter */ /* get current pinnumber= from slotdef= attrib */ current_pin = strtok(cptr, DELIMITERS); while(current_pin != NULL) { /* get pin on this component with pinseq == pin_counter */ o_pin_object = o_attrib_search_pinseq(o_current->complex->prim_objs, pin_counter); if (o_pin_object) { /* Now rename pinnumber= attrib on this part with value found */ /* in slotdef attribute */ string = o_attrib_search_name_single(o_pin_object, "pinnumber", &o_pinnum_object); if (string && o_pinnum_object && o_pinnum_object->type == OBJ_TEXT && o_pinnum_object->text->string) { g_free(o_pinnum_object->text->string); o_pinnum_object->text->string = g_strdup_printf ("pinnumber=%s", current_pin); o_text_recreate(toplevel, o_pinnum_object); } g_free(string); pin_counter++; } else { s_log_message(_("component missing pinseq= attribute\n")); } current_pin = strtok(NULL, DELIMITERS); } g_free(slotdef); }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void o_slot_end(GSCHEM_TOPLEVEL *w_current, const char *string, int len) { TOPLEVEL *toplevel = w_current->toplevel; OBJECT *new_obj; OBJECT *object; OBJECT *temp; char *slot_value; char *numslots_value; OBJECT *slot_text_object; char *value = NULL; int numslots; int new_slot_number; int status; status = o_attrib_get_name_value(string, NULL, &value); if (!status) { s_log_message(_("Slot attribute malformed\n")); return; } object = o_select_return_first_object(w_current); /* get the parent object if the selection is only a text object */ if (object != NULL && object->type == OBJ_TEXT) { if (object->attached_to != NULL) { object = object->attached_to; } } /* now find the slot attribute on the outside first */ if (object != NULL) { numslots_value = o_attrib_search_numslots(object, NULL); if (!numslots_value) { s_log_message(_("numslots attribute missing\n")); s_log_message( _("Slotting not allowed for this component\n")); g_free(value); return; } numslots = atoi(numslots_value); g_free(numslots_value); new_slot_number = atoi(value); #if DEBUG printf("numslots = %d\n", numslots); #endif if (new_slot_number > numslots || new_slot_number <=0 ) { s_log_message(_("New slot number out of range\n")); g_free(value); return; } /* first see if slot attribute already exists outside * complex */ slot_value = o_attrib_search_slot(object, &slot_text_object); if (slot_value) { o_text_set_string (toplevel, slot_text_object, string); temp = slot_text_object; if (temp->visibility == VISIBLE || (temp->visibility == INVISIBLE && toplevel->show_hidden_text)) { o_invalidate (w_current,temp); } o_text_recreate(toplevel, temp); /* this doesn't deal with the selection list * item */ if (temp->visibility == VISIBLE || (temp->visibility == INVISIBLE && toplevel->show_hidden_text)) { o_invalidate (w_current,temp); } g_free(slot_value); } else { /* here you need to do the add the slot attribute since it doesn't exist */ new_obj = o_text_new (toplevel, OBJ_TEXT, ATTRIBUTE_COLOR, object->complex->x, object->complex->y, LOWER_LEFT, 0, /* zero is angle */ string, 10, INVISIBLE, SHOW_NAME_VALUE); s_page_append (toplevel->page_current, new_obj); /* manually attach attribute */ o_attrib_attach (toplevel, new_obj, object, FALSE); slot_text_object = new_obj; } o_invalidate (w_current, object); o_attrib_slot_update(toplevel, object); o_invalidate (w_current,object); toplevel->page_current->CHANGED = 1; g_free(value); } else { fprintf(stderr, _("uggg! you tried to slot edit something that doesn't exist!\n")); g_free(value); exit(-1); } }
/* * Sets several text properties of the given <B>attribute smob</B>: - <B>coloridx</B>: The index of the text color, or -1 to keep previous color. - <B>size</B>: Size (numeric) of the text, or -1 to keep the previous size. - <B>alignment</B>: String with the alignment of the text. Possible values are: * "" : Keep the previous alignment. * "Lower Left" * "Middle Left" * "Upper Left" * "Lower Middle" * "Middle Middle" * "Upper Middle" * "Lower Right" * "Middle Right" * "Upper Right" - <B>rotation</B>: Angle of the text, or -1 to keep previous angle. - <B>x</B>, <B>y</B>: Coords of the text. */ SCM g_set_attrib_text_properties(SCM attrib_smob, SCM scm_coloridx, SCM scm_size, SCM scm_alignment, SCM scm_rotation, SCM scm_x, SCM scm_y) { struct st_attrib_smob *attribute = (struct st_attrib_smob *)SCM_CDR(attrib_smob); OBJECT *object; GSCHEM_TOPLEVEL *w_current = global_window_current; TOPLEVEL *toplevel = w_current->toplevel; int color = -1; int size = -1; char *alignment_string; int alignment = -2; int rotation = 0; int x = -1, y = -1; SCM_ASSERT (scm_is_integer(scm_coloridx), scm_coloridx, SCM_ARG2, "set-attribute-text-properties!"); SCM_ASSERT ( scm_is_integer(scm_size), scm_size, SCM_ARG3, "set-attribute-text-properties!"); SCM_ASSERT (scm_is_string(scm_alignment), scm_alignment, SCM_ARG4, "set-attribute-text-properties!"); SCM_ASSERT ( scm_is_integer(scm_rotation), scm_rotation, SCM_ARG5, "set-attribute-text-properties!"); SCM_ASSERT ( scm_is_integer(scm_x), scm_x, SCM_ARG6, "set-attribute-text-properties!"); SCM_ASSERT ( scm_is_integer(scm_y), scm_y, SCM_ARG7, "set-attribute-text-properties!"); color = scm_to_int(scm_coloridx); SCM_ASSERT (!(color < -1 || color >= MAX_COLORS), scm_coloridx, SCM_ARG2, "set-attribute-text-properties!"); size = scm_to_int(scm_size); rotation = scm_to_int(scm_rotation); x = scm_to_int(scm_x); y = scm_to_int(scm_y); alignment_string = SCM_STRING_CHARS(scm_alignment); if (strlen(alignment_string) == 0) { alignment = -1; } if (strcmp(alignment_string, "Lower Left") == 0) { alignment = 0; } if (strcmp(alignment_string, "Middle Left") == 0) { alignment = 1; } if (strcmp(alignment_string, "Upper Left") == 0) { alignment = 2; } if (strcmp(alignment_string, "Lower Middle") == 0) { alignment = 3; } if (strcmp(alignment_string, "Middle Middle") == 0) { alignment = 4; } if (strcmp(alignment_string, "Upper Middle") == 0) { alignment = 5; } if (strcmp(alignment_string, "Lower Right") == 0) { alignment = 6; } if (strcmp(alignment_string, "Middle Right") == 0) { alignment = 7; } if (strcmp(alignment_string, "Upper Right") == 0) { alignment = 8; } if (alignment == -2) { /* Bad specified */ SCM_ASSERT (scm_is_string(scm_alignment), scm_alignment, SCM_ARG4, "set-attribute-text-properties!"); } if (attribute && attribute->attribute) { object = attribute->attribute; if (object && object->text) { o_invalidate (w_current, object); if (x != -1) { object->text->x = x; } if (y != -1) { object->text->y = y; } if (size != -1) { object->text->size = size; } if (alignment != -1) { object->text->alignment = alignment; } if (rotation != -1) { object->text->angle = rotation; } o_text_recreate(toplevel, object); if (!toplevel->DONT_REDRAW) { o_invalidate (w_current, object); } } } return SCM_BOOL_T; }
/*! \brief mirror a text object horizontaly at a centerpoint * \par Function Description * This function mirrors a text \a object horizontaly at the point * (\a world_centerx, \a world_centery). * * \param [in] toplevel The TOPLEVEL object * \param [in] world_centerx x-coord of the mirror position * \param [in] world_centery y-coord of the mirror position * \param [in] object The text object */ void geda_text_object_mirror (TOPLEVEL *toplevel, int world_centerx, int world_centery, OBJECT *object) { int origx, origy; int x, y; g_return_if_fail (object != NULL); g_return_if_fail (object->text != NULL); g_return_if_fail (object->type == OBJ_TEXT); origx = object->text->x; origy = object->text->y; x = origx + (-world_centerx); y = origy + (-world_centery); if ((object->text->angle%180)==0) { switch(object->text->alignment) { case(LOWER_LEFT): object->text->alignment=LOWER_RIGHT; break; case(MIDDLE_LEFT): object->text->alignment=MIDDLE_RIGHT; break; case(UPPER_LEFT): object->text->alignment=UPPER_RIGHT; break; case(LOWER_RIGHT): object->text->alignment=LOWER_LEFT; break; case(MIDDLE_RIGHT): object->text->alignment=MIDDLE_LEFT; break; case(UPPER_RIGHT): object->text->alignment=UPPER_LEFT; break; default: break; } } else { switch(object->text->alignment) { case(LOWER_LEFT): object->text->alignment=UPPER_LEFT; break; case(UPPER_LEFT): object->text->alignment=LOWER_LEFT; break; case(LOWER_RIGHT): object->text->alignment=UPPER_RIGHT; break; case(UPPER_RIGHT): object->text->alignment=LOWER_RIGHT; break; case(LOWER_MIDDLE): object->text->alignment=UPPER_MIDDLE; break; case(UPPER_MIDDLE): object->text->alignment=LOWER_MIDDLE; break; default: break; } } object->text->x = -x + (world_centerx); object->text->y = y + (world_centery); o_text_recreate(toplevel, object); }