Annotation of 43BSDReno/contrib/emacs-18.55/src/indent.c, revision 1.1

1.1     ! root        1: /* Indentation functions.
        !             2:    Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
        !             3: 
        !             4: This file is part of GNU Emacs.
        !             5: 
        !             6: GNU Emacs is distributed in the hope that it will be useful,
        !             7: but WITHOUT ANY WARRANTY.  No author or distributor
        !             8: accepts responsibility to anyone for the consequences of using it
        !             9: or for whether it serves any particular purpose or works at all,
        !            10: unless he says so in writing.  Refer to the GNU Emacs General Public
        !            11: License for full details.
        !            12: 
        !            13: Everyone is granted permission to copy, modify and redistribute
        !            14: GNU Emacs, but only under the conditions described in the
        !            15: GNU Emacs General Public License.   A copy of this license is
        !            16: supposed to have been given to you along with GNU Emacs so you
        !            17: can know your rights and responsibilities.  It should be in a
        !            18: file named COPYING.  Among other things, the copyright notice
        !            19: and this notice must be preserved on all copies.  */
        !            20: 
        !            21: 
        !            22: #include "config.h"
        !            23: #include "lisp.h"
        !            24: #include "buffer.h"
        !            25: #include "indent.h"
        !            26: #include "window.h"
        !            27: #include "termchar.h"
        !            28: #include "termopts.h"
        !            29: 
        !            30: #define CR '\015'
        !            31: 
        !            32: /* Indentation can insert tabs if this is non-zero;
        !            33:    otherwise always uses spaces */
        !            34: int indent_tabs_mode;
        !            35: 
        !            36: #define min(a, b) ((a) < (b) ? (a) : (b))
        !            37: #define max(a, b) ((a) > (b) ? (a) : (b))
        !            38: 
        !            39: /* These three values memoize the current column to avoid recalculation */
        !            40: /* Some things in set last_known_column_point to -1
        !            41:   to mark the memoized value as invalid */
        !            42: /* Last value returned by current_column */
        !            43: int last_known_column;
        !            44: /* Value of point when current_column was called */
        !            45: int last_known_column_point;
        !            46: /* Value of bf_modified when current_column was called */
        !            47: int last_known_column_modified;
        !            48: 
        !            49: extern int minibuf_prompt_width;
        !            50: 
        !            51: DEFSIMPLE ("current-column", Fcurrent_column, Scurrent_column,
        !            52:   "Return the horizontal position of point.  Beginning of line is column 0.\n\
        !            53: This is calculated by adding together the widths of all the displayed\n\
        !            54: representations of the character between the start of the previous line\n\
        !            55: and point.  (eg control characters will have a width of 2 or 4, tabs\n\
        !            56: will have a variable width)\n\
        !            57: Ignores finite width of screen, which means that this function may return\n\
        !            58: values greater than (screen-width).\n\
        !            59: Whether the line is visible (if `selective-display' is t) has no effect.",
        !            60:   Lisp_Int, XSETINT, current_column ())
        !            61: 
        !            62: int
        !            63: current_column ()
        !            64: {
        !            65:   register int col;
        !            66:   register unsigned char *ptr, *stop, c;
        !            67:   register int tab_seen;
        !            68:   register int post_tab;
        !            69:   register int tab_width = XINT (bf_cur->tab_width);
        !            70:   int ctl_arrow = !NULL (bf_cur->ctl_arrow);
        !            71: 
        !            72:   if (point == last_known_column_point
        !            73:       && bf_modified == last_known_column_modified)
        !            74:     return last_known_column;
        !            75: 
        !            76:   ptr = &CharAt (point - 1) + 1;
        !            77:   stop = point <= bf_s1 + 1 ? bf_p1 + 1 : bf_p2 + bf_s1 + 1;
        !            78:   if (tab_width <= 0 || tab_width > 20) tab_width = 8;
        !            79: 
        !            80:   col = 0, tab_seen = 0, post_tab = 0;
        !            81: 
        !            82:   while (1)
        !            83:     {
        !            84:       if (ptr == stop)
        !            85:        {
        !            86:          if (ptr == bf_p1 + 1)
        !            87:            break;
        !            88:          stop = bf_p1 + 1;
        !            89:          ptr = stop + bf_s1;
        !            90:          if (!bf_s1) break;
        !            91:        }
        !            92: 
        !            93:       c = *--ptr;
        !            94:       if (c >= 040 && c < 0177)
        !            95:        {
        !            96:          col++;
        !            97:        }
        !            98:       else if (c == '\n')
        !            99:        break;
        !           100:       else if (c == '\r' && EQ (bf_cur->selective_display, Qt))
        !           101:        break;
        !           102:       else if (c == '\t')
        !           103:        {
        !           104:          if (tab_seen)
        !           105:            col = ((col + tab_width) / tab_width) * tab_width;
        !           106: 
        !           107:          post_tab += col;
        !           108:          col = 0;
        !           109:          tab_seen = 1;
        !           110:        }
        !           111:       else
        !           112:        col += (ctl_arrow && c < 0200) ? 2 : 4;
        !           113:     }
        !           114: 
        !           115:   if (tab_seen)
        !           116:     {
        !           117:       col = ((col + tab_width) / tab_width) * tab_width;
        !           118:       col += post_tab;
        !           119:     }
        !           120: 
        !           121:   last_known_column = col;
        !           122:   last_known_column_point = point;
        !           123:   last_known_column_modified = bf_modified;
        !           124: 
        !           125:   return col;
        !           126: }
        !           127: 
        !           128: ToCol (col)
        !           129:      int col;
        !           130: {
        !           131:   register int fromcol = current_column ();
        !           132:   register int n;
        !           133:   register int tab_width = XINT (bf_cur->tab_width);
        !           134: 
        !           135:   if (fromcol > col)
        !           136:     return;
        !           137: 
        !           138:   if (tab_width <= 0 || tab_width > 20) tab_width = 8;
        !           139: 
        !           140:   if (indent_tabs_mode)
        !           141:     {
        !           142:       n = col / tab_width - fromcol / tab_width;
        !           143:       if (n)
        !           144:        {
        !           145:          while (n-- > 0)
        !           146:            InsCStr ("\t", 1);
        !           147: 
        !           148:          fromcol = (col / tab_width) * tab_width;
        !           149:        }
        !           150:     }
        !           151: 
        !           152:   while (fromcol < col)
        !           153:     {
        !           154:       InsCStr ("        ", min (8, col - fromcol));
        !           155:       fromcol += min (8, col - fromcol);
        !           156:     }
        !           157: 
        !           158:   last_known_column = col;
        !           159:   last_known_column_point = point;
        !           160:   last_known_column_modified = bf_modified;
        !           161: }
        !           162: 
        !           163: DEFUN ("indent-to", Findent_to, Sindent_to, 1, 2, "NIndent to column: ",
        !           164:   "Indent from point with tabs and spaces until COLUMN is reached.\n\
        !           165: Always do at least MIN spaces even if that goes past COLUMN;\n\
        !           166: by default, MIN is zero.")
        !           167:   (col, minimum)
        !           168:      Lisp_Object col, minimum;
        !           169: {
        !           170:   int mincol;
        !           171: 
        !           172:   CHECK_NUMBER (col, 0);
        !           173:   if (NULL (minimum))
        !           174:     XFASTINT (minimum) = 0;
        !           175:   CHECK_NUMBER (minimum, 1);
        !           176: 
        !           177:   mincol = current_column () + XINT (minimum);
        !           178:   if (mincol < XINT (col)) mincol = XINT (col);
        !           179: 
        !           180:   ToCol (mincol);
        !           181: 
        !           182:   XSETINT (col, mincol);
        !           183:   return col;
        !           184: }
        !           185: 
        !           186: DEFUN ("current-indentation", Fcurrent_indentation, Scurrent_indentation,
        !           187:   0, 0, 0,
        !           188:   "Return the indentation of the current line.\n\
        !           189: This is the horizontal position of the character\n\
        !           190: following any initial whitespace.")
        !           191:   ()
        !           192: {
        !           193:   Lisp_Object val;
        !           194: 
        !           195:   XFASTINT (val) = position_indentation (find_next_newline (point, -1));
        !           196:   return val;
        !           197: }
        !           198: 
        !           199: position_indentation (pos)
        !           200:      register int pos;
        !           201: {
        !           202:   register int col = 0;
        !           203:   register int c;
        !           204:   register int end = NumCharacters + 1;
        !           205:   register int tab_width = XINT (bf_cur->tab_width);
        !           206: 
        !           207:   if (tab_width <= 0 || tab_width > 20) tab_width = 8;
        !           208: 
        !           209:   while (pos < end &&
        !           210:         (c = CharAt (pos),
        !           211:          c == '\t' ? (col += tab_width - col % tab_width)
        !           212:            : (c == ' ' ? ++col : 0)))
        !           213:     pos++;
        !           214: 
        !           215:   return col;
        !           216: }
        !           217: 
        !           218: DEFUN ("move-to-column", Fmove_to_column, Smove_to_column, 1, 1, 0,
        !           219:   "Move point to column COLUMN in the current line.\n\
        !           220: COLUMN is calculated by adding together the widths of all the displayed\n\
        !           221: representations of the character between the start of the previous line\n\
        !           222: and point.  (eg control characters will have a width of 2 or 4, tabs\n\
        !           223: will have a variable width)\n\
        !           224: Ignores finite width of screen, which means that this function may be\n\
        !           225: passed values greater than (screen-width)")
        !           226:   (column)
        !           227:      Lisp_Object column;
        !           228: {
        !           229:   register int pos = point;
        !           230:   register int col = current_column ();
        !           231:   register int goal;
        !           232:   register int end = NumCharacters;
        !           233:   register int tab_width = XINT (bf_cur->tab_width);
        !           234:   register int ctl_arrow = !NULL (bf_cur->ctl_arrow);
        !           235: 
        !           236:   Lisp_Object val;
        !           237: 
        !           238:   if (tab_width <= 0 || tab_width > 20) tab_width = 8;
        !           239:   CHECK_NUMBER (column, 0);
        !           240:   goal = XINT (column);
        !           241:   if (col > goal)
        !           242:     {
        !           243:       pos = find_next_newline (pos, -1);
        !           244:       col = 0;
        !           245:     }
        !           246: 
        !           247:   while (col < goal && pos <= end)
        !           248:     {
        !           249:       int c = CharAt (pos);
        !           250:       if (c == '\n')
        !           251:        break;
        !           252:       if (c == '\r' && EQ (bf_cur->selective_display, Qt))
        !           253:        break;
        !           254:       pos++;
        !           255:       col++;
        !           256:       if (c == '\t')
        !           257:        {
        !           258:          col += tab_width - 1;
        !           259:          col = col / tab_width * tab_width;
        !           260:        }
        !           261:       else if (ctl_arrow && (c < 040 || c == 0177))
        !           262:         col++;
        !           263:       else if (c < 040 || c >= 0177)
        !           264:         col += 3;
        !           265:     }
        !           266: 
        !           267:   SetPoint (pos);
        !           268: 
        !           269:   last_known_column = col;
        !           270:   last_known_column_point = point;
        !           271:   last_known_column_modified = bf_modified;
        !           272: 
        !           273:   XFASTINT (val) = col;
        !           274:   return val;
        !           275: }
        !           276: 
        !           277: struct position val_compute_motion;
        !           278: 
        !           279: struct position *
        !           280: compute_motion (from, fromvpos, fromhpos, to, tovpos, tohpos, width, hscroll, tab_offset)
        !           281:      int from, fromvpos, fromhpos, to, tovpos, tohpos;
        !           282:      register int width;
        !           283:      int hscroll, tab_offset;
        !           284: {
        !           285: /* Note that `cpos' is CURRENT_VPOS << SHORTBITS + CURRENT_HPOS,
        !           286:    and that CURRENT_HPOS may be negative.  Use these macros
        !           287:    to extract the hpos or the vpos from cpos or anything like it.
        !           288:  */
        !           289: #ifndef SHORT_CAST_BUG
        !           290: #define HPOS(VAR) (short) (VAR)
        !           291: #else
        !           292: #define HPOS(VAR) (((VAR) & (1 << (SHORTBITS - 1)) \
        !           293:                    ? ~((1 << SHORTBITS) - 1) : 0) \
        !           294:                   | (VAR) & ((1 << SHORTBITS) - 1))
        !           295: /* #define HPOS(VAR) (((VAR) & 0x8000 ? 0xffff0000 : 0) | ((VAR) & 0xffff)) */
        !           296: #endif /* SHORT_CAST_BUG */
        !           297: 
        !           298: #define VPOS(VAR) (((VAR) >> SHORTBITS) + (HPOS (VAR) < 0))
        !           299: 
        !           300: 
        !           301: #ifndef TAHOE_REGISTER_BUG
        !           302:   register
        !           303: #endif /* TAHOE_REGISTER_BUG */
        !           304:     int cpos = fromhpos + (fromvpos << SHORTBITS);
        !           305:   register int target = tohpos + (tovpos << SHORTBITS);
        !           306:   register int pos;
        !           307:   register int c;
        !           308:   register int tab_width = XFASTINT (bf_cur->tab_width);
        !           309:   register int ctl_arrow = !NULL (bf_cur->ctl_arrow);
        !           310:   int selective
        !           311:     = XTYPE (bf_cur->selective_display) == Lisp_Int
        !           312:       ? XINT (bf_cur->selective_display)
        !           313:        : !NULL (bf_cur->selective_display) ? -1 : 0;
        !           314:   int prevpos;
        !           315: 
        !           316:   if (tab_width <= 0 || tab_width > 20) tab_width = 8;
        !           317:   for (pos = from; pos < to && cpos < target; pos++)
        !           318:     {
        !           319:       prevpos = cpos;
        !           320:       c = CharAt (pos);
        !           321:       if (c >= 040 && c < 0177)
        !           322:        cpos++;
        !           323:       else if (c == '\t')
        !           324:        {
        !           325:          cpos += tab_width
        !           326:            - HPOS (cpos + tab_offset + hscroll - (hscroll > 0)
        !           327:                    /* Add tab_width here to make sure positive.
        !           328:                       cpos can be negative after continuation
        !           329:                       but can't be less than -tab_width.  */
        !           330:                    + tab_width)
        !           331:              % tab_width;
        !           332:        }
        !           333:       else if (c == '\n')
        !           334:        {
        !           335:          if (selective > 0 && position_indentation (pos + 1) >= selective)
        !           336:            {
        !           337:              /* Skip any number of invisible lines all at once */
        !           338:              do
        !           339:                {
        !           340:                  while (++pos < to && CharAt(pos) != '\n');
        !           341:                }
        !           342:              while (selective > 0 && position_indentation (pos + 1) >= selective);
        !           343:              pos--;
        !           344:              /* Allow for the " ..." that is displayed for them. */
        !           345:              if (!NULL (bf_cur->selective_display_ellipses))
        !           346:                {
        !           347:                  cpos += 4;
        !           348:                  if (HPOS (cpos) >= width)
        !           349:                    cpos -= HPOS (cpos) - width;
        !           350:                }
        !           351:            }
        !           352:          else
        !           353:            cpos += (1 << SHORTBITS) - HPOS (cpos);
        !           354:          cpos -= hscroll;
        !           355:          if (hscroll > 0) cpos++; /* Count the ! on column 0 */
        !           356:          tab_offset = 0;
        !           357:        }
        !           358:       else if (c == CR && selective < 0)
        !           359:        {
        !           360:          /* In selective display mode,
        !           361:             everything from a ^M to the end of the line is invisible */
        !           362:          while (pos < to && CharAt(pos) != '\n') pos++;
        !           363:          pos--;
        !           364:          /* Allow for the " ..." that is displayed for them. */
        !           365:          if (!NULL (bf_cur->selective_display_ellipses))
        !           366:            {
        !           367:              cpos += 4;
        !           368:              if (HPOS (cpos) >= width)
        !           369:                cpos -= HPOS (cpos) - width;
        !           370:            }
        !           371:        }
        !           372:       else
        !           373:        cpos += (ctl_arrow && c < 0200) ? 2 : 4;
        !           374: 
        !           375:       if (HPOS (cpos) >= width
        !           376:          && (HPOS (cpos) > width
        !           377:              || (pos < NumCharacters
        !           378:                  && CharAt (pos + 1) != '\n')))
        !           379:        {
        !           380:          if (cpos >= target)
        !           381:            break;
        !           382:          if (hscroll
        !           383:              || (truncate_partial_width_windows
        !           384:                  && width + 1 < screen_width)
        !           385:              || !NULL (bf_cur->truncate_lines))
        !           386:            {
        !           387:              while (pos < to && CharAt(pos) != '\n') pos++;
        !           388:              pos--;
        !           389:            }
        !           390:          else
        !           391:            {
        !           392:              cpos += (1 << SHORTBITS) - width;
        !           393:              tab_offset += width;
        !           394:            }
        !           395: 
        !           396:        }
        !           397:     }
        !           398: 
        !           399:   val_compute_motion.bufpos = pos;
        !           400:   val_compute_motion.hpos = HPOS (cpos);
        !           401:   val_compute_motion.vpos = VPOS (cpos);
        !           402:   val_compute_motion.prevhpos = HPOS (prevpos);
        !           403: 
        !           404:   /* Nonzero if have just continued a line */
        !           405:   val_compute_motion.contin
        !           406:     = pos != from
        !           407:       && (val_compute_motion.vpos != VPOS (prevpos))
        !           408:       && c != '\n';
        !           409: 
        !           410:   return &val_compute_motion;
        !           411: }
        !           412: #undef HPOS
        !           413: #undef VPOS
        !           414: 
        !           415: 
        !           416: pos_tab_offset (w, pos)
        !           417:      struct window *w;
        !           418:      register int pos;
        !           419: {
        !           420:   int opoint = point;
        !           421:   int col;
        !           422: 
        !           423:   if (pos == FirstCharacter || CharAt (pos - 1) == '\n')
        !           424:     return 0;
        !           425:   SetPoint (pos);
        !           426:   col = current_column ();
        !           427:   SetPoint (opoint);
        !           428:   return col - (col % (XFASTINT (w->width) - 1));
        !           429: }
        !           430: 
        !           431: /* start_hpos is the hpos of the first character of the buffer:
        !           432:    zero except for the minibuffer window,
        !           433:    where it is the width of the prompt.  */
        !           434: 
        !           435: struct position val_vmotion;
        !           436: 
        !           437: struct position *
        !           438: vmotion (from, vtarget, width, hscroll, window)
        !           439:      register int from, vtarget, width;
        !           440:      int hscroll;
        !           441:      Lisp_Object window;
        !           442: {
        !           443:   struct position pos;
        !           444:   /* vpos is cumulative vertical position, changed as from is changed */
        !           445:   register int vpos = 0;
        !           446:   register int prevline;
        !           447:   register int first;
        !           448:   int lmargin = hscroll > 0 ? 1 - hscroll : 0;
        !           449:   int selective
        !           450:     = XTYPE (bf_cur->selective_display) == Lisp_Int
        !           451:       ? XINT (bf_cur->selective_display)
        !           452:        : !NULL (bf_cur->selective_display) ? -1 : 0;
        !           453:   int start_hpos = (EQ (window, minibuf_window) ? minibuf_prompt_width : 0);
        !           454: 
        !           455:  retry:
        !           456:   if (vtarget > vpos)
        !           457:     {
        !           458:       /* Moving downward is simple, but must calculate from beg of line 
        !           459:         to determine hpos of starting point */
        !           460:       if (from > FirstCharacter && CharAt (from - 1) != '\n')
        !           461:        {
        !           462:          prevline = find_next_newline (from, -1);
        !           463:          while (selective > 0
        !           464:                 && prevline > FirstCharacter
        !           465:                 && position_indentation (prevline) >= selective)
        !           466:            prevline = find_next_newline (prevline - 1, -1);
        !           467:          pos = *compute_motion (prevline, 0,
        !           468:                                 lmargin + (prevline == 1 ? start_hpos : 0),
        !           469:                                 from, 10000, 10000,
        !           470:                                 width, hscroll, 0);
        !           471:        }
        !           472:       else
        !           473:        {
        !           474:          pos.hpos = lmargin + (from == 1 ? start_hpos : 0);
        !           475:          pos.vpos = 0;
        !           476:        }
        !           477:       return compute_motion (from, vpos, pos.hpos,
        !           478:                             1 + NumCharacters, vtarget, - (1 << (SHORTBITS - 1)),
        !           479:                             width, hscroll, pos.vpos * width);
        !           480:     }
        !           481: 
        !           482:   /* To move upward, go a line at a time until
        !           483:      we have gone at least far enough */
        !           484: 
        !           485:   first = 1;
        !           486: 
        !           487:   while ((vpos > vtarget || first) && from > FirstCharacter)
        !           488:     {
        !           489:       prevline = from;
        !           490:       while (1)
        !           491:        {
        !           492:          prevline = find_next_newline (prevline - 1, -1);
        !           493:          if (prevline == FirstCharacter
        !           494:              || selective <= 0
        !           495:              || position_indentation (prevline) < selective)
        !           496:            break;
        !           497:        }
        !           498:       pos = *compute_motion (prevline, 0,
        !           499:                             lmargin + (prevline == 1 ? start_hpos : 0),
        !           500:                             from, 10000, 10000,
        !           501:                             width, hscroll, 0);
        !           502:       vpos -= pos.vpos;
        !           503:       first = 0;
        !           504:       from = prevline;
        !           505:     }
        !           506: 
        !           507:   /* If we made exactly the desired vertical distance,
        !           508:      or if we hit beginning of buffer,
        !           509:      return point found */
        !           510:   if (vpos >= vtarget)
        !           511:     {
        !           512:       val_vmotion.bufpos = from;
        !           513:       val_vmotion.vpos = vpos;
        !           514:       val_vmotion.hpos = lmargin;
        !           515:       val_vmotion.contin = 0;
        !           516:       val_vmotion.prevhpos = 0;
        !           517:       return &val_vmotion;
        !           518:     }
        !           519:   
        !           520:   /* Otherwise find the correct spot by moving down */
        !           521:   goto retry;
        !           522: }
        !           523: 
        !           524: DEFUN ("vertical-motion", Fvertical_motion, Svertical_motion, 1, 1, 0,
        !           525:   "Move to start of screen line LINES lines down.\n\
        !           526: If LINES is negative, this is moving up.\n\
        !           527: Sets point to position found; this may be start of line\n\
        !           528:  or just the start of a continuation line.\n\
        !           529: Returns number of lines moved; may be closer to zero than LINES\n\
        !           530:  if beginning or end of buffer was reached.")
        !           531:   (lines)
        !           532:      Lisp_Object lines;
        !           533: {
        !           534:   struct position pos;
        !           535:   register struct window *w = XWINDOW (selected_window);
        !           536: 
        !           537:   CHECK_NUMBER (lines, 0);
        !           538: 
        !           539:   pos = *vmotion (point, XINT (lines),
        !           540:                  XFASTINT (w->width) - 1
        !           541:                  - (XFASTINT (w->width) + XFASTINT (w->left)
        !           542:                     != XFASTINT (XWINDOW (minibuf_window)->width)),
        !           543:                  /* Not XFASTINT since perhaps could be negative */
        !           544:                  XINT (w->hscroll), selected_window);
        !           545: 
        !           546:   SetPoint (pos.bufpos);
        !           547:   return make_number (pos.vpos);
        !           548: }
        !           549: 
        !           550: syms_of_indent ()
        !           551: {
        !           552:   DEFVAR_BOOL ("indent-tabs-mode", &indent_tabs_mode,
        !           553:     "*Indentation can insert tabs if this is non-nil.\n\
        !           554: Setting this variable automatically makes it local to the current buffer.");
        !           555:   indent_tabs_mode = 1;
        !           556: 
        !           557:   defsubr (&Scurrent_indentation);
        !           558:   defsubr (&Sindent_to);
        !           559:   defsubr (&Scurrent_column);
        !           560:   defsubr (&Smove_to_column);
        !           561:   defsubr (&Svertical_motion);
        !           562: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.